194 lines
5.6 KiB
MQL5
194 lines
5.6 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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<typename TFlt>
|
|
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<TFlt> &X);
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Save / Load |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
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<typename TFlt>
|
|
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<double, CStringConvert>(FileReadString(handle), m_std, ',');
|
|
CStringFunc::ToVector<double, CStringConvert>(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<typename TFlt>
|
|
bool StandardizationScalerBase::LoadByArr(const string &arr[])
|
|
{
|
|
if(ArraySize(arr) < 4)
|
|
{
|
|
m_last_err = SCALERBYLEO_ERR_INVALID_DATA;
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
int p = 0;
|
|
CStringFunc::ToVector<double, CStringConvert>(arr[p++], m_std, ',');
|
|
CStringFunc::ToVector<double, CStringConvert>(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<typename TFlt>
|
|
bool StandardizationScalerBase::Fit(const matrix<TFlt> &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
|
|
//+------------------------------------------------------------------+
|