| #resource "Python/model.onnx" as uchar ExtModel[]// model as a resource
 #define TESTS 10000  // number of test datasets
 //+------------------------------------------------------------------+
 //| Script program start function                                    |
 //+------------------------------------------------------------------+
 int OnStart()
 {
 //--- create the model
 long session_handle=OnnxCreateFromBuffer(ExtModel,ONNX_DEBUG_LOGS);
 if(session_handle==INVALID_HANDLE)
 {
 Print("Cannot create model. Error ",GetLastError());
 return(-1);
 }
 
 //--- since the input tensor size is not defined for the model, specify it explicitly
 //--- first index is batch size, second index is series size, third index is number of series (OHLC)
 const long input_shape[]={1,10,4};
 if(!OnnxSetInputShape(session_handle,0,input_shape))
 {
 Print("OnnxSetInputShape error ",GetLastError());
 return(-2);
 }
 
 //--- since the output tensor size is not defined for the model, specify it explicitly
 //--- first index is batch size, must match the batch size in the input tensor
 //--- second index is number of predicted prices (only Close is predicted here)
 const long output_shape[]={1,1};
 if(!OnnxSetOutputShape(session_handle,0,output_shape))
 {
 Print("OnnxSetOutputShape error ",GetLastError());
 return(-3);
 }
 //--- run tests
 vector closes(TESTS);      // vector to store validation prices
 vector predicts(TESTS);    // vector to store obtained predictions
 vector prev_closes(TESTS); // vector to store preceding prices
 
 matrix rates;              // matrix to get the OHLC series
 matrix splitted[2];        // two submatrices to divide the series into test and validation
 ulong  parts[]={10,1};     // sizes of divided submatrices
 
 //--- start from the previous bar
 for(int i=1; i<=TESTS; i++)
 {
 //--- get 11 bars
 rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,i,11);
 //--- divide the matrix into test and validation
 rates.Vsplit(parts,splitted);
 //--- take the Close price from the validation matrix
 closes[i-1]=splitted[1][3][0];
 //--- last Close in the tested series
 prev_closes[i-1]=splitted[0][3][9];
 
 //--- submit the test matrix of 10 bars to testing
 predicts[i-1]=PricePredictionTest(session_handle,splitted[0]);
 //--- runtime error
 if(predicts[i-1]<=0)
 {
 OnnxRelease(session_handle);
 return(-4);
 }
 }
 //--- complete operation
 OnnxRelease(session_handle);
 //--- evaluate if price movement was predicted correctly
 int    right_directions=0;
 vector delta_predicts=prev_closes-predicts;
 vector delta_actuals=prev_closes-closes;
 
 for(int i=0; i<TESTS; i++)
 if((delta_predicts[i]>0 && delta_actuals[i]>0) || (delta_predicts[i]<0 && delta_actuals[i]<0))
 right_directions++;
 PrintFormat("right direction predictions = %.2f%%",(right_directions*100.0)/double(TESTS));
 //---
 return(0);
 }
 //+------------------------------------------------------------------+
 //|  Prepare the data and run the model                              |
 //+------------------------------------------------------------------+
 double PricePredictionTest(const long session_handle,matrix& rates)
 {
 static matrixf input_data(10,4); // matrix for the transformed input
 static vectorf output_data(1);   // vector to receive the result
 static matrix mm(10,4);          // matrix of horizontal vectors Mean
 static matrix ms(10,4);          // matrix of horizontal vectors Std
 
 //--- a set of OHLC vertical vectors must be input into the model
 matrix x_norm=rates.Transpose();
 //--- normalize prices
 vector m=x_norm.Mean(0);
 vector s=x_norm.Std(0);
 for(int i=0; i<10; i++)
 {
 mm.Row(m,i);
 ms.Row(s,i);
 }
 x_norm-=mm;
 x_norm/=ms;
 
 //--- run the model
 input_data.Assign(x_norm);
 if(!OnnxRun(session_handle,ONNX_DEBUG_LOGS,input_data,output_data))
 {
 Print("OnnxRun error ",GetLastError());
 return(0);
 }
 //--- unnormalize the price from the output value
 double y_pred=output_data[0]*s[3]+m[3];
 
 return(y_pred);
 }
 |