【Python】bitflyer の API を使って注文をキャンセルする

2018年3月21日Python,開発

おはようございます。

前回、注文まで出来るようにしたのですが、
取消のことをすっかり忘れていました。

ので注文の取消も実装してみたいと思います。

プログラムは前回のものを流用します。

【Python】bitflyer の API を使って注文を送信する

スポンサーリンク

画面の修正

Main.html
注文取消ボタン用の列を追加

<div id="childOrderContainer">
   <table id="childOrderTable">
      <tr class="header">
         <th style="width:20%">ID</th>
         <th style="width:10%">売買</th>
         <th style="width:10%">種別</th>
         <th style="width:10%">値段</th>
         <th style="width:10%">数量</th>
         <th style="width:10%">注文日時</th>
         <th style="width:10%">期限</th>
         <th style="width:5%">取消</th>
      </tr>
   </table>
</div>

_ChildOrder.html

同じく注文取消ボタン用列の追加と、ボタンの表示

    <!DOCTYPE html>
    <table id="childOrderTable">
        <tr class="header">
            <th style="width:20%">ID</th>
            <th style="width:10%">売買</th>
            <th style="width:10%">種別</th>
            <th style="width:10%">値段</th>
            <th style="width:10%">数量</th>
            <th style="width:10%">注文日時</th>
            <th style="width:10%">期限</th>
            <th style="width:5%">取消</th>
        </tr>
        {% for item in data %}
            <tr>
                <td>{{ item["child_order_id"] }}</td>
                <td>{{ item["side"] }}</td>
                <td>{{ item["child_order_type"] }}</td>
                <td>{{ item["price"] }}</td>
                <td>{{ item["size"] }}</td>
                <td>{{ parse_date (item["child_order_date"]) }}</td>
                <td class="cnt">{{ parse_date (item["expire_date"]) }}</td>
                <td><input type="button" value="取消"child_order_id"] }}')"</td>
            </tr>
        {% end %}
    </table>

style.css
注文取消しボタンのセンタリング

    td.cnt {
        text-align:center;
    }

プログラムの修正

bfTool.py

注文取消し用リクエストハンドラ―を追加

class CancelChildOrderHandler(RequestHandler):
    """
    注文を取消
    """

    def initialize(self):
        logging.info("SendChildOrderHandler [initialize]")

    def post(self):
        logging.info("SendChildOrderHandler [post]")

        param = json.loads(self.request.body)
        param["product_code"] = "FX_BTC_JPY"
        logging.info(param)

        api = BfApi()
        data = api.send_req(api_path="/v1/me/cancelchildorder", http_method="POST", **param)
        self.write(json.dumps(data, ensure_ascii=False))

URLマッピングの追加

    app = tornado.web.Application([
        (r"/", MainHandler),
        (r"/ticker", SendWebSocket),
        (r"/balance", GetBalanceHandler),
        (r"/execution", GetExecutionHandler),
        (r"/childOrder", GetChildOrderHandler),
        (r"/sendOrder", SendChildOrderHandler),
        (r"/cancelOrder", CancelChildOrderHandler)
        ],
        template_path=os.path.join(os.getcwd(), "templates"),
        static_path=os.path.join(os.getcwd(), "static"),
        js_path=os.path.join(os.getcwd(), "js"),
    )

取消ボタン押下時の処理

script.js

/**
 * 注文をキャンセルします.
 */
function cancelOrder(order_id) {

   var param = {
      child_order_id : order_id
   }

   $.ajax({
      url: "http://localhost:8888/cancelOrder",
      type: "POST",
      data: JSON.stringify(param),
      success: function(jsonResponse) {
         jsonResponse = jsonResponse.replace( /\\/g , "" );
         var data = JSON.parse(jsonResponse);
         updateChildOrder();
         alert("注文をキャンセルしました。")
      },
      error: function() {
      }
   });
}

ついでに注文一覧を2秒毎に更新するように

script.js

/**
 * 画面読み込み時の処理
 */
function initialize() {

    // 各テーブルに空行を追加しておく
    addEmptyRow("tickerTable", 10, 12);
    addEmptyRow("executionTable", 10, 8);

    // 初期表示時に一度データを取得
    updateBalance();
    updateExecution();
    updateChildOrder();

    var connection = new WebSocket('ws://127.0.0.1:8888/ticker');
    connection.onmessage = function (e) {
        var data = JSON.parse(e.data.replace( /\\/g , "" ));

        var table = $("#tickerTable");

        // 日付け変換
        var date = new Date(data.timestamp);
        data.timestamp = date.toLocaleString();

        // テーブルに追加
        var tr = document.createElement("tr");
        $.each(data, function(i, cell){
            var td = document.createElement("td");
            td.innerHTML = cell;
            tr.appendChild(td);
        });
        var rows = table.find("tr");
        if (rows.length > 10) {
            $("#tickerTable tr:last").remove();
        }
        $(tr).insertAfter("#tickerTable tr.header");

    };

    // 注文種別変更時の処理
   $("#order_type").change(function () {
       if($(this).val() == "MARKET") {
            $("#order_price").prop("disabled", true);
       } else {
           $("#order_price").prop("disabled", false);
       }
   });

   // 注文一覧を2秒ごとに更新
   setInterval("updateChildOrder()", 2000);
}

起動してみる

変更後の画面

注文を出している状態。
取消ボタンをクリックします。

取消完了メッセージ

取消の完了メッセージが表示されます。

注文一覧

注文一覧からも注文がいなくなりました。

まとめ

何度か試している際に気付いたのが、
(bitflyer)サーバーに負荷がかかっている状態だとやっぱり注文も取消もしばらく時間がかかってしまうようですね。

注文が正常に受け付けられたとしても注文一覧で取得できない状態ではまだ約定までは至らないような感じです。

まあしょうがないんですかね。

次回はSQLiteなんかと組み合わせてみましょうか。

ではでは。

 

スポンサーリンク


関連するコンテンツ

2018年3月21日Python,開発Python,プログラミング

Posted by doradora