テクノロジーであそぼ!

プログラミング(Python)や投資、仮想通貨についての情報サイト。

TypeError: 'str' object is not callableの治し方

f:id:kichie_com:20171109200257p:plain

TypeError: 'str' object is not callableの出るコード

if __name__=='__main__':
    str = """sushi habanero yasai juice time
    howdy! it's sunny day! """
    age = 21
    name = 'tomo'
    
    print(str)
    print(name,str(21))
  File "/Users/", line 20, in <module>
print(name,str(21))

TypeError: 'str' object is not callable

原因

Stringに変換するstrではなくstrと言うオブジェクト(変数)が呼び出されているためにエラーが発生している

解決策

変数名を変える

if __name__=='__main__':
    text = """sushi habanero yasai juice time
    howdy! it's sunny day! """
    age = 21
    name = 'tomo'
    
    print(text)
    print(name,str(21))

もしこれでも治らない場合

統合開発環境のspyderやターミナルから扱えるインタラクティブシェルなどで使用している場合はstrと言う変数がまだ残っているために、同じエラーが出る可能性があります。

その場合は一度実行しているそのプログラムを閉じてすべての変数がクリアされている状態から始めると治る可能性があります。

Python プログラムの経過時間を測定して正確に待つ

f:id:kichie_com:20171109194032p:plain

正確な時間待ちたい!

そんなときありますよね。

正確に1秒間で計測しなくていならない。
正確に5秒間隔でサンプリングしなくてはならない。
正確に10秒ごとに音をならした。

などなど

下記のコードは1秒ごとに5回繰り返すプログラムになっています。

実行コード

import time

interval = 1

if __name__=='__main__':
    for _ in range(0,5):
        start_time = time.time()
        for i in range(0,100):
            print("実行中...")
        end_time = time.time()
        elapsed_time = end_time - start_time
        print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")
        print("wait_time:{0}".format(1-elapsed_time)+"[sec]")
        #interval秒-elapsed_time秒 待つ
        time.sleep(interval-elapsed_time)

実行結果

実行中...
.
.
実行中...
elapsed_time:0.010354042053222656[sec]
wait_time:0.9896459579467773[sec]
実行中...
.
.
実行中...
elapsed_time:0.010250091552734375[sec]
wait_time:0.9897499084472656[sec]
.
.

start_timeでプログラムが始まった時刻を計測し、
end_timeで終わった時刻を計測。

そして、interval(待ちたい時間)からelapsed_time(経過時間)を引いてあげるとある程度正確に待ちたい時間待つことができます。

※PCのスペックにより若干のズレは起きる可能性があります。

以上です。

この記事は以下のサイトを参考にさせていただきました。ありがとうございます。
【Python】処理にかかる時間を計測して表示 - Qiita

Python 辞書型のキーとバリューの3つの値取り出し方法

f:id:kichie_com:20171109000412p:plain

Keyだけを取り出したい場合

以下のコードをインタラクティブシェルで実行してください。

>>> for name in name_age.keys():
...     print(name)
...
tadashi
tomo

Valueだけを取り出したい場合

以下のコードをインタラクティブシェルで実行してください。

>>> for age in name_age.values():
...     print(age)
...
42
21

KeyとValueの両方を取り出したい場合

以下のコードをインタラクティブシェルで実行してください。

>>> for name,age in name_age.items():
...     print(name,age)
...
tadashi 42
tomo 21

以上です。

Python print関数の改行の抜き方

f:id:kichie_com:20171108081349p:plain

問題のprint()関数

次のコードをインタラクティブシェルに入力してください。

>>> print('Hello');print('World')
Hello
World

print()関数のend=''オプションを使って解決

次のコードをインタラクティブシェルに入力してください。

>>> print('Hello',end='');print('World')
HelloWorld

print()関数にはデフォルトでendオプションが付いています。
これを使用するとprint()関数の出力の最後に文字列を付け加えることができます、

print()関数にはsepオプションも存在する

print()関数にはendオプションの他にsepオプションも存在します。
次のコードをインタラクティブシェルに入力してください。

>>> print('satoshi','tomonari','tadashi','masataka','yuko')
satoshi tomonari tadashi masataka yuko
>>> print('satoshi','tomonari','tadashi','masataka','yuko', sep='->')
satoshi->tomonari->tadashi->masataka->yuko

sepオプションは、print関数の第1引数から第n引数の引数同士の間に文字列を挿入することができます。


以上

Python 文法 リスト,辞書型の代入する時に気をつけるたった1つのこと

f:id:kichie_com:20171108071806p:plain

値は値が、リストは参照が代入される

まずはコンソールで

python

を入力し、インタラクティブシェルでこちらを入力していただきたい。

>>> number = [0,1,2,3,4]
>>> more_one = number
>>> number[1] = 'hello'
>>> number
[0, 'hello', 2, 3, 4]
>>> more_one
[0, 'hello', 2, 3, 4]

ひょっとすると変に見えるかもしれません。

more_oneのリストしか変えていないのに、numberのリストの値も変わってしまいました。

この結果からわかることは、リストの代入の場合は値が代入されるのではなくリストの参照(IDのようなもの)が代入されるということです。

この情報だけを知ると値とリストの概念は少し違うように思えますが実は一緒です。

変数は良く箱と称されますが、値の代入の場合、値そのものが格納されます。
リストの場合は

number = [0,1,2,3,4]

ここの段階でこのリストの参照(リンク)が入り、リスト自体は別の場所へ格納されます。そしてその参照がmore_oneへ代入されます。

どうすればリスト自体をコピーできるのか?

copyモジュールのcopy()関数を使うと値自体をコピーすることができます。

以下のコードをインタラクティブシェルで実行してください。

>>> import copy
>>> number = [0,1,2,3,4]
>>> more_one = copy.copy(number)
>>> more_one[1] = 'fix'
>>> more_one
[0, 'fix', 2, 3, 4]
>>> number
[0, 1, 2, 3, 4]

copy()関数を使うことによってnumberリストの値自体がコピーされ、どこかに保存されます。そして、more_oneに新しくコピーされた値の参照が格納されます。

リストの中にリストがある場合はdeepcopy()

リストの中にリストがあるものをコピーする場合はcopy()の代わりに、depcopy()の関数を使用する。

以下のコードをインタラクティブシェルで実行してください。

>>> team = [[0,1],[2,3,4],[5,6,7]]
>>> new_team = copy.deepcopy(team)
>>> new_
new_name  new_team
>>> new_team[0] = [10,20]
>>> new_team
[[10, 20], [2, 3, 4], [5, 6, 7]]
>>> team
[[0, 1], [2, 3, 4], [5, 6, 7]]

まとめ

変数への代入をする時は、
値の自体が代入される
リストの場合は参照が代入される。
そのため、別の変数に代入する場合も同じように参照が代入される。

値自体をコピーしたい場合はimport copyをしてcopu()関数を使用する。


以上

Python特有の文法 global文

f:id:kichie_com:20171108050149p:plain

グローバル変数の指定をする

グローバル変数を使う場合にはglobal文宣言をする。

name = 'jack'

#関数
def whatYourName():
    global name    #global文
    name = input()
    
#main文
if __name__=='__main__':
    whatYourName()
    print(name)
satoshi  //入力した文字
satoshi

C言語やSwiftと違って使う変数の宣言をしなくていい分、グローバル変数を使用する場合には宣言が必要な模様です。

また、global文を使用するとその関数の名ではnameはローカル変数ではなくグローバル変数として扱われます。

global文を使わなかったらどうなるか?

試しにglobal文を使わないとします。

name = 'jack'

#関数
def whatYourName():
#    global name  コメントアウト
    name = input()
    
#main文
if __name__=='__main__':
    whatYourName()
    print(name)
satoshi    //入力した文字
jack

以上です。

Zaifの自動トレードプログラム書いたら10%利益出たからそのプログラムを載せてみる

f:id:kichie_com:20171030092337p:plain

Python × ZaifAPI 取引時間をハックするプログラム【資産情報取得編】
Python × ZaifAPI 取引時間をハックするプログラム【取引編】
Python × ZaifAPI 取引時間をハックするプログラム【価格取得編】


以前の続きです。

前回までの三回を組み合わせて取引

以下のサイトを参考に、アレンジを加えてプログラムを書いてみました。
初心者が一攫千金を目指してBitcoin自動取引botを作るよ! その3【ローカルBot】

①前回の取引額を渡す(この金額が判断の基準となる)
②Bitcoinを持っていて(0.001以上)かつ0.25%値上がりした場合、売る!(そして、前回取引額を更新する)
③Bitcoinを持っていない(0.001以下)かつ0.1%値下がりした場合、買う!(そして、前回取引額を更新する)
④取引が処理されない場合、1分待って、待っても処理されない場合、キャンセルする(そして、前回取引額を元に戻す)
【参考】
・取引後のResponseの「order_id」が0でない(order_idが発行されている)場合、取引が保留となっている。
・売買タイミングとして、インベスターzの10%利食いと5%損切りの考え方を採用してみました。
また、今回は人ではなくプログラムで行うため、高速で取引ができるという利点があります。

それゆえに、かなり少ない値にすれば、良い結果が出るのではないかと考え、0.25%で利食い、0.1%で損切りという値を設定しました。

実装

参考サイトにのっとりまして、KEYとSECRETをjsonファイルとして管理をすることにします。
今回より、keyとsecretをjsonにして別ファイルで保管するように変えました。
[]・・・フォルダ
[zaif]
 |- zaif_trade.py
 |- [config] - zaifkeys.json
 |- ...<略>

import json
import time
from zaifapi import ZaifPublicApi
from zaifapi import ZaifTradeApi
from decimal import (Decimal)

zaif_keys_json = open('config/zaifkeys.json', 'r')
zaif_keys = json.load(zaif_keys_json)

KEY = zaif_keys["key"]
SECRET = zaif_keys["secret"]

if __name__=='__main__':
    # get environ ver
    zaif_public = ZaifPublicApi()
    zaif_trade = ZaifTradeApi(KEY,SECRET)
    
    CANCEL_FLUG = False
    
    Last_trade_price = int(zaif_public.last_price('btc_jpy')["last_price"])
    
    
    while(True):
        print("■ 現在の情報です")
        funds_btc = zaif_trade.get_info2()['funds']['btc']
        funds_jpy = zaif_trade.get_info2()['funds']['jpy']
        last_price = int(zaif_public.last_price('btc_jpy')["last_price"])
        print("市場取引価格:"+str(last_price))
        print("btc資産:"+str(funds_btc))
        print("jpy資産:"+str(funds_jpy))
        print("最終取引価格:"+str(Last_trade_price))
        
        
        #btcを持っていて0.25%値上がり
        if(funds_btc >= 0.001 and int(Last_trade_price*1.0025)< last_price):
            #売却
            bid_amount = Decimal(funds_btc).quantize(Decimal('0.0001'))
            trade_result = zaif_trade.trade(currency_pair="btc_jpy", action="ask", price=last_price, amount=bid_amount)
            print('■ Bitcoinの売却申請を行いました。')
            print(trade_result)
            print("売却注文価格:"+str(last_price))
            print("売却注文量 :"+str(bid_amount))
            Last_trade_price_pre = Last_trade_price
            Last_trade_price = last_price
            
            if(trade_result["order_id"] != 0):
                CANCEL_FLUG = True
                order_id = trade_result["order_id"]
            else:
                print("■ 取引が完了しました。")
        #btcを持っていて0.1%値下がり
        elif(funds_btc >= 0.001 and int(Last_trade_price*0.999) > last_price):
            #売却
            bid_amount = Decimal(funds_btc).quantize(Decimal('0.0001'))
            trade_result = zaif_trade.trade(currency_pair="btc_jpy", action="ask", price=last_price, amount=bid_amount)

            print('■ Bitcoinの売却申請を行いました。')
            print(trade_result)
            print("売却注文価格:"+str(last_price))
            print("売却注文量 :"+str(bid_amount))
            Last_trade_price_pre = Last_trade_price
            Last_trade_price = last_price
            
            if(trade_result["order_id"] != 0):
                CANCEL_FLUG = True
                order_id = trade_result["order_id"]
            else:
                print("■ 取引が完了しました。")
        #btcを持っていないでlastpriceより値下がりしたら買い
        elif(funds_btc < 0.001 and last_price < Last_trade_price):
            ask_amount = (Decimal(funds_jpy*0.5)/last_price).quantize(Decimal('0.0001'))
            trade_result = zaif_trade.trade(currency_pair="btc_jpy", action="bid", price=last_price, amount=ask_amount)
            print('■ Bitcoinの購入申請を行いました')
            print(trade_result)
            print("購入注文価格:"+str(last_price))
            print("購入注文量 :"+str(ask_amount))
            Last_trade_price_pre = Last_trade_price
            Last_trade_price = last_price
            
            if trade_result["order_id"] != 0:
                CANCEL_FLUG = True
                order_id = trade_result["order_id"]
            else:
                print('■ 取引が完了しました。')
            
            if CANCEL_FLUG:
                print('■ 60秒間待機します。')
                time.sleep(60)
                trade_info = zaif_trade.get_info2()
                if trade_info["open_orders"] > 0:
                    print("■ キャンセルしました")
                    print(zaif_trade.cancel_order(order_id=order_id))
                    Last_trade_price = Last_trade_price_pre
                else:
                    print("■ 取引が完了しました。")
        time.sleep(5)


main.pyと同じ階層にフォルダ「config」を作成し、下記jsonファイルに保存します。

{
    "key":"【zaifで作成したkey】",
    "secret":"【zaifで作成したsecret】"
}

実行結果

5日間約2時間ずつ動かしてみた結果

ノートパソコンで持ち歩くので、ずっと動かすことはしにくかったため、20秒ごとに1回動くようにして、合計4時間動かしてみました。

その結果!



JPY:10000 → JPY:11018.61967652


約10%増加した...!

あれ意外といいんじゃ!?

反省点と改善点

Bitcoinがこの数日間で60万円代から80万円代に乗ったこともあっていい感じに利益につながったのかも?
まだまだ謎のエラーが出るのと、zaifのサーバーが弱いのか、加熱時には「ZaifApiError: trade temporarily unavailable.」や「ZaifServerException: return status code is 502」(サーバが落ちている?)などのエラーが出る。


また、売りのタイミングは良いが、買いのタイミングがただ値段が下がったら買っているだけなので、MACDやRSIなどを利用して買いのタイミングを工夫すべきですね。


※このプログラムを利用して利益損害が出たとしても自己責任でお願い致します。

間違えや質問がございましたら気軽にコメントください!


====
キャンセルのプログラムが書いてなかったので追記しました。
コード

print("■ キャンセルしました")
print(zaif_trade.cancel_order(order_id=order_id)) #ここ
Last_trade_price = Last_trade_price_pre

Githubにコードを公開しました。

記事に乗っているコードとは
github/zaif-auto-trade

Next!

12/23 19:30公開予定
Python × ZaifAPI 取引時間をハックするプログラム【ボリンジャーバンド編】



読者登録をして待つ

もしくは、

Twitterをフォローして待つ

Excelをプログラムに任せて、空いてる時間でトレードする

仕事でExcelを使ってらっしゃる方はこちらもおすすめ
【Python x Excel】 めんどくさいExcel作業を自動化しよう!基本操作編 - テクノロジーであそぼ!