あまりにもEAの検証時間が長すぎたので簡単な性能チューニングをしたら劇的に改善した。EAの処理でそこまで重い処理はないと思っていたが甘かったビジュアルモードで使うチャートへの描画処理はかなり重く性能悪化の原因となっていた。結論としてビジュアルモード処理の除外とデバッグコードの削除で30倍近く性能が改善した。性能改善をさぼったせいでかなり無駄に時間を使ってしまった。悪いことは言わないのでバックテスト前に性能チューニングはしておいた方がいい。
本記事はFXの自動売買に使用されるプログラムについて解説していますが内容を保証するものではありません。金銭にかかわる内容であるためご注意ください。参考にする場合は自己責任でお願いします。
本記事ではMT4を使用する。
FXDD – MetaTrader
・Version: 4.00 build 1322
・8Feb 2021
MetaEditor
・Version 5.00 build 2375
・7 Jan 2021
過去10年のバックテストに12時間以上かかる
バックテストに時間がかかるため多くの組み合わせを検証できない。
時間がかかりすぎて色々なパターンを試せない
パラーメーター値や条件などの組み合わせを考えると数多くの組み合わせがあり、バランス良く効く組み合わせを見つけるにはより多くのパターンを試す必要がある。1年以内のバックテストであれば数時間で終わるが別の年の成績が悪い可能性もあり最終的には長期のバックテストが必要となる。
マシン3台での検証生活
過去10年のバックテストが12時間以上かかるのでデスクトップ1台とノートPC2台、合計3台のPCをつあって検証。電気代の問題もあるが寝室にマシンがあるためファンの音が気になってしまう。
システムの性能問題
仕事で性能チューニングを色々やってきた。性能問題の原因によく上げられるのがデータベースへのアクセスである。
記憶媒体へのアクセスがネックになる
通常ハードディスク等のデバイスへのアクセスが性能問題の原因となることが多い。データベースも性能問題の原因になりやすい。データベースではインデックスと呼ばれる機能を使い検索スピードを上げたりできるがシステム全体でみればボトルネックである。物理デバイスへのアクセスが圧倒的にコストがかかる。すべての情報がメモリ上にあるシステムであれば比較的性能はよいはず。
キャストや変換関数やメソッド
文字列から数値、数値から文字列にする関数なども一般的に性能のボトルネックになると言われている。言語ごとにコストのかかる(処理時間が長い)関数やメソッドがあるので性能改善する場合は回避したり代替機能を使って問題を解決する。
デバイスへのアクセス
ディスプレイ表示処理などもコストがかかる。プログレスバーなどで進捗状況をレポートする場合はマルチスレッドと呼ばれる仕組みを使って表示処理と計算処理を分けたりする。標準出力なども含め性能を上げたい場合は外部への出力処理を出来るだけ少なくした方がよい。
EAの性能チューニング
バックテストで使うEAはファイルアクセスなどしないので筆者はあまり性能を気にしていなかった。しかしそれは大間違い。バックテストのような大量の処理を連続して行う場合はファイルアクセスが無くても性能チューニングが重要になってくる。特に全ティックでバックテストをするならなおさらである。
EA性能計測
EAの開始と終了に時間計測処理を追加。
uint g_startTime; uint g_endTime; int OnInit() { // EA開始時刻を記録 g_startTime = GetTickCount(); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { // EA終了時刻を記録 g_endTime = GetTickCount(); // EA稼働時間をレポート Print( "処理時間:" + string((double)(g_endTime - g_startTime) / 1000) + "秒" ); }
1. チューニング前
チューニング前は一カ月のテストで約13秒。
2021.06.19 01:21:54.161 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:13.188秒 2021.06.19 01:28:35.846 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:13.266秒 2021.06.19 01:29:26.256 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:13.172秒
2. ビジュアルモード用コードの除外
ビジュアルモードでデバッグ用のメッセージをチャート上に表示していたのでそれを抑止する。非ビジュアルモードではビジュアルモードでしか使わない処理をすべて動かないように切り替える。
// ビジュアルモードの取得 bool g_visualMode = IsVisualMode(); if(g_visualMode) { // ビジュアルモードの処理 }
チューニング後10倍近く性能が改善。非ビジュアルモードであってもチャートへの描画処理が影響していたようだ。ObjectCreateのような描画処理はボトルネックになる可能性が高いので注意した方がよさそう。
2021.06.19 01:41:46.708 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:1.64秒 2021.06.19 01:42:22.920 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:1.656秒 2021.06.19 01:47:33.539 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:1.641秒
3. デバック用文字列変換関数を削除
デバッグ用で使っているIntegerToStringなどの変換関数を削除。手当たり次第削除したので4倍ほど性能が改善した。
2021.06.19 02:58:28.528 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:0.407秒 2021.06.19 02:58:57.383 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:0.375秒 2021.06.19 02:59:45.295 2021.01.19 23:59:42 ea008-trend02kai-back USDJPY,M5: 処理時間:0.39秒
性能改善
ビジュアルモードとデバッグコードを削除しただけで30倍近く性能が改善した。まさかビジュアルモードの処理がここまで悪影響しているとは思いもしなかった。デバッグコードも想像以上に重い。結論を言うとバックテストが余分な処理で30倍遅かったことないなる。1時間で終わる処理が30時間と・・・。
セクション | 1回目 | 2回目 | 3回目 | 平均 |
---|---|---|---|---|
1. チューニング前 | 13.19 | 13.27 | 13.17 | 13.21 |
2. ビジュアルモード用コードの除外 | 1.64 | 1.66 | 1.64 | 1.65 |
3. デバック用文字列変換関数を削除 | 0.41 | 0.38 | 0.39 | 0.39 |
まとめ
しばらくチューニングしないでテストしていないので、とてつもなく無駄な時間を過ごしてしまった。多くのパターンを検証するためにも性能チューニングはテスト前に必ずやっておいた方がいい。
- 多くの組み合わせテストを効率的にするためEAの性能チューニングは必須
- ビジュアルモードでしか使わない処理は非ビジュアルモードで除外する
- デバッグコードは極力削除しておく
チャートへの描画は重い処理なのでご注意ください。