Python {Article109}

ようこそ「Python」へ...

ITエンジニアが仮想通貨の自作自動売買システム(BOT)で月収7万円のパッシブインカムを得るには [1] BOTを作成する目的とBOTの完成品を紹介

ここではITエンジニアがPythonで仮想通貨の自動売買システム(BOT)を作成してパッシブインカム(Passive Income)を得る方法を解説します。 「仮想通貨のボット(BOT)でパッシブインカムを得る」シリースは以下の11回に分けて解説します。 第1回目ではこのシリーズで作成するBOTの目的と完成品の概要を紹介します。 なお、このシリーズで作成するBOTは日本の取引所「GMOコイン」を利用することを前提にしています。 bitFlyer、Binanceなどの取引所を利用するBOTについては後日、別記事にて解説します。

仮想通貨で自動売買(システムトレード)を行うには「1: 自作の自動売買システムを使う」、「2: 自動売買サービスを使う」などの方法があります。 さらに「自動売買サービス」は、「1: 専用ソフトによる自動売買」「2: クラウドサービスによる自動売買」「3: 取引所のサービスによる自動売買」 「4: トークン購入による自動売買」などがあります。

自動売買サービスを使う場合は、中身がブラックボックス化されていて公開されていないので新しいアルゴリズムを追加するとか、 パラメータを追加するといったことができないという制約があります。 つまり、自由度が制限されます。 また、自動売買サービスは仮想通貨の取引所が制限されたり、使用料が必要になる場合もあるといったデメリットがあります。

一方、自作の自動売買システムは自分で作成しているのでシステムの中身がすべて把握できています。 なので新しいアルゴリズムを追加したり、パラメータを追加するといったことが可能になります。 つまり、自由度が非常に高いといったメリットがあります。 ただし、自作の自動売買システムを作成するにはPythonなどのプログラミングの知識が必要になるといったデメリットがあります。 こういったことを踏まえた上で、ここでは自作の自動売買システムを作成することを推奨します。

予め断っておきますが、BOTを作成したからといってすぐには稼げるようにはなりません。 3ヶ月から6ヶ月かけて仮想取引とリアル取引をしてBOTのアルゴリズムとパラメータを調整する必要があります。 そうすれば半年後には投資額にもよりますが月5万円から10万円くらいは稼げるようになっているはずです。

半年経っても月10万円稼げないときは次の「座右の銘」を思い出してください。 きっと稼げるようになるはずです。

「上がり始めたら買え(下がっている間は買うな)。 下がり始めたなら売れ(上がっている間は売るな)。 また、そもそも当てられるわけのない天井や底で売買しようとするな。 一番安いところで買ったり、 一番高いところで売れるものだと思うな。」 このシリーズではMicrosoftのVisual Studio Code(VS Code)を使用しますが、Jupyter NotebookなどのツールでもOKです。 説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

【免責事項】
当記事や当サイトの情報を参考に仮想通貨のBOT(自動トレードプログラム)を動かす場合は、すべて自己責任でお願いいたします。 当サイトの情報を参考にして発生したいかなる損害も責任を負いません。

click image to zoom!
図A
click image to zoom!
図B
click image to zoom!
図C
click image to zoom!
図D
click image to zoom!
図E


BOTを作成する目的とBOTの完成品を紹介

  1. BOTを作成する目的

    2022年9月現在、どんな企業が利益を上げているかと言えばGAFAMです。GAFAM(ガーファム)とは、Google, Amazon, Facebook, Apple, Microsoftの頭文字を取った呼び名です。 GAFAMの共通点はいずれもIT企業だということです。 これらの企業の経営者は、利益を上げるには自社にとってITが非常に重要であることを認識しています。 そして、優秀なITエンジニアを雇うために高額の報酬を与えています。 たとえば、米国では新卒者でも年収500万円くらいで数年経てば年収が1000万円を越えます。

    一方、日本の経営者は自社にとってITが重要であることをあまり認識していません。 なので、日本のITエンジニアは新卒者で年収350万円くらいで数年経過しても年収が500~600万円くらいと米国の2分の1から3分の1の年収になっています。 日本のITエンジニアは米国と比較するとかなり冷遇されています。

    日本のITエンジニアが年収を上げるには、 英語を勉強して米国など報酬が高い国で働く、 日本の企業で働いて副業で年収を上げる、 独立して自分で稼ぐなどの選択肢があります。 今回の「自作BOTでパッシブインカムを得る」シリーズは、 日本企業でITエンジニアとして働きながら副業で年収を上げる方法です。 一般の副業と異なるのは、あなたが寝ている間も、会社で仕事をしている間も、自作のBOTがあなたの代わりに24時間365日あなたのためにお金を稼いでくれるということです。 これをパッシブインカム(Passive Income)といいます。 あなたのBOTの収入が会社の年収を上回ればFIREして経済的自由を得ることも可能です。 そしてあなたの好きな時間に好きなことをして過ごすといった人生を手に入れることができます。
  2. ここで作成するBOTの特徴

    • BOTで取引する仮想通貨(BTC, ETH, BCH, LTC, XRP,...)を簡単に追加・削除することが可能
    • BOTで最大限に利益を上げるためにレバレッジ取引に対応(現物取引も可能ですがここではレバレッジ取引に特化)
    • シミュレーションモードとリアルモードをサポート(実際のリアルデータを利用した仮想取引が可能)
    • 通常の「買い注文▶売り注文」と空売りから入る「売り注文▶買い注文」双方ともサポート
    • 買い注文・売り注文の数量を任意に設定可能
    • 利益率・ロスカット率を設定することが可能
    • 任意のタイミングで買い注文・売り注文を強制的にキャンセルすることが可能
    • 任意のタイミングでポジション(売り・買い)をキャンセルすることが可能
    • 買い注文・売り注文は「成り行き」「指値」どちらでも選択可能
    • BOTのログ情報を画面とファイルに出力することが可能(デバッグモートと通常モードを切り替えてログ情報をコントロールすることも可能)
    • パラメターを変えて複数のBOTを同時に実行することが可能(1~5のBOTを並行して走らせることが可能)
    • 仮想通貨ごとの日次・週次・月次の利益がリアルタイムで取得可能
    • 仮想通貨ごとの日次・週次・月次の約定件数がでリアルタイムで取得可能
    • 仮想通貨ごとのロスカットがパーセント(5%, 10%, 15%, 18%, 20%,...)ごとに取得可能
    • 仮想通貨ごとの買い注文・売り注文の明細をCSVファイルに作成(EXCELで表示して分析可能)
    • 仮想通貨ごとの日次・週次・月次の利益明細をEXCELファイルに作成(EXCELで利益率の分析可能)
    • 特定の事象が発生したとき3種類の音を鳴らして管理者に知らせる
    • 特定の事象が発生したときGmailを送信して管理者に通知する
    • 取引所がメンテの時間帯はBOTは自動的にスリープモードに切り替わる
    • 取引所がレバレッジ取引でポジションを持っているときに24時間経過すると手数料を加算しますがこの手数料を計算して利益計算に自動的に反映させる
    • 取引所のAPIでタイムアウトが発生したときは自動的に再試行する

  3. BOTを起動する前に各種パラメータを設定する

    BOTを起動する前に各種パラメータを設定します。 ここではGMOの取引所を利用することを前提に各種パラメータを設定します。 行2では取引所のAPIでサポートしている仮想通貨(レバレッジ取引)のシンボルを定義します。 ここでは5種類の仮想通貨のシンボルを定義しています。 行3-4では仮想通貨の取引を有効・無効にするかを設定します。 ここではすべて有効にするので「False」を定義しています。 行3は「買い注文▶売り注文」の取引に関する設定です。

    行4は「売り注文▶買い注文」の取引に関する設定です。 行5-6では取引の数量を定義します。 数量の最小値・最大値は仮想通貨により異なります。 たとえば、「BTC_JPY」の場合は数量は「0.01BTC_JPY~5BTC_JPY」の範囲になります。 ここではそれぞれの仮想通貨の最小値を設定しています。 行7では利益率を定義します。 XRP_JPYの場合、数量が「10」のとき利益率が「0.0035」以上でないと利益が出ません。 なぜなら、利益が出ても小数点以下が切り捨てとなるからです。 つまり、取引所に有利になるように計算されます。 行8ではストップ・ロスのパーセントを指定します。 相場がここで指定した価格を越えたら強制的に注文をキャンセルして損切りします。

    ここで設定したパラメータは仮想取引・リアル取引をしながら3ヶ月~6ヶ月くらいかけて調整します。

    gmo81_BuySell_v10_Bot0.py:
    # BOT Parameters
    symbol_list             = ['BTC_JPY',  'ETH_JPY',  'BCH_JPY',   'LTC_JPY',  'XRP_JPY']   
    buy_sell_suspend_list   = [False,       False,      False,      False,      False]   
    sell_buy_suspend_list   = [False,       False,      False,      False,      False]   
    buy_sell_qty_list       = [0.01,        0.1,        0.1,        1,          10]       
    sell_buy_qty_list       = [0.01,        0.1,        0.1,        1,          10]                   
    profit_rate_list        = [0.0015,      0.0015,     0.0015,     0.0015,     0.0035]  
    stop_loss_rate_list     = [0.05,        0.05,       0.005,      0.005,      0.05]
    # End of Parameters
    「config.csv」ファイルにはBOTの実行環境を設定します。 行1はCSVファイルのヘッダーです。 行2はCSVファイルのデータ(パラメータ値)です。 ヘッダー「run_mode」の列には「run」「stop」のいずれかを指定します。 「stop」を指定したときは全ての仮想通貨の取引を1回行ったあとにBOTが終了します。 「run」を指定したときは仮想通貨の取引を自動的に繰り返し行います。 通常「run」を設定して24時間365日稼働させます。 日次・週次・月次のタイミングでBOTを終了させるときは「config.csv」ファイルの「run」を「stop」に書き換えて保存します。

    まとめると、取引する仮想通貨のシンボルと数量を定義します。そして「config.csv」ファイルには「run」を設定します。 これで前準備は完了です。

    config.csv:
    run_mode
    run  # run or stop

  4. BOTを起動する

    BOT「gmo...Bot0.py」を起動するには、BOT起動時のパラメータを指定する必要があります。 パラメータは4パターンあります。 パラメータの「real」はリアルモードで取引をするときに指定します。 パラメータの「fake」はシミュレーションモードで仮想取引をするときに指定します。 仮想取引であっても取引データはリアルタイムのデータを使います。 パラメータの「reset」は各種ファイルを初期化して取引するときに指定します。 パラメータの「restart」は前回の取引を継続して取引するときに指定します。

    # Bot Run parameters
    run: python gmo81_BuySell_v10_Bot0.py --real_reset
    run: python gmo81_BuySell_v10_Bot0.py --real_restart
    run: python gmo81_BuySell_v10_Bot0.py --fake_reset
    run: python gmo81_BuySell_v10_Bot0.py --fake_restart   
    # End of Bot Run parameters

    click image to zoom!
    図4-1
    BOTを起動するにはVisual Studio Code(VS Code)から「TERMINAL」ウィンドウを開いて起動します。 たとえば、BOTを初期化モードでシミュレーション(仮想取引)したいときは、行4のコマンド「python ... --fake_reset」を入力します。

    図4-1はBOTを実行したときの画面です。 画面にはBOTのログが表示されています。 各種CSVファイルが削除されて初期化されます。 ちなみに、ここではBOTをデバッグモードで実行しています。 図4-1には仮想通貨の利益(月次・週次・日次)、約定件数(月次・週次・日次)、ロスカットの件数などが表示されています。


    click image to zoom!
    図4-2
    図4-2はBOTをシミュレーションモード(仮想取引)でかつ継続取引のモードで実行しています。 「python ... --fake_restart」で起動します。 BOT起動時にログに起動時のモードが表示されます。 ここでは「gmo...Bot0: (real=False, reset=False, stop_loss=True, cancel=True, debug=True) started」が表示されています。 「real=False」はシミュレーションモードで実行していることを意味します。 「reset=False」は継続取引モードで実行していることを意味します。 「debug=True」はデバッグモードで実行していることを意味します。 デバッグモードで実行すると取引の詳細ログが画面とファイルに出力されます。


    click image to zoom!
    図4-3
    図4-3は複数の仮想通貨を取引している画面です。 仮想通貨ごとに仮想通貨のシンボル「BTC_JPY」、数量「0.01, 0.01, 0.01」、利益率・ストップロス率「1.0015, 0.0200」が表示されています。 なお、数量は「Min, Mid, Max」の3種類設定できます。 取引の最後には仮想通貨の買い注文の件数「coin.buy[0, 0]」、売り注文の件数「coin.sell[0, 0]」、ストップロスの件数「con.sl[0]」が表示されます。 買い注文の件数[]内に2種類の数値が表示されていますが左側が「約定件数」で、右側は「キャンセル件数」です。 同様に売り注文の左側が「約定件数」で、右側が「キャンセル件数」です。


    click image to zoom!
    図4-4
    図4-4は仮想通貨の取引の詳細ログです。 ログには取引の明細がインデントされて表示されます。 「buy_sell():」では買い注文、売り注文の条件をチェックしてそれぞれの条件を満足したときに注文を実行します。

    ここに買い注文・売り注文のタイミングを処理するロジック(アルゴリズム)を組み込みます。 ここに組み込むアルゴリズムには、さまざまなトレード・インジケーターを利用します。 BOTで利益が出るかどうかは、ここに組み込んだアルゴリズムに依存します。 したがって、ここがBOTの肝となる部分です。

    「create_sell_order():」では買い注文(Long Position)を決済するために売り注文(指値)を実行しています。 内部的にはGMOのAPI「exe_sell_close_order_limit()」経由で注文します。

    「update_order():」では指値の売り注文が約定したかどうかを調べています。 内部的にはGMOのAPI「get_order_status()」で売り注文の状況を取得します。 売り注文が約定したらGMOのAPI「get_price()」で実際の売値を取得します。

    「update_order2():」では注文ファイルを更新しています。 注文ファイルには「買い注文」と「売り注文」が格納されていて利益を計算するときに使用します。 注文ファイルはEXCEL形式でも作成します。

    「stop_loss_v3():」ではストップロスをチェックします。 このBOTではGMOが強制的に注文をロスカットする前に事前にロスカットさせます。


    click image to zoom!
    図4-5
    図4-5には仮想通貨ごとの利益、約定件数、ロスカットが表示されています。 利益は月次・週次・日次ごとに集計されて表示されます。 同様に約定件数も月次・週次・日次ごとに集計されて表示されます。 ロスカットはパーセントごとに件数が表示されます。 ここに表示されているのは実際にロスカットされた件数ではありません。 この情報を元にどのタイミング(%)でロスカットさせるかの判断材料に利用します。


  5. ログ・ファイルから取引の詳細を分析する

    BOTのログはVisual Studio Code (VS Code)のTEMINALウィンドウにも表示されますが、 バグがあるのかすべてのログが表示されないことがあります。 なので仮想通貨の取引の詳細を確認するにはログ・ファイルを見ます。

    ここではログ・ファイル「log(20220910).txt」の一部を掲載しています。 関数「buy_sell()」では仮想通貨の「買い注文」と「売り注文」のタイミングを調べています。 行3には、現在売りのポジション(short position)を持っている状態であることが表示されています。

    行4には、マーケットのトレンドが下降トレンドでないので「売り注文」をスキップしたという情報が表示されています。 ちなみに、このBOTでは「損小利大」になるようなアルゴリズムを組み込んでいるのでマーケットが上昇トレンドから下降トレンドに変わったタイミングで売り注文を出しています。 関数「buy_sell()」では、なぜ「買い注文」及び「売り注文」が実行されなかったを示すさまざまな情報が表示されます。 これらの情報を分析してBOTのアルゴリズムと各種パラメータを調整します。

    buy_sell():
    realBuySell() class initiated: BTC_JPY, qty=[0.01, 0.01, 0.01], rate=[1.0015, 0.0200]  [2022-09-10 07:00:49]
    .... buy_sell(): buy_sell_condition(2), mas_buy_df.shape(327),  mas_sell_df.shape(362)  [2022-09-10 07:02:09]
    .... buy_sell(): SELL position (short position)  [2022-09-10 07:02:09]
    .... buy_sell(): SKIP(2) due to market is not down trend  [2022-09-10 07:02:09]
    .... update_order(): sell position(True), mas_df.shape(689), close(False), cancel(True)  [2022-09-10 07:02:09]
    .... update_order(): sell_position=110, order_sell_price=3,040,085, book_sell_price=3,028,340  [2022-09-10 07:02:10]
    .... update_order(): reverse_sell_position: [110]  [2022-09-10 07:02:10]
    .... update_order2(): first_pass(True), last_order_completed(False)  [2022-09-10 07:02:10]
    .... update_order2(): update_order_info(buy_order_id=B0910-065535-503611, buy_real_qty=0.01, buy_real_price=3,024,743, buy_real_fee=0)  [2022-09-10 07:02:10]
    .... stop_loss_v3(): mas_df.shape(689), loss cut: 18%(False), 15%(False), 10%(False)  [2022-09-10 07:02:10]
    .... update_order2(): first_pass(False), last_order_completed(False)  [2022-09-10 07:02:10]
    .... update_order2(): update_order_info(buy_order_id=B0910-065535-503611, buy_real_qty=0.01, buy_real_price=3,024,743, buy_real_fee=0)  [2022-09-10 07:02:10]
    .... main(2): sell position count 0~10[0] 11~30[0] 31~50[0] 51~70[0] 71~90[0] 91~999[1]   [2022-09-10 07:02:10]
    gmo81BuySellv10Bot2 main(2): real(BTC_JPY), real_order_completed(False), close(False), cancel(True), coin.buy[1, 0], coin.sell[0, 0], coin.sl[0]  [2022-09-10 07:02:10]

    行1-21には仮想通貨「XRP_JPY」のログの一部を掲載しています。 行5では現在、買いポジション(long position)を持っていることが表示されています。 そして買い注文の条件が満足したので関数「create_buy_order()」を呼び出しています。 行6-13は関数「create_buy_order()」のログです。 行7では関数「exe_buy_order_market_wait()」を呼び出して成り行きの「買い注文」を出しています。 この関数の引数には「数量、買値」を指定します。 買値は仮想取引のときのみ有効です。リアルの取引では無視されます。 この関数からは戻り値として注文ID、ポジションID等が返されます。 行8-12では買い注文のログを生成しています。 参考までに買い注文は「成り行き」「指値」どちらでも可能です。

    create_buy_order():
    realBuySell() class initiated: XRP_JPY, qty=[10, 10, 10], rate=[1.0035, 0.0200]  [2022-09-10 06:39:38]
    .... buy_sell(): mas_buy_df.shape(686)  [2022-09-10 06:40:53]
    .... buy_sell(): mas_sell_df.shape(782)  [2022-09-10 06:40:53]
    .... buy_sell(): NEW BUY ORDER REQUEST last sell order has been closed: buy_real_qty=10.0, sell_real_qty=10.0  [2022-09-10 06:40:53]
    .... buy_sell(): BUY position (long position)  [2022-09-10 06:40:53]
    .... create_buy_order(): create_buy_order(buy_time=2022-09-09 21:31:00, qty=10, price=50.173)  [2022-09-10 06:40:53]
    .... create_buy_order(): exe_buy_order_market_wait(qty=10, price=50.173): ▶ 0, order_id=B0910-064053-975179 FAKE [2022-09-10 06:40:53]
    .... create_buy_order(): while(1): exe_buy_order_market_wait(10, 50.173) ▶ status=0, res_df.shape=(1, 11)  [2022-09-10 06:40:53]
    .... create_buy_order(): write_buy_order_child_log(buy_order_id=B0910-064053-975179, position_id=P0910-064053-975179, real_qty=10, real_price=50.173, real_fee=0): ▶ 1  [2022-09-10 06:40:53]
    .... create_buy_order(): write_buy_sub_order_log(buy_order_id=B0910-064053-975179, position_id=P0910-064053-975179, qty=10, price=50.173, real_qty=10, real_price=50.173, real_fee=0): ▶ 1  [2022-09-10 06:40:53]
    .... create_buy_order(): while(1): buy_qty=10.0, header_sum_real_qty=10.0  [2022-09-10 06:40:53]
    .... create_buy_order(): write_buy_order_log(buy_time=2022-09-09 21:31:00, qty=10, price=50.173, real_qty=10, real_price=50.173, real_fee=0): ▶ 1  [2022-09-10 06:40:53]
    .... create_buy_order(): create_buy_order() ▶ status=0 normal return...  [2022-09-10 06:40:53]
    .... update_order(): sell position(False), mas_df.shape(1468), close(False), cancel(True)  [2022-09-10 06:40:54]
    .... update_order2(): first_pass(True), last_order_completed(True)  [2022-09-10 06:40:54]
    .... update_order2(): write_order_info(buy_order_id=B0910-064053-975179, buy_real_qty=10, buy_real_price=50.173, buy_real_fee=0)  [2022-09-10 06:40:54]
    .... stop_loss_v3(): mas_df.shape(1468), loss cut: 18%(False), 15%(False), 10%(False)  [2022-09-10 06:40:54]
    .... update_order2(): first_pass(False), last_order_completed(False)  [2022-09-10 06:40:54]
    .... update_order2(): update_order_info(buy_order_id=B0910-064053-975179, buy_real_qty=10, buy_real_price=50.173, buy_real_fee=0)  [2022-09-10 06:40:54]
    .... main(3): sell position count 0~10[0] 11~30[0] 31~50[0] 51~70[0] 71~90[0] 91~999[0]   [2022-09-10 06:40:54]
    gmo81BuySellv10Bot0 main(3): real(XRP_JPY), real_order_completed(False), close(False), cancel(True), coin.buy[1, 0], coin.sell[1, 0], coin.sl[0]  [2022-09-10 06:40:54]

    行1-28には仮想通貨「XRP_JPY」のログの一部を掲載しています。 行3の「buy_sell()」では、現在売りポジション(short position)を持っていることが表示されています。 そして売り注文の条件が満足したので関数「create_sell_order()」を呼び出しています。

    行4-11は関数「create_sell_order()」のログです。 行5では関数「get_sell_price()」を呼び出して売値を計算させて取得しています。 売値は利益率から自動的に計算します。 ただし、マーケットの売値がここで計算した売値よりも高いときはマーケットの価格を売値にします。

    行6では関数「exe_sell_close_order_limit()」を呼び出して指値の売り注文を出しています。 この関数の引数には「ポジションID、数量、売値」を指定します。 ポジションIDは買い注文のときに取得したポジションIDを指定します。 この関数からは戻り値として注文IDが返されます。

    行7-10ではログを作成・更新しています。

    create_sell_order():
    realBuySell() class initiated: XRP_JPY, qty=[10, 10, 10], rate=[1.0035, 0.0200]  [2022-09-10 07:06:25]
    .... buy_sell(): buy_sell_condition(0), mas_buy_df.shape(679),  mas_sell_df.shape(784)  [2022-09-10 07:07:52]
    .... buy_sell(): SELL position (short position)  [2022-09-10 07:07:52]
    .... create_sell_order(): create_sell_order(sell_time=2022-09-09 22:05:00, ms_price=50.060, buy_time=2022-09-09 21:31:00)  [2022-09-10 07:07:52]
    .... create_sell_order(): get_sell_price(buy_price=50.173): ▶ sell_price=50.349  [2022-09-10 07:07:52]
    .... create_sell_order(): exe_sell_close_order_limit(P0910-064053-975179, qty=10, price=50.349): ▶ status=0, order_id=S0910-070752-748214 FAKE [2022-09-10 07:07:52]
    .... create_sell_order(): write_sell_sub_order_log(sell_time=2022-09-09 22:05:00, buy_time=2022-09-09 21:31:00, sell_order_id=S0910-070752-748214, position_id=P0910-064053-975179, qty=10, price=50.349): ▶ 1  [2022-09-10 07:07:52]
    .... create_sell_order(): update_buy_sub_order_log(buy_time=2022-09-09 21:31:00, buy_order_id=B0910-064053-975179, sell_order_id=S0910-070752-748214, sell_time=2022-09-09 22:05:00)  [2022-09-10 07:07:52]
    .... create_sell_order(): write_sell_order_log(sell_time=2022-09-09 22:05:00, buy_time=2022-09-09 21:31:00, qty=10, price=50.349): ▶ 1  [2022-09-10 07:07:52]
    .... create_sell_order(): update_buy_order_log(col_name=sell_time, col_value=2022-09-09 22:05:00): ▶ 1  [2022-09-10 07:07:52]
    .... create_sell_order(): create_sell_order() ▶ status=0 normal return...  [2022-09-10 07:07:52]
    .... update_order(): sell position(True), mas_df.shape(1463), close(False), cancel(True)  [2022-09-10 07:07:52]
    .... update_order(): sell_position=48, order_sell_price=50.349, book_sell_price=50.136  [2022-09-10 07:07:53]
    .... update_order(): reverse_sell_position: [48]  [2022-09-10 07:07:53]
    .... update_order(): update_sell_sub_order_log_count(sell_order_id=S0910-070752-748214, get_price_count=1)   [2022-09-10 07:07:53]
    .... update_order(): get_order_status(orderId=S0910-070752-748214, qty=10, price=50.349): ▶ status=0, order_status=EXECUTED FAKE [2022-09-10 07:07:53]
    .... update_order(): get_price(order_id=S0910-070752-748214, qty=10, price=50.349): ▶ status=9 FAKE [2022-09-10 07:07:54]
    .... update_order(): get_price(50.349) ▶ status=9 pending exe_sell_close_order_limit() request: continue to next sell sub orders...  [2022-09-10 07:07:55]
    .... update_order(): update_sell_order_log(sell_time=2022-09-09 22:05:00, real_qty=0, real_price=0.000, real_fee=0)  [2022-09-10 07:07:55]
    .... update_order2(): first_pass(True), last_order_completed(False)  [2022-09-10 07:07:55]
    .... update_order2(): update_order_info(buy_order_id=B0910-064053-975179, buy_real_qty=10, buy_real_price=50.173, buy_real_fee=0)  [2022-09-10 07:07:55]
    .... update_order2(): update_order_info(sell_order_id=S0910-070752-748214, sell_real_qty=0, sell_real_price=0.000, sell_real_fee=0)  [2022-09-10 07:07:55]
    .... stop_loss_v3(): mas_df.shape(1463), loss cut: 18%(False), 15%(False), 10%(False)  [2022-09-10 07:07:55]
    .... update_order2(): first_pass(False), last_order_completed(False)  [2022-09-10 07:07:55]
    .... update_order2(): update_order_info(buy_order_id=B0910-064053-975179, buy_real_qty=10, buy_real_price=50.173, buy_real_fee=0)  [2022-09-10 07:07:55]
    .... update_order2(): update_order_info(sell_order_id=S0910-070752-748214, sell_real_qty=0, sell_real_price=0.000, sell_real_fee=0)  [2022-09-10 07:07:55]
    .... main(1): sell position count 0~10[0] 11~30[0] 31~50[1] 51~70[0] 71~90[0] 91~999[0]   [2022-09-10 07:07:55]
    gmo81BuySellv10Bot0 main(1): real(XRP_JPY), real_order_completed(False), close(False), cancel(True), coin.buy[0, 0], coin.sell[0, 0], coin.sl[0]  [2022-09-10 07:07:55]

  6. 注文ファイルから仮想通貨ごとの損益を分析する

    注文ファイルは仮想通貨ごとにEXCELファイルとして作成されます。

    EXCELファイルの一覧:
    order_by(BCH_JPY).xlsx
    order_by(BTC_JPY).xlsx
    order_by(ETH_JPY).xlsx
    order_by(LTC_JPY).xlsx
    order_by(XRP_JPY).xlsx

    click image to zoom!
    図6
    図6にはビットコインのEXCELファイルが表示されています。 ここではビットコインのEXCELファイル「order_by(BTC_JPY).xlsx」を開いています。 表の利益「profit(AMT)」と利益率「profit(%)」はBOTが自動的に計算します。

    EXCELのデータが表示されたら関数「=SUM(...)」を埋め込んで利益の合計を計算します。 ここでは1933円の利益が出ています。 ちなみに、GMOの取引ではポジションを保持した状態で24時間経過すると手数料が発生します。 EXCELのファイルにはこの手数料も自動的に反映されます。 具体的には列「fee(L)」に手数料が表示されます。 列「count(L)」には手数料が加算された回数が表示されます。 たとえば、ポジションを3日間保持すれば「3」が格納されます。 これらの情報はBOTのパラメータを調整するときに参考にします。

    列「closed」が「TRUE」のときはこの注文の買い、売りとも完了していることを意味します。 「FALSE」のときは売り注文が保留であることを意味します。 つまり、売りポジションを保持している状態です。


  7. 買い注文のログファイルから成り行きの買い注文を詳細に分析する

    ここでは成り行きの買い注文を発行したときに数量がどのように分割して約定しているかを調べます。 成り行き注文のとき取引所(GMO)では「FAK: Fill and Kill」で処理します。 つまり、全ての数量が約定しないときでも注文を完結させます。 ちなみに、指値の注文のときは「FAS: Fill and Store」の指定ができます。 この場合、すべての数量が約定されます。

    買い注文の数量が分割して約定したときに何が問題かといえば、 1回の注文に対してポジションIDが複数生成されるということです。 この場合、複数の売りポジション(Sell Position)を持っているということになります。 このような時に売り注文を出すときは、複数のポジションIDに対して行う必要があるので処理が複雑になります。 詳細は図7-1で具体的に説明します。

    click image to zoom!
    図7-1
    図7-1は仮想通貨(XRP_JPY)の成り行きの買い注文のログ・ファイル「buy_sub_order(XRP_JPY).csv」です。 EXCELの行70のセルCには2個のポジションID「169031027, 169031026」が表示されています。 この注文は数量を「1000」に設定しています。 ところが数量が「540」と「460」に分割(図7-2参照)されて約定しています。 そしてポジションIDも2個「169031027, 169031026」生成されています。

    この場合、売り注文を出すときは2個のポジションID「169031027, 169031026」に対して行う必要があります。

    さらに複雑なのは成り行きの買い注文に「FAK: Fill and Kill」が適用された場合です。 EXCELの行81-82では数量が「1000」の成り行き注文に対して「FAK」が適用されています。 1回目の成り行き注文では全数量「1000」ではなく、一部の「220」のみ約定しています。 しかも、この「220」がさらに2個「180」と「40」に分割(図7-2参照)されて約定されています。 そして2個のポジションID「169031907, 169031906」が生成されています。

    この場合、BOTは残りの数量「780」に対して自動的に成り行きの買い注文を出します。 2回目の成り行き注文では数量「780」が分割されないですべて(図7-2参照)約定しています。 そしてポジションIDも1個「169031912」生成されています。

    このような場合、売り注文を出すときは合計3個「169031907, 169031906, 169031912」のポジションIDに対して行う必要があります。 BOT側ではかなり複雑な処理になります。

    これでBOTの処理に関するログファイルと、 買い注文、売り注文等の注文のログファイルを作成することが重要であることが理解できたと思います。 これらのログ・ファイルがないと何か問題が発生しても時系列的なデータがないので原因を追求することが困難になります。

    click image to zoom!
    図7-2
    図7-2は仮想通貨(XRP_JPY)の成り行きの買い注文のログ・ファイル明細「buy_sub_child_order(XRP_JPY).csv」です。 EXCELの行81-82に成り行きの買い注文「数量:1000」が2個の数量「540, 460」に分割されて表示されています。 EXCELの行100-102に成り行きの買い注文「数量:1000」が3個の数量「180, 40, 780」に分割されて表示されています。