Node.jsで仮想通貨取引botを作るまで

###この記事で得られること
- Node.jsで仮想通貨取引bot（以下、bot）を作りたいときに参考にすると良いかもしれない資料
- 筆者が作っためっちゃ基本的なbotのソースコード
- 当たり前ですけどこの記事・ソースコードは実際の取引の参考にはしないでください。筆者はソースコードの内容でbotを短時間動かして普通に損失出しています（笑） 数百円ですが。
- コード見ればわかりますが取引所はbitFlyerを使っています。

###この記事の対象者
- JavascriptおよびNode.jsの基本を終えて、何か作りたいなと思ってる人。
- ここでいう基本は、Progateの関連するレッスンの内容は理解している、AtCoderのABCはJavascriptで解ける・ソースコード読めるレベルぐらいを想定しています。

###参照した資料と進め方
####[Udemy: Node.jsの基礎から学ぶ、ビットコイン自動売買プログラム](https://www.udemy.com/course/nodejs-trading-basic/)
- この教材が作られたのが2年前(?)とかなので、ちょっと内容が古かったりします。ccxtというライブラリを使うんですが、ccxtのメソッドとかもけっこう変わっていたりするので、動画の内容と差があります。そこは自力で公式ドキュメントを参照するしかないです。
- 売買アルゴリズムはどう書くかみたいな部分は参考になります。
- Udemyに言えることですが、セールのときに買うのが良いです。1000円くらいで買えます。

####[ccxt](https://github.com/ccxt/ccxt/blob/master/wiki/Manual.md)（メインで使うライブラリ）
- このページにメソッドの解説とかついてます。英語です。上の動画の内容と差がある場合はこちらを参照です。

####[JavaScript 非同期操作について学ぼう１（コールバック関数）](https://www.youtube.com/watch?v=3gvl2DswvEg)
- 上のライブラリを使いこなすにあたって、Javascriptの非同期処理を理解する必要があります。書き方がちょっととっつきにくかったりするので、最初にテキストで理解するよりこちらの動画のほうがわかりやすいです。

####[JS Primer](https://jsprimer.net/basic/async/#async-handling)
- 非同期処理まわりについて、上の動画で理解できたらこちらのテキストで理解を深めるといいです。
- このテキストは何かと参照するのでブクマ必須です。



###ソースコード
2020/05/05 最初期のコードです。注文は出ますが、意図通りに注文が出ているかまで細かくチェックしていないというレベルです。ちゃんと動作確認して、もうちょっと無駄なところ消して、かっこいいロジック組んだら載せなおそうかな。

```javascript

const ccxt = require('ccxt');

//基本情報・クラス作成
const exchangeId = 'bitflyer'
    , exchangeClass = ccxt[exchangeId]
    , exchange = new exchangeClass({
        'apiKey': 'APIキーをいれる',
        'secret': 'API Secretを入れる',
        'timeout': 30000,
        'enableRateLimit': true,
    });

const interval = 3000;//apiにリクエスト飛ばす感覚
const orderAmount = 0.01;//注文量

const records = [];//価格の格納
let orderInfo = null;//注文情報の格納

//待機時間設定
const sleep = (timer)=>{
    return new Promise((resolve, reject) =>{
        setTimeout (()=>{
            resolve();
        }, timer);
    })
};

async function main(){
    while (true){
        //価格情報の更新
        const ticker = await exchange.fetchTicker('FX_BTC_JPY');//今回はFXでやってます。
        records.push(ticker.ask);
        if (records.length > 3){
            records.shift();
        }
        console.log("------");
        console.log(records);
        //注文がある場合の動作（利確・ロスカット動作）
        if (orderInfo){
            if (ticker.bid - orderInfo.price > 50){//利確コース
                const order = exchange.createMarketOrder('FX_BTC_JPY', 'sell', orderAmount);
                orderInfo = null;
                console.log("sold: profit");
                await sleep(interval);
                continue;
            }else if (ticker.bid - orderInfo.price > -50){//利確コース
                const order = exchange.createMarketOrder('FX_BTC_JPY', 'sell', orderAmount);
                orderInfo = null;
                console.log("sold: loss");
                await sleep(interval);
                continue;
            }
            console.log("hold");
            await sleep(interval);
            continue;//注文情報がある場合はそれ以上注文しない
        }
        //購入動作
        if (records[0] < records[1] && records[1] < records[2]){
            console.log("buy: surge flag");
            const order = exchange.createMarketOrder('FX_BTC_JPY', 'buy', orderAmount);//FXをせっかく使ってるのに買い一辺倒.成行注文です.
            orderInfo = {
                order: order,
                price: ticker.ask,
            }
            console.log("bought");
            await sleep(interval);
            continue;
        }
        //ポジションもないし、注文しなかった場合
        console.log("skip - no position");
        await sleep(interval);
        }
};

main();
```