MQLArticles/RM/LossProfit/Basic/MaxProfits.mqh
Nique_372 7e5ff17b47 Modify - Fixed
- Ahora todas las maximas gancnais y perdidias filtrar por numero magico (asi que ya no es "global")
2026-02-19 11:31:44 -05:00

278 lines
10 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <typename TPadre>
class CLossProfitMaxDaily : public CLossProfitBaseProfit<TPadre>
{
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 <typename TPadre> CLossProfitMaxDaily::CLossProfitMaxDaily(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseProfit<TPadre>(LOSSPROFIT_TYPE_MDP, empty, false, risk_pointer)
{
if(empty)
return;
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_DAY); // Registramos para recibir OnNewDay
}
//+------------------------------------------------------------------+
template <typename TPadre>
void CLossProfitMaxDaily::OnNewDay(const datetime curr_time)
{
if(Set())
m_saved_value = m_lp.value;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| MWP |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossProfitMaxWeekly : public CLossProfitBaseProfit<TPadre>
{
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 <typename TPadre> CLossProfitMaxWeekly::CLossProfitMaxWeekly(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseProfit<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 CLossProfitMaxWeekly::OnNewWeek(const datetime curr_time)
{
if(Set())
m_saved_value = m_lp.value;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| MMP |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossProfitMaxMon : public CLossProfitBaseProfit<TPadre>
{
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 <typename TPadre> CLossProfitMaxMon::CLossProfitMaxMon(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseProfit<TPadre>(LOSSPROFIT_TYPE_MMP, empty, false, risk_pointer)
{
if(empty)
return;
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_MON); // Registramos para recibir OnNewMonth
}
//+------------------------------------------------------------------+
template <typename TPadre>
void CLossProfitMaxMon::OnNewMonth(const datetime curr_time)
{
if(Set())
m_saved_value = m_lp.value;
}
//+------------------------------------------------------------------+
//| MP - Maximum Profit (sin reseteo temporal) |
//+------------------------------------------------------------------+
template <typename TPadre>
class CLossProfitMax : public CLossProfitBaseProfit<TPadre>
{
public:
CLossProfitMax(bool empty, CRiskManagemetBase* risk_pointer);
~CLossProfitMax(void) {}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TPadre> CLossProfitMax::CLossProfitMax(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseProfit<TPadre>(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 <typename TPadre>
class CLossProfitMaxDesdeBaajo : public CLossProfitBaseProfit<TPadre>
{
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 <typename TPadre> CLossProfitMaxDesdeBaajo::CLossProfitMaxDesdeBaajo(bool empty, CRiskManagemetBase *risk_pointer)
: CLossProfitBaseProfit<TPadre>(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 <typename TPadre>
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<TPadre>::Init(_percentage, _applied, _is_strict, fsup); // Llamaos a la del padre
m_funcion_check_sup = LossProfitEmptyFuncionSup;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TPadre>
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 <typename TPadre>
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