Pythonによるauカブコム証券kabuステーションAPIを利用したトレーニングストップブログラム解説 3 PUSH配信受信 /websocket

スポンサーリンク

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)から次の成行決済処理を呼び出してしまっても全く問題はありません。

つづく

コメント