RM1/Experts/Advisors/RegressionModels3.mqh
2025-10-15 09:24:04 +02:00

292 lines
No EOL
26 KiB
MQL5

//+------------------------------------------------------------------+
//| RegressionModels3.mqh |
//| |
//| This library implements simple machine learning models for |
//| price prediction, including Logistic and Linear Regression. |
//| |
//+------------------------------------------------------------------+
#property strict
//--- Include files
#include <Indicators\Indicators.mqh>
//+------------------------------------------------------------------+
//| Class for Logistic Regression Model |
//| Predicts the probability of a binary outcome (e.g., up/down). |
//+------------------------------------------------------------------+
class CLogisticRegression
{
private:
double weights[];
double learning_rate;
double lambda;
double learning_decay;
double ema_trend_min;
double ema_trend_max;
double normalized_rsi_min;
double normalized_rsi_max;
double normalized_atr_min;
double normalized_atr_max;
double normalized_pivot_dist_min;
double normalized_pivot_dist_max;
double normalized_volume_min;
double normalized_volume_max;
double normalized_adx_min;
double normalized_adx_max;
double sigmoid(double x)
{
return 1.0 / (1.0 + MathExp(-x));
}
double normalize(double value, double min_value, double max_value)
{
if (max_value - min_value == 0) return 0.5;
return (value - min_value) / (max_value - min_value);
}
public:
CLogisticRegression(double regularization_lambda = 0.002, double decay_factor = 0.999)
{
ArrayResize(weights, 8); // 1 bias + 7 feature
for(int i = 0; i < 8; i++) weights[i] = 0.0;
learning_rate = 0.02;
lambda = regularization_lambda;
learning_decay = decay_factor;
ema_trend_min = -100 * _Point;
ema_trend_max = 100 * _Point;
normalized_rsi_min = 0;
normalized_rsi_max = 100;
normalized_atr_min = 0;
normalized_atr_max = 200;
normalized_pivot_dist_min = 0;
normalized_pivot_dist_max = 500;
normalized_volume_min = 0;
normalized_volume_max = 5;
normalized_adx_min = 0;
normalized_adx_max = 100;
}
double to_sym(double x01) { return 2.0 * x01 - 1.0; };
double PredictAndLearn(
int actual_output,
string symbol, ENUM_TIMEFRAMES period,
int rsi_period, int bollinger_period, double bollinger_dev,
int atr_period, bool enable_ema_filter, ENUM_TIMEFRAMES ema_filter_timeframe,
int ema_fast_period, int ema_slow_period,
double pivot_distance_pips, double volume_ratio, double adx_value)
{
double rsi_value = iRSI(symbol, period, rsi_period, PRICE_CLOSE);
double atr_value = iATR(symbol, period, atr_period);
double current_close = iClose(symbol, period, 0);
double bollinger_upper = iBands(symbol, period, bollinger_period, 0, bollinger_dev, 0);
double bollinger_lower = iBands(symbol, period, bollinger_period, 0, bollinger_dev, 1);
double bollinger_position = 0.5;
if (bollinger_upper > bollinger_lower)
{
bollinger_position = (current_close - bollinger_lower) / (bollinger_upper - bollinger_lower);
}
double ema_fast_val = iMA(symbol, ema_filter_timeframe, ema_fast_period, 0, MODE_EMA, PRICE_CLOSE);
double ema_slow_val = iMA(symbol, ema_filter_timeframe, ema_slow_period, 0, MODE_EMA, PRICE_CLOSE);
double ema_trend_input01 = 0.5;
if(enable_ema_filter && ema_fast_val > 0 && ema_slow_val > 0)
{
if (ema_fast_val - ema_slow_val < ema_trend_min)
ema_trend_min = ema_fast_val - ema_slow_val;
if (ema_fast_val - ema_slow_val > ema_trend_max)
ema_trend_max = ema_fast_val - ema_slow_val;
ema_trend_input01 = normalize(ema_fast_val - ema_slow_val, ema_trend_min, ema_trend_max);
}
// Aggiorna i range dinamici come già fai
if (rsi_value < normalized_rsi_min) normalized_rsi_min = rsi_value;
if (rsi_value > normalized_rsi_max) normalized_rsi_max = rsi_value;
double rsi01 = normalize(rsi_value, normalized_rsi_min, normalized_rsi_max);
double atrp = atr_value / _Point;
if (atrp < normalized_atr_min) normalized_atr_min = atrp;
if (atrp > normalized_atr_max) normalized_atr_max = atrp;
double atr01 = normalize(atrp, normalized_atr_min, normalized_atr_max);
if (pivot_distance_pips < normalized_pivot_dist_min) normalized_pivot_dist_min = pivot_distance_pips;
if (pivot_distance_pips > normalized_pivot_dist_max) normalized_pivot_dist_max = pivot_distance_pips;
double pivot01 = normalize(pivot_distance_pips, normalized_pivot_dist_min, normalized_pivot_dist_max);
if (volume_ratio < normalized_volume_min) normalized_volume_min = volume_ratio;
if (volume_ratio > normalized_volume_max) normalized_volume_max = volume_ratio;
double vol01 = normalize(volume_ratio, normalized_volume_min, normalized_volume_max);
if (adx_value < normalized_adx_min) normalized_adx_min = adx_value;
if (adx_value > normalized_adx_max) normalized_adx_max = adx_value;
double adx01 = normalize(adx_value, normalized_adx_min, normalized_adx_max);
// 1) Centra in [-1,1]
double ema_trend_sym = to_sym(ema_trend_input01);
double rsi_sym = to_sym(rsi01);
double bbpos_sym = to_sym(bollinger_position);
double atr_sym = to_sym(atr01);
double pivot_sym = to_sym(pivot01);
double vol_sym = to_sym(vol01);
double adx_sym = to_sym(adx01);
// 2) Input con bias in testa
double x[8] = {
-1.0, // bias
rsi_sym,
bbpos_sym,
atr_sym,
ema_trend_sym,
pivot_sym,
vol_sym,
adx_sym
};
// 3) Somma pesata e gain di risposta
double weighted_sum = 0.0;
for (int i = 0; i < ArraySize(weights); i++)
weighted_sum += weights[i] * x[i];
const double response_gain = 2.0; // 1.5-3.0 tipicamente
double prediction = sigmoid(response_gain * weighted_sum);
// 4) Aggiorna i pesi con regolarizzazione e decay
double error = actual_output - prediction;
for (int i = 0; i < ArraySize(weights); i++)
{
// weight decay moltiplicativo + gradiente regolarizzato
double grad = error * x[i] - lambda * weights[i];
weights[i] = weights[i] * learning_decay + learning_rate * grad;
}
Print("inputs_logistic", x[1], "/", x[2], "/", x[3], "/", x[4], "/", x[5], "/", x[6], "/", x[7]);
return prediction;
}
double get_probability(string symbol, ENUM_TIMEFRAMES period, int rsi_period, int bollinger_period, double bollinger_dev, int atr_period, bool enable_ema_filter, ENUM_TIMEFRAMES ema_filter_timeframe, int ema_fast_period, int ema_slow_period, double pivot_distance_pips, double volume_ratio, double adx_value)
{
double rsi_value = iRSI(symbol, period, rsi_period, PRICE_CLOSE);
double atr_value = iATR(symbol, period, atr_period);
double current_close = iClose(symbol, period, 0);
double bollinger_upper = iBands(symbol, period, bollinger_period, 0, bollinger_dev, 0);
double bollinger_lower = iBands(symbol, period, bollinger_period, 0, bollinger_dev, 1);
double bollinger_position = 0.5;
if (bollinger_upper > bollinger_lower)
{
bollinger_position = (current_close - bollinger_lower) / (bollinger_upper - bollinger_lower);
}
double ema_fast_val = iMA(symbol, ema_filter_timeframe, ema_fast_period, 0, MODE_EMA, PRICE_CLOSE);
double ema_slow_val = iMA(symbol, ema_filter_timeframe, ema_slow_period, 0, MODE_EMA, PRICE_CLOSE);
double ema_trend_input = 0.5;
if(enable_ema_filter && ema_fast_val > 0 && ema_slow_val > 0)
{
ema_trend_input = normalize(ema_fast_val - ema_slow_val, -100 * _Point, 100 * _Point);
}
double normalized_rsi = normalize(rsi_value, 0, 100);
double normalized_atr = normalize(atr_value / _Point, 0, 200);
double normalized_pivot_dist = normalize(pivot_distance_pips, 0, 500);
double normalized_volume = normalize(volume_ratio, 0, 5);
double normalized_adx = normalize(adx_value, 0, 100);
double inputs_logistic[7] = { normalized_rsi, bollinger_position, normalized_atr, ema_trend_input, normalized_pivot_dist, normalized_volume, normalized_adx };
//Print("inputs_logistic", inputs_logistic[0], "/", inputs_logistic[1], "/", inputs_logistic[2], "/", inputs_logistic[3], "/", inputs_logistic[4], "/", inputs_logistic[5], "/", inputs_logistic[6]);
double weighted_sum = 0.0;
for (int i = 0; i < ArraySize(weights); i++) {
weighted_sum += weights[i] * inputs_logistic[i];
}
return sigmoid(weighted_sum);
}
};
//+------------------------------------------------------------------+
//| Class for Linear Regression Model |
//| Predicts the magnitude of a continuous outcome (e.g., pips). |
//+------------------------------------------------------------------+
class CLinearRegression
{
private:
double weights[];
double learning_rate;
double lambda;
double learning_decay;
double normalize(double value, double min_value, double max_value)
{
if (max_value - min_value == 0) return 0.5;
return (value - min_value) / (max_value - min_value);
}
public:
CLinearRegression(double regularization_lambda = 0.001, double decay_factor = 0.999)
{
ArrayResize(weights, 7); // 6 + 1 per il ADX
for(int i = 0; i < 7; i++) weights[i] = 0.0;
learning_rate = 0.01;
lambda = regularization_lambda;
learning_decay = decay_factor;
}
double PredictAndLearn(double actual_output_magnitude_in_pips, string symbol, ENUM_TIMEFRAMES period, int rsi_period, int bollinger_period, double bollinger_dev, int atr_period, bool enable_ema_filter, ENUM_TIMEFRAMES ema_filter_timeframe, int ema_fast_period, int ema_slow_period, double pivot_distance_pips, double volume_ratio, double adx_value)
{
double rsi_value = iRSI(symbol, period, rsi_period, PRICE_CLOSE);
double atr_value = iATR(symbol, period, atr_period);
double current_close = iClose(symbol, period, 0);
double bollinger_upper = iBands(symbol, period, bollinger_period, 0, bollinger_dev, 0);
double bollinger_lower = iBands(symbol, period, bollinger_period, 0, bollinger_dev, 1);
double bollinger_position = 0.5;
if (bollinger_upper > bollinger_lower)
{
bollinger_position = (current_close - bollinger_lower) / (bollinger_upper - bollinger_lower);
}
double ema_fast_val = iMA(symbol, ema_filter_timeframe, ema_fast_period, 0, MODE_EMA, PRICE_CLOSE);
double ema_slow_val = iMA(symbol, ema_filter_timeframe, ema_slow_period, 0, MODE_EMA, PRICE_CLOSE);
double ema_trend_input = 0.5;
if(enable_ema_filter && ema_fast_val > 0 && ema_slow_val > 0)
{
ema_trend_input = normalize(ema_fast_val - ema_slow_val, -100 * _Point, 100 * _Point);
}
double normalized_rsi = normalize(rsi_value, 0, 100);
double normalized_atr = normalize(atr_value / _Point, 0, 200);
double normalized_pivot_dist = normalize(pivot_distance_pips, 0, 500);
double normalized_volume = normalize(volume_ratio, 0, 5);
double normalized_adx = normalize(adx_value, 0, 100);
double inputs_linear[7] = { normalized_rsi, bollinger_position, normalized_atr, ema_trend_input, normalized_pivot_dist, normalized_volume, normalized_adx };
//Print("inputs_linear", inputs_linear[0], "/", inputs_linear[1], "/", inputs_linear[2], "/", inputs_linear[3], "/", inputs_linear[4], "/", inputs_linear[5], "/", inputs_linear[6]);
double prediction = 0.0;
for (int i = 0; i < ArraySize(weights); i++) {
prediction += weights[i] * inputs_linear[i];
}
double error = actual_output_magnitude_in_pips - prediction;
for (int i = 0; i < ArraySize(weights); i++)
{
weights[i] = weights[i] * learning_decay + learning_rate * (error * inputs_linear[i] - lambda * weights[i]);
}
return prediction;
}
};