websocket_exit.py
これは前回よりシンプルになりましたが、ちょっと内容が変わってますので、説明します。
import sys
import websocket
import pprint
import json
import settings
import datetime
isException = True
def on_message(ws, message):
printWithTime('--- RECV MSG. --- ')
#print(message)
content = json.loads(message)
pprint.pprint(content)
curPrice = content["CurrentPrice"]
if curPrice is None:
settings.previous_value = 0.0
return
pprint.pprint(curPrice)
global isException
if settings.previous_value == 0.0:
settings.previous_value = curPrice
else:
if settings.side == '1':
now_delta = curPrice - settings.previous_value
pprint.pprint(now_delta)
# 最安値を更新していたら、比較する値を更新
if curPrice < settings.previous_value:
settings.previous_value = curPrice
else:
now_delta = settings.previous_value - curPrice
pprint.pprint(now_delta)
# 最高値を更新していたら、比較する値を更新
if curPrice > settings.previous_value:
settings.previous_value = curPrice
if now_delta >= settings.delta:
isException = False
ws.close()
pprint.pprint(settings.previous_value)
def on_error(ws, error):
if len(error) != 0:
printWithTime('--- ERROR --- ')
print(error)
def on_close(ws):
printWithTime('--- DISCONNECTED --- ')
def on_open(ws):
printWithTime('--- CONNECTED --- ')
def websocket_exit():
printWithTime('--- websocket_exit Start--- ')
global isException
isException = True
url = 'ws://localhost:' + settings.port + '/kabusapi/websocket'
# websocket.enableTrace(True)
ws = websocket.WebSocketApp(url,
on_message = on_message,
on_error = on_error,
on_close = on_close)
ws.on_open = on_open
ws.run_forever()
printWithTime('--- websocket_exit End--- ')
if isException:
print("exit")
sys.exit()
def printWithTime(message):
print(str(datetime.datetime.now()) + ' ' + message)
if __name__ == "__main__":
import sys
websocket_exit()
グローバル変数:isExceptionが、最後にFalseだったら成功、Trueのままだったら失敗
isExceptionは初期値True
グローバル変数「isException」は初期値Trueです。
関数外のところはそのモジュールがアクセスされた最初の1回だけ実行されるからです。
関数外に宣言してある変数はグローバル変数と言い、モジュール内のどこからでも参照できます。settings.pyに宣言しないのは、このモジュール以外から使われないからです。
def websocket_exit():websocketを開始して、PUSH API受信開始
58行目の
global isException
が割と落とし穴です。Pythonは変数宣言が必須でないため、「settings.token」のように、モジュール名を付けないと、デフォルトですべてローカル変数として扱うという仕様があります。
そこで、わざわざ「globalだよ」という宣言を関数内でおこってから、グローバル変数にアクセスする必要があるのです。
こんなことをするんだったら、「websocket_exit.isException」のように、自分のモジュール名を付けたほうが簡単かもしれません。
59行目の「isException = true」は1回だけしかwebsocket_exitを呼ばないプログラムでは必要ないのですが、2回以上呼ぶプログラムでも流用できるようにこうしています。
def on_message(ws, message):PUSH APIで株価を受信して判定
ここでも、21行目で「global isException」を宣言しています。
株価が閾値に達したら(この場合ではトレーリングストップに引っかかったら)webSocketを終了します。例外が発生せず正常終了なのでisExceptionをFalseにしておきます。
逆に、isExceptionがTrueのままwebsocketが終了した場合は、何らかの異常が発生したということになります。
再びdef websocket_exit():websocketの続き isExceptionがTrueだとプログラム終了
isExceptionがTrueだとプログラム自体が終了し、逆にisExceptionがFalseだとそのまま関数が終了するので、def websocket_exit()の呼び出し元(このプログラムの場合はメイン)に処理が戻ります。
このことにより、何か異常があった場合はそこで処理を終了し、正常の場合だけ次の処理に進むという実装を行うことができます。
よく分からない人は、ここだけ数珠繋ぎ方式にすればよい
こういう処理は、マルチスレッドプログラミングといって、1つの変数が別々の流れでアクセスされる群像劇みたいなプログラムなので、初心者の方にはややハードルが高いと思われます。
よくわからなかったら、ここだけ数珠繋ぎ方式にして、def on_message(ws, message)から次の成行決済処理を呼び出してしまっても全く問題はありません。
つづく
コメント