Article-22745-Categorical-H.../Scripts/ModelSelection.mq5

140 lines
5.3 KiB
MQL5
Raw Permalink Normal View History

2026-06-02 13:36:51 +03:00
//+------------------------------------------------------------------+
//| ModelSelection.mq5 |
//| Eugene |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Eugene"
#property link "https://www.mql5.com"
#property version "1.00"
#include <CategoricalHMM\CategoricalHMM.mqh>
#include <Graphics\Graphic.mqh>
//+------------------------------------------------------------------+
//| 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);
}
//+------------------------------------------------------------------+