2011/01/09

バックテスト(自動)時代 - ForexTester2ストラテジプログラミング①(苦労した点と共通部品)



さてさて、前回は、バックテスト用ストラテジ(自動売買プログラム)のプログラム構造とGetSingleTick内の基本的なロジックの流れの話ををしました。
今回も、いつもと趣向を変え、ForexTester2ストラテジプログラミングにおいての注意点や共通部品等の情報について書きます。


●最初わからなくて色々苦労したロジック
 ①オーダがストップロスとなったかどうかの判定
   わかってしまえば単純なロジック
    if ( (OrderHandle <> -1) AND ( OrderClosed(OrderHandle) ) ) then
    begin
            もろもろのロジック
   end;
   
   ※OrderHandleはグローバル変数で、発注時のオーダハンドルを格納。ポジション無しの場合は"-1"を設定している

 ②指値/逆指値注文が約定されたかどうかの判定
    if OrderHandle<>-1 then
    begin
       GetOrderInfo(OrderHandle,OrderInfo);
       if (OrderTime<>OrderInfo.OpenTime) AND (OrderOpenTime<>OrderInfo.OpenTime) then
       begin
      もろもろのロジック
       end;
    end;
 
  ※変数OrderTimeは、注文API呼び出し成功後、OrderInfo.OpenTimeを格納しておく。
   変数OrderInfoは、オーダの情報が格納されている構造体の変数を自分で定義し、注文API呼出し後、GetOrderInfoで情報を取得する
   どちらの変数もグローバル変数として、自分で定義が必要

  →ここのクセは、OrderInfo.OpenTimeが指値/逆指値注文時は注文時の時刻だけど、約定されると約定時刻に書き換えられる。これを理解するのに時間かかったよ。
   ヘルプにちゃんと書いとけ!!もう英語でもいいから。。。

 ③口座残高固定比率のサイジング(ロット数計算)
  ForexTester2の口座の通貨はUS$固定。口座残高の一定比率の金額を元にサイジングする場合に必要
  自動で取得するインタフェースが用意されていないので、こんな汚いロジックに。  
     →誰かキレイなロジックの書き方教えて!!
  例えば、EURJPYという通貨ペアで口座残高固定比率のサイジングしようとするとごっつう複雑。
  このロジック動かす時は、USDとの通貨ペアも合わせてジェネレートしておく必要がある。
  例えば、EURJPYのテストの時、EURUSDもジェネレートが必要ということ。

  引数:
     risk : US$ベースの最大リスク額(AccountEquity()*0.02の値を指定すると、口座残高の2%となる)
     price : 例えば発注額とストップロスの価格差。例えば、EURJPYで、0.50円の価格差であれば、0.50を指定。もち、ATRとかのボラティリティ値でもOK.
  戻り値:ロット数。でも、最低が0.1ロットなので、結果が0になってしまうことも。
  前提条件:ResetStrategy関数内で、GetCurrencyInfo関数でグローバル変数のCurrencyInfoを設定しておくこと。


    function CalcLotSize_00(const risk:double; const price:double) : double;
    var
        usdrate:double;
        curr,rateCurr:String;
        p : Integer;
    begin
      usdrate := 1;
      rateCurr := Copy(Currency,4,3);
      if rateCurr<>'USD' then
      begin
           if (Pos('GBP',rateCurr)>0) OR (Pos('AUD',rateCurr)>0) OR (Pos('EUR',rateCurr)>0)
           then begin
                   usdrate := iClose(rateCurr+'USD',TimeFrame,1);
                   usdrate := 1/usdrate;
                end
           else begin
                    usdrate := iClose('USD'+rateCurr,TimeFrame,1);
              end;
      end;
      result := Trunc(risk / ( ((Abs(price)/usdrate))*(CurrencyInfo.lot) )*10)/10;
    end;
  

●その他注意点
 ・チャート上の価格はBid
  なので、”買い”注文の価格(※)を計算する時にはスプレッドを足しこむ必要あり。
  従って、移動平均線等のテクニカル指標が示す価格もBidベース。
  スプレッドは、CurrencyInfo.spread*Pointで計算可能。
  CurrencyInfoは、ResetStrategy関数内で、GetCurrencyInfo(Currency,CurrencyInfo)しておく。
  例えば、ショートポジションで、前バーの最高値にストップロスを移動させる場合の価格計算は、
  
    High(1)+CurrencyInfo.spread*Point

  ※ここでの”買い”は、新規買い注文の”買い”と、売りポジション手仕舞い時の”買い”の両方。

 ・逆指値注文の場合は、現在のAsk/Bidから一定(3)pips離れている必要あり
  これに気づかず、何回注文失敗のバグを作ってしまったことか。。
  しかもこのpips数を取得する方法が提供されていないので、自分でプログラムに埋め込んでおく必要あり。
   


お!!今回もまるで、役に立つブログ書いてるみたいやんけ!!


でも、ソースコードを人に見せるのは恥ずかしいわ。

そして、「FXシステムトレード初心者奮闘記」のバックテスト(自動)時代は、続くのでした。
今度も他の共通部品関連にしよっと!!

0 件のコメント:

コメントを投稿