チャネルブレイクアウト戦略botでの注文執行を考える
チャネルブレイクアウトとは、直前まで抵抗線や支持線と見られていた価格を突き抜ける動きのことをいいます。
利益を確定したり損失を回避したりと、人間のためらいや決断、そして実際の注文行動が集中するポイントが、抵抗線であり支持線です。
その集中ポイントに価格が到達してからベーシックな成行注文を出しても、混雑により注文が通りにくいことがあります。そこで規律に従って注文を執行するbotでは、あらかじめ決めた価格にトリガーをかけておく逆指値注文を採用しています。
逆指値注文(ストップ成行注文)とは、上図ひとつめの黄色丸印をトリガーとした成行注文です。成行注文ですので、他者の注文状況によっては桃色丸印の価格で約定する可能性もあります。
ほぼ確実に注文全量が約定しますが、想定より高い価格での保有になる可能性もあり、またBitMEXではテイカーフィーが徴収されるのもデメリットです。ブレイクアウト不発が続けば高コストがじわじわと効いてきます。
チャネルブレイクアウト戦略botの2019年5月15日アップデートでは、これまでのストップ成行注文だけではなく、ストップ指値注文も選べるようにしました。ストップ指値注文を初期値としています。
上図ひとつめの黄色丸印で買い切れなかった玉数があれば指値注文が維持され、ふたつめの黄色丸印で買われます。状況によってはメイカーフィーが得られる可能性もあり、ダマシによる疲弊をやわらげる効果も期待できます。
指値注文でメイカーフィーが必ず得られるわけではありません。出した指値が板に並んでいるAsk/Bidと相対した場合は、成行扱いになりテイカーフィーが徴収されます。
ストップ指値のデメリットは、上図のようにブレイクアウト後に価格が押さず、想定数量を買い切れない可能性があることです。
充分な玉数が持てないことは、コツコツ負けても大きく勝ち取るという戦略の特性を考えると看過できません。桃色丸印の位置で残量を買わざるを得ないこともあります。
ストップ指値を採用するに当たり、買い切れなかった玉をどういうルールで買い集めるかを考えました。
1. 当初の指値で買い切れなかった数量は即買う
2. 一定の価格変動があった場合に買う
3. 一定の期間が経過した場合に買う
4. その他の変化発生をトリガーとして買う
5. あきらめて買わない
1.では成行に準ずる動きになりストップ指値のメリットが失われてしまいます。5.は前述したように、戦略の期待値を下げる可能性が高いです。
2.や3.は定数をどう決めるか考えねばなりません。ATRや価格変動割合、板情報、時計や足数などが思いつきます。いずれもこれといった根拠は求めにくいです。
あまり時間を経過させると、ブレイクアウトという参入根拠価格よりも実際の参入価格が、著しく不利になってしまう可能性もあります。
考えて試して最終的に採用したのは、建玉の不足があったら、
4. チャネル判定が変化した時に買う
というルールです。
価格が横ばい傾向の時と傾斜気味の時とで指値の約定待ち期間が動的に変化して、マーケットの状況を自ずとbot動作に取り込めるかたちになりました。
STOPLIMIT = True
def main():
partially = False
while True:
"""略"""
orders = check_orders()
if orders:
# 一部約定 チャネル変化を期限に全数約定を待つ
if previous_hL == hL_channel and STOPLIMIT:
partially = False
for i in reversed(range(len(orders))):
if orders[i]['triggered']:
partially = True
if partially:
sleep(ORDER_WAIT)
continue
# チャネルが変化したら残量を再発注
elif previous_hL != hL_channel and partially:
partially = False
remaining_qty = 0
for i in range(len(orders)):
if orders[i]['triggered']:
remaining_qty += orders[i]['leavesQty']
post_params = {
'order_side': orders[i]['side'],
'last_price': last_price,
'leaves_qty': remaining_qty,
}
if not fills_remaining_qty(**post_params):
partially = True
continue
"""略"""
"""略"""
def fills_remaining_qty(
order_side,
last_price,
leaves_qty):
"""未約定数量を現在価格で埋める"""
cancel_orders()
order_params = [{
'symbol': MARKET_ID,
'ordType': 'StopLimit',
'price': last_price,
'side': order_side,
'orderQty': leaves_qty,
'stopPx': last_price,
'execInst': 'LastPrice',
}]
bitmex.privatePostOrderBulk({
'orders': json.dumps(order_params),
})
sleep(ORDER_WAIT)
if check_orders():
return False
else:
return True
"""略"""
1分間に3回程度の状況取得で動いている低頻度取引手法のbotです。板の厚みは見ず、一定時間毎に約定残を確認し現在価格で再注文をします。
- -
チャネルブレイクアウト戦略はダマシに耐え続ける手法です。たび重なるテイカーフィー負担やスリッページが軽減されれば、時々ある約定残の買い集めコストと比較しても、ストップ指値注文にも利があるかもしれません。
日足戦略の場合は指値の見直しが1日1度かそれ以上の間隔になります。指値で約定するまでの待ち時間が取れるともいえますが、買えないうちに大きく価格が離れてしまう可能性もあります。
場合によってはスリッページ設定にゆとりを持たせるか、ストップ成行注文にするかの判断も必要です。
ストップ成行注文とストップ指値注文とは簡単に切り替えられるようにしてあります。戦う市場に合わせて使い分けてみてください。
- -
追記 2019年5月19日
2018年3月から現在まで高値安値50時間参入10時間退出でのバックテストです。ストップ指値注文を想定して、手数料率とスリッページを画面のとおり調節してテストしてみました。
RESOLUTION = '1d' FIRST_PERIOD_STICKS = 14 SECOND_PERIOD_STICKS = 3 MARKET_ID = 'ETHUSD' OC_MODE = True