190 lines
No EOL
6.4 KiB
MQL5
190 lines
No EOL
6.4 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ExtraTreeRegressor.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 ModelName "ExtraTreeRegressor"
|
|
#define ONNXFilenameFloat "models\\extra_tree_regressor_float.onnx"
|
|
#define ONNXFilenameDouble "models\\extra_tree_regressor_double.onnx"
|
|
|
|
#resource ONNXFilenameFloat as const uchar ExtModelFloat[];
|
|
#resource ONNXFilenameDouble as const uchar ExtModelDouble[];
|
|
|
|
#define TestFloatModel 1
|
|
#define TestDoubleModel 2
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate regression using float values |
|
|
//+------------------------------------------------------------------+
|
|
bool RunModelFloat(long model,vector &input_vector, vector &output_vector)
|
|
{
|
|
//--- check number of input samples
|
|
ulong batch_size=input_vector.Size();
|
|
if(batch_size==0)
|
|
return(false);
|
|
//--- prepare output array
|
|
output_vector.Resize((int)batch_size);
|
|
//--- prepare input tensor
|
|
float input_data[];
|
|
ArrayResize(input_data,(int)batch_size);
|
|
//--- set input shape
|
|
ulong input_shape[]= {batch_size, 1};
|
|
OnnxSetInputShape(model,0,input_shape);
|
|
//--- copy data to the input tensor
|
|
for(int k=0; k<(int)batch_size; k++)
|
|
input_data[k]=(float)input_vector[k];
|
|
//--- prepare output tensor
|
|
float output_data[];
|
|
ArrayResize(output_data,(int)batch_size);
|
|
//--- set output shape
|
|
ulong output_shape[]= {batch_size,1};
|
|
OnnxSetOutputShape(model,0,output_shape);
|
|
//--- run the model
|
|
bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output_data);
|
|
//--- copy output to vector
|
|
if(res)
|
|
{
|
|
for(int k=0; k<(int)batch_size; k++)
|
|
output_vector[k]=output_data[k];
|
|
}
|
|
//---
|
|
return(res);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate regression using double values |
|
|
//+------------------------------------------------------------------+
|
|
bool RunModelDouble(long model,vector &input_vector, vector &output_vector)
|
|
{
|
|
//--- check number of input samples
|
|
ulong batch_size=input_vector.Size();
|
|
if(batch_size==0)
|
|
return(false);
|
|
//--- prepare output array
|
|
output_vector.Resize((int)batch_size);
|
|
//--- prepare input tensor
|
|
double input_data[];
|
|
ArrayResize(input_data,(int)batch_size);
|
|
//--- set input shape
|
|
ulong input_shape[]= {batch_size, 1};
|
|
OnnxSetInputShape(model,0,input_shape);
|
|
//--- copy data to the input tensor
|
|
for(int k=0; k<(int)batch_size; k++)
|
|
input_data[k]=input_vector[k];
|
|
//--- prepare output tensor
|
|
double output_data[];
|
|
ArrayResize(output_data,(int)batch_size);
|
|
//--- set output shape
|
|
ulong output_shape[]= {batch_size,1};
|
|
OnnxSetOutputShape(model,0,output_shape);
|
|
//--- run the model
|
|
bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output_data);
|
|
//--- copy output to vector
|
|
if(res)
|
|
{
|
|
for(int k=0; k<(int)batch_size; k++)
|
|
output_vector[k]=output_data[k];
|
|
}
|
|
//---
|
|
return(res);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate synthetic data |
|
|
//+------------------------------------------------------------------+
|
|
bool GenerateData(const int n,vector &x,vector &y)
|
|
{
|
|
if(n<=0)
|
|
return(false);
|
|
//--- prepare arrays
|
|
x.Resize(n);
|
|
y.Resize(n);
|
|
//---
|
|
for(int i=0; i<n; i++)
|
|
{
|
|
x[i]=(double)1.0*i;
|
|
y[i]=(double)(4*x[i] + 10*sin(x[i]*0.5));
|
|
}
|
|
//---
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| TestRegressionModel |
|
|
//+------------------------------------------------------------------+
|
|
bool TestRegressionModel(const string model_name,const int model_type)
|
|
{
|
|
//---
|
|
long model=INVALID_HANDLE;
|
|
ulong flags=ONNX_DEFAULT;
|
|
|
|
if(model_type==TestFloatModel)
|
|
{
|
|
PrintFormat("\nTesting ONNX float: %s (%s)",model_name,ONNXFilenameFloat);
|
|
model=OnnxCreateFromBuffer(ExtModelFloat,flags);
|
|
}
|
|
else
|
|
if(model_type==TestDoubleModel)
|
|
{
|
|
PrintFormat("\nTesting ONNX double: %s (%s)",model_name,ONNXFilenameDouble);
|
|
model=OnnxCreateFromBuffer(ExtModelDouble,flags);
|
|
}
|
|
else
|
|
{
|
|
PrintFormat("Model type is not incorrect.");
|
|
return(false);
|
|
}
|
|
//--- check
|
|
if(model==INVALID_HANDLE)
|
|
{
|
|
PrintFormat("model_name=%s OnnxCreate error %d",model_name,GetLastError());
|
|
return(false);
|
|
}
|
|
//---
|
|
vector x_values= {};
|
|
vector y_true= {};
|
|
vector y_predicted= {};
|
|
//---
|
|
int n=100;
|
|
GenerateData(n,x_values,y_true);
|
|
//---
|
|
bool run_result=false;
|
|
if(model_type==TestFloatModel)
|
|
{
|
|
run_result=RunModelFloat(model,x_values,y_predicted);
|
|
}
|
|
else
|
|
if(model_type==TestDoubleModel)
|
|
{
|
|
run_result=RunModelDouble(model,x_values,y_predicted);
|
|
}
|
|
//---
|
|
if(run_result)
|
|
{
|
|
PrintFormat("MQL5: R-Squared (Coefficient of determination): %.16f",y_predicted.RegressionMetric(y_true,REGRESSION_R2));
|
|
PrintFormat("MQL5: Mean Absolute Error: %.16f",y_predicted.RegressionMetric(y_true,REGRESSION_MAE));
|
|
PrintFormat("MQL5: Mean Squared Error: %.16f",y_predicted.RegressionMetric(y_true,REGRESSION_MSE));
|
|
}
|
|
else
|
|
PrintFormat("Error %d",GetLastError());
|
|
//--- release model
|
|
OnnxRelease(model);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Script program start function |
|
|
//+------------------------------------------------------------------+
|
|
int OnStart(void)
|
|
{
|
|
//--- test ONNX regression model for float
|
|
TestRegressionModel(ModelName,TestFloatModel);
|
|
//--- test ONNX regression model for double
|
|
TestRegressionModel(ModelName,TestDoubleModel);
|
|
//---
|
|
return(0);
|
|
}
|
|
//+------------------------------------------------------------------+ |