运行策略测试
策略测试中的模型验证
为金融市场操作创建的模型可以在 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年是正确的。

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