优化结果的可视化评估

问题解决步骤

由于我们必须修改智能交易系统的代码,然而我们要尽量减少这些修改。

  • 因此,整个数据收集代码将在单独的包含文件 SkrShotOpt.mqh 中实现,而自定义准则将在 CustomCriterion.mqh 文件中计算。

  • ScreenShotOptimization.mq5 屏幕截图将绘制图形,并保存屏幕截图。

因此,我们只需要在智能交易系统中添加几行代码。

1. 收集数据。 SkrShotOpt.mqh

净值的最大值和最小值将在 OnTick() 函数里写入。 double _Equity = AccountInfoDouble(ACCOUNT_EQUITY); if(tempEquityMax < _Equity) tempEquityMax = _Equity; if(tempEquityMin > _Equity) tempEquityMin = _Equity; 为了避免每次即时报价来临时都要检查持仓变化,我们将在 OnTradeTransaction() 函数中跟踪持仓变化 void IsOnTradeTransaction(const MqlTradeTransaction & trans, const MqlTradeRequest & request, const MqlTradeResult & result) { if(trans.type == TRADE_TRANSACTION_DEAL_ADD) if(HistoryDealSelect(trans.deal)) { if(_deal_entry != DEAL_ENTRY_OUT && _deal_entry != DEAL_ENTRY_OUT_BY) _deal_entry = HistoryDealGetInteger(trans.deal, DEAL_ENTRY); if(trans.deal_type == DEAL_TYPE_BUY || trans.deal_type == DEAL_TYPE_SELL) if(_deal_entry == DEAL_ENTRY_IN || _deal_entry == DEAL_ENTRY_OUT || _deal_entry == DEAL_ENTRY_INOUT || _deal_entry == DEAL_ENTRY_OUT_BY) allowed = true; } } 当开仓成交的数量发生变化时,填写余额和净值数组。 if(allowed) // if there was a trade { double accBalance = AccountInfoDouble(ACCOUNT_BALANCE); double accEquity = AccountInfoDouble(ACCOUNT_EQUITY); ArrayResize(balance, _size + 1); ArrayResize(equity, _size + 1); balance[_size] = accBalance; if(_deal_entry != DEAL_ENTRY_OUT && _deal_entry != DEAL_ENTRY_OUT_BY) // if a new position appeared equity[_size] = accEquity; else // if position closed { if(changesB < accBalance) equity[_size] = tempEquityMin; else switch(s_view) { case min_max_E: equity[_size] = tempEquityMax; break; default: equity[_size] = tempEquityMin; break; } tempEquityMax = accEquity; tempEquityMin = accEquity; } _size = _size + 1; changesPos = PositionsTotal(); changesB = accBalance; _deal_entry = -1; allowed = false; }

含有帧数据的文件大小是有限的。 如果有多笔交易,文件大小会增加,处理起来会很困难。 因此,只应向其写入最必要的信息。

交易开始时,写入余额和净值数额:

  • 交易完成后,如果成交以亏损了结,则写入最大净值数额

  • 如果成交以盈利了结,则写入最少净值数额。

因此,几乎所有成交都有四个数组值:开盘时的余额和净值、收盘时的余额和最大/最小净值。

也许会出现在一次即时报价期间,一笔持仓被平仓,然后另开一笔新仓的情况。 在此情况下,只会写入一笔持仓。 这不会影响图形的可视化,同时大大减少了数组。

将收集的数据保存到文件

收集可盈利的优化通测才有意义。 此参数在设置中实现,因此,如果您有需要,可以另外登记亏损通测。 至于前向通测,它们也都会有记录。

在每次测试结束时,会触发测试器事件,此时利用 FrameAdd() 函数,把收集到的数据将写入一个文件。 而测试器事件由 OnTester() 函数处理。

 
 

bool FrameAdd( const string name, // public name/tag long id, // public id double value, // value const void& data[] // array of any type );

此处提供了一个关于如何使用 FrameAdd() 函数的详细且清晰的示例:Визуализируй стратегию в тестере MetaTrader 5 - Общее обсуждение - MQL5

由于 FrameAdd() 只能写入一个数组和一个数值,但除了余额和净值之外,传递 ENUM_STATISTICS 枚举的数值之一也很不错,数据将按顺序写入一个数组,而数组大小将写入所传递的 “value” 数值。

 
 

if(id == 1) // if it is a backward pass { // if profit % and the number of trades exceed those specified in the settings, the pass is written into the file if(TesterStatistics(STAT_PROFIT) / TesterStatistics(STAT_INITIAL_DEPOSIT) * 100 > _profit && TesterStatistics(STAT_TRADES) >= trades) { double TeSt[42]; // total number of elements in the ENUM_STATISTICS enumeration is 41 IsRecordStat(TeSt); // writing testing statistics to the array IsCorrect(); // adjusting balance and equity arrays if(m_sort != none) { while((sort)size_sort != none) size_sort++; double LRB[], LRE[], coeff[]; Coeff = Criterion(balance, equity, LRB, LRE, TeSt, coeff, 3);// calculating custom criterion ArrayInsert(balance, equity, _size + 1, 0); // joining balance and equity arrays into one ArrayInsert(balance, TeSt, (_size + 1) * 2, 0); // add to the resulting array the array with the ENUM_STATISTICS data FrameAdd(name, id, _size + 1, balance); // write the frame into the file } else { ArrayInsert(balance, equity, _size + 1, 0); // joining balance and equity arrays into one ArrayInsert(balance, TeSt, (_size + 1) * 2, 0); // add to the resulting array the array with the ENUM_STATISTICS data FrameAdd(name, id, _size + 1, balance); // write the frame into the file } } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值