//+------------------------------------------------------------------+ //| RegressionModels3.mqh | //| | //| This library implements simple machine learning models for | //| price prediction, including Logistic and Linear Regression. | //| | //+------------------------------------------------------------------+ #property strict //--- Include files #include //+------------------------------------------------------------------+ //| 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; } };