forked from nique_372/MQLArticles
421 lines
28 KiB
MQL5
421 lines
28 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 MQLARTICLES_UTILS_FA_CLASESBASES_MQH
| |
#define MQLARTICLES_UTILS_FA_CLASESBASES_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| Includes |
| |
//+------------------------------------------------------------------+
| |
//--- (Eventos basicos | CManagerBase | CSpecializedManager | CLoggerBase)
| |
#include "Events.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
| |
};
| |
| |
| |
//+-------------------------------------------------------------------------+
| |
//| Class CDiff - Difference calculation based on ATR or fixed points |
| |
//+-------------------------------------------------------------------------+
| |
/*
| |
ESP:
| |
Para usar la clase, solo se puede setear una vez..
| |
1. llame y configure el modo SetMode
| |
2. Luego condigura SetAtr y SetMode
| |
| |
Nota: El atr, ya debera de copiar los datos que luego seran accedios por esta clase, la clase unicamente calcula la
| |
diferencia.
| |
| |
ENG:
| |
| |
To use the class, you can only set it once.
| |
1. Call and set the SetMode mode.
| |
2. Then set SetAtr and SetMode.
| |
| |
Note: The atr should already copy the data that will later be accessed by this class, the class only calculates the difference.
| |
*/
| |
| |
//---
| |
class CDiff : public CLoggerBase
| |
{
| |
private:
| |
//---
| |
int idx; // Index for ATR
| |
string symbol; // Symbol for point calculation
| |
double diff; // Calculated difference value
| |
ENUM_MODE_DIFF mode_diff; // Difference calculation mode
| |
double mul; // Multiplier for ATR
| |
CAtr* atr; // Pointer to ATR object
| |
bool is_atr; // Flag to indicate if ATR is used
| |
| |
//---
| |
bool set_atr;
| |
bool set_point;
| |
| |
public:
| |
CDiff();
| |
CDiff(const CDiff & diff_);
| |
~CDiff() {}
| |
| |
//--- Configuration methods
| |
void SetMode(ENUM_MODE_DIFF mode_diff_);
| |
void SetAtr(CAtr * atr_, int idx_, double mul_);
| |
void SetPoint(string symbol_, int min_diff_points_);
| |
| |
//--- Method to update on new candle
| |
__forceinline void OnNewBar() { if(is_atr) diff = mul * atr[idx]; }
| |
| |
//---
| |
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; }
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Default constructor |
| |
//+------------------------------------------------------------------+
| |
CDiff::CDiff(void)
| |
: idx(0), set_atr(false), set_point(false), diff(0.00), mul(1.00), atr(NULL), is_atr(false)
| |
{
| |
// Initialize with default values
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Copy constructor |
| |
//+------------------------------------------------------------------+
| |
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),
| |
is_atr(diff_.is_atr),
| |
set_atr(diff_.set_atr),
| |
set_point(diff_.set_point)
| |
{
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Updates difference value based on ATR |
| |
//+------------------------------------------------------------------+
| |
void CDiff::SetNewDiffAtrValue(const int new_idx)
| |
{
| |
if(!is_atr) //Only set diff if it's atr and valid
| |
return;
| |
this.diff = atr[new_idx] * mul;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Sets the calculation mode |
| |
//+------------------------------------------------------------------+
| |
void CDiff::SetMode(ENUM_MODE_DIFF mode_diff_)
| |
{
| |
//-- Don't allow changing mode if already configured
| |
if(set_atr || set_point) //If a mode has already been set then don't allow
| |
return;
| |
| |
this.mode_diff = mode_diff_;
| |
this.is_atr = (mode_diff_ == MODE_DIFF_BY_ATR);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Changes the ATR multiplier |
| |
//+------------------------------------------------------------------+
| |
void CDiff::AtrMul(double new_value)
| |
{
| |
if(!set_atr) //If atr hasn't been set, return
| |
return;
| |
| |
//--
| |
this.mul = new_value;
| |
| |
//--
| |
if(mul <= 0.00)
| |
{
| |
LogWarning(StringFormat("Invalid ATR multiplier ( %f ), switching to points mode", mul), __FUNCTION__);
| |
is_atr = false;
| |
}
| |
else
| |
{
| |
is_atr = true;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Configures calculation by points |
| |
//+------------------------------------------------------------------+
| |
void CDiff::SetPoint(string symbol_, int min_diff_points_)
| |
{
| |
if(mode_diff != MODE_DIFF_BY_FIXED_POITNS)
| |
return;
| |
| |
//--
| |
if(set_point) //Points have already been set
| |
{
| |
LogError("Points mode already configured. Use DiffPoints to change", __FUNCTION__);
| |
return;
| |
}
| |
| |
//--
| |
this.symbol = symbol_;
| |
set_point = true;
| |
| |
//--
| |
bool c;
| |
if(symbol_ == "" || !SymbolExist(symbol_, c))
| |
{
| |
LogFatalError(StringFormat("Invalid symbol in SetPoint: %s", symbol_), __FUNCTION__);
| |
this.diff = 0;
| |
Remover();
| |
return;
| |
}
| |
| |
//---
| |
this.diff = SymbolInfoDouble(this.symbol, SYMBOL_POINT) * min_diff_points_;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Configures calculation by ATR |
| |
//+------------------------------------------------------------------+
| |
void CDiff::SetAtr(CAtr* atr_, int idx_, double mul_)
| |
{
| |
if(mode_diff != MODE_DIFF_BY_ATR)
| |
return; //If it's not atr then we exit
| |
| |
//--
| |
if(set_atr) //ATR has already been set
| |
{
| |
LogError("ATR mode already configured. Use AtrMul to change", __FUNCTION__);
| |
return;
| |
}
| |
| |
//--
| |
set_atr = true;
| |
| |
//---
| |
if(CheckPointer(atr_) == POINTER_INVALID)
| |
{
| |
LogCriticalError("Invalid ATR pointer in SetAtr", __FUNCTION__);
| |
return;
| |
}
| |
| |
//---
| |
if(atr_.Handle() == INVALID_HANDLE)
| |
{
| |
LogFatalError("The passed handle is invalid", FUNCION_ACTUAL);
| |
Remover();
| |
return;
| |
}
| |
| |
//---
| |
if(idx_ < 0)
| |
{
| |
LogWarning(StringFormat("Invalid ATR index %d, adjusting to 0", idx_), __FUNCTION__);
| |
idx_ = 0;
| |
}
| |
| |
//---
| |
this.atr = atr_;
| |
this.idx = idx_;
| |
this.mul = mul_;
| |
| |
//--- Optimize, if mul is invalid, then we use points
| |
if(mul_ <= 0.00)
| |
{
| |
LogWarning(StringFormat("Invalid ATR multiplier %f, switching to points mode", mul_), FUNCION_ACTUAL);
| |
is_atr = false;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Creates a CDiff object on the heap and returns its pointer |
| |
//+------------------------------------------------------------------+
| |
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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Creates a CDiff object on the stack and returns it |
| |
//+------------------------------------------------------------------+
| |
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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Class to detect if the PC has been suspended |
| |
//+------------------------------------------------------------------+
| |
class CSuspendChecker
| |
{
| |
private:
| |
uint m_lastTick; // Last recorded tick
| |
uchar m_threshold; // Threshold in minutes
| |
datetime m_last_time_revised;
| |
| |
public:
| |
// Constructor, sets the time threshold
| |
CSuspendChecker()
| |
| |
{
| |
m_threshold = 2;
| |
m_lastTick = GetTickCount64Minutes; // Initialize with current time
| |
m_last_time_revised = TimeCurrent();
| |
}
| |
| |
// Checks if there has been a suspension
| |
bool CheckForSuspend(const bool& flag_new_day, const datetime& curr_time)
| |
{
| |
if(TESTER_FLAG)
| |
return false;
| |
| |
const uint currentTick = GetTickCount64Minutes;
| |
m_last_time_revised = curr_time;
| |
m_lastTick = currentTick; // Update the last tick
| |
| |
// If the difference exceeds the threshold, the PC was likely suspended
| |
if(!flag_new_day && (currentTick - m_lastTick) > m_threshold)
| |
return true;
| |
| |
return false;
| |
}
| |
| |
inline datetime GetLasTimeRevised()
| |
{
| |
return this.m_last_time_revised;
| |
}
| |
| |
inline void Threshold(uchar new_minutes)
| |
{
| |
m_threshold = new_minutes;
| |
}
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| CConversions Class: price ↔ pixels ↔ bars |
| |
//+------------------------------------------------------------------+
| |
class CGraphConversion
| |
{
| |
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:
| |
CGraphConversion(long chartID = 0) : chart_id(chartID) { Update(); }
| |
// Price → pixels
| |
inline int PrecioAPixeles(double distancia_precio)
| |
{
| |
return (int)(distancia_precio * this.valor_1_unidad_precio_a_px);
| |
}
| |
| |
// Pixels → price
| |
inline double PixelesAPrecio(int pixeles)
| |
{
| |
return pixeles * this.valor_1_px_a_unidad_precio;
| |
}
| |
| |
// Bars → pixels
| |
inline int BarrasAPixeles(double num_barras)
| |
{
| |
return (int)(num_barras * this.valor_1_barra_a_px);
| |
}
| |
| |
// Pixels → bars
| |
inline double PixelesABarras(int pixeles)
| |
{
| |
return pixeles * this.valor_1_px_a_barra;
| |
}
| |
| |
// Update scale
| |
void Update()
| |
{
| |
// Vertical scale (price)
| |
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;
| |
}
| |
// Horizontal scale (bars)
| |
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;
| |
}
| |
}
| |
| |
// Automatic handling of zoom and chart changes
| |
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();
| |
}
| |
| |
// Extra method to get current dimensions
| |
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("Current chart dimensions: width=%d px, height=%d px, visible bars=%d",
| |
chart_width, chart_height, barras_horizontal);
| |
}
| |
};
| |
| |
CGraphConversion manager_graph;
| |
| |
//+------------------------------------------------------------------+
| |
#endif // MQLARTICLES_UTILS_FA_CLASESBASES_MQH
| |
//+------------------------------------------------------------------+
|