このシリーズの記事一覧 (クリックで開閉)
【 strategy解説(Pine) 】
ocastrategy.entryとstrategy.orderのオプションに関する解説の第3回目である。
オプションは以下の中から
strategy.order(id, long, qty, limit, stop, oca_name, oca_type, comment, when)oca_nameoca_typeに絞って解説していく
OCA(One-Cancels-All)注文というものがあるらしい。私はPine Script以外では使ったことがない。
OCA(One-Cancels-All)注文 | インタラクティブ・ブローカーズ証券株式会社
一つ約定すると他に出しておいた指値注文をキャンセルするグループを作る。
これまでの記事通りサンプルとしてわかりやすいようにバーに数字を与えている。
コードは次
bar_no = 0
if(bar_index > 21699)
bar_no := bar_index - 21699
l = label.new(bar_index,na,text=tostring(bar_no),color=color.blue, textcolor=color.white,style=label.style_labeldown,yloc=yloc.abovebar)最初の数字は適当に私の方で調整しただけであり、各ユーザーは無視すること。
こんな感じでラベルがつく。これは以前からやっているのでおなじみのコードである。
oca_nameとoca_type別々の注文一度グループにすると考えれば良い。
別々の注文なのでIDが違う注文だ。
まずocaを設定しない例として3つロングしてみる。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000)
strategy.order("LONG 2", strategy.long,limit=1000000)
strategy.order("LONG 3", strategy.long,limit=995000)結果は
3回約定するコードである。
次で解説するがoca_nameとoca_typeはセットで使うと覚えておく。
strategy.oca.cancelさっそくocaを追加する。
oca_nameを"A"oca_typeをstrategy.oca.cancelにする。
コードは先程のorder3行にocaを追加。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, oca_name="A" ,oca_type=strategy.oca.cancel)
strategy.order("LONG 2", strategy.long,limit=1000000, oca_name="A" ,oca_type=strategy.oca.cancel)
strategy.order("LONG 3", strategy.long,limit=995000, oca_name="A" ,oca_type=strategy.oca.cancel)すると...
最初の一個目以外はの注文はキャンセルされた。
oca_nameによって同じ名前がつけられたものを「グループ」として扱い
oca_typeによってそれらのグループに属する発注同士がどういう風に干渉するのかを指定する。
つまり初めにグループの一つが約定した時点で
oca_typeに設定されたstrategy.oca.cancelが発動し残りの指値はキャンセルされたわけだ。
これがcancel
strategy.oca.reduce今度はreduceを見てみよう。基本的にはこの2つを覚えておけば良い。
これは発注の数量を抑えるコードで、発注数qtyとセットで使う。
次のコードを用意した。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)
strategy.order("LONG 3", strategy.long,limit=995000, qty=5, oca_name="A" ,oca_type=strategy.oca.reduce)1つ目の発注からqtyが順に1, 2, 5としてstrategy.oca.reduceしている。
さて、どうなる。
分かる人には分かると思う。
左から順に実際の発注数が1, 1, 3となっている。
何が起こったのか。
設定は1, 2, 5。実際に発注されたのは1, 1, 3。
これは「最大の発注数」を設定しているのである。
つまり始めは0ポジションからスタートで
0ポジションからqty=1まで発注して良いので +11の指値を持った状態からqty=2まで発注して良いので +1発注して合計が2(qtyの値)2の指値を持った状態でqty=5まで発注して良いので+3発注して合計が5(qtyの値)ちょっと難しいが理解してしまえば単純だ。
qty=5をqty=1にかえたらどうなる?次のコードはどうだろうか。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)
strategy.order("LONG 3", strategy.long,limit=995000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce) //ここのqtyを変えた結果は
最後の行はqty=1。この時点でポジションは2なので3番目のロングはキャンセルされた。
注意点としてはあくまでキャンセルであって、逆にショートしてポジションを削ってqtyに合わせるということはない。
戦略の中でポジション管理を行うコードなので、私はここまで戦略を練ったことがないが
strategy.order関数を使っていてピラミッディングがロングとショートで可変数になる設計の場合の最大値を設定するには有用に思う。
例えばマーチンゲール投資法で初期ロットをダイアログで変更できるストラテジ等だろうか・・・他にアイデアが無くて申し訳ない。
reduceは一括発注がオススメif (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)
strategy.order("LONG 3", strategy.long,limit=995000, qty=3, oca_name="A" ,oca_type=strategy.oca.reduce)想定内のロット数を維持したい場合はこのように一度に発注を出す時に使うこと。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 2)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 3)
strategy.order("LONG 3", strategy.long,limit=995000, qty=5, oca_name="A" ,oca_type=strategy.oca.reduce)この用に使うのはかなり詳しい理解が必要なのでおすすめしない。
ここが完璧なら最上級ストラテジストになるのではないかと思う。
一つだけ覚えておくとするならばstrategy.oca.reduce現在のポジションではなく、現在溜まっている「指値のロット数」に対して差し引きを行う物だ。
ここまで理解できれば良い。
というかこのコードを使いこなしている人はいるのだろうか。
私は単にBLOGネタのためだけにやっている。
一応説明する。
プログラミングオタクであれば挑戦してみてほしい。
reduceを発注するとポジションが難しくなるこのコードがなぜ難しいのか。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 2)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 3)
strategy.order("LONG 3", strategy.long,limit=995000, qty=5, oca_name="A" ,oca_type=strategy.oca.reduce)あれ?違いがわからない。
結果を見てみよう。
こういうことになる。よく見ると発注している数字が想定していたものと違う。
さらに一行増やしてこうしてみよう
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 2)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 3)
strategy.order("LONG 3", strategy.long,limit=995000, qty=5, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 4)
strategy.order("LONG 4", strategy.long,limit=992800, qty=10, oca_name="A" ,oca_type=strategy.oca.reduce) //追加最後に10ロットを追加した。
最後が7になった。もうなにがなんだか。
reduceは現在溜まっている指値注文(つまり未約定)の総ロットに対して差し引きされるという点を覚えておく。
もう一つ、指値発注は対象のバーのCLOSEが確定した時点で行われるということ。これは以前も解説した。
では、いってみよう。
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)これは問題ない。普通に1ロットが指値で積まれる。
if (bar_no == 2)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)まず1の足で既に1の発注が出ている。
それから前述したとおり
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.reduce)この発注が発射されるのは2の足のCLOSEが確定した直後である。
ということは、2の足が確定した直後にこの発注が出る瞬間に「溜まっている指値のロット総数」はいくらだろうか。
0である。これは分かるだろうか。
バーの中で約定しているので、CLOSE時に溜まっている発注は0である。
もう一度言う。2の足の中で1の足で出した発注が解決されているので、指値発注は残っていない。
qtyに設定されている2から0を引いて2である。
LONG 2というIDで2の指値が入った。
3の足では溜まっていた指値は刺さらなかった。
3の足に仕掛けられた指値コードは
if (bar_no == 3)
strategy.order("LONG 3", strategy.long,limit=995000, qty=5, oca_name="A" ,oca_type=strategy.oca.reduce)溜まっている指値ロットは2であると述べた。
つまりここのcloseで発注される数量は
qtyに設定されている5 から 溜まっていた2 を引いて実際に指値に入るロットは3(IDはLONG 3) となる
コード
if (bar_no == 4)
strategy.order("LONG 4", strategy.long,limit=992800, qty=10, oca_name="A" ,oca_type=strategy.oca.reduce)まず、ここではLONG 2と書いてある指値が刺さった。つまり2の足で出した2ロットの指値だ。
さて、この足がcloseしようとしている。残っている指値はなんだろうか。
3の足で出した3のロットがまだ指値として残っている。
そしてこのcloseが処理された直後に4のオーダーが実行される。
ということは
qtyの10 から 溜まっている3 を引いて 7 のロットが発注される(IDはLONG 4)
ここまで理解できれば残りは新規エントリーがないので指値を解決するだけだ。
6の足でLONG 3が解決された(3ロット)
9の足でLONG 4が解決された(7ロット)
strategy.oca.noneここまでやってさらにおまけもある。strategy.oca.none
if (bar_no == 1)
strategy.order("LONG 1", strategy.long,limit=1030000, qty=1, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 2)
strategy.order("LONG 2", strategy.long,limit=1000000, qty=2, oca_name="A" ,oca_type=strategy.oca.none) //ここをnoneにした!
if (bar_no == 3)
strategy.order("LONG 3", strategy.long,limit=995000, qty=5, oca_name="A" ,oca_type=strategy.oca.reduce)
if (bar_no == 4)
strategy.order("LONG 4", strategy.long,limit=992800, qty=10, oca_name="A" ,oca_type=strategy.oca.reduce)これはreduceもcancelも受けない発注にするオプションだ。
このようにすると
bar_no == 3で2の発注が溜まっていたにもかかわらず無視されてで5がそのまま発注された。
これも細かくやれば説明できるが...そこまでやっても需要がなさそうなのであとは任せる。
更にcancelも組み合わせ始めたらプログラマー側に異次元のIQが必要になるかもしれない。
さて、適当に書いたがこれでいいのかわからないが...
とりあえず作ってみた
指値ばらまきストラテジ。
//@version=4
strategy("マイストラテジー", overlay=true)
price_range = input(2000, step=1000)
if(strategy.openprofit == 0)
strategy.order("long", strategy.long)
if(strategy.openprofit < 0)
strategy.order("short1", strategy.short,limit=close + price_range*1, qty=abs(strategy.position_size * 2), oca_name="S_group", oca_type=strategy.oca.reduce)
strategy.order("short2", strategy.short,limit=close + price_range*2, qty=abs(strategy.position_size * 2 * 2), oca_name="S_group", oca_type=strategy.oca.reduce)
strategy.order("short3", strategy.short,limit=close + price_range*3, qty=abs(strategy.position_size * 2 * 2 * 2), oca_name="S_group", oca_type=strategy.oca.reduce)
strategy.order("short4", strategy.short,limit=close + price_range*4, qty=abs(strategy.position_size * 2 * 2 * 2 * 2), oca_name="S_group", oca_type=strategy.oca.reduce)
strategy.order("long1", strategy.long, limit=close - price_range*1, qty=abs(strategy.position_size * 2), oca_name="L_group", oca_type=strategy.oca.reduce)
strategy.order("long2", strategy.long, limit=close - price_range*2, qty=abs(strategy.position_size * 2 * 2), oca_name="L_group", oca_type=strategy.oca.reduce)
strategy.order("long3", strategy.long, limit=close - price_range*3, qty=abs(strategy.position_size * 2 * 2 * 2), oca_name="L_group", oca_type=strategy.oca.reduce)
strategy.order("long4", strategy.long, limit=close - price_range*4, qty=abs(strategy.position_size * 2 * 2 * 2 * 2), oca_name="L_group", oca_type=strategy.oca.reduce)
if(strategy.openprofit > 1)
strategy.close_all()1分足
負けてる間は永遠に指値をばらまき続けるストラテジなので実際にこの通りにトレードしないように。
reduceを使って実際にどれだけエントリーされるかを追いかけていくと結構難しい。
とはいったものの、実際にエントリーされるポジションを目視で追いかけると難しいだけで
単純に「溜まってる指値の注文量をキャップする」という意味では簡単なのかもしれない。
私は使いこなせていないが、きっと使いこなしている人もいるんだろう。
