ボット・クローラー Advent Calendar 2016 20日目の記事です。
今回のサンプルプロジェクト
以下に今回のサンプルコードを含むプロジェクトをあげてあります。
仮想通貨の取引所
仮想通貨(今回はビットコインを扱うことにします)の取引所が国内にいくつかあります。
比較として以前このような記事を書きました。
取引所の売買で儲ける(または損をする)ことを考える
要は株取引とか為替のFXとかと同じような雰囲気で考えてもらえばいいです。
ビットコインにはビットコイン(BTC)の相場というものがあって、例えば昨日は1BTC=8万円だったのが、明日は1BTC=9万円になることがあったりします。そんなときは(正確な予測は難しいですが)昨日1BTCを買っておいて明日1BTCを売ったとしたら1万円の利益が出ます。そういうやつです。
取引所における情報の取得や売買をプログラムで制御する
各取引所における取引は Web 画面から行えるので手動でポチポチするのも良いですが、せっかくなのでプログラムで売買を自動化してみましょう。
いくつかの取引所では公式に WebAPI が提供されています。
今回は bitFlyer の API を操作してみることにします。
都合よく(?)bitFlyer API の操作用の NuGet パッケージがこちらにありますので、今回はこれを用いて C# で自動売買プログラムを組んでみましょう。
Visual Studio プロジェクトの作成
今回はシンプルに C# のコンソールプロジェクトを作成します。
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 にて取引履歴を確認することができます。
今回は 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); } } } }
天気予報をもとに売買を行うというふざけたシステムですが下手な人間よりは良い結果を出す可能性もあります。