ここでは、一定時間毎にドローダウンをファイルに記録するEAの作り方を解説します。サンプルとして、ランダムエントリーするEAに、ドローダウンファイル記録機能を追加しました。
サンプルEA【FileWriteSample_New.mq4】をダウンロード
ランダムエントリーするEAの作り方は、過去記事【利益を出すランダムエントリーシステム!?】を参考にしてください。
過去記事【利益を出すランダムエントリーシステム!?】へ
記録ファイルを出力する方法
記録ファイルについて
今回のサンプルEAは、4時間足が更新されるたびに月、日、時間、残高、有効証拠金、現在のポジションのドローダウン、残高ピーク時からのドローダウンを記録します。
バックテストで実行した場合は、testerフォルダ→filesフォルダ内に記録ファイルが作成されます。
リアルタイムで実行した場合は、MQL4フォルダ→Filesフォルダ内に記録ファイルが作成されます。
さっそく編集の流れを見ていくぞい!
パラメータ用の変数
次の3つのパラメーターを追加します。
extern string FileName = "writesample"; extern string FileType = "csv"; extern string Separator = ",";
FileNameにはファイル名を、FileTypeには拡張子を入力します。Separatorには、区切り文字を入力します。
グローバル変数
次に、グローバル変数3つを追加します。
int write_bar; double ab_best; string filename;
整数 ファイルに書き込んだ時の4時間足のローソク足の数 小数 過去最高残高の値 文字列 出力ファイル名
OnInit()関数内の処理
OnInit()関数内に次のコードを追加します。
filename = FileName + "." + FileType; int handle = FileOpen(filename, FILE_WRITE, Separator); if (handle > 0) { FileWrite(handle, "Month", "Day", "Hour", "Balance", "Equity", "Pos DD", "AC DD"); FileClose(handle); }
変数「filename」には、パラメータで設定したファイル名と拡張子を「.(ドット)」でつなげたものを格納するようにします。
そして、書き込みモードでそのファイルを開き、項目名を書き込んでファイルを閉じます。
FileWrite()関数の括弧内の最初やFileClose()関数の括弧内は、ファイル名ではなくファイルハンドルで指定しますので気をつけましょう!
残高の最高額を記録しておく
OnTick()関数内で、次のコードを追加します。
double ab = AccountBalance(); // 口座残高 // 残高の最高額更新 if (ab_best < ab) ab_best = ab;
ティック毎に現在残高を取得して、記録しておいた残高最高額より大きければ上書き更新します。
ファイルに出力する
先ほどのコードの下に、次のコードを追加します。
// ファイル書き込み if (iBars(NULL, PERIOD_H4) != write_bar) { double ae = AccountEquity(); // 有効証拠金 double dd = (1 - ae / ab); // 現在のドローダウン double dd_best = (1 - ae / ab_best);// 残高最高額からのドローダウン // 各ドローダウンの文字列 string dd_str = "-"; if (dd > 0) dd_str = DoubleToStr(dd * 100, 2) + "%"; string dd_best_str = "-"; if (dd_best > 0) dd_best_str = DoubleToStr(dd_best * 100, 2) + "%"; int handle = FileOpen(filename, FILE_READ|FILE_WRITE, Separator); if (handle > 0) { FileSeek(handle, 0, SEEK_END); FileWrite(handle, Month(), Day(), Hour(), DoubleToStr(ab, 2), DoubleToStr(ae, 2), dd_str, dd_best_str); FileClose(handle); write_bar = iBars(NULL, PERIOD_H4); } }
4時間足が更新されたら、必要な情報を取得してファイルに追記という流れです。
ここでのFileOpen()関数は記録を追記していきたいので、ファイルオープンモードを「FILE_READ|FILE_WRITE」(読み書きモード)にする必要があります。
正常にファイルが開いたら、FileSeek()関数でファイルの最後の段にポインタを移動させ、FileWrite()関数で各項目の値をファイルに書き込みます。
そしてファイルを閉じて、現在の4時間足のローソク足の数を write_bar に記録することで、その後の約4時間はファイル出力を実行しないような構造にしています。
書き込みのタイミングや、記録する内容など改造したりして試してみてくださいね。
では、このへんで(^0^)/
記事アップありがとうございます
ヒントどころか、コードそのもの+詳しい解説までしていただいて、本当に感激ものです、PIDSP4と言うEAを使ってみてナンピン系EAの含み損の怖さを思い知りました
で、今回のお願いだったのですが、本当に助かります
商用EAだとMQ4ではないので組み込みは無理ですが、少し改造して売買しないようにすれば、同時に稼働しておくことによって、外のEAの売買記録がとれますね
実は、PIDSP5にはこの機能が付いていたんですが、PipMaker系にも組み込んでテストしてみたいな、と思ったのがきっかけです
MT4自体にこの機能が有るのがベストでしょうけど・・・
あ、VQSimpleもおいしく頂きました
完全にとけ込んでますねW
とりあえず、お礼と言っては些少すぎますがランクリいたしました
こちらは、お礼では有りませんが、気になるアドセンス見させた頂きました、勿論狩りになったりしてはいけないので数個に止めています
時々おじゃましますね
内容は、まだ、さっと見ただけなので、理解できない部分も有りますが、後ほどよく見させていただきます、よく見ても判らない公算が大ですがW
取り急ぎお礼まで。
弱気なブルートさん
クリックありがとうございます!
これからもよろしくお願い致します。
EA研究がんばりましょうね!
じっくりコードを見させていただき、なんとか大まかには理解できました、有り難うございます。
そして、色々いじって楽しんでいます。
思いついたのは、ex4しか公開されておらず、なおかつストップを入れないEAを、こちらのEAをエントリーしないようにしてさらにマジックを合わせて、同時に走らせ、トレーリングストップにしてみたり(先に元のEAがクローズする事もありますが)、手動でエントリーした物をこちらのEAでコントロールして貰ったり、色々と楽しめます。
勿論、同時に記録も残りますし。
一定以上の期間が有れば、あらゆる時間足、あらゆる通貨ペアにおいて全くパラメータをいじることなく、利益を上げられるロジックが有れば、それは、聖杯と言うことなのでしょうが、あり得ないものかも知れませんね。
そして、前の記事に有ったわけですが、まだ試していませんでした。
ATRの数倍のトレイリングストップ、いろんな通貨ペア、いろんな時間足で有る程度、パラメータを変えずに利益を出せるってすばらしいですね、なおかつランダムエントリーで。
エントリーにとらわれがちですが、クローズこそ大事なのだと、つくづく感じました。
ただ、どうしても判らないのが、このEA、オプティマイズが上手くいきません。
倍率を最適化しようとすると、結果はちゃんと出るんですが、そのパラメータでバックテストすると、全く違った結果になります。
何故なのでしょうか?
よろしくお願いします。
弱気なブルートさん
こんにちわ!
サンプルがお役に立ててよかったです(^-^)
サンプルは、ランダムエントリーなので完全な最適化はできないかと思います。
やはり、エントリも優位性の有る一定の理由に基づいて行なった方が勝率が良くなると思います。ですので、クローズの方法の一つといった具合に考えていただければと思います。
コメント有り難うございます
私も、乱数を使っているからなのかな、とは思ったのですが、一度オプティマイズした後、他のeaをオプティマイズして、再度同じオプティマイズをしてみても、結果は完全に一致し、バックってストはバックテストで、こちらも同じことが言えるのですが、オプティマイズとバックテスト結果が一致しないのが腑に落ちませんでした。
さらに、バックテストを一日ずらしてテストしてみても大体似たような曲線を描くのに、オプティマイズ結果数個をバックテストしてみるとあまりにも、違いすぎるようなので、質問してみました。
言葉がたりなくてすみませんでした。
まあ、MT4の乱数の仕様だと、割り切るしか無いのでしょうかね。
確かに仰有るように、実際使おうとすれば、トレンドが出ているときに、順張り、とかでエントリーする訳で、深く考えてもしょうがないのでようけど。
その後ちょっと思いついて試してみたのですが、MathSrand(1);でイニシャライズすればいいのかな?なんて思ってやってみたのですが結果はダメで、MathSrand(TimeLocal());
でやってみたら、少しは近い値になりました、中には完全一致している物もあります。
よく見てみたら、それは、Pass1でした、要するに、オプティマイズでは、2回目以降は前回の系列を引き継ぐとかなのでしょうかね。
MathSrand(TimeLocal());で近い値になったのは、たまたまだったのかな?
ちなみにstart以降でイニシャライズしてみても、結果は同じになりませんでした。
細かいことに、長々とすみませんでした。
ぽちっとな
弱気なブルートさん
こんにちわ!
乱数を使う時は、
MathSrand(TimeLocal());
をつけないといけないのですね!
サンプルのファイルの方も直させていただきました^^;
ありがとうございます!