| //+------------------------------------------------------------------+
|
| //| 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"
|
| #resource "Python/model.onnx" as uchar ExtModel[]
|
| #define SAMPLE_SIZE 10 // bars count in sample as defined in Python\PricePredictionTraining.py
|
| // X, y = collect_dataset(df, history_size=10)
|
|
|
| //+------------------------------------------------------------------+
|
| //| 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(ExtModel,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[3]+m[3];
|
|
|
| Print("predicted: ",y_pred);
|
| //--- finalize
|
| OnnxRelease(handle);
|
| return(0);
|
| }
|
| //+------------------------------------------------------------------+
|