【AWS】bitflyer注文受付API Gateway実装(フロントエンド編)

【前回の記事】


1. 使用するサービス

前回作成したサービス(過去記事参照)
使用言語はnodeに合わせてjavascriptです。


2. 概要

前回作成したAPI Gatewayに対してHTTP通信を行うクライアント作成をします。ブラウザはChromeで、通信の実装はjavascriptで行います。


3. 実装

通常注文と特殊注文に分けて説明します。

3-1. 通常注文

①見た目の部分

見た目は簡単な部分だけ実装します。

<style>
        
        .orderArea{
            display: inline-block;
            position: relative;
            height: 80px;
        }

        #nomalOrder{
            display: flex;
        }

        .orderArea > .decideOrder{
            position: absolute;
            bottom: 0;
        }
        
    </style>
    <body>
        <div class="displayOrder">
            <div id="nomalOrder">
                <div id="Market" class="orderArea">
                        <div class="orderTitle">Market</div>
                        <div class="detailArea">
                            <span>
                                <label for="MarketOrderNumber">Num: </label>
                                <input type="text" id="MarketOrderNumber"/>
                            </span>
                        </div>
                        
                        <div class="decideOrder">
                            <input type="button" id="marketBuy" onClick="marketBuy()" value="BUY"/>
                            <input type="button" id="marketSell" onClick="marketSell()" value="SELL"/>
                        </div>
                </div>

                <div id="Limit" class="orderArea">
    
                        <div class="orderTitle">Limit</div>
                        <div class="detailArea">
                            <span>
                                <label for="LimitOrderNumber">Num: </label>
                                <input type="text" id="LimitOrderNumber"/>
                            </span>
                            <br>
                            <span>
                                <label for="LimitOrderPrice">Price: </label>
                                <input type="text" id="LimitOrderPrice"/>
                            </span>
                        </div>
                        <div class="decideOrder">
                            <input type="button" id="limitBuy" onClick="limitBuy()" value="BUY"/>
                            <input type="button" id="limitSell" onClick="limitSell()" value="SELL"/>
                        </div>
                    </div>
                </div>
            </div>
        </div>

②リクエスト送信メソッド

  const URL = "API GatewayのURL" // ステージのURLを貼り付け

        // 共通で使用するリクエストメソッド
        function sendRequest(data){

            var request = new XMLHttpRequest();

    // 引数にメソッドとURLを持してあるので、それらを入力
            request.open(data.method, data.url);
            request.setRequestHeader("Content-Type", "application/json");

            // 送信後の処理。特に画面表示等はない
            request.onload = function(err){
                console.log(err)
                if(request.readyState === 4){
                    if(request.status === 200){
                        console.log("success")
                        var res = JSON.parse(request.responseText)   
                        console.log(res);  
                    }
                    else{
                        console.error(request.status, request.response);
                    }
                }
            };

    // エラーの処理
            request.onerror = function(err){
                console.log("err" + request.statusText);
            };

            console.log("sending")

            var body = null;

            // リクエストに付随するbodyを入力
            if(data.body){
                body = {
                    "body": JSON.stringify(data.body)
                }
                body = JSON.stringify(body);
            }

            console.log(body);
            request.send(body);
        }

③Market注文メソッド
購入と売却のメソッドを実装します。どちらもタグから枚数を参照し、リクエスト送信メソッドに渡すbodyを

function marketBuy(){

            // 枚数参照
            var num = document.getElementById("MarketOrderNumber").value;
            if(!num){
                console.log("element empty");
                return;
            }
    
            // body作成
            var data = {
                "coin_pair": "FX_BTC_JPY",
                "type": "MARKET",
                "size": num,
                "side": "BUY"
            }

            // リクエスト送信メソッド呼び出し
            sendRequest(data);
        }

        // marketBuyと同様
        function marketSell(){
            var num = document.getElementById("MarketOrderNumber").value;
            if(!num){
                console.log("element empty");
                return;
            }

            var data = {
                "coin_pair": "FX_BTC_JPY",
                "type": "MARKET",
                "size": num,
                "side": "SELL"
            }
            sendRequest(data);
        }

④Limit注文

Market注文とほど同様で、違いは参照する値に価格が追加されただけです。

function limitBuy(){
            var num = document.getElementById("LimitOrderNumber").value;
            var price = document.getElementById("LimitOrderPrice").value;
            if(!num || !price){
                console.log("element empty");
                return;
            }

            var body = {
                "coin_pair": "FX_BTC_JPY",
                "type": "LIMIT",
                "size": num,
                "side": "BUY",
                "price": price
            }

            var data = {
                url: URL,
                method: 'POST',
                body: body
            }

            sendRequest(data);
        }

        function limitSell(){
            var num = document.getElementById("LimitOrderNumber").value;
            var price = document.getElementById("LimitOrderPrice").value;
            if(!num || !price){
                console.log("element empty");
                return;
            }

            var body = {
                "coin_pair": "FX_BTC_JPY",
                "type": "LIMIT",
                "size": num,
                "side": "SELL",
                "price": price
            }

            var data = {
                url: URL,
                method: 'POST',
                body: body
            }

            sendRequest(data);
        }

3-3. 特殊注文実装

通常注文とほとんど同様です。

①見た目の部分

<style>
        
        .orderArea{
            display: inline-block;
            position: relative;
            height: 200px;
        }

        #specialOrder{
            display: flex;
        }

        .orderArea > .decideOrder{
            position: absolute;
            bottom: 0;
        }
        
    </style>
    <body>
        <div class="displayOrder">
            <div id="specialOrder">
                <div id="ifd-buy" class="orderArea">
                    <div class="orderTitle">IFD BUY</div>
                    <br>
                    <div class="firstArea">
                        <div class="orderTitle">STOP BUY</div>
                        <div class="detailArea">
                            <span>
                                <label for="ifdFbuyNumber">Num: </label>
                                <input type="text" id="ifdFbuyNumber"/>
                            </span>
                            <br>
                            <span>
                                <label for="ifdFbuyPrice">Price: </label>
                                <input type="text" id="ifdFbuyPrice"/>
                            </span>
                        </div>
                    </div>
                    <br>
                    <div class="secondArea">
                        <div class="orderTitle">STOP SELL</div>
                        <div class="detailArea">
                            <span>
                                <label for="ifdSsellNumber">Num: </label>
                                <input type="text" id="ifdSsellNumber"/>
                            </span>
                            <br>
                            <span>
                                <label for="ifdSsellPrice">Price: </label>
                                <input type="text" id="ifdSsellPrice"/>
                            </span>
                        </div>
                    </div>
                        <div class="decideOrder">
                            <input type="button" id="ifdBuy" onClick="ifdBuy()" value="SUBMIT"/>
                        </div>
                </div>

                <div id="ifd-sell" class="orderArea">
                    <div class="orderTitle">IFD SELL</div>
                    <br>
                    <div class="firstArea">
                        <div class="orderTitle">STOP SELL</div>
                        <div class="detailArea">
                            <span>
                                <label for="ifdFsellNumber">Num: </label>
                                <input type="text" id="ifdFsellNumber"/>
                            </span>
                            <br>
                            <span>
                                <label for="ifdFsellPrice">Price: </label>
                                <input type="text" id="ifdFsellPrice"/>
                            </span>
                        </div>
                    </div>
                    <br>
                    <div class="secondArea">
                        <div class="orderTitle">STOP BUY</div>
                        <div class="detailArea">
                            <span>
                                <label for="ifdSbuyNumber">Num: </label>
                                <input type="text" id="ifdSbuyNumber"/>
                            </span>
                            <br>
                            <span>
                                <label for="ifdSbuyPrice">Price: </label>
                                <input type="text" id="ifdSbuyPrice"/>
                            </span>
                        </div>
                    </div>
                        <div class="decideOrder">
                            <input type="button" id="ifdSell" onClick="ifdSell()" value="SUBMIT"/>
                        </div>
                </div>

                <div id="stop" class="orderArea">
    
                    <div class="orderTitle">STOP</div>
                    <br>
                    <div class="detailArea">
                        <span>
                            <label for="StopOrderNumber">Num: </label>
                            <input type="text" id="StopOrderNumber"/>
                        </span>
                        <br>
                        <span>
                            <label for="StopOrderPrice">Price: </label>
                            <input type="text" id="StopOrderPrice"/>
                        </span>
                    </div>
                    <div class="decideOrder">
                        <input type="button" id="StopBuy" onClick="stopBuy()" value="BUY"/>
                        <input type="button" id="StopSell" onClick="stopSell()" value="SELL"/>
                    </div>
                </div>
            </div>
        </div>

②リクエスト送信メソッド

通常注文と同様です。

③ifdメソッド

BUYSELLとSELLBUYを記載します。これらもLimit注文とほど同様で、リクエスト送信メソッドに渡すbodyが異なるだけです。

function ifdSell(){
            var sell_num = document.getElementById("ifdFsellNumber").value;
            var sell_price = document.getElementById("ifdFsellPrice").value;

            if(!sell_num || !sell_price){
                console.log("element empty");
                return;
            }
            
            var buy_num = document.getElementById("ifdSbuyNumber").value;
            var buy_price = document.getElementById("ifdSbuyPrice").value;

            if(!buy_num || !buy_price){
                console.log("element empty");
                return;
            }

            var parameters = [
                {
                    'type': 'STOP',
                    'side': 'SELL',
                    'price': sell_price,
                    'size': sell_num
                },
                {
                    'type': 'STOP',
                    'side': 'BUY',
                    'price': buy_price,
                    'size': buy_num
                }
            ]

            var body = {
                'coin_pair': 'FX_BTC_JPY',
                'parameters': parameters,
                'order_method': 'IFD'
            };

            var data = {
                url: URL,
                method: 'POST',
                body: body
            }

            sendRequest(data);
        }

        function ifdBuy(){
            var buy_num = document.getElementById("ifdFbuyNumber").value;
            var buy_price = document.getElementById("ifdFbuyPrice").value;

            if(!buy_num || !buy_price){
                console.log("element empty");
                return;
            }
            
            var sell_num = document.getElementById("ifdSsellNumber").value;
            var sell_price = document.getElementById("ifdSsellPrice").value;

            if(!sell_num || !sell_price){
                console.log("element empty");
                return;
            }

            var parameters = [
                {
                    'type': 'STOP',
                    'side': 'BUY',
                    'price': buy_price,
                    'size': buy_num
                },
                {
                    'type': 'STOP',
                    'side': 'SELL',
                    'price': sell_price,
                    'size': sell_num
                }
            ]

            
            var body ={
                'coin_pair': 'FX_BTC_JPY',
                'parameters': parameters,
                'order_method': 'IFD'
            };

            var data = {
                url: URL,
                method: 'POST',
                body: body
            }
            
           sendRequest(data);
        }

④STOP注文

説明は割愛します。

function stopBuy(){
            var num = document.getElementById("StopOrderNumber").value;
            var price = document.getElementById("StopOrderPrice").value;
            if(!num || !price){
                console.log("element empty");
                return;
            }

            var parameters = [{
                "type": "STOP",
                "size": num,
                "price": price,
                "side": "BUY"
            }];

            var body ={
                'coin_pair': 'FX_BTC_JPY',
                'parameters': parameters,
                'order_method': 'SIMPLE'
            };

            var data = {
                url: URL,
                method: 'POST',
                body: body
            }

            sendRequest(data);
        }

        function stopSell(){
            var num = document.getElementById("StopOrderNumber").value;
            var price = document.getElementById("StopOrderPrice").value;
            if(!num || !price){
                console.log("element empty");
                return;
            }

            var parameters = [{
                "type": "STOP",
                "size": num,
                "price": price,
                "side": "SELL"
            }];

            var body ={
                'coin_pair': 'FX_BTC_JPY',
                'parameters': parameters,
                'order_method': 'SIMPLE'
            };

            var data = {
                url: URL,
                method: 'POST',
                body: body
            }

            sendRequest(data);
        }

4. おわりに

これで自作のbitflyer注文サイトが完成しました。見た目としては簡素ですが以下の様になります。

normalOrder
通常注文
specialOrder
特殊注文

実際に注文が通っていれば、bitflyerのご自身のアカウントの注文欄に追加されているはずです。
これでbitflyerのwebサーバに負荷がかかっている時でもAPIを叩くことで注文が比較的通りやすくなるかと思います。
※筆者は次の暴落時に検証してみようと思います。9月あたりに115万超えなければ60万あたりまで落ちると予想してます。暴落時にナンピンとか勝負する時はIFDでしっかり損切りできる注文を入れましょう。IFDOCOや自作注文も実装してみては面白いでしょう。

次回、注文は入れたけどキャンセル機能がまだなので、そこら辺を説明していきたいと思います。