読者です 読者をやめる 読者になる 読者になる

clock-up-blog

go-mi-tech

C# でビットコイン自動売買 (bitFlyer API を利用)

ボット・クローラー Advent Calendar 2016 20日目の記事です。

今回のサンプルプロジェクト

以下に今回のサンプルコードを含むプロジェクトをあげてあります。

仮想通貨の取引所

仮想通貨(今回はビットコインを扱うことにします)の取引所が国内にいくつかあります。
比較として以前このような記事を書きました。

取引所の売買で儲ける(または損をする)ことを考える

要は株取引とか為替のFXとかと同じような雰囲気で考えてもらえばいいです。

円でビットコインが買える。
ビットコインを円で売れる。

ビットコインにはビットコイン(BTC)の相場というものがあって、例えば昨日は1BTC=8万円だったのが、明日は1BTC=9万円になることがあったりします。そんなときは(正確な予測は難しいですが)昨日1BTCを買っておいて明日1BTCを売ったとしたら1万円の利益が出ます。そういうやつです。

取引所における情報の取得や売買をプログラムで制御する

各取引所における取引は Web 画面から行えるので手動でポチポチするのも良いですが、せっかくなのでプログラムで売買を自動化してみましょう。

いくつかの取引所では公式に WebAPI が提供されています。
今回は bitFlyerAPI を操作してみることにします。

都合よく(?)bitFlyer API の操作用の NuGet パッケージがこちらにありますので、今回はこれを用いて C# で自動売買プログラムを組んでみましょう。

bitFlyer の API キーの準備

https://lightning.bitflyer.jp/developer にて API Key, API Secret を取得します。

f:id:kobake:20161213173804p:plain:w500

Visual Studio プロジェクトの作成

今回はシンプルに C# のコンソールプロジェクトを作成します。
f:id:kobake:20161213182926p:plain

BitflyerApi パッケージの導入

Visual Studio の Package Manager Console にて以下を実行。

PM> Install-Package BitflyerApi

プログラムの実装

ロジックとしては愚直ですが、例えばこんなふうに自動売買システムを組むことができます。

using BitflyerApi;
....
class Program
{
    static BitflyerClient client;
    
    static void Main(string[] args)
    {
        // 通信用クライアント生成
        client = new BitflyerClient(
            "xxxxxxx", // ※実際の API Key に差し替えること
            "xxxxxxx", // ※実際の API Secret に差し替えること
            ProductCode.FX_BTC_JPY // 今回は BTC-FX を選択
        );

        // 非同期なタスクを生成
        Task.Run(async () =>
        {
            try
            {
                await BotLogic();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }
        }).Wait(); // タスクが終わるまで待つ
    }

    static async Task BotLogic()
    {
        // 5秒毎にランダムに買い注文、売り注文を出し続ける
        Random r = new Random();
        while (true)
        {
            // 2分の1の確率で買い注文または売り注文
            if (r.Next() % 2 == 0)
            {
                Console.WriteLine("buy");
                await client.Buy(0.001); // 成行で 0.001BTC 買い注文
            }
            else
            {
                Console.WriteLine("sell");
                await client.Sell(0.001); // 成行で 0.001BTC 売り注文
            }

            // 5秒待機
            Console.WriteLine("wait");
            await Task.Delay(5000);
        }
    }
}

https://lightning.bitflyer.jp/trade/btcfx にて取引履歴を確認することができます。

f:id:kobake:20161213183759p:plain

今回は 0.001BTC を 89813円 (取引額 89.813円) で売り、0.001BTC を 89824円 (取引額 89.824円)で買い戻した、ということが分かりました。89.813 - 89.824 = -0.011。0.011円損した計算になります。

損得はともかくこんな感じで自動売買システムを稼働させることができます。

※ちなみに5秒毎にランダムな成行注文などしていたら(説明は省きますが)ほぼ確実に損害だけが膨らみます。

ロジックの変更

ここからは BotLogic() だけに的を絞って考えていきましょう。

相場の変動をトリガーとした売買

// 相場の変動が大きく変動したときに売買を行う例
static async Task BotLogic()
{
    // 1分毎にチェック
    double lastPrice = 0;
    while (true)
    {
        // 板情報を取得
        var board = await client.GetBoard();
        double currentPrice = board.MiddlePrice; // 現在の中間価格
        Console.WriteLine("current = " + currentPrice);

        // 前回の相場と比較する
        if (lastPrice != 0)
        {
            double gap = board.MiddlePrice - lastPrice;
            // 1分間で100円値下がりしていたら買い時とみて買う
            if (gap <= -100)
            {
                Console.WriteLine("buy");
                await client.Buy(0.001);
            }
            // 1分間で100円値上がりしていたら売り時とみて売る
            else if (gap >= 100)
            {
                Console.WriteLine("sell");
                await client.Sell(0.001);
            }
        }
        lastPrice = currentPrice;

        // 1分待機
        Console.WriteLine("wait");
        await Task.Delay(60 * 1000);
    }
}

どうでしょう。先ほどのランダム取引よりはまともに見えるでしょうか。しかし実際に得するか損するかは分かりません。売りと買いはもしかしたら逆のほうが良いかもしれません。

東京の天気をトリガーにした売買

// 東京の天気によって売買を判断する例
static async Task BotLogic()
{
    // 東京の今日の天気
    string url = "http://weather.livedoor.com/forecast/webservice/json/v1?city=130010";
    HttpClient httpClient = new HttpClient();
    string json = await httpClient.GetStringAsync(url);
    var data = JsonConvert.DeserializeObject<dynamic>(json);
    string telop = data.forecasts[0].telop;

    // ログ
    Console.WriteLine("東京の今日の天気: " + telop);

    // 晴れっぽい天気なら買う
    if (telop.IndexOf("晴") >= 0)
    {
        Console.WriteLine("buy");
        await client.Buy(0.001);
    }
    // それ以外なら建玉の手じまいを行う
    else
    {
        Console.WriteLine("leave all positions");
        var positions = await client.GetMyPositions();
        foreach(var p in positions)
        {
            if(p.Side== OrderSide.BUY)
            {
                await client.Sell(p.Size);
            }
            else if(p.Side== OrderSide.SELL)
            {
                await client.Buy(p.Size);
            }
        }
    }
}

天気予報をもとに売買を行うというふざけたシステムですが下手な人間よりは良い結果を出す可能性もあります。

あと地味に「建玉手じまい」の部分とても重要です。参考にしてください。

いろいろできます

今回示したのは、あくまでも「こういう判定もできるよ」という例に過ぎません。勝敗はともかく自動売買を動かすこと自体はそこまで難しくないことが伝わりましたでしょうか?

真面目にやるのならば例えばドル円相場を別のサーバから引っ張ってきたりだとか、他の取引所情報も参照したりだとか、機械学習を取り入れるだとか、いろんなロジックの改善方法はあります。

おわり

運用はあくまでも自己責任で。ようこそ (⌒‿⌒) 自動売買の世界へ

});