forked from renat/ONNX.Price.Prediction
103 lines
7.8 KiB
MQL5
103 lines
7.8 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ONNX.Price.Prediction.mq5 |
|
|
//| Copyright 2023, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
|
|
#define SAMPLE_SIZE 10 // bars count in sample as defined in Python\PricePredictionTraining.py
|
|
// X, y = collect_dataset(df, history_size=10)
|
|
|
|
#resource "Python/model3.onnx" as uchar model[]
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Script for demonstration of identical execution of |
|
|
//| Python\PricePrediction.py and |
|
|
//| ONNX.Price.Prediction.mq5 |
|
|
//+------------------------------------------------------------------+
|
|
int OnStart(void)
|
|
{
|
|
//--- create a model from static buffer
|
|
//--- model.onnx file from resources is represented as const uchar model[89591]
|
|
long handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
|
|
if(handle==INVALID_HANDLE)
|
|
{
|
|
Print("OnnxCreateFromBuffer error ",GetLastError());
|
|
return(-1);
|
|
}
|
|
|
|
//--- since not all sizes defined in the input tensor we must set them explicitly
|
|
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
|
|
const long input_shape[] = {1,SAMPLE_SIZE,4};
|
|
if(!OnnxSetInputShape(handle,0,input_shape))
|
|
{
|
|
Print("OnnxSetInputShape error ",GetLastError());
|
|
OnnxRelease(handle);
|
|
return(-1);
|
|
}
|
|
|
|
//--- since not all sizes defined in the output tensor we must set them explicitly
|
|
//--- first index - batch size, must match the batch size of the input tensor
|
|
//--- second index - number of predicted prices (we only predict Close)
|
|
const long output_shape[] = {1,1};
|
|
if(!OnnxSetOutputShape(handle,0,output_shape))
|
|
{
|
|
Print("OnnxSetOutputShape error ",GetLastError());
|
|
OnnxRelease(handle);
|
|
return(-1);
|
|
}
|
|
|
|
//--- prepare input data
|
|
matrix rates; // matrix to get test sample OHLC
|
|
matrix mm(SAMPLE_SIZE,4); // matrix of horizontal vectors Mean
|
|
matrix ms(SAMPLE_SIZE,4); // matrix of horizontal vectors Std
|
|
matrix x_norm(SAMPLE_SIZE,4); // matrix for prices normalize
|
|
matrixf input_data(SAMPLE_SIZE,4); // matrix for prepared input data
|
|
vectorf output_data(1); // vector to get result
|
|
|
|
//--- request last bars
|
|
if(!rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,1,SAMPLE_SIZE))
|
|
{
|
|
Print("CopyRates error ",GetLastError());
|
|
OnnxRelease(handle);
|
|
return(-1);
|
|
}
|
|
//--- the input of the model must be a set of vertical OHLC vectors
|
|
x_norm=rates.Transpose();
|
|
//Print(x_norm);
|
|
//--- get series Mean
|
|
vector m=x_norm.Mean(0);
|
|
//Print(m);
|
|
//--- get series Std
|
|
vector s=x_norm.Std(0);
|
|
//Print(s);
|
|
//--- prepare matrices for prices normalization
|
|
for(int i=0; i<SAMPLE_SIZE; i++)
|
|
{
|
|
mm.Row(m,i);
|
|
ms.Row(s,i);
|
|
}
|
|
//--- get normalized prices
|
|
x_norm-=mm;
|
|
x_norm/=ms;
|
|
//--- run the inference
|
|
input_data.Assign(x_norm);
|
|
if(!OnnxRun(handle,ONNX_NO_CONVERSION,input_data,output_data))
|
|
{
|
|
Print("OnnxRun error ",GetLastError());
|
|
OnnxRelease(handle);
|
|
return(-1);
|
|
}
|
|
|
|
Print("raw output: ",output_data);
|
|
//--- denormalize the price from the output value
|
|
double y_pred = output_data[0] /* * ((s[1] - s[0]) - (s[0] - s[2])) + ((m[1] - m[0]) - (m[0] - m[2]))*/ ;
|
|
|
|
Print("predicted: ",y_pred);
|
|
//--- finalize
|
|
OnnxRelease(handle);
|
|
return(0);
|
|
}
|
|
//+------------------------------------------------------------------+
|