//+------------------------------------------------------------------+ //| MaxProfits.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372 | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372" #property strict #ifndef MQLARTICLES_RM_LOSSPROFIT_BASIC_MAXPROFITS_MQH #define MQLARTICLES_RM_LOSSPROFIT_BASIC_MAXPROFITS_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include "Classes.mqh" //+------------------------------------------------------------------+ //| MDP | //+------------------------------------------------------------------+ template class CLossProfitMaxDaily : public CLossProfitBaseProfit { public: CLossProfitMaxDaily(bool empty, CRiskManagemetBase* risk_pointer); ~CLossProfitMaxDaily(void) { if(!m_empty_flag && CBasicEvents::IsActive()) CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_DAY); } //--- void OnNewDay(const datetime curr_time) override final; }; //+------------------------------------------------------------------+ template CLossProfitMaxDaily::CLossProfitMaxDaily(bool empty, CRiskManagemetBase *risk_pointer) : CLossProfitBaseProfit(LOSSPROFIT_TYPE_MDP, empty, false, risk_pointer) { if(empty) return; CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_DAY); // Registramos para recibir OnNewDay } //+------------------------------------------------------------------+ template void CLossProfitMaxDaily::OnNewDay(const datetime curr_time) { if(Set()) m_saved_value = m_lp.value; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| MWP | //+------------------------------------------------------------------+ template class CLossProfitMaxWeekly : public CLossProfitBaseProfit { public: CLossProfitMaxWeekly(bool empty, CRiskManagemetBase* risk_pointer); ~CLossProfitMaxWeekly(void) { if(!m_empty_flag && CBasicEvents::IsActive()) CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK); } //--- void OnNewWeek(const datetime curr_time) override final; }; //+------------------------------------------------------------------+ template CLossProfitMaxWeekly::CLossProfitMaxWeekly(bool empty, CRiskManagemetBase *risk_pointer) : CLossProfitBaseProfit(LOSSPROFIT_TYPE_MWL, empty, false, risk_pointer) { if(empty) return; CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK); // Registramos para recibir OnNewWeek } //+------------------------------------------------------------------+ template void CLossProfitMaxWeekly::OnNewWeek(const datetime curr_time) { if(Set()) m_saved_value = m_lp.value; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| MMP | //+------------------------------------------------------------------+ template class CLossProfitMaxMon : public CLossProfitBaseProfit { public: CLossProfitMaxMon(bool empty, CRiskManagemetBase* risk_pointer); ~CLossProfitMaxMon(void) { if(!m_empty_flag && CBasicEvents::IsActive()) CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_MON); } //--- void OnNewMonth(const datetime curr_time) override final; }; //+------------------------------------------------------------------+ template CLossProfitMaxMon::CLossProfitMaxMon(bool empty, CRiskManagemetBase *risk_pointer) : CLossProfitBaseProfit(LOSSPROFIT_TYPE_MMP, empty, false, risk_pointer) { if(empty) return; CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_MON); // Registramos para recibir OnNewMonth } //+------------------------------------------------------------------+ template void CLossProfitMaxMon::OnNewMonth(const datetime curr_time) { if(Set()) m_saved_value = m_lp.value; } //+------------------------------------------------------------------+ //| MP - Maximum Profit (sin reseteo temporal) | //+------------------------------------------------------------------+ template class CLossProfitMax : public CLossProfitBaseProfit { public: CLossProfitMax(bool empty, CRiskManagemetBase* risk_pointer); ~CLossProfitMax(void) {} }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template CLossProfitMax::CLossProfitMax(bool empty, CRiskManagemetBase *risk_pointer) : CLossProfitBaseProfit(LOSSPROFIT_TYPE_MP, empty, false, risk_pointer) { // No registra eventos temporales - tracking continuo sin reseteos } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| M desde el bajo | //+------------------------------------------------------------------+ #define LOSSPROFIT_MAXMON_FLAG_BAJO_LISTO (1) template class CLossProfitMaxDesdeBaajo : public CLossProfitBaseProfit { private: uint8_t m_flags; double m_negative_profit; double m_min_negative_profit; FuncionLossProfitSuperate m_func_base; //--- void OnSuperated() override final; public: CLossProfitMaxDesdeBaajo(bool empty, CRiskManagemetBase* risk_pointer); ~CLossProfitMaxDesdeBaajo(void) {} //--- void OnLossProfit(const double p) override final; //--- void Init(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, bool _is_strict, FuncionLossProfitSuperate fsup); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template CLossProfitMaxDesdeBaajo::CLossProfitMaxDesdeBaajo(bool empty, CRiskManagemetBase *risk_pointer) : CLossProfitBaseProfit(LOSSPROFIT_TYPE_MDDBAJO, empty, true, risk_pointer), m_func_base(NULL) , m_negative_profit(0.00), m_min_negative_profit(0.00), m_flags(0) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template void CLossProfitMaxDesdeBaajo::Init(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, bool _is_strict, FuncionLossProfitSuperate fsup) { //--- if(m_empty_flag) return; //--- if(fsup == NULL) { LogError("Function superation cannot be NULL", FUNCION_ACTUAL); return; } //--- m_func_base = fsup; CLossProfitBaseProfit::Init(_percentage, _applied, _is_strict, fsup); // Llamaos a la del padre m_funcion_check_sup = LossProfitEmptyFuncionSup; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template void CLossProfitMaxDesdeBaajo::OnSuperated() { m_flags = 0; m_negative_profit = 0.00; m_min_negative_profit = 0.00; m_funcion_check_sup = LossProfitEmptyFuncionSup; #ifdef MORE_INFO_LOSS_PROFIT_DEFINE LogInfo("Run-up target reached, resetting to search new minimum", FUNCION_ACTUAL); #endif } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template void CLossProfitMaxDesdeBaajo::OnLossProfit(const double p) { //--- if(m_magic_number != NOT_MAGIC_NUMBER && m_magic_number != account_status.LastDealMagic()) return; //--- const bool is_profit = (p > 0.00); m_negative_profit += p; //--- if(m_negative_profit < m_min_negative_profit) { //--- Calculamos el nuevo valor if(Set()) m_saved_value = m_lp.value; //--- m_flags = 0; //--- m_min_negative_profit = m_negative_profit; //--- m_funcion_check_sup = LossProfitEmptyFuncionSup; #ifdef MORE_INFO_LOSS_PROFIT_DEFINE LogInfo(StringFormat("New minimum detected: %.2f, target: %.2f", m_min_negative_profit, m_saved_value), FUNCION_ACTUAL); #endif } //--- if(is_profit && m_min_negative_profit != 0.00 && m_flags == 0) // Caimos y se recupero { m_flags |= LOSSPROFIT_MAXMON_FLAG_BAJO_LISTO; m_funcion_check_sup = m_func_base; #ifdef MORE_INFO_LOSS_PROFIT_DEFINE LogInfo("Recovery tracking activated", FUNCION_ACTUAL); #endif } //--- Perdida if((m_flags & LOSSPROFIT_MAXMON_FLAG_BAJO_LISTO) != 0) { if(p < 0.00) { const double nv = m_lp.value - p; m_lp.value = (m_strict && nv > m_saved_value) ? nv : m_saved_value; } //--- Profit else if(is_profit) { m_lp.value -= p; // Si es negativo es por que ya se supero y se gano demas y por mucho } } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ #endif // MQLARTICLES_RM_LOSSPROFIT_BASIC_MAXPROFITS_MQH