チャネルブレイクアウト戦略botの解説 メインループ編
このときのために
HighLow_channelでの50時間参入10時間退出のバックテストチャートです。 2019年4月2日未明にキャプチャしたものです。きれいな右肩上がりでレンジ変化を評価しやすそうに思いました。
そこで、これをもとに値を変化させたバックテストをいくつか取り、戦略構築ガイドとなるような記事を構想していたのですが、夕方に状況が一変していました。
レンジの間もマーケットに在り続けて、時が来たら大きく刈り取る。この動きがチャネルブレイクアウト戦略の醍醐味です。
何本足で退出ラインと設定したか、価格が降りてくるまでの期間で成果が変わります。まだ利益は確定していません。
大きなレンジブレイクがありましたので、当初の構想とは異なる記事にしてみました。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つの注文が出ていない場合、または前回のチェック時と建玉数が変わっている場合は、注文を出し直します。
例えば退出注文だけが約定して消失し、参入注文が残っている場合が想定されます。注文が重複しないようにキャンセルを掛け一掃してから注文を出します。
# ポジションに変化がない場合は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非対応,
自動再起動機能なし,
おまけの機能なし,
]
]
"""
以前の記事で有料パートのコードを買ってくださった方には、この場であらためてお礼を申し上げます。動かしてみましたか。今日の値動きは取れましたか。
月足2連続陽線は一昨年の12月以来となります。新しいトレンドの成長を期待して、シンプルなバージョンのbotスクリプトを公開します。
マーケットに参加者が増え、それぞれの時間軸で流動性を供給してくれればうれしいです。皆が18本で一斉にドテンしたあの現象も、実験として興味深く懐かしく思い返すのですが、やはり多様な考えが集ってこそ市場は活きると思うのです。
シンプル版のコード全体をご覧になりたい方は有料パートへお進みください。
I hope you will have good fortune!
Channel breakout trading strategy bot for BitMEX
system'cRe5520' ver.2.2.928g.simple
ご購入いただき、ありがとうございます。
Thank you so much for your purchase!
RESOLUTION = '1d' FIRST_PERIOD_STICKS = 14 SECOND_PERIOD_STICKS = 3 MARKET_ID = 'ETHUSD' OC_MODE = True