記録ファイルを作ってみよう!

記録ファイルを作ってみよう!

※2019/10/10 この記事を更新しました。

今回は、弱気なブルートさんのコメントにありました一定時間毎のドローダウンを記録するファイルを作るEAを作ってみましょう!

サンプルとして、ランダムエントリーでATRの数倍のトレイリングストップするシステムとして紹介した記事「利益を出すランダムエントリーシステム!?」を使って、作ってみました。

→今回のmq4ファイル最新バージョンFileWriteSample_New.mq4をダウンロード

内容は、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^)/

2008年8月25日|コメント (6)

カテゴリー:EA作成・カスタマイズ(MT4)

コメント (6)

記事アップありがとうございます
ヒントどころか、コードそのもの+詳しい解説までしていただいて、本当に感激ものです、PIDSP4と言うEAを使ってみてナンピン系EAの含み損の怖さを思い知りました
で、今回のお願いだったのですが、本当に助かります
商用EAだとMQ4ではないので組み込みは無理ですが、少し改造して売買しないようにすれば、同時に稼働しておくことによって、外のEAの売買記録がとれますね
実は、PIDSP5にはこの機能が付いていたんですが、PipMaker系にも組み込んでテストしてみたいな、と思ったのがきっかけです
MT4自体にこの機能が有るのがベストでしょうけど・・・
あ、VQSimpleもおいしく頂きました
完全にとけ込んでますねW
とりあえず、お礼と言っては些少すぎますがランクリいたしました
こちらは、お礼では有りませんが、気になるアドセンス見させた頂きました、勿論狩りになったりしてはいけないので数個に止めています
時々おじゃましますね

内容は、まだ、さっと見ただけなので、理解できない部分も有りますが、後ほどよく見させていただきます、よく見ても判らない公算が大ですがW
取り急ぎお礼まで。

投稿者:弱気なブルート |2008年8月26日 16:18

弱気なブルートさん

クリックありがとうございます!
これからもよろしくお願い致します。

EA研究がんばりましょうね!

投稿者:慶次 |2008年8月27日 02:43

じっくりコードを見させていただき、なんとか大まかには理解できました、有り難うございます。
そして、色々いじって楽しんでいます。
思いついたのは、ex4しか公開されておらず、なおかつストップを入れないEAを、こちらのEAをエントリーしないようにしてさらにマジックを合わせて、同時に走らせ、トレーリングストップにしてみたり(先に元のEAがクローズする事もありますが)、手動でエントリーした物をこちらのEAでコントロールして貰ったり、色々と楽しめます。
勿論、同時に記録も残りますし。

一定以上の期間が有れば、あらゆる時間足、あらゆる通貨ペアにおいて全くパラメータをいじることなく、利益を上げられるロジックが有れば、それは、聖杯と言うことなのでしょうが、あり得ないものかも知れませんね。
そして、前の記事に有ったわけですが、まだ試していませんでした。
ATRの数倍のトレイリングストップ、いろんな通貨ペア、いろんな時間足で有る程度、パラメータを変えずに利益を出せるってすばらしいですね、なおかつランダムエントリーで。
エントリーにとらわれがちですが、クローズこそ大事なのだと、つくづく感じました。

ただ、どうしても判らないのが、このEA、オプティマイズが上手くいきません。
倍率を最適化しようとすると、結果はちゃんと出るんですが、そのパラメータでバックテストすると、全く違った結果になります。
何故なのでしょうか?
よろしくお願いします。

投稿者:弱気なブルート |2008年8月29日 19:59

弱気なブルートさん

こんにちわ!

サンプルがお役に立ててよかったです(^-^)

サンプルは、ランダムエントリーなので完全な最適化はできないかと思います。

やはり、エントリも優位性の有る一定の理由に基づいて行なった方が勝率が良くなると思います。ですので、クローズの方法の一つといった具合に考えていただければと思います。

投稿者:慶次 |2008年8月30日 08:26

コメント有り難うございます
私も、乱数を使っているからなのかな、とは思ったのですが、一度オプティマイズした後、他のeaをオプティマイズして、再度同じオプティマイズをしてみても、結果は完全に一致し、バックってストはバックテストで、こちらも同じことが言えるのですが、オプティマイズとバックテスト結果が一致しないのが腑に落ちませんでした。
さらに、バックテストを一日ずらしてテストしてみても大体似たような曲線を描くのに、オプティマイズ結果数個をバックテストしてみるとあまりにも、違いすぎるようなので、質問してみました。
言葉がたりなくてすみませんでした。
まあ、MT4の乱数の仕様だと、割り切るしか無いのでしょうかね。
確かに仰有るように、実際使おうとすれば、トレンドが出ているときに、順張り、とかでエントリーする訳で、深く考えてもしょうがないのでようけど。

その後ちょっと思いついて試してみたのですが、MathSrand(1);でイニシャライズすればいいのかな?なんて思ってやってみたのですが結果はダメで、MathSrand(TimeLocal());
でやってみたら、少しは近い値になりました、中には完全一致している物もあります。

よく見てみたら、それは、Pass1でした、要するに、オプティマイズでは、2回目以降は前回の系列を引き継ぐとかなのでしょうかね。
MathSrand(TimeLocal());で近い値になったのは、たまたまだったのかな?

ちなみにstart以降でイニシャライズしてみても、結果は同じになりませんでした。

細かいことに、長々とすみませんでした。

ぽちっとな

投稿者:弱気なブルート |2008年8月30日 17:49

弱気なブルートさん

こんにちわ!

乱数を使う時は、
MathSrand(TimeLocal());
をつけないといけないのですね!

サンプルのファイルの方も直させていただきました^^;

ありがとうございます!

投稿者:慶次 |2008年8月31日 13:54

コメントを投稿する

(初めてのコメントの時は、コメントが表示されるためにこのブログのオーナーの承認が必要になることがあります。承認されるまでコメントは表示されませんのでしばらくお待ちください)






画像の中に見える文字を入力してください。

Captchaの認証で入力ミスがありますと、コメントが消えてしまいますのでご注意ください。
コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。