- Ahora todas las maximas gancnais y perdidias filtrar por numero magico (asi que ya no es "global")
278 lines
10 KiB
MQL5
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
|