- Ahora todas las maximas gancnais y perdidias filtrar por numero magico (asi que ya no es "global")
293 lines
23 KiB
MQL5
293 lines
23 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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"
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
class CLossLossGmlpo : public CLossProfitBaseLoss<TPadre>
|
|
{
|
|
public:
|
|
CLossLossGmlpo(bool empty, CRiskManagemetBase* risk_pointer);
|
|
~CLossLossGmlpo(void) {}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre> CLossLossGmlpo::CLossLossGmlpo(bool empty, CRiskManagemetBase *risk_pointer)
|
|
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_GMLPO, empty, false, risk_pointer)
|
|
{
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| MDL - Maximum Daily Loss |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
class CLossLossMaxDaily : public CLossProfitBaseLoss<TPadre>
|
|
{
|
|
public:
|
|
CLossLossMaxDaily(bool empty, CRiskManagemetBase* risk_pointer);
|
|
~CLossLossMaxDaily(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 <typename TPadre> CLossLossMaxDaily::CLossLossMaxDaily(bool empty, CRiskManagemetBase *risk_pointer)
|
|
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MDL, empty, false, risk_pointer)
|
|
{
|
|
if(empty)
|
|
return;
|
|
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_DAY); // Registramos para recibir OnNewDay
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
void CLossLossMaxDaily::OnNewDay(const datetime curr_time)
|
|
{
|
|
if(Set())
|
|
m_saved_value = m_lp.value;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| MWL - Maximum Weekly Loss |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
class CLossLossMaxWeekly : public CLossProfitBaseLoss<TPadre>
|
|
{
|
|
public:
|
|
CLossLossMaxWeekly(bool empty, CRiskManagemetBase* risk_pointer);
|
|
~CLossLossMaxWeekly(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 <typename TPadre> CLossLossMaxWeekly::CLossLossMaxWeekly(bool empty, CRiskManagemetBase *risk_pointer)
|
|
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MWL, empty, false, risk_pointer)
|
|
{
|
|
if(empty)
|
|
return;
|
|
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK); // Registramos para recibir OnNewWeek
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
void CLossLossMaxWeekly::OnNewWeek(const datetime curr_time)
|
|
{
|
|
if(Set())
|
|
m_saved_value = m_lp.value;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| MML - Maximum Monthly Loss |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
class CLossLossMaxMon : public CLossProfitBaseLoss<TPadre>
|
|
{
|
|
public:
|
|
CLossLossMaxMon(bool empty, CRiskManagemetBase* risk_pointer);
|
|
~CLossLossMaxMon(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 <typename TPadre> CLossLossMaxMon::CLossLossMaxMon(bool empty, CRiskManagemetBase *risk_pointer)
|
|
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MML, empty, false, risk_pointer)
|
|
{
|
|
if(empty)
|
|
return;
|
|
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_MON); // Registramos para recibir OnNewMonth
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
void CLossLossMaxMon::OnNewMonth(const datetime curr_time)
|
|
{
|
|
if(Set())
|
|
m_saved_value = m_lp.value;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ML - Maximum Loss (sin reseteo temporal) |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre>
|
|
class CLossLossMax : public CLossProfitBaseLoss<TPadre>
|
|
{
|
|
public:
|
|
CLossLossMax(bool empty, CRiskManagemetBase* risk_pointer);
|
|
~CLossLossMax(void) {}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre> CLossLossMax::CLossLossMax(bool empty, CRiskManagemetBase *risk_pointer)
|
|
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_ML, empty, false, risk_pointer)
|
|
{
|
|
// No registra eventos temporales - tracking continuo
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Pérdida má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:
|
|
CLossLossMaxDesdeArriba(bool empty, CRiskManagemetBase* risk_pointer);
|
|
~CLossLossMaxDesdeArriba(void) {}
|
|
|
|
//---
|
|
void OnLossProfit(const double p) override final;
|
|
|
|
//---
|
|
void Init(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, bool _is_strict, FuncionLossProfitSuperate fsup);
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TPadre> CLossLossMaxDesdeArriba::CLossLossMaxDesdeArriba(bool empty, CRiskManagemetBase *risk_pointer)
|
|
: CLossProfitBaseLoss<TPadre>(LOSSPROFIT_TYPE_MDDPICO, empty, true, risk_pointer), m_func_base(NULL),
|
|
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;
|
|
|
|
if(fsup == NULL)
|
|
{
|
|
LogError("Function superation cannot be NULL", FUNCION_ACTUAL);
|
|
return;
|
|
}
|
|
|
|
m_func_base = fsup;
|
|
CLossProfitBaseLoss<TPadre>::Init(_percentage, _applied, _is_strict, fsup); // Llamamos a la del padre
|
|
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>
|
|
void CLossLossMaxDesdeArriba::OnLossProfit(const double p)
|
|
{
|
|
//---
|
|
if(m_magic_number != NOT_MAGIC_NUMBER && m_magic_number != account_status.LastDealMagic())
|
|
return;
|
|
|
|
//---
|
|
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érdida má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érdida despué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ó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érdida - aumenta el drawdown
|
|
{
|
|
m_lp.value += p; // p es negativo, suma a pé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;
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
#endif // MQLARTICLES_RM_LOSSPROFIT_BASIC_MAXLOSSES_MQH
|