策略测试中的模型验证

为金融市场操作创建的模型可以在 MetaTrader 5程序端策略测试部分进行验证。这是最快、最方便的选项,无需额外模拟市场环境和交易条件。

若要测试模型,需要根据公共项目ONNX.Price.Prediction的代码创建一个EA交易程序。这将需要进行一些编辑。

将模型创建移至OnInit函数。onnx会话将在OnDeinit中关闭。将主要模型操作块定位到OnTick处理程序。

此外,添加获取前两个柱形图的收盘价,需要与实际收盘价和预测收盘价进行比较。

Expert Advisor 代码小且易于阅读。

const long   ExtInputShape [] = {1,10,4}; // 模型输入形状

const long   ExtOutputShape[] = {1,1};    // 模型输出形状

#resource "Python/model.onnx" as uchar ExtModel[];// 作为资源的模型



long handle;         // 模型句柄

ulong predictions=0; // 预测计数器

ulong confirmed=0;   // 成功预测计数器

//+------------------------------------------------------------------+

//| EA交易初始化函数                                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

//--- 基本检查

   if(_Symbol!="EURUSD")

     {

      Print("Symbol must be EURUSD, testing aborted");

      return(-1);

     }

   if(_Period!=PERIOD_H1)

     {

      Print("Timeframe must be H1, testing aborted");

      return(-1);

     }

//--- 创建模型

   handle=OnnxCreateFromBuffer(ExtModel,ONNX_DEBUG_LOGS);

//--- 指定输入数据形状

   if(!OnnxSetInputShape(handle,0,ExtInputShape))

     {

      Print("OnnxSetInputShape failed, error ",GetLastError());

      OnnxRelease(handle);

      return(-1);

     }

//--- 指定输出数据形状

   if(!OnnxSetOutputShape(handle,0,ExtOutputShape))

     {

      Print("OnnxSetOutputShape failed, error ",GetLastError());

      OnnxRelease(handle);

      return(-1);

     }

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| EA交易去初始化函数                                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//--- 完成模型操作

   OnnxRelease(handle);

//--- 计算和输出预测统计

   PrintFormat("Successfull predictions = %.2f %%",confirmed*100./double(predictions));

  }

//+------------------------------------------------------------------+

//| EA报价函数                                                        |

//+------------------------------------------------------------------+

void OnTick()

  {

   static datetime open_time=0;

   static double predict;

//--- 检查当前柱形图开盘时间

   datetime time=iTime(_Symbol,_Period,0);

   if(time==0)

     {

      PrintFormat("Failed to get Time(0), error %d", GetLastError());

      return;

     }

//--- 如果开盘时间没有改变,则退出直至下一次OnTick调用

   if(time==open_time)

      return;

//--- 获取最后两个已完成柱形图的收盘价

   double close[];

   int recieved=CopyClose(_Symbol,_Period,1,2,close);

   if(recieved!=2)

     {

      PrintFormat("CopyClose(2 bars) failed, error %d",GetLastError());

      return;

     }

   double delta_predict=predict-close[0]; // predicted price change

   double delta_actual=close[1]-close[0]; // actual price change

   if((delta_predict>0 && delta_actual>0) || (delta_predict<0 && delta_actual<0))

      confirmed++;



//--- 计算新柱形图上的收盘价,以验证下一个柱形图上的价格

   matrix rates;

//--- 获取10个柱形图

   if(!rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,1,10))

      return;

//--- 输入一组OHLC向量

   matrix x_norm=rates.Transpose();

   vector m=x_norm.Mean(0);

   vector s=x_norm.Std(0);

   matrix mm(10,4);

   matrix ms(10,4);

//--- 填充归一化矩阵

   for(int i=0; i<10; i++)

     {

      mm.Row(m,i);

      ms.Row(s,i);

     }

//--- 标准化输入数据

   x_norm-=mm;

   x_norm/=ms;

//--- 将标准化输入数据转换为浮点类型

   matrixf x_normf;

   x_normf.Assign(x_norm);

//--- 在这里获取模型的输出数据,即价格预测

   vectorf y_norm(1);

//--- 运行模型

   if(!OnnxRun(handle,ONNX_DEBUG_LOGS | ONNX_NO_CONVERSION,x_normf,y_norm))

     {

      Print("OnnxRun failed, error ",GetLastError());

     }

//--- 进行反向转换,以获得预测价格并在新柱形图上对其验证

   predict=y_norm[0]*s[3]+m[3];

   predictions++;  // 增加预测计数器

   Print(predictions,". close prediction = ",predict);

//--- 保存柱形图开盘时间,以检查下一个报价

   open_time=time;

  }

 

编译EA交易,并在2022年期间运行测试。使用H1时间周期指定EURUSD,这是训练模型的数据。可以忽略报价建模模式,因为代码检查的是新柱形图的出现。 

运行并在测试日志中查看结果。它表明略高于50%的预测在2022年是正确的。

如果初步模型测试产生令人满意的结果,您可以开始基于此模型编写完整的交易策略。