さて前回は、売買ルールのうち、決済ロジックプログラムの書き方について話しました。
今回は、トレーリング(ストップロス価格を随時変更していき、利益を管理すること)のロジックの書き方について説明します。今回も色々試行錯誤できる様な構成になっております。
実は、今自分が使っている構成と若干異なるのですが、ややこしい割にメリットが無いので、シンプルにしたのを掲載いたします。(つまり、こうしておけば良かったって内容)
ちなみに、トレーリングのポリシーとして、以下の様にしています。
1.1バーでストップロスの価格を変更するのは1回だけ
2.一方向にしか価格変動させない
つまり、ロングポジションの場合、ストップロスの価格が上昇することはあっても下がることは無い。
ショートポジションの場合は逆。
3.トレーリングの開始は注文約定後から(成行き注文であれば即時)
●トレーリング
関数呼び出しの流れは以下の様な感じ。
構造的にはとっても単純ですね。GetSingleTick → CalcTrailPrice()→各種ストップロス価格計算ロジック→ 共通関数(AdjustTrailPrice)
では、関数毎に説明します。
①GetSingleTick
「②手仕舞い関連ロジック」内の最後の箇所にあたります。
ロジックは以下の通り。
補足説明としては、OrderHandleには発注済みオーダのオーダハンドルが格納// if it is neccesary to modify StopLoss of Orderif (OrderHandle<>-1) AND (Bars()<>OrderModifiedBars) thenbeginGetOrderInfo( OrderHandle , OrderInfo );tmpTargetPrice := OrderInfo.TakeProfit;newSLPrice := CalcTrailPrice( OrderInfo , tmpToModify );if ((OrderTime<>OrderInfo.OpenTime) OR (OrderPrice<0)) AND (newSLPrice<>OrderInfo.StopLoss) thenbeginModifyOrder(OrderHandle , 0 , newSLPrice , tmpTargetPrice );end;OrderModifiedBars := Bars();end;
されており、発注していなければ-1を設定しておく。
OrderModifyBarsはInteger型グローバル変数として定義し、ResetStrategyで、
-1で初期化しておく。tmpTargetPrice/newSLPriceはdouble型のローカル変数です。
OrderTimeは、発注した時の時刻情報を格納しているTDateTime型のグローバル変数。
以下の判定分のうち、(OrderPrice<0)という箇所は、成行き注文の場合はdouble型の
グローバル変数のOrderPriceに-1を設定しておく様にしている為。
ここのミソは、ForexTester2、StopLossの価格だけを変える事ができないので、一回
決済価格情報も取得しておき、再設定が必要という事。
そんな事もあって、GetSingleTick内のロジックがちょっと面倒でした。
②CalcTrailPrice(const OrderInfo : TTradePosition)
この関数で新たなストップロス価格を計算する、いろいろな計算関数を並べて、
コメントアウトしたりしなかったりして、試行錯誤します。
以下の例では、"Highest/Lowest N-Bar"という計算式だけが採用されている状態です。
{-----Calculate Trailing Stop Loss Price(System6) ----------------------------}function CalcTrailPrice(const OrderInfo : TTradePosition) : double;varprice1 : double;beginresult := OrderInfo.StopLoss;///////////////////////////////price1 := CalcTrailPrice_3(OrderInfo,5); // Highest/Lowest N-Bar//price1 := CalcTrailPrice_2(OrderInfo); // BollingerBand 2sigma//price1 := CalcTrailPrice_1(OrderInfo); // Praboric-SAR//////////////////////////////end;
③トレーリング用の共通関数 - AdjustTrailPrice
以下の関数は共通関数で、個別にストップロス価格の計算結果を引数として渡す事により、
逆行したトレーリングにならないで、且、現在価格にミスマッチな価格にならない(例えば、
ロングポジションなのに、今のBid価格より高い価格)様になります。
この場合、ストップロスの価格は変更されません。
例によって、OrderTypeには、ロングポジションであれば1、ショートポジションであれば-1を
設定しておく様にします。
{-----Adjust Trailing Stop Loss Price ---------------------------------------- }function AdjustTrailPrice(const OrderInfo : TTradePosition; tmpPrice:double) : double;beginresult := OrderInfo.StopLoss;// Check and Set StopPriceif (OrderType>0) AND (tmpPrice<>(-1)) thenbeginif (tmpPrice>result) AND (Bid>tmpPrice) then result := tmpPrice;end;if (OrderType<0) AND (tmpPrice<>(-1)) thenbeginif ((result=0) OR (tmpPrice<result)) AND (Ask<tmpPrice) then result := tmpPrice;end;end;
④各種ストップロス価格計算ロジックの例
以下の例は、引数で渡された期間(period)の高値/安値をトレーリング価格にする場合の例です。
計算時に気をつけなければならないのは、ショートポジションの場合、スプレッドを考慮する必要
があることです。 チャート上の価格は全てBidベースである事を思い出してください。
{-----Calculate Trailing Stop Loss Price(High/Low) ----------------------------}function CalcTrailPrice_3(const OrderInfo : TTradePosition; period:Integer) : double;varspread :double ;beginresult := OrderInfo.StopLoss;spread := CurrencyInfo.spread*Point;// メインの計算ロジックif OrderType>0 thenbeginresult := Lowest(1,period);end;if OrderType<0 thenbeginresult := Highest(1,period)+spread; // ショートポジションの場合はスプレッドを足しこむ必要ありend;result := AdjustTrailPrice(OrderInfo,result); // 上記共通関数の呼び出しend;
この記事までで、発注~決済までのプログラム構造に関しては終わりです。
全般的にプログラミングの記事は説明が不十分な箇所が結構あると思うので、
本当に気軽に、コメントなり左上にリンクしている掲示板で不明点等を質問してくださいね!!
そうすれば、私も報われるというものです!
説明不十分自認してますので!
今回も笑いは無し!!
当初の趣旨からずれていってるやん。。
そして、「FXシステムトレード初心者奮闘記」のストラテジプログラミング集は続くのでした。
次は、ついにプログラミング時代最終編、複数通貨ペアを連続で評価するプログラミングの工夫等について説明します。
0 件のコメント:
コメントを投稿