MQLArticles/RM/LossProfit/Basic/MaxLosses.mqh

294 lines
23 KiB
MQL5
Raw Permalink Normal View History

2026-01-28 12:07:14 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| MaxLosses.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_MAXLOSSES_MQH
#define MQLARTICLES_RM_LOSSPROFIT_BASIC_MAXLOSSES_MQH
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include "Classes.mqh"
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossLossGmlpo : public CLossProfitBaseLoss<TPadre>
{
public:
2026-01-31 19:44:40 -05:00
CLossLossGmlpo(bool empty, CRiskManagemetBase* risk_pointer);
2026-01-28 13:02:22 -05:00
~CLossLossGmlpo(void) {}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
template <typename TPadre> CLossLossGmlpo::CLossLossGmlpo(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_GMLPO, empty, false, risk_pointer)
2026-01-28 13:02:22 -05:00
{
}
2026-01-28 12:07:14 -05:00
//+------------------------------------------------------------------+
//| MDL - Maximum Daily Loss |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossLossMaxDaily : public CLossProfitBaseLoss<TPadre>
{
public:
2026-01-31 19:44:40 -05:00
CLossLossMaxDaily(bool empty, CRiskManagemetBase* risk_pointer);
~CLossLossMaxDaily(void) { if(!m_empty_flag && CBasicEvents::IsActive()) CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_DAY); }
2026-01-28 12:07:14 -05:00
//---
2026-02-14 17:00:45 -05:00
void OnNewDay(const datetime curr_time) override final;
2026-01-28 12:07:14 -05:00
};
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
template <typename TPadre> CLossLossMaxDaily::CLossLossMaxDaily(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MDL, empty, false, risk_pointer)
2026-01-28 12:07:14 -05:00
{
if(empty)
return;
2026-01-28 17:12:28 -05:00
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_DAY); // Registramos para recibir OnNewDay
2026-01-28 12:07:14 -05:00
}
//+------------------------------------------------------------------+
template <typename TPadre>
2026-02-14 17:00:45 -05:00
void CLossLossMaxDaily::OnNewDay(const datetime curr_time)
2026-01-28 12:07:14 -05:00
{
if(Set())
m_saved_value = m_lp.value;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| MWL - Maximum Weekly Loss |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossLossMaxWeekly : public CLossProfitBaseLoss<TPadre>
{
public:
2026-01-31 19:44:40 -05:00
CLossLossMaxWeekly(bool empty, CRiskManagemetBase* risk_pointer);
~CLossLossMaxWeekly(void) { if(!m_empty_flag && CBasicEvents::IsActive()) CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK); }
2026-01-28 12:07:14 -05:00
//---
2026-02-14 17:00:45 -05:00
void OnNewWeek(const datetime curr_time) override final;
2026-01-28 12:07:14 -05:00
};
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
template <typename TPadre> CLossLossMaxWeekly::CLossLossMaxWeekly(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MWL, empty, false, risk_pointer)
2026-01-28 12:07:14 -05:00
{
if(empty)
return;
2026-01-28 17:12:28 -05:00
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK); // Registramos para recibir OnNewWeek
2026-01-28 12:07:14 -05:00
}
//+------------------------------------------------------------------+
template <typename TPadre>
2026-02-14 17:00:45 -05:00
void CLossLossMaxWeekly::OnNewWeek(const datetime curr_time)
2026-01-28 12:07:14 -05:00
{
if(Set())
m_saved_value = m_lp.value;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| MML - Maximum Monthly Loss |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossLossMaxMon : public CLossProfitBaseLoss<TPadre>
{
public:
2026-01-31 19:44:40 -05:00
CLossLossMaxMon(bool empty, CRiskManagemetBase* risk_pointer);
~CLossLossMaxMon(void) { if(!m_empty_flag && CBasicEvents::IsActive()) CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_MON); }
2026-01-28 12:07:14 -05:00
//---
2026-02-14 17:00:45 -05:00
void OnNewMonth(const datetime curr_time) override final;
2026-01-28 12:07:14 -05:00
};
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
template <typename TPadre> CLossLossMaxMon::CLossLossMaxMon(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MML, empty, false, risk_pointer)
2026-01-28 12:07:14 -05:00
{
if(empty)
return;
2026-01-28 17:12:28 -05:00
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_MON); // Registramos para recibir OnNewMonth
2026-01-28 12:07:14 -05:00
}
//+------------------------------------------------------------------+
template <typename TPadre>
2026-02-14 17:00:45 -05:00
void CLossLossMaxMon::OnNewMonth(const datetime curr_time)
2026-01-28 12:07:14 -05:00
{
if(Set())
m_saved_value = m_lp.value;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ML - Maximum Loss (sin reseteo temporal) |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossLossMax : public CLossProfitBaseLoss<TPadre>
{
public:
2026-01-31 19:44:40 -05:00
CLossLossMax(bool empty, CRiskManagemetBase* risk_pointer);
2026-01-28 12:07:14 -05:00
~CLossLossMax(void) {}
};
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
template <typename TPadre> CLossLossMax::CLossLossMax(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_ML, empty, false, risk_pointer)
2026-01-28 12:07:14 -05:00
{
// No registra eventos temporales - tracking continuo
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| P<EFBFBD>rdida m<EFBFBD>xima desde pico |
//+------------------------------------------------------------------+
#define LOSSPROFIT_MAXLOSS_FLAG_PICO_LISTO (1)
template <typename TPadre>
class CLossLossMaxDesdeArriba : public CLossProfitBaseLoss<TPadre>
{
private:
uint8_t m_flags;
double m_positive_profit;
double m_max_positive_profit;
FuncionLossProfitSuperate m_func_base;
//---
void OnSuperated() override final;
public:
2026-01-31 19:44:40 -05:00
CLossLossMaxDesdeArriba(bool empty, CRiskManagemetBase* risk_pointer);
2026-01-28 12:07:14 -05:00
~CLossLossMaxDesdeArriba(void) {}
//---
2026-02-14 17:00:45 -05:00
void OnLossProfit(const double p) override final;
2026-01-28 12:07:14 -05:00
//---
void Init(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, bool _is_strict, FuncionLossProfitSuperate fsup);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
template <typename TPadre> CLossLossMaxDesdeArriba::CLossLossMaxDesdeArriba(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MDDPICO, empty, true, risk_pointer), m_func_base(NULL),
2026-01-28 12:07:14 -05:00
m_positive_profit(0.00), m_max_positive_profit(0.00),
m_flags(0)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TPadre>
void CLossLossMaxDesdeArriba::Init(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, bool _is_strict, FuncionLossProfitSuperate fsup)
{
if(m_empty_flag)
return;
2026-01-28 12:07:14 -05:00
if(fsup == NULL)
{
LogError("Function superation cannot be NULL", FUNCION_ACTUAL);
return;
}
m_func_base = fsup;
2026-01-28 13:02:22 -05:00
CLossProfitBaseLoss<TPadre>::Init(_percentage, _applied, _is_strict, fsup); // Llamamos a la del padre
2026-01-28 12:07:14 -05:00
m_funcion_check_sup = LossProfitEmptyFuncionSup;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TPadre>
void CLossLossMaxDesdeArriba::OnSuperated()
{
m_flags = 0;
m_positive_profit = 0.00;
m_max_positive_profit = 0.00;
m_funcion_check_sup = LossProfitEmptyFuncionSup;
if(Set())
m_saved_value = m_lp.value;
#ifdef MORE_INFO_LOSS_PROFIT_DEFINE
LogInfo("Drawdown limit reached, resetting to search new peak", FUNCION_ACTUAL);
#endif
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TPadre>
2026-02-14 17:00:45 -05:00
void CLossLossMaxDesdeArriba::OnLossProfit(const double p)
2026-01-28 12:07:14 -05:00
{
2026-01-28 13:02:22 -05:00
//---
if(m_magic_number != NOT_MAGIC_NUMBER && m_magic_number != account_status.LastDealMagic())
return;
//---
2026-01-28 12:07:14 -05:00
const bool is_loss = (p < 0.00);
m_positive_profit += p;
//--- Nuevo pico detectado - recalcular objetivo
if(m_positive_profit > m_max_positive_profit)
{
//--- Calculamos el nuevo valor (p<EFBFBD>rdida m<EFBFBD>xima desde este pico)
if(Set())
m_saved_value = m_lp.value;
m_flags = 0;
m_max_positive_profit = m_positive_profit;
m_funcion_check_sup = LossProfitEmptyFuncionSup; // Volver a buscar pico
#ifdef MORE_INFO_LOSS_PROFIT_DEFINE
LogInfo(StringFormat("New peak detected: %.2f, DD limit: %.2f", m_max_positive_profit, m_saved_value), FUNCION_ACTUAL);
#endif
}
//--- Primera p<EFBFBD>rdida despu<EFBFBD>s de pico - activar tracking
if(is_loss && m_max_positive_profit != 0.00 && (m_flags & LOSSPROFIT_MAXLOSS_FLAG_PICO_LISTO) == 0)
{
m_flags |= LOSSPROFIT_MAXLOSS_FLAG_PICO_LISTO;
m_funcion_check_sup = m_func_base; // Activar verificaci<EFBFBD>n real
#ifdef MORE_INFO_LOSS_PROFIT_DEFINE
LogInfo("Drawdown tracking activated", FUNCION_ACTUAL);
#endif
}
//--- Ajustar valor si estamos tracking drawdown
if((m_flags & LOSSPROFIT_MAXLOSS_FLAG_PICO_LISTO) != 0)
{
if(is_loss) // P<EFBFBD>rdida - aumenta el drawdown
{
m_lp.value += p; // p es negativo, suma a p<EFBFBD>rdida acumulada
}
else
if(p > 0.00) // Profit - reduce el drawdown
{
const double nv = m_lp.value + p;
m_lp.value = (!m_strict && nv > m_saved_value) ? nv : m_saved_value;
}
}
}
//+------------------------------------------------------------------+
2026-01-28 13:02:22 -05:00
#endif // MQLARTICLES_RM_LOSSPROFIT_BASIC_MAXLOSSES_MQH