Multichartsにおける決済の処理についてコメントがありましたので
回答致します!
【相談内容】
1枚ずつEntry、1枚ずつExitであれば、
"Sell ("S") 1 contract total next bar at market"
にて実行できるのですが、これが1回のEntryで5枚した後となると、決済は1枚しか
実行されずに、4枚のポジションは残ってしまうという現象が発生します。
確かに問い合わせの多い処理事項でございます。Multichartsはプログラムに
おいて予期せぬエラーにより誤発注を避けるために厳しい発注環境が設定さ
れています。代表的な厳しい発注環境としては、
ⅰ) 複数数量のポジションを1つの決済処理で分割して決済できない
⇒つまりご相談内容
⇒強いて言えば、間違った決済を防ぐための環境ですかね・・
ⅰの現象としては例えば下記のソースコードで確認できます!
条件は例題ソースコードと同じなので↓を参照してくださいね♪
Inputs:Length(50);
If close crosses over Average(close,Length) then buy 5 contracts next bar at market;
If close crosses under Average(close,Length) then sellshort 5 contracts next bar at market;
If marketposition=1 and close>close[1] then sell 1 contracts next bar at market;
If marketposition=-1 and close<close[1] then buytocover 1 contracts next bar at market;
とした時に、ロングを保有していれば現在バーの終値が前バーの終値より高い安い
でバー毎に1枚ずつの決済が出てくれるような気がします。でも・・
1回しか1枚決済はしてくれないのですよねえ ( p_q)
どうやら決済のリザーブワードは使い捨てで何度も使えないようです・・
結局、持ち越されたポジションはドテンで処理されてますね!
こうした動作への対処方法は下記にて述べますが、他にも売買命令に
関する制限ってのがあって、
ⅱ) 売買命令はループ構文内に組み込めない
⇒知らずに無限ループになっている可能性もありますからね・・
ⅲ) バーの寄付にて計算を行い、その寄付で注文が出せない
⇒つまり This bar on open とはできない(当然のことながらhigh・lowも指定不可)
⇒リアル環境ではThis bar on close が条件適合時に即座に発注とはなります
(ただしバックテストは終値ベースでの処理になるのですねえ・・)
ってのがあります。これは知っておく必要のある制限でしょう。もちろん、他にも細かいところ
はあります。で、今回はご相談内容の解決方法なので、その件に特化します。
分割で決済する場合の基本的な処理は下記の処理にて行います。
① ポジションの変化を変数にて監視
② ポジション量の変化に沿って指定数量まで決済を行うために決済処理を複数用意する
面倒ですが、この方法であれば確実に指定条件に沿って、指定枚数を決済で
きるようになります。わかりにくいので例題を画像と共に示しておきます↓↓↓
■ 例題
【Entry条件】
終値が50バー移動平均線を上に抜いた ⇒ 5枚ロング保有
⇒ ポジション数量変数に5を代入
終値が50バー移動平均線を下にぬいた ⇒ 5枚ショート保有
⇒ ポジション数量変数に5を代入
【ロングポジションExit条件】
ロングポジション保有時、かつ前のバーの終値より現在のバーの終値が高い場合
⇒ 前のバーのポジション数量が5の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が4の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が3の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が2の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が1の時に1枚決済&ポジション数量変数-1を行う
【ショートポジションExit条件】
ショートポジション保有時、かつ前のバーの終値より現在のバーの終値が安い場合
⇒ 前のバーのポジション数量が5の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が4の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が3の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が2の時に1枚決済&ポジション数量変数-1を行う
⇒ 前のバーのポジション数量が1の時に1枚決済&ポジション数量変数-1を行う
【ソースコード】
Length : 移動平均線の観測バー数
D1C : ポジション数量を監視する変数
Inputs:Length(50);
Vars:D1C(0);
If close crosses over Average(close,Length) then begin
buy 5 contracts next bar at market;
D1C=5;//Position Counter
end;
If close crosses under Average(close,Length) then begin
sellshort 5 contracts next bar at market;
D1C=5;//Position Counter
end;
If D1C[1]=5{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=5{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=4{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=4{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=3{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=3{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=2{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=2{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=1{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=1{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
ちなみに、タイムフレームの合わせて何本経過後に決済という条件を入れたい
時はBarsSinceEntryを使うと指定したバーの本数分後から決済が始まります。
下記の事例はポジションを5枚保有している時に限りエントリーから5本間を空
けて条件適合場面から決済をしていくとなります。
【BarsSinceEntryを使ったソースコード】
BarsSinceEntryはエントリー時からの経過バー本数を取得するリザーブワード
Inputs:Length(50);
Vars:D1C(0);
If close crosses over Average(close,Length) then begin
buy 5 contracts next bar at market;
D1C=5;//Position Counter
end;
If close crosses under Average(close,Length) then begin
sellshort 5 contracts next bar at market;
D1C=5;//Position Counter
end;
If BarsSinceEntry>5 and D1C[1]=5{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If BarsSinceEntry>5 and D1C[1]=5{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=4{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=4{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=3{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=3{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=2{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=2{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=1{Position Check} and marketposition=1 and close>close[1] then begin
sell 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
If D1C[1]=1{Position Check} and marketposition=-1 and close<close[1] then begin
buytocover 1 contracts next bar at market;
D1C=D1C-1;//Position Count
end;
ちょっと不便な気にしますが、不具合や不正パフォーマンスを避けるための処理
みたいなので許容して対処するしかないと思います。
分割処理に関してはブログの中の人が使わない処理なので、(トレードを許容する
区間が厳格に設定されているので一挙に建てて、一挙に落としてます)他の回避
策もあるかもしれません。心優しき方がいれば情報頂けたら幸いです o(^▽^)o