//+------------------------------------------------------------------+ //| DiffCalc.mqh | //| Copyright 2026, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, MetaQuotes Ltd." #property link "https://www.mql5.com" #property strict #ifndef MQLARTICLES_UTILS_FA_DIFFCALC_MQH #define MQLARTICLES_UTILS_FA_DIFFCALC_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include "Atr.mqh" //+------------------------------------------------------------------+ //| Clase CDiff - Defines | //+------------------------------------------------------------------+ enum ENUM_MODE_DIFF { MODE_DIFF_BY_FIXED_POITNS = 0, // By Points MODE_DIFF_BY_ATR // By Atr }; //--- Flags #define MQLARTICLES_DIFFCALC_FLAG_SUPPORT_HISTORIAL (1) #define MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE (2) #define MQLARTICLES_DIFFCALC_ALL_FLAG (MQLARTICLES_DIFFCALC_FLAG_SUPPORT_HISTORIAL|MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE) //+------------------------------------------------------------------+ //| class CDiff | //+------------------------------------------------------------------+ class CDiff : public CLoggerBase { protected: //--- const ENUM_MODE_DIFF m_type; // Differene type uint8_t m_flags; // Flags double m_diff; // Calculated difference value public: CDiff(const ENUM_MODE_DIFF type, const uint8_t flags) : m_type(type), m_diff(0.00), m_flags(flags) {} ~CDiff() {} //--- Method to update on new candle virtual void OnNewBar() {} //--- __forceinline ENUM_MODE_DIFF GetTypeDiff() const { return m_type; } __forceinline double Diff() const { return m_diff; } //--- Flags __forceinline bool HasFlags(const int flags) const { return (m_flags & flags) != 0; } __forceinline bool HasAllFlags(const int flags) const { return (m_flags & flags) == flags; } __forceinline uint8_t GetFlags() const { return m_flags; } //--- Modo historial virtual void SetNewIdx(const int bar_idx) {} virtual void OnHistorialCopyData(const int start, const int count) {} }; //+------------------------------------------------------------------+ //| class CDiffPoint | //+------------------------------------------------------------------+ class CDiffPoint : public CDiff { private: string symbol; // Symbol for point calculation public: CDiffPoint(void) : CDiff(MODE_DIFF_BY_FIXED_POITNS, MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE) {} ~CDiffPoint(void) {} //--- void Set(string symbol_, int min_diff_points_); //--- inline void DiffPoints(int new_diff_points) { this.m_diff = new_diff_points * SymbolInfoDouble(this.symbol, SYMBOL_POINT); } inline int DiffPoints() const { return (int)(this.m_diff / SymbolInfoDouble(this.symbol, SYMBOL_POINT)); } }; //+------------------------------------------------------------------+ //| Configures calculation by points | //+------------------------------------------------------------------+ void CDiffPoint::Set(string symbol_, int min_diff_points_) { //-- this.symbol = symbol_; //-- static bool c; if(symbol_ == "" || !SymbolExist(symbol_, c)) { LogFatalError(StringFormat("Invalid symbol in SetPoint: %s", symbol_), __FUNCTION__); Remover(); return; } //--- this.m_diff = SymbolInfoDouble(this.symbol, SYMBOL_POINT) * min_diff_points_; } //+------------------------------------------------------------------+ //| class CDiffAtr | //+------------------------------------------------------------------+ class CDiffAtr : public CDiff { private: int idx; // Index for ATR CAtr* atr; // Pointer to ATR object double mul; // Multiplier for ATR public: CDiffAtr(void) : CDiff(MODE_DIFF_BY_ATR, MQLARTICLES_DIFFCALC_ALL_FLAG), idx(0), atr(NULL), mul(0.00) {} ~CDiffAtr(void) {} //--- General setterr void Set(CAtr * atr_, int idx_, double mul_); //--- void OnNewBar() override final; //--- Nuevo idx void SetNewIdx(const int bar_idx) override final; //--- Atr inline CAtr* GetAtrPointer() const { return atr; } //--- Atr mul inline double AtrMul() const { return mul; } void AtrMul(double new_value); //--- void OnHistorialCopyData(const int start, const int count) override final { atr.CopyData(start, count); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CDiffAtr::OnNewBar(void) { if((m_flags & MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE) != 0) m_diff = mul * atr[idx]; } //+------------------------------------------------------------------+ //| Updates difference value based on ATR | //+------------------------------------------------------------------+ void CDiffAtr::SetNewIdx(const int bar_idx) { if((m_flags & MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE) != 0) this.m_diff = atr[bar_idx] * mul; } //+------------------------------------------------------------------+ //| Changes the ATR multiplier | //+------------------------------------------------------------------+ void CDiffAtr::AtrMul(double new_value) { //-- this.mul = new_value; //-- if(mul <= 0.00) { // Here forze print FastLog(FUNCION_ACTUAL, WARNING_TEXT, StringFormat("Invalid ATR multiplier %f, disabling the class to avoid meaningless calls to OnNewBar, etc.", mul)); m_diff = 0.00; MQLARTICLES_FUNC_REMOVE_FLAG(m_flags, MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE); } else { if(!CheckPointer(atr)) { LogError("Atr is invalid", FUNCION_ACTUAL); Remover(); return; } m_flags |= MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE; } } //+------------------------------------------------------------------+ //| Configures calculation by ATR | //+------------------------------------------------------------------+ void CDiffAtr::Set(CAtr* atr_, int idx_, double mul_) { //--- if(mul_ <= 0.00) { FastLog(FUNCION_ACTUAL, WARNING_TEXT, StringFormat("Invalid ATR multiplier %f, disabling the class to avoid meaningless calls to OnNewBar, etc.", mul_)); MQLARTICLES_FUNC_REMOVE_FLAG(m_flags, MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE); m_diff = 0.00; return; } //--- if(!CheckPointer(atr_)) { LogCriticalError("Invalid ATR pointer in SetAtr", __FUNCTION__); Remover(); 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_; m_flags |= MQLARTICLES_DIFFCALC_FLAG_IS_ACTIVE; } //+------------------------------------------------------------------+ //| 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 = NULL; //--- switch(diff_mod) { case MODE_DIFF_BY_FIXED_POITNS: { obj = new CDiffPoint(); CDiffPoint* diff_point = (CDiffPoint*)obj; diff_point.Set(symbol_, int(mul_or_points)); break; } case MODE_DIFF_BY_ATR: { obj = new CDiffAtr(); CDiffAtr* diff_atr = (CDiffAtr*)obj; diff_atr.Set(atr_, idx_, mul_or_points); break; } default: FastLog(FUNCION_ACTUAL, CRITICAL_ERROR_TEXT, StringFormat("Invalid type of Diff = %s", EnumToString(diff_mod))); return NULL; } //-- return obj; } #endif // MQLARTICLES_UTILS_FA_DIFFCALC_MQH //+------------------------------------------------------------------+