見出し画像

チャネルブレイクアウト戦略botの解説 メインループ編

告知 2021年11月28日
BitMEXでのバルクオーダーエンドポイントの廃止に伴い、同取引所用のコードは動作しなくなりました。コード修正の予定はありません。

更新 2021年1月11日
通常版のコードを無償で閲覧できるようにしました。

更新 2019年9月28日

例外処理などの仕様を通常版に近づけ、動作をより安定させました。

このときのために

画像1

画像4

HighLow_channelでの50時間参入10時間退出のバックテストチャートです。 2019年4月2日未明にキャプチャしたものです。きれいな右肩上がりでレンジ変化を評価しやすそうに思いました。

そこで、これをもとに値を変化させたバックテストをいくつか取り、戦略構築ガイドとなるような記事を構想していたのですが、夕方に状況が一変していました。

画像2

画像3

レンジの間もマーケットに在り続けて、時が来たら大きく刈り取る。この動きがチャネルブレイクアウト戦略の醍醐味です。
何本足で退出ラインと設定したか、価格が降りてくるまでの期間で成果が変わります。まだ利益は確定していません。

大きなレンジブレイクがありましたので、当初の構想とは異なる記事にしてみました。botスクリプトがブレイクアウトの瞬間をどう待ち構えているのか、紹介します。

今回もコードをお見せしながら簡単な解説をする記事になりました。これでこのbotスクリプトの大半が無料パートに公開されます。ご覧の方のスキルによっては、これまでの記事をつなぎ合わせて補完もすれば、動くコードが作れるかもしれません。

以前までの記事ではローソク足の処理やバルク注文の出し方などを紹介しましたが、今回のコードはメインループです。取得した情報から状況を判別して、それに応じた発注や注文修正を執行するという流れを担います。

説明のため簡略化したり入れ換えたりしているので、これまでのものを単純につないでも動きませんのでお気をつけください。

動くか待つか

ORDER_WAIT = 40
LOOP_WAIT = 20

def run():

    previous_hL = []
    previous_qty = 0
    result = False

    while True:

        hL_channel = fetch_candles()

        position = fetch_position()
        last_price = position[0]
        current_qty = position[1]

        orders = check_orders()

        # 判定足もポジションも変化がなく,注文も出ていれば待機する
        if (previous_hL == hL_channel
                and previous_qty == current_qty
                and orders):
            sleep(LOOP_WAIT)
            continue

        order_lot = fetch_balance(last_price)

メインループの冒頭では、何らかの判定に使う変数を初期化します。

ローソク足、現在価格と建玉、出ている注文、これらを取得して注文を出す必要の有無を判定します。足に変化がなく、建玉にも変化がなく(stop約定が起きていない)、注文も既に出ていれば状況に変化がないとみなします。
一定時間待機してループ冒頭に戻ります。

状況が変わっていれば、残高を取得して発注量を決めます。

2つの注文

        if current_qty < 0:
            order_side = 'Buy'
            break_price1 = hL_channel[0] + 0.5
            break_price2 = hL_channel[2] + 0.5
        elif current_qty > 0:
            order_side = 'Sell'
            break_price1 = hL_channel[1] - 0.5
            break_price2 = hL_channel[3] - 0.5
        else:
            order_side = None
            break_price1 = hL_channel[0] + 0.5
            break_price2 = hL_channel[1] - 0.5

チャネルブレイクアウト戦略では、ポジションがない場合は上下にブレイク注文を出し、ポジションがある場合は退出方向にひとつだけ注文を出すのが一般的かと思います。

退出注文が約定するような状況下では、市場が混んで新たな参入注文が通らなかったり、通っても著しく不利な価格で約定することがあり得ます。

そこでこのbotスクリプトでは、退出注文の外側に新たな注文を常に仕掛けています。ギャップのあるドテン注文と言えます。まさに今日2019年4月2日午後のような、トレーダー達が仕掛けていた逆張りの指値群を突き抜けていく動きに備えた発想です。

常に2つの注文があるため条件分岐がシンプルになり、結果的にコードが整理できました。

修正できるのか

        # ポジションがない場合やポジションが変化した場合は新たに発注する
        if (not current_qty and len(orders) != 2
                or previous_qty != current_qty):
            post_params = {
                'order_side': order_side,
                'last_price': last_price,
                'current_qty': current_qty,
                'order_lot': order_lot,
                'break_price1': break_price1,
                'break_price2': break_price2,
            }
            cancel_orders(orders)
            result = post_orders(**post_params)

新たに注文を出す必要があるのか、修正だけですむのか、状況を判定します。ポジションがないのに2つの注文が出ていない場合、または前回のチェック時と建玉数が変わっている場合は、注文を出し直します。

例えば退出注文だけが約定して消失し、参入注文が残っている場合が想定されます。注文が重複しないようにキャンセルを掛け一掃してから注文を出します。

ワンポイント
退出約定でポジションが変化し注文の出し直しが発生することで、せっかく置いていた参入注文が約定直前に取り消されてしまう可能性があります。
つまり定数LOOP_WAITはユーザーに調整余地があるということです。

追記 2019年4月6日
別記事の通常版では、参入注文の取り消しが起きないように改良されています。
        # ポジションに変化がない場合はstopの移動とLOTの調整をする
        # 'LF' means Low and Far(entry_line)
        # 'HN' means High and Near(exit_line)
        else:
            amend_params = {
                'order_id_LF': orders[0]['orderID'],
                'order_id_HN': orders[1]['orderID'],
                'order_lot_LF': order_lot,
            }
            if current_qty:
                amend_params['order_lot_HN'] = None
                amend_params['break_price_LF'] = break_price1
                amend_params['break_price_HN'] = break_price2
            else:
                amend_params['order_lot_HN'] = order_lot
                amend_params['break_price_LF'] = break_price2
                amend_params['break_price_HN'] = break_price1
            result = amend_orders(**amend_params)

建玉に変化がなければ時間が進んでチャネルが変化したことになります。取得した注文IDをターゲットに、ローソク足から割り出したライン2本と、残高や現在価格をもとに決めた発注量を上書きします。

注文修正は、キャンセルして新たに出し直す注文より処理が早いとされています。

        if not result:
            continue

        previous_hL = hL_channel
        previous_qty = current_qty
        sleep(ORDER_WAIT)

万一注文処理から結果が返らない場合は、ループ先頭に戻って状況取得からやり直します。
注文が完了していれば、次の状況変化との比較用に現在のチャネル値とポジションを記録し、ループ先頭に戻り以後繰り返します。

シンプルに動かす

"""
system'cRe5520' 改元記念有償単機能版[
    通常版との違い[
        レバレッジ指定機能なし,
        ATRからのロット設定機能なし,
        OHLCチャネル1時間足専用,
        stopオフセット0.5USD固定,
        太郎チャート非対応,
        ストップ指値注文非対応,
        Discord通知なし,
        WebSocket非対応,
        自動再起動機能なし,
        おまけの機能なし,
    ]
]
"""
追記 2019年9月28日
例外処理などを通常版に近づけ、動作をより安定させました。

追記 2019年5月19日
通常版との機能差が大きくなったので、シンプル版の価格を改定しました。

追記 2019年5月15日
通常版のアップデートにより、シンプル版との差違を追記しました。

以前の記事で有料パートのコードを買ってくださった方には、この場であらためてお礼を申し上げます。動かしてみましたか。今日の値動きは取れましたか。

月足2連続陽線は一昨年の12月以来となります。新しいトレンドの成長を期待して、シンプルなバージョンのbotスクリプトを公開します。

別記事である通常版を買ってくださった方々への差別化のため、シンプル版の機能は大きく絞り込んでいます。基本機能のものなので無償化も考えましたが、付帯機能の削除では差別化が不十分と考え、価格をつけさせていただきました。

通常版にはシンプル版の機能が全て含まれていますので、両方のコードを閲覧する必要はありません。

このシンプル版は1時間足専用で足数は可変です。50時間参入10時間退出を初期設定にしています。

マーケットに参加者が増え、それぞれの時間軸で流動性を供給してくれればうれしいです。皆が18本で一斉にドテンしたあの現象も、実験として興味深く懐かしく思い返すのですが、やはり多様な考えが集ってこそ市場は活きると思うのです。

シンプル版のコード全体をご覧になりたい方は有料パートへお進みください。

追記
通常版とこのシンプル版をセットで閲覧できる記事を公開しています。2本のコードを別々に閲覧するよりもお得になっています。
--> system'cRe5520' コード閲覧権

更新 2021年1月11日
通常版のコードを無償で閲覧できるようにしました。

I hope you will have good fortune!

Channel breakout trading strategy bot for BitMEX
system'cRe5520' ver.2.2.928g.simple

ここから先は

55字

¥ 500

RESOLUTION = '1d' FIRST_PERIOD_STICKS = 14 SECOND_PERIOD_STICKS = 3 MARKET_ID = 'ETHUSD' OC_MODE = True