//+------------------------------------------------------------------+ //| StdBase.mqh | //| Copyright 2026, Leo. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Leo." #property link "https://www.mql5.com/en/users/nique_372" #property strict #ifndef SCALERBYLEO_SRC_SCALER_STD_STDBASE_MQH #define SCALERBYLEO_SRC_SCALER_STD_STDBASE_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "..\\ScalerBase.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| Standardization Scaler | //+------------------------------------------------------------------+ template class StandardizationScalerBase : public ScalerBase { protected: vector m_mean, m_std, m_std_inv; virtual bool OnLoad() { return true; } public: StandardizationScalerBase() : ScalerBase() { m_prefix_file = "_mean_std.csv"; } //--- bool Save(string prefix_name, int extra_file_flags = FILE_COMMON); bool LoadByFile(string prefix_name, int extra_file_flags = FILE_COMMON); bool LoadByArr(const string &arr[]) override; //--- bool Fit(const matrix &X); }; //+------------------------------------------------------------------+ //| Save / Load | //+------------------------------------------------------------------+ template bool StandardizationScalerBase::Save(string prefix_name, int extra_file_flags = FILE_COMMON) { //--- m_file_name_out = prefix_name + m_prefix_file; FileDelete(m_file_name_out); ResetLastError(); //--- const int handle = FileOpen(m_file_name_out, FILE_WRITE | FILE_CSV | extra_file_flags); if(handle == INVALID_HANDLE) { m_last_err = SCALERBYLEO_ERR_FILE_OPEN; return false; } //--- FileWrite(handle, vector_to_string(m_std)); FileWrite(handle, vector_to_string(m_mean)); FileWrite(handle, m_i_start); FileWrite(handle, m_i_count); //--- FileClose(handle); return true; } //+------------------------------------------------------------------+ template bool StandardizationScalerBase::LoadByFile(string prefix_name, int extra_file_flags = FILE_COMMON) { //--- m_file_name_out = prefix_name + m_prefix_file; //--- ResetLastError(); const int handle = FileOpen(m_file_name_out, FILE_READ | FILE_CSV | extra_file_flags, "\n"); if(handle == INVALID_HANDLE) { m_last_err = SCALERBYLEO_ERR_FILE_OPEN; return false; } //--- CStringFunc::ToVector(FileReadString(handle), m_std, ','); CStringFunc::ToVector(FileReadString(handle), m_mean, ','); m_i_start = ulong(FileReadString(handle)); m_i_count = long(FileReadString(handle)); //--- m_std_inv = 1.0 / m_std; //--- FileClose(handle); return (m_loaded_scaler = OnLoad()); } //+------------------------------------------------------------------+ template bool StandardizationScalerBase::LoadByArr(const string &arr[]) { if(ArraySize(arr) < 4) { m_last_err = SCALERBYLEO_ERR_INVALID_DATA; return false; } //--- int p = 0; CStringFunc::ToVector(arr[p++], m_std, ','); CStringFunc::ToVector(arr[p++], m_mean, ','); m_i_start = ulong(arr[p++]); m_i_count = long(arr[p++]); //--- m_std_inv = 1.0 / m_std; //--- return (m_loaded_scaler = OnLoad()); } //+------------------------------------------------------------------+ //| Fit | //+------------------------------------------------------------------+ template bool StandardizationScalerBase::Fit(const matrix &X) { //--- const ulong total_cols = X.Cols(); const ulong rows = X.Rows(); if(total_cols == 0 || rows == 0) { m_last_err = SCALERBYLEO_ERR_EMPTY_INPUT; return false; } if(m_i_start >= total_cols) { m_last_err = SCALERBYLEO_ERR_INVALID_RANGE; return false; } //--- const ulong fs = SCALERBYLEO_SIZE(total_cols); const double rows_inv = 1.0 / double(rows); //--- m_mean.Resize(fs); m_std.Resize(fs); m_std_inv.Resize(fs); //--- for(ulong c = 0; c < fs; c++) { //--- media de la columna c (double, sin importar TFlt) double sum = 0.0; for(ulong r = 0; r < rows; r++) sum += X[r][m_i_start + c]; const double mean_v = sum * rows_inv; //--- varianza de la columna c double sq = 0.0; for(ulong r = 0; r < rows; r++) { const double d = X[r][m_i_start + c] - mean_v; sq += d * d; } const double std_v = MathSqrt(sq * rows_inv); //--- if(std_v < SCALER_BASE_MIN_VALUE) { m_last_err = SCALERBYLEO_ERR_DEGENERATE_SCALE; return false; } //--- m_mean[c] = mean_v; m_std[c] = std_v; m_std_inv[c] = 1.0 / std_v; } //--- return (m_loaded_scaler = OnLoad()); } } #endif // SCALERBYLEO_SRC_SCALER_STD_STDBASE_MQH //+------------------------------------------------------------------+