- www.mql5.com
if (prev_calculated) EventChartCustom(Chart, 0, Index, 0, NULL);イベントがキューに入れられていない場合、ティックを見逃すことがあります。こうしたことは(主にVPS や処理速度の遅いコンピュータで)起こり得ます。
残念ながら、OnTick関数だけを備えた単純なエキスパートアドバイザーでさえ、ティックを見逃してしまうことがあります。実戦用のエキスパートアドバイザーでは、CopyTicks関数やその他の工夫を用いて、ティックを見逃さずに動作するようにしています。
このライブラリは、テスター内でのみティックの欠落を確実に防ぎます。動作はOnTickと全く同じです。
/* //https://www.mql5.com/ru/blogs/post/755348 #define VIRTUAL_TESTER_MULTI // OnTickMultiの仮想取引環境での実行 #define VIRTUAL_LIMITS_TP_SLIPPAGE // ストップロスとTPは最初の約定価格で執行される - ポジティブスリッページ #define VIRTUAL_CLOSEALL_BYEND // テスト終了時にすべての注文を強制的に決済する // #define VIRTUAL_ALTERNATIVE // 代替の計算速度 */ #include <MT4Orders.mqh> //https://www.mql5.com/ja/code/16006 #include <fxsaber\OnTickMulti\OnTickMulti.mqh> //https://www.mql5.com/ja/code/47647 /* #define REPORT_TESTER // テスターにレポートが自動的に記録される #define REPORT_BROWSER // ブラウザを起動してレポートを作成する - DLLの許可が必要。 #include <Report.mqh> //https://www.mql5.com/ja/code/18801 */ input group "Trading" input double LotSize=0.01; input double TPdist=0.1; // TP (%) input double SLdist=0.2; // SL (%) input long MyMagic=123; input group "Benchmark: https://www.mql5.com/ru/forum/282062/page49#comment_50801337" input int inRange = 0; // マルチシンボルのOnTick。 void OnTickMulti( const string &Symb, const int &Index ) { TradeStep(Symb, Index); } double OnTester() { return AccountInfoDouble(ACCOUNT_BALANCE); } int GetHour( const datetime time ) { return((int)(time / 3600) % 24); } void TradeStep( const string &symbol, const int &Index ) { if(GetHour(TimeTradeServer()) < 2) return; DoTrade(symbol, Index); } bool IsMySymbol( const string &Symb, const int &Index ) { return(OnTickMulti.IsOnlySymbolBase || ( #ifdef __VIRTUAL__ VIRTUAL::GetHandle() ? (OrderSymbolID() == Index) : //https://www.mql5.com/ru/forum/282062/page52#comment_51051261 #endif // #ifdef __VIRTUAL__ (OrderSymbol() == Symb))); } void DoTrade(const string &symbol, const int &Index ) { int total=OrdersTotal(); bool haveBuy=false; bool haveSell=false; for(int i=0; i<total; i++) { if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber()==MyMagic && IsMySymbol(symbol, Index)) { int type=OrderType(); if(type==OP_BUY) haveBuy=true; if(type==OP_SELL) haveSell=true; } } if(!haveBuy) { double price=SymbolInfoDouble(symbol,SYMBOL_ASK); int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); double tp=NormalizeDouble(price*(1.0+TPdist/100.0), digits); double sl=NormalizeDouble(price*(1.0-SLdist/100.0), digits); OrderSend( symbol, OP_BUY, LotSize, price, 0, sl, tp, NULL, MyMagic); } if(!haveSell) { double price=SymbolInfoDouble(symbol,SYMBOL_BID); int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); double tp=NormalizeDouble(price*(1.0-TPdist/100.0), digits); double sl=NormalizeDouble(price*(1.0+SLdist/100.0), digits); OrderSend( symbol, OP_SELL, LotSize, price, 0, sl, tp, NULL, MyMagic); } }
テスターの設定。
高速化。
冒頭の数行のコメントを外せば、処理を高速化 できます。
測定結果。
| 設定 | 結果 |
|---|---|
| Virtual.mqh なし。 | 最短パス 0:00:13.184、最長パス 0:00:15.031、平均パス 0:00:13.633 |
| Virtual.mqh を使用、inVirtualTester = false。 | 最短パス 0:00:14.735、最長パス 0:00:16.384、平均パス 0:00:15.081 |
| Virtual.mqh を使用、inVirtualTester = true。 | 最短パス 0:00:05.872、最長パス 0:00:05.964、平均パス 0:00:05.919 |
| Virtual.mqh を使用し、inVirtualTester = true + VIRTUAL_ALTERNATIVE。 | 最短パス 0:00:06.172、最長パス 0:00:07.791、平均パス 0:00:06.524 |
このアドバイザーは極めて単純な仕組み(各銘柄につき0~2つのオープンポジション、固定のSL/TP、指値注文なし)であるため、この設定では処理速度を2.5倍に高速化することしかできません。
TickValue+Swap+Commission。
上記のテストは、各ティックごとにTickValueを再計算したり、他の銘柄を接続したりする必要がないよう、ピップ単位のモード(設定画面のスクリーンショット参照)で行われました。このモードでも結果は同じです。
フルファッシュによる高速化が必要な場合は、このソリューション を使用する必要があります。
- 2023.12.25
- www.mql5.com
トレーディング、自動売買システム、および取引戦略のバックテストに関するフォーラム
fxsaber, 2024年3月18日 18:36
void DoTrade(const string &symbol, const int &Index ) { int total=OrdersTotal(); bool haveBuy=false; bool haveSell=false; for(int i=0; i<total; i++) { if(OrderSelect(i, SELECT_BY_POS) && (OrderMagicNumber()==Index)) { int type=OrderType(); if(type==OP_BUY) haveBuy=true; if(type==OP_SELL) haveSell=true; } } if(!haveBuy) { double price=SymbolInfoDouble(symbol,SYMBOL_ASK); int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); double tp=NormalizeDouble(price*(1.0+TPdist/100.0), digits); double sl=NormalizeDouble(price*(1.0-SLdist/100.0), digits); OrderSend( symbol, OP_BUY, LotSize, price, 0, sl, tp, NULL, Index); } if(!haveSell) { double price=SymbolInfoDouble(symbol,SYMBOL_BID); int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); double tp=NormalizeDouble(price*(1.0-TPdist/100.0), digits); double sl=NormalizeDouble(price*(1.0+SLdist/100.0), digits); OrderSend( symbol, OP_SELL, LotSize, price, 0, sl, tp, NULL, Index); } }
| 設定 | 結果 |
|---|---|
| Virtual.mqh を使用しない場合。 | 最短パス 0:00:13.184、最長パス 0:00:15.031、平均パス 0:00:13.633 |
上記では、Virtualライブラリを一切使用せずに、多通貨EAを高速化する簡単な方法をコード内で紹介しました。
| 設定 | 結果 |
|---|---|
| Virtual.mqh なし +MagicNumberOrderSymbol | 最短パス 0:00:08.608、最長パス 0:00:10.236、平均パス 0:00:08.942 |
無料で1.5倍の高速化を実現!
単一シンボルモードから複数シンボルモードに移行する際のテスターの動作遅延を確認しました。検証方法は完璧とは言えませんが、これはダミーのエキスパートアドバイザーです。
単一シンボル用アドバイザー。
#property tester_no_cache input group "Benchmark: https://www.mql5.com/ru/forum/282062/page49#comment_50801337" input int inRange = 0; const ulong StartTime = GetMicrosecondCount(); int AmountTicks = 0; double OnTester() { return((double)(GetMicrosecondCount() - StartTime)); // return(AmountTicks); // return((double)AmountTicks / (GetMicrosecondCount() - StartTime)); } void OnTick() { AmountTicks++; }
| 設定 (OnTick) | TimeLength (mcs) | AmountTicks | パフォーマンス (ticks/mcs) |
|---|---|---|---|
| EURUSD | 1079331 | 9927153 | 9.19 |
| GBPUSD | 1229032 | 11309740 | 9.20 |
| USDJPY | 1307322 | 11986756 | 9.16 |
| USDCHF | 1121541 | 10359511 | 9.23 |
| AUDUSD | 1175578 | 10758136 | 9.15 |
テスターのパフォーマンス(単位時間あたりのティック数)が銘柄に依存しないこと(ピップスモード)がはっきりとわかります。
マルチシンボルEA。
#property tester_no_cache input group "Benchmark: https://www.mql5.com/ru/forum/282062/page49#comment_50801337" input int inRange = 0; #include <fxsaber\OnTickMulti\OnTickMulti.mqh> //https://www.mql5.com/ja/code/47647 const ulong StartTime = GetMicrosecondCount(); int AmountTicks = 0; double OnTester() { return((double)(GetMicrosecondCount() - StartTime)); // return(AmountTicks); // return((double)AmountTicks / (GetMicrosecondCount() - StartTime)); } // マルチシンボルのOnTick。 void OnTickMulti( const string &Symb, const int &Index ) { AmountTicks++; }
| 設定 (OnTickMulti) | TimeLength (OnTickMulti) | TimeLength (OnTick) | ティック数 | パフォーマンス (OnTickMulti) | パフォーマンス (OnTick) |
|---|---|---|---|---|---|
| EURUSD | 3455901 | 1079331 | 9927153 | 2.87 | 9.19 |
| EURUSD、GBPUSD | 6617085 | 2308363 | 21236893 | 3.20 | 9.19 |
| EURUSD、GBPUSD、USDJPY | 9188781 | 3615685 | 33223649 | 3.61 | 9.18 |
| EURUSD、GBPUSD、USDJPY、USDCHF | 11517804 | 4737226 | 43,583,160 | 3.78 | 9.20 |
| EURUSD、GBPUSD、USDJPY、USDCHF、AUDUSD | 16058223 | 5912804 | 54341296 | 3.38 | 9.19 |
処理性能は文字数にほとんど依存しないが、その一方で3分の1の性能にとどまる。
結論。
もしあなたのマルチ通貨EAが、独立した単一通貨のサブTSの寄せ集めであるならば、 (少なくとも)1つのマルチ通貨EAとしてまとめて最適化するよりも、各サブTSを個別に最適化し(その後、Validateを通じて1回のパスで統合する)、それぞれを個別に最適化する方が3倍速くなります。
- www.mql5.com
// マルチシンボルのOnTick。 void OnTickMulti( const string &Symb, const u int &Index )
こんにちは、
最新のビルド(5200+)では、コードがコンパイルできなくなっているようです:
#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // マルチシンボルのOnTick。 int TicksCounter[]; // 指定された各文字の受信ティック数をカウントするカウンター。 void OnInit() { // 受信したティック数のカウンタを初期化する。 ArrayResize(TicksCounter, ArraySize(OnTickMulti.Symbols)); ArrayInitialize(TicksCounter, 0); } double OnTester() { // 指定された各文字について、発生したティック数を表示します。 for (uint i = ArraySize(TicksCounter); (bool)i--;) Print(OnTickMulti.Symbols[i] + " - " + (string)TicksCounter[i] + " ticks."); ArrayPrint(OnTickMulti.Symbols); // OnTickMulti の文字一覧。 return(0); } // マルチシンボルのOnTick。 void OnTickMulti( const string &Symb, const uint &Index ) { TicksCounter[Index]++; // 指定された文字に対するティック受信回数のカウントを増加させた。 }
MQL5_b520 0 +の変更に合わせてライブラリが更新されました。
- 2025.07.31
- www.mql5.com
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索


オンティック・マルチ:
マルチシンボルのオンティック。
Author: fxsaber