このシリーズの記事一覧 (クリックで開閉)
【 strategy解説(Pine) 】
oca
strategy.entry
とstrategy.order
のオプションに関する解説の第3回目である。
オプションは以下の中から
strategy.order(id, long, qty, limit, stop, oca_name, oca_type, comment, when)
oca_name
oca_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
にする。
コードは先程のorder
3行に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
まで発注して良いので +1
1
の指値を持った状態から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
を使って実際にどれだけエントリーされるかを追いかけていくと結構難しい。
とはいったものの、実際にエントリーされるポジションを目視で追いかけると難しいだけで
単純に「溜まってる指値の注文量をキャップする」という意味では簡単なのかもしれない。
私は使いこなせていないが、きっと使いこなしている人もいるんだろう。