さて前回は、ストラテジで独自ログを出力し、スィーニーのMAE/MFE分析や、R期待値を求めれる様にするプログラムの書き方について話しました。
今回は、売買ルールを色々試行錯誤しやすい様な、発注ロジックの構造について記述します。
以下の構造にする事で、特定の手法を追加したり、その後削除したりというのを、一部だけコメントアウトしたり元に戻したりするだけで、色々な組合せを簡単に試せる様になります。
●発注ロジックの構造
関数呼び出しの流れは以下の様な感じ。
vOrderTypeは、ロングポジションの場合は1、ショートポジションの場合は-1を指定。
indexは、どのバーで判断するか指定します。
GetSingleTick→ToBuy()/ToSell()→ToOrder(vOrderType:Integer)→WkToOrder(vOrderType:Integer; index:integer)→各種発注判断関数Filter1(vOrderType:Ingeter; index:Integer)→ 各種フィルタ関数(フィルタ条件を満たしたタイミングで発注)Filter2(vOrderType:Integer; index:Integer)→ 各種フィルタ関数(各種発注判断関数が発注要と判断したタイミングで、満たしていなければならない条件)
なんだか複雑で、改良の余地ありそうですが、今はこんなロジックにしています。
以下は、各関数の説明です。
①ToBuy()/ToSell()
ToOrder(1)/ToOrder(-1)を呼び出し、Trueが返却された場合、手仕舞いに向けた変数の
初期化とストップロス価格計算関数を呼び出し、結果をグローバル変数に設定。
また、グローバル変数OrderTypeに1/-1を設定。
わざわざToOrder関数に切り出している理由は、ToOrderをドテン手仕舞いに使用する為です。
②ToOrder(vOrderType:Integer){----- Judge to Buy -----------------------------------}function ToBuy(): Boolean;beginresult := False;if ToOrder(1) thenbeginOrderType := 1;OrderSLPrice := CalcSLPrice(OrderPrice);result:=True;end;end;
基本的な発注判断関数と、フィルター用関数を呼び出します。
ここのミソは、実際の発注判断ロジックを書く時に、前のバーの事は気にせずに、純粋に
指定されたバーが発注条件を満たしているかどうかだけ書けばよくなる事です。
(ロジック単純化の為)
以下のソースでは、2本前のバーでは発注要件を満たしていなかったが、 1本前のバー
では、発注要件を満たす様になった場合にTrueを返します。
③WkToOrder(vOrderType:Integer;index:Integer){----- Judge to Order ------------------------------------}function ToOrder(vOrderType:double) : Boolean;beginresult := False;if Not(WkToOrder(vOrderType,2) AND Filter1(vOrderType,2))AND (WkToOrder(vOrderType,1) AND Filter1(vOrderType,1) AND Filter2(vOrderType,1) )then result := True;end;
実際の売買判定用関数を、呼び出します。
以下の例では、3本の移動平均クロス判定と、2本移動平均クロス判定の関数が用意されており、
2本移動平均クロスの方はコメントアウトされています。
つまり、コメントアウトしたり外したりして、仕掛け方法を切り替えます。
その後、発注要の場合、発注価格を設定する関数を呼び出しています。
ここも、発注価格の計算方法毎に関数を用意し、コメントアウトで切り替えています。
④ToOrder2(3つの移動平均線クロスの例){----- Judge to Order Worker -----------------------------}function WkToOrder(vOrderType:double;index:integer) : Boolean;beginresult := False;{----------------- Judge to order ----------------------------}result := ToOrder2(vOrderType,index); // 3SMA cross//result := ToOrder1(vOrderType,index); // 2SMA cross{----------------- Call function of setting order price ------------------}if result thenbeginSetOrderPrice1(vOrderType,0.04,0); // Set OrderPrice from Ask/Bid+ratio//SetOrderPrice2(vOrderType,6); // Set OrderPrice from Highest/Lowest last N-Barend;end;
以下は、3本の移動平均線クロスで発注する場合のロジックです。
前のバーでは条件を満たしていない事をロジック上書かなくていいところがミソです。
⑤Filter1(vOrderType:Ingeter; index:Integer){----- Judge to Order2 3SMA cross ----------------------------------}function ToOrder2(vOrderType:double;index:integer) : Boolean;beginresult := False;if vOrderType>0 thenbeginif (GetSMA3(index)<GetSMA2(index)) AND (GetSMA2(index)<GetSMA1(index)) thenbeginresult := True;end;end;if vOrderType<0 thenbeginif (GetSMA3(index)>GetSMA2(index)) AND (GetSMA2(index)>GetSMA1(index)) thenbeginresult := True;end;end;end;
この関数ではフィルタ条件を記載します。ここでも個別のフィルタ判定関数を呼び出す事
になります。 以下の例では、フィルターAだけが有効になっています。
※参考:「ForexTester2ストラテジの内部設計(GetSingleTick内ロジックの流れ)」
ここで書いたフィルタは、売買判定時はフィルタ要件を満たしていなくても、フィルタ要件が満たされ
次第発注させたい場合に書く場所です。
⑥Filter2(vOrderType:Ingeter; index:Integer){----- Filter to Order(System6:Getting satisfy filter condition) --------------}function Filter1(vOrderType:double;index:integer) : Boolean;beginresult := True;if result then result := Filter_A(vOrderType,index); // Filter A//if result then result := Filter_B(vOrderType,index); // Filter Bend;
この関数でも、フィルタ条件を記載します。上記⑤との違いは、
ここで書いたフィルタは、売買判定時はフィルタ要件を満たしていない場合は発注されません。
以下の例では、そういうフィルタを用意しない場合の例です。
(いくつか用意したものの、全てコメントアウトしている状態)
⑦FilterA(vOrerType:Integer; index:Integer)-個別フィルターロジックです。{----- Filter to Order(System6:Getting satisfy filter condition) --------------}function Filter2(vOrderType:double;index:integer) : Boolean;beginresult := True;//if result then result := Filter_A(vOrderType,index); // Filter A//if result then result := Filter_B(vOrderType,index); // Filter Bend;
以下のフィルタ例は、DMIと同じ向きの時のみ発注するロジック例です。
基本はTrueで、発注NGのときだけ、Falseを設定する様になっている事に注意してください。
{----- Filter to Order(DMI) ------------------------------}function Filter_A(vOrderType:double;index:integer) : Boolean;beginresult := True;if vOrderType>0 thenbeginif Not(GetMDI(index)<GetPDI(index)) then result := False;end;if vOrderType<0 thenbeginif Not(GetPDI(index)<GetMDI(index)) then result := False;end;end;
発注ロジックだけでこんなことになってしまった。。。
説明がイマイチわかりにくくなってしまったので、わからんとこは質問お願いします!!
※参考:「ForexTester2ストラテジの内部設計(GetSingleTick内ロジックの流れ)」
そして、「FXシステムトレード初心者奮闘記」のストラテジプログラミング集がまたまた続くのでした。
次回は手仕舞いです。
0 件のコメント:
コメントを投稿