forked from nique_372/MQLArticles
		
	
		
			
				
	
	
		
			450 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			450 lines
		
	
	
	
		
			30 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
 | 
						|
 };
 | 
						|
 | 
						|
//--- Function type definition to manage different calculation modes
 | 
						|
typedef void(*FuncionCDiffOnBar)(double atr_mul, double atr_val, double &diff_prev);
 | 
						|
 | 
						|
//--- Function to calculate difference based on ATR
 | 
						|
inline void Diff_OnBarFuncionAtr(double atr_mul, double atr_val, double &diff_prev)
 | 
						|
 {
 | 
						|
  diff_prev = atr_mul * atr_val;
 | 
						|
 }
 | 
						|
 | 
						|
//--- Function to calculate difference based on points (does nothing, as it's set during initialization)
 | 
						|
inline void Diff_OnBarFuncionPoint(double atr_mul, double atr_val, double &diff_prev)
 | 
						|
 {
 | 
						|
  return;
 | 
						|
 }
 | 
						|
 
 | 
						|
//+-------------------------------------------------------------------------+
 | 
						|
//| 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:
 | 
						|
  //---
 | 
						|
  bool               set_atr;
 | 
						|
  bool               set_point;
 | 
						|
 | 
						|
  //---
 | 
						|
  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
 | 
						|
  FuncionCDiffOnBar  f;             // Function pointer for calculation according to mode
 | 
						|
  static float       empty_val;     // Static empty value
 | 
						|
  bool               is_atr;        // Flag to indicate if ATR is used
 | 
						|
 | 
						|
 | 
						|
  //---
 | 
						|
  inline double      GetVal() { return is_atr ? atr[idx] : 0.00; }
 | 
						|
 | 
						|
public:
 | 
						|
                     CDiff();
 | 
						|
                     CDiff(const CDiff & diff_);
 | 
						|
 | 
						|
  //--- 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
 | 
						|
  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;
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Default constructor                                              |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CDiff::CDiff(void)
 | 
						|
  : idx(0), set_atr(false), set_point(false), diff(0.00), mul(1.00), atr(NULL), f(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),
 | 
						|
    f(diff_.f),
 | 
						|
    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);
 | 
						|
 | 
						|
//-- Assign the appropriate function according to mode
 | 
						|
  if(mode_diff_ == MODE_DIFF_BY_ATR)
 | 
						|
    f = Diff_OnBarFuncionAtr;
 | 
						|
  else
 | 
						|
    f = Diff_OnBarFuncionPoint;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| 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__);
 | 
						|
    f = Diff_OnBarFuncionPoint;
 | 
						|
    is_atr = false;
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    f = Diff_OnBarFuncionAtr;
 | 
						|
    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;
 | 
						|
 | 
						|
//--
 | 
						|
  if(symbol_ == "" || !SymbolInfoDouble(symbol_, SYMBOL_POINT))
 | 
						|
   {
 | 
						|
    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);
 | 
						|
    f = Diff_OnBarFuncionPoint;
 | 
						|
    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(bool flag_new_day)
 | 
						|
   {
 | 
						|
    if(TESTER_FLAG)
 | 
						|
      return false;
 | 
						|
 | 
						|
    const uint currentTick = GetTickCount64Minutes;
 | 
						|
    m_last_time_revised = TimeCurrent();
 | 
						|
    m_lastTick = currentTick; // Update the last tick
 | 
						|
 | 
						|
    // If the difference exceeds the threshold, the PC was likely suspended
 | 
						|
    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;
 | 
						|
   }
 | 
						|
 };
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| 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
 | 
						|
//+------------------------------------------------------------------+
 |