//+------------------------------------------------------------------+ //| MinMaxBase.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_MINMAX_MINMAXBASE_MQH #define SCALERBYLEO_SRC_SCALER_MINMAX_MINMAXBASE_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "..\\ScalerBase.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| MaxMin Scaler Base | //+------------------------------------------------------------------+ template class MaxMinScalerBase : public ScalerBase { protected: vector m_min_vals, m_diff, m_diff_inv; virtual bool OnLoad() { return true; } public: MaxMinScalerBase() : ScalerBase() { m_prefix_file = "_min_max.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 MaxMinScalerBase::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_diff)); FileWrite(handle, vector_to_string(m_min_vals)); FileWrite(handle, m_i_start); FileWrite(handle, m_i_count); //--- FileClose(handle); return true; } //+------------------------------------------------------------------+ template bool MaxMinScalerBase::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_diff, ','); CStringFunc::ToVector(FileReadString(handle), m_min_vals, ','); m_i_start = ulong(FileReadString(handle)); m_i_count = long(FileReadString(handle)); //--- m_diff_inv = 1.0 / m_diff; //--- FileClose(handle); return (m_loaded_scaler = OnLoad()); } //+------------------------------------------------------------------+ template bool MaxMinScalerBase::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_diff, ','); CStringFunc::ToVector(arr[p++], m_min_vals, ','); m_i_start = ulong(arr[p++]); m_i_count = long(arr[p++]); //--- m_diff_inv = 1.0 / m_diff; //--- return (m_loaded_scaler = OnLoad()); } //+------------------------------------------------------------------+ //| Fit | //+------------------------------------------------------------------+ template bool MaxMinScalerBase::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); //--- m_min_vals.Resize(fs); m_diff.Resize(fs); m_diff_inv.Resize(fs); //--- for(ulong c = 0; c < fs; c++) { //--- min max de la columa c double min_v = DBL_MAX, max_v = -DBL_MAX; for(ulong r = 0; r < rows; r++) { const double v = X[r][m_i_start + c]; if(v < min_v) min_v = v; if(v > max_v) max_v = v; } //--- const double d = max_v - min_v; if(d < SCALER_BASE_MIN_VALUE) { m_last_err = SCALERBYLEO_ERR_DEGENERATE_SCALE; return false; } //--- m_min_vals[c] = min_v; m_diff[c] = d; m_diff_inv[c] = 1.0 / d; } //--- return (m_loaded_scaler = OnLoad()); } } #endif // SCALERBYLEO_SRC_SCALER_MINMAX_MINMAXBASE_MQH //+------------------------------------------------------------------+