//+------------------------------------------------------------------+ //| ModelSelection.mq5 | //| Eugene | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Eugene" #property link "https://www.mql5.com" #property version "1.00" #include #include //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { int n_samples = 5000; int n_states_true = 3; int n_emissions = 6; // --- 1. ИНИЦИАЛИЗАЦИЯ ИСТИННОЙ МОДЕЛИ ДЛЯ ГЕНЕРАЦИИ --- matrix tr_true = { {0.8, 0.1, 0.1}, {0.05, 0.9, 0.05}, {0.1, 0.1, 0.8} }; matrix e_true = { {1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6}, {0.1, 0.1, 0.1, 0.1, 0.1, 0.5}, {0.4, 0.1, 0.1, 0.1, 0.1, 0.2} }; vector y, states_true; CCategoricalHMM gen_model(n_states_true, n_emissions, 42); // Seed 42 gen_model.Sample(n_samples, tr_true, e_true, y, states_true); //VectorToCSV("Sample5000.csv",y); // --- РАСЧЕТ ИСТИННОГО LOG-LIKELIHOOD --- double true_ll = 0; matrix p_true, fs_true, bs_true; vector s_true; // --- Вызываем Inference на истинных параметрах --- gen_model.Inference(y, tr_true, e_true, p_true, true_ll, fs_true, bs_true, s_true); PrintFormat("=================================================="); PrintFormat("TRUE MODEL LOG-LIKELIHOOD: %.2f", true_ll); PrintFormat("=================================================="); // --- 2. ПОДБОР МОДЕЛИ (MODEL SELECTION) --- int ns[] = {1,2, 3, 4, 5, 6, 7}; int n_fits = 10; int n_points = ArraySize(ns); double x_vals[], aic_vals[], bic_vals[]; // Массивы для графика ArrayResize(x_vals, n_points); ArrayResize(aic_vals, n_points); ArrayResize(bic_vals, n_points); Print("=================================================="); Print("HMM MODEL SELECTION "); PrintFormat("True States: %d | Samples: %d", n_states_true, n_samples); Print("=================================================="); for(int i = 0; i < ArraySize(ns); i++) { int n_curr = ns[i]; double best_ll = -DBL_MAX; int n_params; // --- Пробуем несколько случайных стартов для каждого N --- for(int fit = 0; fit < n_fits; fit++) { CCategoricalHMM model(n_curr, n_emissions, fit); n_params = model.GetParams(); // --- Обучаем (20 итераций для быстрой оценки) --- if(!model.Fit(y, 20, 1e-4,false)) continue; // --- Получаем Log-Likelihood --- double current_ll = 0; matrix p, fs, bs; vector s; if(model.Inference(y, model.m_TR, model.m_E, p, current_ll, fs, bs, s)) { if(current_ll > best_ll) best_ll = current_ll; } } // --- Оценка информационных критериев для лучшей попытки в текущем N --- CCategoricalHMM eval_model(n_curr, n_emissions); double val_aic = eval_model.AIC(best_ll); double val_bic = eval_model.BIC(best_ll, n_samples); // --- Сохраняем данные для графика --- x_vals[i] = n_curr; aic_vals[i] = val_aic; bic_vals[i] = val_bic; PrintFormat("N=%d | LL: %.2f | AIC: %.2f | BIC: %.2f | n_params:%d", n_curr, best_ll, val_aic, val_bic,n_params); } Print("=================================================="); // --- ВИЗУАЛИЗАЦИЯ --- ChartSetInteger(0, CHART_SHOW, false); CGraphic graphic; ulong width = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS); ulong height = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS); if(ObjectFind(0, "HMM_Selection_Plot") < 0) graphic.Create(0, "HMM_Selection_Plot", 0, 0, 0, int(width), int(height)); else graphic.Attach(0, "HMM_Selection_Plot"); CCurve *curveAIC = graphic.CurveAdd(x_vals, aic_vals, ColorToARGB(clrDodgerBlue, 255), CURVE_POINTS_AND_LINES, "AIC"); curveAIC.LinesStyle(STYLE_SOLID); CCurve *curveBIC = graphic.CurveAdd(x_vals, bic_vals, ColorToARGB(clrLimeGreen, 255), CURVE_POINTS_AND_LINES, "BIC"); curveBIC.LinesStyle(STYLE_SOLID); graphic.BackgroundMainColor(ColorToARGB(clrBlack, 255)); graphic.BackgroundMainSize(24); graphic.BackgroundMain("HMM Model Selection (AIC vs BIC)"); graphic.XAxis().Name("Number of States"); graphic.XAxis().NameSize(18); graphic.YAxis().Name("AIC/BIC Value (Lower is Better)"); graphic.YAxis().NameSize(18); graphic.CurvePlotAll(); graphic.Update(); Sleep(10000); ChartSetInteger(0, CHART_SHOW, true); graphic.Destroy(); ChartRedraw(0); } //+------------------------------------------------------------------+