プログラミング

【BitMEX】C#で仮想通貨自動取引BOTを作ってみようー開発編ー

はじめに

こんにちは!WEBプログラマーのどらです。

この記事ではBitMEX(ビットメックス)で実際に運用する仮想通貨取引BOTの開発を行っていきます!

準備編でも書きましたが自分でBOTを作れれば、BOTが自動でトレードしてくれるので一日中チャートに張り付いたり、欲をかいて思わぬ損をすることがなくなります♪

どら
どら
僕もBOTを作ってからはチャートを見ることが少なくなったよ!

24時間365日、相場が動くチャンスで自動で注文を入れてくれるので頼もしい存在です。

BOTは作った人によって作り方は違いますが、基本的に必要な機能は同じだと思いますので今回はその基本的な機能の実装方法を具体的なソースコードを交えて紹介していきたいと思います。

使う言語はC#です。

準備編で紹介しているプログラムを使うのでソースコードを知りたい方は準備編の記事もぜひご覧ください。

あわせて読みたい
【BitMEX】C#で仮想通貨自動取引BOTを作ってみようー準備編ーBitMEXで仮想通貨取引を自動で行うBOTを開発するまでに必要な準備についてまとめています。BitMEXからAPI経由で情報を取得するソースコードも公開しています。...

必要な機能の洗い出し

実装を行う前に必要な機能をあらかじめ洗い出しておくと開発がスムーズに進みやすいです。

どら
どら
機能の洗い出しは普段自分がトレードしている時にしている作業を思い出すと浮かんできやすいよ!

BOTに最低限必要そうな機能をぱっと洗い出してみます。

必要な機能
  1. 相場(ローソク足)の情報を取得する
  2. 自分の注文状況を確認する
  3. 自分のポジション状況を確認する
  4. 資金の確認をする
  5. 注文を行う
  6. 注文をキャンセルする
  7. ポジションをクローズ(決済)する

BitMEXだとまだまだ便利な機能を実装できますが、最低限これだけの機能を組み合わせればBOTの開発を行うことが出来ます。

「注文を行う」や「相場(ローソク足)の情報を取得する」はぱっと浮かんできやすい機能ですが、「資金を確認する」や「注文をキャンセルする」といった機能は忘れるとそもそも取引できなかったりいつの間にか大損してしまうといったことを招くので必ず実装しましょう。

どら
どら
では各機能を実装していきますが、その前にBitMEXApiクラスについて触れます

BitMEXApiクラスについて

今回BitMEXのGithubページで公開されているサンプルコードであるBitMEXApiクラスをベースに開発していきます。

BitMEXApiクラスはAPIへの接続部分の実装が一通り行われています。

めんどうな認証部分のロジックを自分で書かなくてよくなるので助かりますね。

使わないメソッド(機能)も実装されているのでいらないものは削除してもよいです。
準備編で使わないメソッドを削除したバージョンのソースコードを公開しています。

またAPIから返却されるJSONを扱いやすくするためJilというライブラリを使ってデシリアライズしています。
NuGetから取得できるのでぜひ使ってみてください。

どら
どら
これから紹介するソースコードもBitMEXApiクラスの中に書き足してあげてください!

相場(ローソク足)の情報を取得する

普段注文を行う際、チャートや取引量を見て注文するか決定しますよね。

この機能がないと注文を行う判断材料がないので実装します。

public List<TradeEntity> GetTradeBucketed()
{
    var param = new Dictionary<string, string>
    {
        ["symbol"] = "XBTUSD",
        ["binSize"] = "1h",
        ["count"] = 100.ToString(),
    };

    return JSON.Deserialize<List<TradeEntity>>(Query("GET", "/trade/bucketed", param, true));
}

symbolは通貨ペア、binSizeはローソク足の単位です。
1m(1分)、5m(5分)、1h(1時間)、1d(1日)から選択できます。

取得できる情報は始値、終値、高値、安値、ボリュームといったローソク足の基本情報になります。

詳細な情報はこちら

自分の注文状況を確認する

過剰に注文を行ったりしないよう、現在の自分の注文状況を取得する機能を実装します。

すでに約定した注文情報を取得してもあまり意味がないので現在のアクティブな注文のみを取得します。

public List<OrderEntity> GetOrders()
{
    var param = new Dictionary<string, string>
    {
        ["symbol"] = "XBTUSD",
        ["filter"] = "{\"open\":true}",
        ["count"] = 100.ToString()
    };
    return JSON.Deserialize<List<OrderEntity>>(Query("GET", "/order", param, true));
}

symbolは通貨ペア。

filterで取得する注文の条件を絞ることができます。
{“open”:true}を指定すると現在アクティブな注文のみ取得することができます。

指値、注文方法といった注文の基本情報を取得できます。

詳細な情報はこちら

自分のポジション状況を確認する

注文が約定した場合ポジションがオープンするので、ポジションの状況を確認する機能を実装します。

注文と同じくアクティブなポジションのみ取得します。

public PositionEntity GetPosition()
{
    var param = new Dictionary<string, string>
    {
    	["filter"] = "{\"isOpen\":true}",
    	["count"] = 1.ToString()
    };
    return JSON.Deserialize<List<PositionEntity>>(Query("GET", "/position", param, true)).SingleOrDefault();
}

filterに{“isOpen”:true}でアクティブなポジションのみ取得できます。

参入価格、数量といったポジションに関する情報を取得できます。

詳細な情報はこちら

資金の確認をする

トレードに使う資金(ウォレット残高)情報がないと注文が出せないので資金情報を取得する機能を実装します。

public WalletEntity GetUserWallet()
{
    var param = new Dictionary<string, string>();
    param["currency"] = "XBt";
    return JSON.Deserialize<WalletEntity>(Query("GET", "/user/wallet", param, true));
}

currencyにウォレット残高を取得する通貨を指定できます。

詳細な情報はこちら

注文を行う

注文を行う機能を実装します。

買い、売りの2種類用意しておきます。

public void PostBuyOrder(double simpleOrderQty, double price, double stopPx)
{
    var param = new Dictionary<string, string>
    {
        ["symbol"] = "XBTUSD",
        ["side"] = "Buy",
        ["simpleOrderQty"] = simpleOrderQty.ToString(),
        ["price"] = price.ToString(),
        ["stopPx"] = stopPx.ToString(),
        ["ordType"] = "StopLimit"
    };
    Query("POST", "/order", param, true);
}

public void PostSellOrder(double simpleOrderQty, double price, double stopPx)
{
    var param = new Dictionary<string, string>
    {
        ["symbol"] = "XBTUSD",
        ["side"] = "Sell",
        ["simpleOrderQty"] = simpleOrderQty.ToString(),
        ["price"] = price.ToString(),
        ["stopPx"] = stopPx.ToString(),
        ["ordType"] = "StopLimit"
    };
    Query("POST", "/order", param, true);
}

symbol:通貨ペア
side:Buyは買い、Sellは売りの意味
simpleOrderQty:注文を行う数量(XBT単位)
price:指値
stopPx:ストップ指値。指値注文の時は指定しなくてOKです。
ordType:注文方法を指定します。”Limit”は指値、”StopLimit”はストップ指値です。

詳細な情報はこちら

注文をキャンセルする

現在の注文を全てキャンセルする機能を実装します。

約定しなかった注文を一掃できます。

public void DelletAllOrder()
{
    Query("DELETE", "/order/all", null, true);
}

もちろんある注文を指定してキャンセルすることもできます。

詳細な情報はこちら

ポジションをクローズ(決済)する

オープン中のポジションを決済する機能を実装します。

public void PostClosePosition()
{
    var param = new Dictionary<string, string>
    {
        ["symbol"] = "XBTUSD",
    };
    Query("POST", "/order/closePosition", param, true);
}

特にパラメータを指定していないので、このメソッドは成行決済を行います。
priceパラメータに値を指定すると指値で決済することができます。

詳細な情報はこちら

各機能を呼び出してBOTを完成させよう

どら
どら
これまで作り上げた機能を組み合わせてトレードルールにのっけてあげればBOTが完成するよ!

以下のシンプルな条件でBOTを作ってみます。
1時間足で見るのでBOTも1時間毎に動かすことが前提条件です。

条件
  • 1時間足で過去3本の足の最高値を上回った場合はロング、最安値を下回った場合はショートでエントリーする
  • ポジションがロングかつ前の足が2本前の足を下回った場合、成行決済する
  • ポジションがショートかつ前の足が2本前の足を上回った場合、成行決済する
using System.Linq;

namespace BitMEXBot
{
    public class Program
    {
        private static string bitmexKey = "自分のAPIキー";
        private static string bitmexSecret = "自分の秘密鍵";


        static void Main(string[] args)
        {

            var bitmex = new BitMEXApi(bitmexKey, bitmexSecret);

            //現在の注文状況を取得
            var orders = bitmex.GetOrders();

            //現在のポジションを取得
            var position = bitmex.GetPosition();

            //注文あり
            if (orders.Any())
            {
                bitmex.DelletAllOrder();
            }

            //ローソク足取得
            var trades = bitmex.GetTradeBucketed();

            //現在の価格
            var price = trades.First().Close;

            var closedPosition = false;

            //ポジションあり
            if (position != null)
            {

                //ロング
                if (position.CurrentQty > 0)
                {
                    //前の足の終値を下回った場合、成行決済
                    if (trades.Close < trades.Close)
                    {
                        bitmex.PostClosePosition();

                        closedPosition = true;
                    }
                }
                //ショート
                else
                {
                    //前の足の終値を上回った場合、成行決済
                    if (trades.Close > trades.Close)
                    {
                        bitmex.PostClosePosition();

                        closedPosition = true;
                    }

                }

            }

            //ポジションなし
            if (position == null || closedPosition)
            {

                //資金を取得
                var wallet = bitmex.GetUserWallet();
                if (wallet == null)
                {
                    //資金がないので終了
                    return;
                }
                var orderQty = CalcOrderQty(wallet.Amount);

                //直近3本の最高値
                double highest = trades.Skip(1).Take(5).Max(x => x.High);

                //直近3本の最安値
                double lowest = trades.Skip(1).Take(5).Min(x => x.Low);

                //注文
                bitmex.PostBuyOrder(orderQty, highest, highest + 0.5);
                bitmex.PostSellOrder(orderQty, lowest, lowest - 0.5);
            }

        }

        /// <summary>
        /// 投入資金を算出
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public static double CalcOrderQty(double amount)
        {
            //全資金の3分の1を投入する
            return amount / 3 / 100000000;
        }

    }
}

最後に

いかがでしたでしょうか。

BOT開発は難しそうなイメージがありますが、コード量的にはかなり少なくプログラムもそこまで難しくないかな?という印象です。

ユニ
ユニ
本当に難しいのはトレードルール作り
どら
どら
あはは・・・

本当に苦戦してます笑

当ブログで紹介しているソースコードを使えばベースのプログラムはほぼ出来ているのでトレードルールの条件の調整をするだけで実運用ができます。

もし興味がある方はぜひBOT開発を始めてみてください!

ではまたノシ

bitFlyer ビットコインを始めるなら安心・安全な取引所で