单次运行报告中的所有统计数据都可用。以前,即使拥有智能交易系统的源代码,也无法获得这些数据。
double ghpr; // 几何平均数交易 double ghprpercent; // 以百分比表示的几何平均交易量 double ahpr; // 交易的算术平均数 double ahprpercent; // 以百分比表示的交易算术平均数 double zscore; // 系列测试 double zscorepercent; // 以百分比为单位的序列测试 double lrcorr; // 线性回归的相关系数 double lrstderror; // 线性回归的平衡偏差标准误差 double corr_prf_mfe; // MFE 与利润之间的相关性 double corr_prf_mae; // Mae 与利润之间的相关性 double corr_mfe_mae; // Mae 和 Mfe 之间的相关性 double mfe_a; //市场份额与利润之间的相关性,线性回归线系数 double mfe_b; //市场份额与利润之间的相关性,线性回归线系数 double mae_a; // Mae 与利润之间的相关性,线性回归线的系数 double mae_b; // Mae 与利润之间的相关性,线性回归线的系数 UINT in_per_hours[24]; // 按小时分配投入 UINT in_per_week_days[7]; // 按星期分配投入 UINT in_per_months[12]; // 按月分配投入 double out_per_hours[24][2]; // 按小时分配投入 double out_per_week_days[7][2]; // 按星期分配投入 double out_per_months[12][2]; // 按月分配投入 INT64 holding_time_min; // 最短位置保持时间 INT64 holding_time_max; // 最大位置保持时间 INT64 holding_time_avr; // 平均位置保持时间
当前版本的 tst 格式没有以下数据
- 时间(毫秒)。
- 位置 ID。
- 魔数。
这对使用场景 造成了限制。
重现几个错误。在对冲账户上运行测试器中的智能交易系统。
#include <MT4Orders.mqh> //https://www.mql5.com/zh/code/16006 #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK) #define PAUSE 100000 void OnTick() { static bool FirstRun = true; if (FirstRun) { OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0); Sleep(PAUSE); OrderSend(_Symbol, OP_BUY, 2, Ask, 0, 0, 0); Sleep(PAUSE); if (OrderSelect(0, SELECT_BY_POS)) OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0); Sleep(PAUSE * 2); if (OrderSelect(0, SELECT_BY_POS)) OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0); Sleep(PAUSE * 2); TesterWithdrawal(100); FirstRun = false; } } void OnDeinit( const int ) { const int Total = OrdersHistoryTotal(); for (int i = 0; i < Total; i++) if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { OrderPrint(); Print(OrderTicketID()); // MT5-PositionID } }
结果如下
2020.01.08 23:59:58 #1 2020.01.01 00:00:00 balance 0.00 0.00000 0.00000 0.00000 2020.01.01 00:00:00 0.00000 0.00 0.00 100000.00 0 2020.01.08 23:59:58 0 2020.01.08 23:59:58 #4 2020.01.02 06:00:00 buy 1.00 EURUSD 1.12137 0.00000 0.00000 2020.01.02 06:03:20 1.12132 -3.56 0.00 -4.46 0 2020.01.08 23:59:58 2 2020.01.08 23:59:58 #5 2020.01.02 06:01:40 buy 2.00 EURUSD 1.12137 0.00000 0.00000 2020.01.02 06:06:40 1.12129 -7.14 0.00 -14.27 0 2020.01.08 23:59:58 3 2020.01.08 23:59:58 #6 2020.01.02 06:10:00 balance 0.00 0.00000 0.00000 0.00000 2020.01.02 06:10:00 0.00000 0.00 0.00 -100.00 withdrawal 0 2020.01.08 23:59:58 0
接下来,我们用脚本读取相应的 tst 文件。
#include <fxsaber\SingleTesterCache\SingleTesterCache.mqh> //https://www.mql5.com/zh/code/27611 #include <fxsaber\MultiTester\MTTester.mqh> //https://www.mql5.com/zh/code/26132 void OnStart() { uchar Bytes2[]; if (MTTESTER::GetLastTstCache(Bytes2) != -1) // 如果可以读取单次运行的最后一条缓存记录 { const SINGLETESTERCACHE SingleTesterCache(Bytes2); // 将其驱动到相应的对象中。 for (int i = 0; i < ArraySize(SingleTesterCache.Positions); i++) Print(SingleTesterCache.Positions[i].ToString()); } }
它将显示仓位数据
id = 0 mfe = 0.0 mae = -8.029999999999999 profit = -4.46 lifetime = 00:03:20 id = 0 mfe = 0.0 mae = -21.4 profit = -14.27 lifetime = 00:05:00 id = 0 mfe = 0.0 mae = 0.0 profit = 0.0 lifetime = 00:00:00
如果我们比较一下这篇文章中的所有内容,就会发现以下错误。
- 空 id 而不是正确的 id。
- 计算利润时未考虑佣金和掉期。
- 退出交易被错误地计入平仓数量。
我现在使用 tst 文件来代替设置文件。您可以在它们之间快速切换,不仅有输入参数,还有完整的回溯测试。
遗憾的是,由于 tst 中缺乏毫秒级数据,因此无法将不同的 TS 组合到一个投资组合中。
我希望开发人员能开始充分利用现有字段。
INT64 TradeDeal::time_create; // 记录创建时间 INT64 TradeOrder::time_setup; // 客户向系统发送订单的时间 INT64 TradeOrder::time_done; // 取消订单的时间
通过用毫秒而不是秒来书写时间值。
总的来说,在实践中,为了展示使用 tst 的所有酷点,并没有给出 tst 非常小的缺陷。应予以纠正。
通常需要更详细地查看单程平衡图。
// 交互式单程平衡图。 #include <fxsaber\SingleTesterCache\SingleTesterCache.mqh> //https://www.mql5.com/zh/code/27611 #include <fxsaber\MultiTester\MTTester.mqh> //https://www.mql5.com/zh/code/26132 #include <..\Files\Graph.mqh> //https://www.mql5.com/zh/code/18801 #import "shell32.dll" int ShellExecuteW( int, string, string, string, string, int ); #import #define BASEPATH (::TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Files\\") bool CreateBalanceData( const SINGLETESTERCACHE &SingleTesterCache, const string FileName = "exdat.txt" ) { const int handle = FileOpen(FileName, FILE_WRITE | FILE_TXT | FILE_ANSI); const bool Res = (handle != INVALID_HANDLE); if (Res) { FileWriteString(handle, "var dat1=[\n"); for (uint i = 0; i < SingleTesterCache.Header.equities_total; i++) FileWriteString(handle, "[" + (string)((long)SingleTesterCache.TradeState[i].time * 1000) + "," + ::DoubleToString(SingleTesterCache.TradeState[i].balance, 2) + "],\n"); FileWriteString(handle, "];\n"); FileWriteString(handle, "var T1=dat1[0][0];\n"); FileWriteString(handle, "var T2=dat1[dat1.length-1][0];\n"); FileWriteString(handle, "var nTrades=dat1.length;\n"); FileWriteString(handle, "var Balance=" + ::DoubleToString(SingleTesterCache.TradeState[SingleTesterCache.Header.equities_total - 1].balance, 2) + ";\n"); FileWriteString(handle, "var Currency=\"" + (SingleTesterCache.Header.trade_pips ? "Pips" : SingleTesterCache.Header.trade_currency[]) + "\";\n"); FileClose(handle); } return(Res); } void OnStart() { uchar Bytes2[]; if (MTTESTER::GetLastTstCache(Bytes2) != -1) // 如果可以读取单次运行的最后一条缓存记录 { const SINGLETESTERCACHE SingleTesterCache(Bytes2); // 将其驱动到相应的对象中。 const string FileName = "Report.htm"; uchar Array[]; if ((StringToCharArray(StrMQH, Array) > 0) && FileSave(FileName, Array) && CreateBalanceData(SingleTesterCache)) ShellExecuteW(0, "Open", BASEPATH + FileName, NULL, NULL, 3); } }
如果我们将
TradeState[i].balance -> TradeState[i].equity
就是一个权益图。
在 tst 中,交易量/订单量的写法不正确。它总是按照SYMBOL_TRADE_CONTRACT_SIZE= 100 000 计算。
如果设置了不同的值,则对 tst 中的交易量值没有影响。
TesterPortfolio - портфель ТС
- www.mql5.com
Возьмем третий пункт. Допустим, взяли несколько приглянувшихся советников из Маркета. Настроили их для каждого символа. TesterPortfolio запустит все варианты одновременно, показав общую торговую статистику (просадка эквити на реальных тиках и т.д.). Чаще всего использую для оценки диверсификации различных настроек своих ТС. Использование. На...
TesterPortfolio - портфель ТС
- 2020.01.16
- www.mql5.com
В приложении советник/робот, который объединяет несколько независимых одиночных проходов MT5-Тестера в один. Сценарии использования. Чужой советник с закрытым исходным кодом не запускается в MT5-Визуализаторе. TesterPortfolio сможет немного помочь. Сбор статистики прямо во время торговли советников с закрытым исходным кодом. Например...
在那里回答。
我不知道在博客上是如何发生的,新评论(如果不是回复)的出现是否有某种信号?还是在新评论可见的论坛主题中发表更好?
他们为什么不在知识库中发布呢?这样更方便。
那么在哪里发布才能得到及时回复呢?


单测试器缓存:
测试仪的单程数据。
Author: fxsaber