さてさて、前回は、バックテスト用ストラテジ(自動売買プログラム)のプログラム構造と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 件のコメント:
コメントを投稿