453 Zeilen
29 KiB
MQL5
453 Zeilen
29 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ClasesBases.mqh |
|
|
//| Copyright 2025, Niquel Mendoza. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025, Niquel Mendoza."
|
|
#property link "https://www.mql5.com"
|
|
#property strict
|
|
|
|
#ifndef UTILS_FA_CLASES_BASES_MQH
|
|
#define UTILS_FA_CLASES_BASES_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Includes |
|
|
//+------------------------------------------------------------------+
|
|
//--- (CManagerBase | CSpecializedManager)
|
|
#include "Managers.mqh"
|
|
|
|
//--- (CBarControler | CBarControlerFast | CAtr | CAtrOptimized | CAtrOptimizedZero | CAtrOptimizedNonZero | CAtrUltraOptimized)
|
|
#include "Atr.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Clase CDiff - Defines |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_MODE_DIFF
|
|
{
|
|
MODE_DIFF_BY_FIXED_POITNS, // By Points
|
|
MODE_DIFF_BY_ATR // By Atr
|
|
};
|
|
|
|
|
|
//--- Definición del tipo de función para gestionar diferentes modos de cálculo
|
|
typedef void(*FuncionCDiffOnBar)(double atr_mul, double atr_val, double &diff_prev);
|
|
|
|
//--- Función para calcular diferencia basada en ATR
|
|
inline void Diff_OnBarFuncionAtr(double atr_mul, double atr_val, double &diff_prev)
|
|
{
|
|
diff_prev = atr_mul * atr_val;
|
|
}
|
|
|
|
//--- Función para calcular diferencia basada en puntos (no hace nada, ya que se establece al inicializar)
|
|
inline void Diff_OnBarFuncionPoint(double atr_mul, double atr_val, double &diff_prev)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Clase CDiff - Cálculo de diferencia basado en ATR o puntos fijos |
|
|
//+------------------------------------------------------------------+
|
|
/*
|
|
Para usar la clase, solo se puede setear una vez..
|
|
1. llame y configure el modo SetMode
|
|
2. Luego condigura SetAtr y SetMode
|
|
|
|
To use the class, you can only set it once.
|
|
1. Call and set the SetMode mode.
|
|
2. Then set SetAtr and SetMode.
|
|
*/
|
|
|
|
//---
|
|
class CDiff : public CLoggerBase
|
|
{
|
|
private:
|
|
//---
|
|
bool set_atr;
|
|
bool set_point;
|
|
|
|
//---
|
|
int idx; // Índice para ATR
|
|
string symbol; // Símbolo para cálculo de puntos
|
|
double diff; // Valor de diferencia calculado
|
|
ENUM_MODE_DIFF mode_diff; // Modo de cálculo de diferencia
|
|
double mul; // Multiplicador para ATR
|
|
CAtr* atr; // Puntero a objeto ATR
|
|
FuncionCDiffOnBar f; // Puntero a función para cálculo según modo
|
|
static float empty_val; // Valor vacío estático
|
|
bool is_atr; // Flag para indicar si se usa ATR
|
|
|
|
|
|
//---
|
|
inline double GetVal() { return is_atr ? atr[idx] : 0.00; }
|
|
|
|
public:
|
|
CDiff();
|
|
CDiff(const CDiff & diff_);
|
|
|
|
//--- Métodos para configuración
|
|
void SetMode(ENUM_MODE_DIFF mode_diff_);
|
|
void SetAtr(CAtr * atr_, int idx_, double mul_);
|
|
void SetPoint(string symbol_, int min_diff_points_);
|
|
|
|
//--- Método para actualizar en nueva vela
|
|
inline void OnNewBar() { f(mul, GetVal(), diff); }
|
|
|
|
//---
|
|
inline bool AtrIsActivate() const { return is_atr; }
|
|
inline ENUM_MODE_DIFF GetTypeDiff() const { return mode_diff; }
|
|
inline double AtrMul() const { return mul; }
|
|
void AtrMul(double new_value);
|
|
inline CAtr * GetAtrPointer() const { return atr; }
|
|
inline void SetNewDiffAtrValue(const int new_idx);
|
|
inline void DiffPoints(int new_diff_points) { this.diff = new_diff_points * SymbolInfoDouble(this.symbol, SYMBOL_POINT); }
|
|
inline int DiffPoints() const { return (int)(this.diff / SymbolInfoDouble(this.symbol, SYMBOL_POINT)); }
|
|
inline double Diff() const { return diff; }
|
|
};
|
|
|
|
float CDiff::empty_val = 0.00;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor por defecto |
|
|
//+------------------------------------------------------------------+
|
|
CDiff::CDiff(void)
|
|
: idx(0), set_atr(false), set_point(false), diff(0.00), mul(1.00), atr(NULL), f(NULL), is_atr(false)
|
|
{
|
|
// Inicializamos con valores por defecto
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor de copia |
|
|
//+------------------------------------------------------------------+
|
|
CDiff::CDiff(const CDiff &diff_)
|
|
: idx(diff_.idx),
|
|
symbol(diff_.symbol),
|
|
diff(diff_.diff),
|
|
mode_diff(diff_.mode_diff),
|
|
mul(diff_.mul),
|
|
atr(diff_.atr),
|
|
f(diff_.f),
|
|
is_atr(diff_.is_atr),
|
|
set_atr(diff_.set_atr),
|
|
set_point(diff_.set_point)
|
|
{
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Actualiza el valor de diferencia basado en ATR |
|
|
//+------------------------------------------------------------------+
|
|
void CDiff::SetNewDiffAtrValue(const int new_idx)
|
|
{
|
|
if(!is_atr) //Solo estabelcer diff si es atr y es valido
|
|
return;
|
|
this.diff = atr[new_idx] * mul;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Establece el modo de cálculo |
|
|
//+------------------------------------------------------------------+
|
|
void CDiff::SetMode(ENUM_MODE_DIFF mode_diff_)
|
|
{
|
|
//-- No permitir cambiar el modo si ya está configurado
|
|
if(set_atr || set_point) //Si ya se ha establecido un modo enotnces no permitir
|
|
return;
|
|
|
|
this.mode_diff = mode_diff_;
|
|
this.is_atr = (mode_diff_ == MODE_DIFF_BY_ATR);
|
|
|
|
//-- Asignar la función adecuada según el modo
|
|
if(mode_diff_ == MODE_DIFF_BY_ATR)
|
|
f = Diff_OnBarFuncionAtr;
|
|
else
|
|
f = Diff_OnBarFuncionPoint;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Cambia el multiplicador ATR |
|
|
//+------------------------------------------------------------------+
|
|
void CDiff::AtrMul(double new_value)
|
|
{
|
|
if(!set_atr) //Si no se ha seteado el atr, retun
|
|
return;
|
|
|
|
//--
|
|
this.mul = new_value;
|
|
|
|
//--
|
|
if(mul <= 0.00)
|
|
{
|
|
LogWarning(StringFormat("Multiplicador ATR invalido ( %f ), cambiando a modo puntos", mul), __FUNCTION__);
|
|
f = Diff_OnBarFuncionPoint;
|
|
is_atr = false;
|
|
}
|
|
else
|
|
{
|
|
f = Diff_OnBarFuncionAtr;
|
|
is_atr = true;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Configura el cálculo por puntos |
|
|
//+------------------------------------------------------------------+
|
|
void CDiff::SetPoint(string symbol_, int min_diff_points_)
|
|
{
|
|
if(mode_diff != MODE_DIFF_BY_FIXED_POITNS)
|
|
return;
|
|
|
|
//--
|
|
if(set_point) //Ya se ha seteado puntos
|
|
{
|
|
LogError("Modo por puntos ya configurado. Use DiffPoints para cambiar", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
//--
|
|
this.symbol = symbol_;
|
|
set_point = true;
|
|
|
|
//--
|
|
if(symbol_ == "" || !SymbolInfoDouble(symbol_, SYMBOL_POINT))
|
|
{
|
|
LogFatalError(StringFormat("Simbolo invalido en SetPoint: %s", symbol_), __FUNCTION__);
|
|
this.diff = 0;
|
|
Remover();
|
|
return;
|
|
}
|
|
|
|
this.diff = SymbolInfoDouble(this.symbol, SYMBOL_POINT) * min_diff_points_;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Configura el cálculo por ATR |
|
|
//+------------------------------------------------------------------+
|
|
void CDiff::SetAtr(CAtr* atr_, int idx_, double mul_)
|
|
{
|
|
if(mode_diff != MODE_DIFF_BY_ATR)
|
|
return; //Si no es atr entonces salimos
|
|
|
|
//--
|
|
if(set_atr) //Ya se ha seteado atr
|
|
{
|
|
LogError("Modo ATR ya configurado. Use AtrMul para cambiar", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
//--
|
|
set_atr = true;
|
|
|
|
//---
|
|
if(CheckPointer(atr_) == POINTER_INVALID)
|
|
{
|
|
LogCriticalError("Puntero ATR invalido en SetAtr", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
//---
|
|
if(atr_.Handle() == INVALID_HANDLE)
|
|
{
|
|
LogFatalError("El handle pasado es invalido", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
|
|
//---
|
|
if(idx_ < 0)
|
|
{
|
|
LogWarning(StringFormat("Indice ATR invalido %d, ajustando a 0", idx_), __FUNCTION__);
|
|
idx_ = 0;
|
|
}
|
|
|
|
//---
|
|
this.atr = atr_;
|
|
this.idx = idx_;
|
|
this.mul = mul_;
|
|
|
|
//--- Opimtizar, si el mul es invalido, entonces usamos puntos
|
|
if(mul_ <= 0.00)
|
|
{
|
|
LogWarning(StringFormat("Multiplicador ATR invalido %f, cambiando a modo puntos", mul_), FUNCION_ACTUAL);
|
|
f = Diff_OnBarFuncionPoint;
|
|
is_atr = false;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Crea un objeto CDiff en el heap y devuelve su puntero |
|
|
//+------------------------------------------------------------------+
|
|
CDiff* CreateDiffptr(ENUM_MODE_DIFF diff_mod, string symbol_, CAtr* atr_, int idx_, double mul_or_points)
|
|
{
|
|
CDiff* obj = new CDiff();
|
|
obj.SetMode(diff_mod);
|
|
|
|
//--
|
|
if(diff_mod == MODE_DIFF_BY_FIXED_POITNS)
|
|
obj.SetPoint(symbol_, (int)mul_or_points);
|
|
else
|
|
obj.SetAtr(atr_, idx_, mul_or_points);
|
|
|
|
return obj;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Crea un objeto CDiff en el stack y lo devuelve |
|
|
//+------------------------------------------------------------------+
|
|
CDiff CreateDiffInstance(ENUM_MODE_DIFF diff_mod, string symbol_, CAtr* atr_, int idx_, double mul_or_points)
|
|
{
|
|
CDiff obj;
|
|
obj.SetMode(diff_mod);
|
|
|
|
//--
|
|
if(diff_mod == MODE_DIFF_BY_FIXED_POITNS)
|
|
obj.SetPoint(symbol_, (int)mul_or_points);
|
|
else
|
|
obj.SetAtr(atr_, idx_, mul_or_points);
|
|
|
|
return obj;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Clase para detectar si la PC ha sido suspendida |
|
|
//+------------------------------------------------------------------+
|
|
class CSuspendChecker
|
|
{
|
|
private:
|
|
uint m_lastTick; // Último tick registrado
|
|
uchar m_threshold; // Umbral en minutos
|
|
datetime m_last_time_revised;
|
|
|
|
public:
|
|
// Constructor, establece el umbral de tiempo
|
|
CSuspendChecker()
|
|
|
|
{
|
|
m_threshold = 2;
|
|
m_lastTick = GetTickCount64Minutes; // Inicializa con el tiempo actual
|
|
m_last_time_revised = TimeCurrent();
|
|
}
|
|
|
|
// Verifica si ha habido una suspensión
|
|
bool CheckForSuspend(bool flag_new_day)
|
|
{
|
|
if(TESTER_FLAG)
|
|
return false;
|
|
|
|
const uint currentTick = GetTickCount64Minutes;
|
|
m_last_time_revised = TimeCurrent();
|
|
m_lastTick = currentTick; // Actualiza el último tick
|
|
|
|
// Si la diferencia supera el umbral, es probable que la PC estuviera suspendida
|
|
if((currentTick - m_lastTick) > m_threshold && flag_new_day == false)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
inline datetime GetLasTimeRevised()
|
|
{
|
|
return this.m_last_time_revised;
|
|
}
|
|
|
|
inline void Threshold(uchar new_minutes)
|
|
{
|
|
m_threshold = new_minutes;
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Clase CConversions: precio ↔ píxeles ↔ barras |
|
|
//+------------------------------------------------------------------+
|
|
class CConversions
|
|
{
|
|
private:
|
|
double valor_1_unidad_precio_a_px;
|
|
double valor_1_px_a_unidad_precio;
|
|
|
|
double valor_1_barra_a_px;
|
|
double valor_1_px_a_barra;
|
|
|
|
long chart_id;
|
|
|
|
public:
|
|
CConversions(long chartID = 0) : chart_id(chartID) { Update(); }
|
|
|
|
// Precio → píxeles
|
|
inline int PrecioAPixeles(double distancia_precio)
|
|
{
|
|
return (int)(distancia_precio * this.valor_1_unidad_precio_a_px);
|
|
}
|
|
|
|
// Píxeles → precio
|
|
inline double PixelesAPrecio(int pixeles)
|
|
{
|
|
return pixeles * this.valor_1_px_a_unidad_precio;
|
|
}
|
|
|
|
// Barras → píxeles
|
|
inline int BarrasAPixeles(double num_barras)
|
|
{
|
|
return (int)(num_barras * this.valor_1_barra_a_px);
|
|
}
|
|
|
|
// Píxeles → barras
|
|
inline double PixelesABarras(int pixeles)
|
|
{
|
|
return pixeles * this.valor_1_px_a_barra;
|
|
}
|
|
|
|
// Actualizar escala
|
|
void Update()
|
|
{
|
|
// Escala vertical (precio)
|
|
double precio_max = ChartGetDouble(chart_id, CHART_PRICE_MAX);
|
|
double precio_min = ChartGetDouble(chart_id, CHART_PRICE_MIN);
|
|
double dist_precio = MathAbs(precio_max - precio_min);
|
|
|
|
int chart_height_px = (int)ChartGetInteger(chart_id, CHART_HEIGHT_IN_PIXELS);
|
|
int chart_width_px = (int)ChartGetInteger(chart_id, CHART_WIDTH_IN_PIXELS);
|
|
|
|
if(chart_height_px > 0 && dist_precio > 0)
|
|
{
|
|
this.valor_1_unidad_precio_a_px = (double)chart_height_px / dist_precio;
|
|
this.valor_1_px_a_unidad_precio = dist_precio / (double)chart_height_px;
|
|
}
|
|
|
|
// Escala horizontal (barras)
|
|
int barras_horizontal = (int)ChartGetInteger(chart_id, CHART_WIDTH_IN_BARS);
|
|
|
|
if(chart_width_px > 0 && barras_horizontal > 0)
|
|
{
|
|
this.valor_1_barra_a_px = (double)chart_width_px / (double)barras_horizontal;
|
|
this.valor_1_px_a_barra = (double)barras_horizontal / (double)chart_width_px;
|
|
}
|
|
}
|
|
|
|
// Manejo automático del zoom y cambios gráficos
|
|
void OnEvent(const int id,
|
|
const long & lparam,
|
|
const double & dparam,
|
|
const string & sparam)
|
|
{
|
|
if(id != CHARTEVENT_CHART_CHANGE)
|
|
return;
|
|
|
|
if(lparam == 49 || lparam == 2)
|
|
Update();
|
|
}
|
|
|
|
// Método extra para obtener dimensiones actuales
|
|
void ImprimirDimensionesChart()
|
|
{
|
|
int chart_width = (int)ChartGetInteger(chart_id, CHART_WIDTH_IN_PIXELS);
|
|
int chart_height = (int)ChartGetInteger(chart_id, CHART_HEIGHT_IN_PIXELS);
|
|
int barras_horizontal = (int)ChartGetInteger(chart_id, CHART_WIDTH_IN_BARS);
|
|
|
|
PrintFormat("Dimensiones actuales del gráfico: ancho=%d px, alto=%d px, barras visibles=%d",
|
|
chart_width, chart_height, barras_horizontal);
|
|
}
|
|
};
|
|
|
|
CConversions manager_graph;
|
|
|
|
//+------------------------------------------------------------------+
|
|
#endif
|
|
//+------------------------------------------------------------------+
|