ここでは、Multi Lot ScalperというEAのコードを解読していきます。前回記事【Multi_Lot_Scalperの解読3】の続きからです。
ダウンロード元はこちら↓
https://www.mql5.com/en/code/9330
EAのコードを解読(続き)
では、早速続きを見ていきましょう!
最新ポジション情報取得と合計損益額を算出
ここでまた、最新ポジション情報を取得しています。さらに各ポジションの獲得幅(ポイント)×ロット数の合計がProfitに格納されるようにしてPipValueを掛けて利益額にしています。
Profit = 0; LastTicket = 0; LastType = 0; LastClosePrice = 0; LastLots = 0; for (cnt=0; cnt<OrdersTotal(); cnt++) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if(OrderSymbol() == Symbol()) { LastTicket = OrderTicket(); if(OrderType() == OP_BUY) LastType = OP_BUY; if(OrderType() == OP_SELL) LastType = OP_SELL; LastClosePrice = OrderClosePrice(); LastLots = OrderLots(); if(LastType == OP_BUY) { if(OrderClosePrice() < OrderOpenPrice()) Profit = Profit - (OrderOpenPrice() - OrderClosePrice()) * OrderLots() / Point; if(OrderClosePrice() > OrderOpenPrice()) Profit = Profit + (OrderClosePrice() - OrderOpenPrice()) * OrderLots() / Point; } if(LastType==OP_SELL) { if(OrderClosePrice() > OrderOpenPrice()) Profit = Profit - (OrderClosePrice() - OrderOpenPrice()) * OrderLots() / Point; if(OrderClosePrice() &tl; OrderOpenPrice()) Profit = Profit + (OrderOpenPrice() - OrderClosePrice()) * OrderLots() / Point; } } } Profit = Profit * PipValue; text2 = "Profit: $" + DoubleToStr(Profit, 2) + " +/-";
前々回の記事でも最新ポジションの情報取得を説明しましたが、ここでまとめて処理した方が効率がよいですね。あと、利益額はOrderProfit()で取得した方が楽です。他にも気になる点がありますが次に進みましょう。
AccountProtection機能
次にAccountProtection機能が書かれています。(分かりやすいように少し変形しています)
if (AccountProtection == 1) { if(OpenOrders >= (MaxTrades - OrderstoProtect) && Profit >= SecureProfit) { OrderClose(LastTicket, LastLots, LastClosePrice, slippage, Yellow); ContinueOpening = False; return(0); } }
AccountProtectionが1の場合、 もし、合計ポジション数がMaxTrades - OrderstoProtect 以上で、合計利益額がSecureProfitの場合、 最新ポジションを決済 ContinueOpening にfalseを代入 start()関数終了。
意味がないコードがあっても、特に触れずに進めます。
現在状況をチャート上に表示
テスターでの実行ではない場合に、Comment()関数でチャート左上にポジション情報などを表示するようにしています。
if(!IsTesting()) { if(myOrderType == 3) text="No conditions to open trades"; else text=" "; Comment("LastPrice=", LastPrice, " Previous open orders=", PreviousOpenOrders, "\nContinue opening=", ContinueOpening, " OrderType=", myOrderType, "\n", text2, "\nLots=", lotsi, "\n", text); }
エントリー注文処理
myOrderType = 1 のとき、すなわち売りポジション保有中かポジション無しで売りシグナルのときの処理が次のように書かれています。
if(myOrderType == 1 && ContinueOpening) { if(Bid - LastPrice >= Pips*Point || OpenOrders < 1) { SellPrice = Bid; LastPrice = 0; if(TakeProfit == 0) tp = 0; else tp = SellPrice - TakeProfit*Point; if(InitialStop == 0) sl = 0; else sl = SellPrice + InitialStop*Point; if(OpenOrders != 0) { mylotsi = lotsi; for(cnt=1; cnt<=OpenOrders; cnt++) if(MaxTrades > 12) mylotsi = NormalizeDouble(mylotsi*1.5, 1); else mylotsi = NormalizeDouble(mylotsi*2, 1); } else mylotsi=lotsi; if(mylotsi > 100) mylotsi = 100; OrderSend(Symbol(), OP_SELL, mylotsi, SellPrice, slippage, sl, tp, NULL, 0, 0, Red); return(0); } }
myOrderType が 1 で ContinueOpeningがtrueのとき Bid - LastPrice が Pipsポイント以上 または ポジション無しのとき SellPrice に Bidを代入 LastPrice に 0 を代入 TakeProfit が0より大きい場合にtp を SellPrice - TakeProfitポイントとする InitialStop が0より大きい場合にsl を SellPrice + InitialStopポイントとする ポジション保有時 mylotsi に lotsiを代入 MaxTrades が 12の場合、mylotsi に1.5を保有ポジション数と同じ回数を掛ける そうでない場合、mylotsi に2を保有ポジション数と同じ回数を掛ける ポジション保有していないとき mylotsi に lotsiを代入 mylotsi が 100を超えていたら100にする 売り注文実行 start()関数終了
買い注文処理部分も同様に書かれています。
あとがき
なかなか分かりづらいですよね^^;
そこで、余分な情報などを削除して、取引部分を再構築してみました!
変数名やコード配置などの変更はありますが、まったく同じ取引をするものを作りました。
ブロックごとに内容をメモしてあるので参考にしてください。
しかし、このままではマネーマネジメントの部分や損失を抱え込んでしまうなどの難ありなので、今後改良していきたいと思います。
【MetatoreLotScalper.zip】をダウンロード
2019.11.12 追記
新MQL4で最近のMT4事情を踏まえてリメイクしたものをアップします。
最新バージョン【MetatoreLotScalper_2019.mq4】をダウンロード
こんばんは。
大変参考になっています。
修正された方のトレイリング注文のマジックナンバーは800のままなのですか?
あ、激しく勘違い?
あさん、おはようございます。
トレイリング注文のカッコ内の意味について、勘違いしておりまして、記事を修正しました。スイマセン^^;
800はマジックナンバーではなくて、有効期限だったんですね^^;
また何かありましたら、聞いてくださいね!
こんばんは。
MQL初めて2日目なもんで自分もすっかりマジックナンバーだと思ってました。
これからも勉強させてください!
あさん、こんばんわ。
プログラムについてアドバイスとか
よろしくお願いいたします。
お疲れ様です
以前はありがとうございました
大分理解しました。。まだ完璧ではないですけど・・・
またご質問なのですが、N時になったら
実行するといったPGを記載するときに
TimeHour(CurTime()を使うと思うのですが
N時N分N秒と指定したときはバックテスト、実際の取引では時間足を1分足を使わないとずれるように思うのですが・・・ローソク足が変わるのは時間足の周期になるのでしょうか?
要はint start()関数は時間足の周期でイベントが発生する??ということですか??
後、バックテストをするときは期間をしていしても思い通りの期間をテストしてくれません。。本にはチャートを表示して一番左までもっていかないといけないとかかいてあったりするのですがいまいち意味がよくわかりません。
それと過去のデータはどこかからとってこないといけないとも記載があったのですがどこから取ってくるのでしょうか?
本当に質問ばかりですみません。。
分からないことが次から次へとでてきてしまって・・・
本当にすみません。。。
xyz__さん
おはようございます。
>ローソク足が変わるのは時間足の周期になるのでしょうか?要はint start()関数は時間足の周期でイベントが発生する??ということですか??
ローソク足が変わるのは時間足の周期なんですが、start関数が実行されるのは1tickごとです。なので、数分間値動きが無かった場合は数分間実行されないということになりますね。(1分足でも)
あと、バックテストはモデルをEvery tickにしても精度は最高90%なので、多少のズレがあると思います。
チャートについてですが、私もよく分かってないのですが、チャートを表示させることによってデータを自動的に取り込む感じだと思います。Homeキーを押すとチャートの左端に行きます。そこの年月日が一番古いデータです。
もっと過去を取り込むには
http://fc888.blog40.fc2.com/blog-entry-394.html
こちらの記事が参考になるかもです。
お疲れ様です
早速の回答ありがとうございます
非常に勉強になりました。
こんばんわ。
新規で約定したらその3バー後の終値で決済するというコードはどのように記述すればいいのでしょうか?
例えば4時間足なら
OrderSend(…);
OrderSelect(…);
int opentime = OrderOpenTime();
if(TimeHour(TimeCurrent()) >= opentime + 240*3*60) OrderClose(…);
こんな感じでいけそうな気もしますが、他の時間足で検証しようとするとコードを書き換えなければならないんですよね。
それに週末が絡むとこのコードじゃ使えないですよね?週明けの寄りで決済になってしまいます。
TimeDayOfWeek() と TimeHour()を使って条件分岐すれば可能な気もしますが結構複雑になりそうで…
簡単で他の時間足でも使える記述方法はありますか?
ほんとは面倒とか言ってちゃいけないんでけどね。
red sauceさん
おはようございます。
3バー後の終値とするとやはり複雑になりそうですね。
4バー後の始値でよいなら
int bar;
int start()
{
・・・
OrderSend(…);
bar=Bars;
・・・
if(Bars==bar+4) OrderClose(…);
・・・
return(0);
}
でいけると思います。
あと、週末はやはり条件に時間を加える感じだと思います。
その場合余裕を持たせた方がいいと思います。
終わる時間もぴったりならいいんですけど。
はじめまして、
「インフォ2ちゃんねる」http://info2ch.com
というサイトを運営しているものです。
metatraderの非常に有益なサイト、
非常に参考になります。コメントへの
記載申し訳ありません。
今回、このサイトを立ち上げまして、多くの
方に利用していただきたいと考え、ご連絡を
差し上げております。
情報商材の質の向上のためにも、多くの方に
有益なサイトとしてご利用いただけるように
努めています。
以前より、販売者をレビュー評価するサイトが
ほとんどなく、今回そのような主旨でサイトを
立ち上げました。
■■お願い■■
あなたの貴重な購入体験をレビューとして、
「インフォ2ちゃんねる」http://info2ch.com
にご記入・ご協力いただけますと幸いです。
どうぞ、末永くご愛顧のほう
よろしくお願いします!
こんばんわ。
なるほどBarsをそのように使えばどの足でも使えるしすっきりとしますね。
このやり方でいこうと思います。どうもありがとうございました。
リンクありがとうございました。
よろしくお願いします。