MQLArticles/RM/RiskManagement.mqh

1161 lines
89 KiB
MQL5

2025-09-22 09:09:20 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| RiskManagement.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com/es/users/nique_372/news |
//+------------------------------------------------------------------+
2025-11-10 09:33:30 -05:00
#property copyright "Copyright 2025, Niquel Mendoza."
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
#property link "https://www.mql5.com/es/users/nique_372/news"
2025-09-22 09:09:20 -05:00
#property strict
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
#ifndef MQLARTICLES_RM_RISKMANAGEMENT_MQH
2026-01-29 08:19:03 -05:00
#define MQLARTICLES_RM_RISKMANAGEMENT_MQH
2025-09-22 09:09:20 -05:00
#include "RM_Hooks.mqh"
/*
ADVERTENCIA al momeneto de a<EFBFBD>adir items a esta clase, esta si son dinamicos las eliminara cuidado, como un modificador.
WARNING when adding items to this class, if they are dynamic, it will remove them carefully, as a modifier.
*/
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
//open_positions
2025-09-24 14:00:58 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
//| Clase Base CRiskManagement |
2026-03-05 12:10:29 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
class CRiskManagemet : public CRiskManagemetBase
2026-03-05 12:10:29 -05:00
2025-09-22 09:09:20 -05:00
{
2025-09-24 14:00:58 -05:00
protected:
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-09-24 14:00:58 -05:00
2026-02-14 17:00:45 -05:00
CGetLote* get_lote;
2025-09-22 09:09:20 -05:00
//---
2025-11-26 07:03:20 -05:00
double chosen_balance;
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
//--- Extra Variables
ENUM_GET_LOT type_get_lot;
2025-09-24 14:00:58 -05:00
2026-02-14 17:00:45 -05:00
2025-09-22 09:09:20 -05:00
//-- main variables
long StopLoss; //StopLoss
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
double lote; //Last recorded lot
//--- variables to store the values of the maximum losses
2025-11-26 07:03:20 -05:00
double nmlpo; //last expected loss
2026-03-05 12:10:29 -05:00
bool is_init; //flag indicating if it is init
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
//--- variables that store percentages and enumeration, which will be used for the subsequent calculation of losses
CLossProfitManager loss_profits_manager;
2026-01-07 11:00:48 -05:00
//--- Modifiers
2025-12-21 12:41:35 -05:00
CRiskManagemeHookManager m_hooks;
2025-11-26 07:03:20 -05:00
2025-09-24 14:00:58 -05:00
bool isCachedModifier[LOSS_PROFIT_COUNT];
2025-12-21 12:41:35 -05:00
2025-11-26 07:03:20 -05:00
//--- general function to assign values to loss variables
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
virtual double GetValorWithApplied(double percentage_, int type, ENUM_APPLIED_PERCENTAGES applied) const override;
2026-01-28 12:07:20 -05:00
2026-02-14 17:00:45 -05:00
//--- Update profits function
2026-01-28 12:07:20 -05:00
void UpdateProfit(const double profit, const double acc_total_profit);
2026-02-14 17:00:45 -05:00
2026-01-28 12:07:20 -05:00
virtual void OnOpenTrade() { }
2026-02-14 17:00:45 -05:00
2026-01-28 12:07:20 -05:00
virtual void OnCloseTrade() { }
2025-09-22 09:09:20 -05:00
//---
virtual FuncionLossProfitSuperate SuperateModeToFunctionProfit(ENUM_TYPE_LOSS_PROFIT type) const;
virtual FuncionLossProfitSuperate SuperateModeToFunctionLoss(ENUM_TYPE_LOSS_PROFIT type) const;
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
//---
2025-09-22 09:09:20 -05:00
virtual void* GetPtrLossProfits() { return &this; }
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
2026-02-14 17:00:45 -05:00
public:
2026-01-31 19:44:40 -05:00
2025-09-22 09:09:20 -05:00
//--- Constructor and Destructor
CRiskManagemet(const ulong _magic, const ENUM_GET_LOT type_get_lot_);
2025-09-22 09:09:20 -05:00
~CRiskManagemet();
//--- Set
2026-01-28 12:07:20 -05:00
void EndAddProfitLoss();
virtual void SetGeneralParameters(MqlParam &params[]) = 0;
2026-01-28 13:02:22 -05:00
void SetLote(CGetLote* lote_ptr);
2026-01-28 12:07:20 -05:00
inline void SetStopLoss(double dist_open_sl) { this.StopLoss = (long)ConvertPriceToPoints(_Symbol, dist_open_sl); }
inline void SetStopLoss(long _sl_point_) { this.StopLoss = _sl_point_; }
2026-01-28 13:02:22 -05:00
2026-01-28 12:07:20 -05:00
//--- Get losses and profits
2025-09-22 09:09:20 -05:00
const CLossProfit* const GetLossOrProfit(const ENUM_TYPE_LOSS_PROFIT _type) const { return loss_profits_manager[_type]; }
2026-01-29 08:19:03 -05:00
//--- Superated funcionts
2026-01-31 19:44:40 -05:00
const CLossProfitManager* GetLossProfitManager() const { return &loss_profits_manager; }
2025-09-22 09:09:20 -05:00
2026-01-28 12:07:20 -05:00
2025-09-22 09:09:20 -05:00
//--- Add
2026-01-28 12:07:20 -05:00
2025-09-22 09:09:20 -05:00
// Modificators
2026-01-28 12:07:20 -05:00
bool AddModificator(CExtraModifications* modificator); // Modificator pointer
__forceinline bool AddModificator(CExtraModifications &modificator) { return AddModificator(&modificator); }
// Hook
bool AddRmHook(IRiskManagementHook* hook);
__forceinline bool AddRmHook(IRiskManagementHook& hook) { return AddRmHook(&hook); }
// Loss
2025-09-22 09:09:20 -05:00
bool AddLoss(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, ENUM_RISK_CALCULATION_MODE _mode, ENUM_TYPE_LOSS_PROFIT type, bool strict,
bool is_dynamic = false, string percentages_to_activate = NULL, string risks_to_be_applied = NULL); // Loss
2026-01-28 17:12:28 -05:00
// Profit
2025-09-22 09:09:20 -05:00
2026-01-28 17:12:28 -05:00
bool AddProfit(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, ENUM_RISK_CALCULATION_MODE _mode, ENUM_TYPE_LOSS_PROFIT type, bool is_strict_,
2026-01-31 19:44:40 -05:00
bool is_dynamic = false, string percentages_to_activate = NULL, string risks_to_be_applied = NULL); // Profit
2026-01-28 17:12:28 -05:00
2026-01-31 19:44:40 -05:00
//--- Functions inherited from CAccountGestor
// Basic events
2026-01-28 17:12:28 -05:00
void OnNewDay(const datetime curr_time) override;
void OnNewWeek(const datetime curr_time) override;
void OnNewMonth(const datetime curr_time) override;
2025-09-22 09:09:20 -05:00
// Account status
2026-01-28 12:07:20 -05:00
void OnNewProfit(const ROnOpenClosePosition &profit, const datetime curr_time) override;
void OnOpenClosePosition(const ROnOpenClosePosition &pos) override;
void OnWithdrawalDeposit(const double value) override;
void OnInitNewPos(const ROnOpenClosePosition &position) override;
//--- Get the lot using GMPLO and type_get_lot
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
double GetLote(ENUM_ORDER_TYPE type, double entry_price, ulong deviation, ulong stop_limit);
2025-09-22 09:09:20 -05:00
2026-03-19 18:23:16 -05:00
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
//--- Obtain the SL by risk per operation
2025-09-22 09:09:20 -05:00
long GetSL(ENUM_ORDER_TYPE type, double entry_price, ulong deviation, ulong stop_limit);
2025-11-26 07:03:20 -05:00
2026-03-19 18:23:16 -05:00
//--- Functions for working with the get lot size mod
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
void TypeGetLot(ENUM_GET_LOT new_get_mode) { this.type_get_lot = new_get_mode; }
2025-09-22 09:09:20 -05:00
inline ENUM_GET_LOT TypeGetLot() const { return this.type_get_lot; }
2026-03-19 18:23:16 -05:00
2026-01-28 13:02:22 -05:00
//--- Risk management type
2025-11-26 07:03:20 -05:00
virtual inline ENUM_MODE_RISK_MANAGEMENT ModeRiskManagement() const = 0;
2026-03-19 18:23:16 -05:00
};
2025-11-26 07:03:20 -05:00
2026-03-19 18:23:16 -05:00
//+------------------------------------------------------------------+
2026-01-28 13:02:22 -05:00
//| Constructor |
2025-11-26 07:03:20 -05:00
//+------------------------------------------------------------------+
2026-03-19 18:23:16 -05:00
CRiskManagemet::CRiskManagemet(const ulong _magic, const ENUM_GET_LOT type_get_lot_)
2026-01-28 13:02:22 -05:00
: CRiskManagemetBase(_magic)
2026-03-19 18:23:16 -05:00
{
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
this.chosen_balance = AccountInfoDouble(ACCOUNT_BALANCE);
for(int i = 0 ; i < LOSS_PROFIT_COUNT; i++)
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
{
isCachedModifier[i] = false;
}
2025-09-24 14:00:58 -05:00
2026-01-29 08:19:03 -05:00
2025-09-22 09:09:20 -05:00
2026-01-29 08:19:03 -05:00
//---
2025-09-22 09:09:20 -05:00
2026-02-01 16:17:01 -05:00
const bool ac_i = account_status.IsInitialized();
2026-01-29 08:19:03 -05:00
2026-01-31 19:44:40 -05:00
2025-09-22 09:09:20 -05:00
//--- Registramos la clase para recibir eventos
// Basicos
2026-01-31 19:44:40 -05:00
CBasicEvents::Register(&this, BASICEVENT_REG_ALL_FLAG); // OnNewDay, Week, Month
2025-09-22 09:09:20 -05:00
// Para trabajar con las posiciones
2025-09-24 14:00:58 -05:00
account_status.RegisterEvents(&this,
2025-09-22 09:09:20 -05:00
(ACCOUNT_STATUS_REG_FLAG_ON_OPEN_CLOSE_POSITION |
ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT |
ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT |
(ac_i ? 0 : ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS)
2025-09-22 09:09:20 -05:00
));
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-09-24 14:00:58 -05:00
this.type_get_lot = type_get_lot_;
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
2025-11-26 07:03:20 -05:00
//---
2025-09-22 09:09:20 -05:00
AddLogger(loss_profits_manager); // Si pertenece..
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
AddLogger(m_hooks);
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-09-24 14:00:58 -05:00
if(ac_i) // Se crea luego de que se inicie
2026-01-28 13:02:22 -05:00
{
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
for(int i = PositionsTotal() - 1; i >= 0; i--)
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
{
ulong position_ticket = PositionGetTicket(i);
2025-11-26 07:03:20 -05:00
if(!PositionSelectByTicket(position_ticket))
2026-01-28 13:02:22 -05:00
continue;
2025-11-26 07:03:20 -05:00
2026-01-28 13:02:22 -05:00
ulong position_magic = PositionGetInteger(POSITION_MAGIC);
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
if(position_magic == _magic || _magic == NOT_MAGIC_NUMBER)
{
Position new_pos;
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
new_pos.type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
new_pos.ticket = position_ticket;
new_pos.profit = GetTotalPositionProfitNoCurrent(new_pos.ticket);
2026-01-31 19:44:40 -05:00
new_pos.magic = _magic;
2026-01-28 13:02:22 -05:00
AddArrayNoVerification2(open_positions, new_pos, RISK_MANAGEMENT_RESERVE_POS)
}
}
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
}
}
2026-01-31 19:44:40 -05:00
//+------------------------------------------------------------------+
2026-01-28 13:02:22 -05:00
//| Destructor |
//+------------------------------------------------------------------+
CRiskManagemet::~CRiskManagemet()
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
{
//---
CleanItems("RiskManagement");
//--- Registramos la clase para recibir eventos
// Basicos
2026-01-31 19:44:40 -05:00
if(CBasicEvents::IsActive())
2026-01-28 13:02:22 -05:00
CBasicEvents::Unregister(&this, BASICEVENT_REG_ALL_FLAG); // OnNewDay, Week, Month
// Account status
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
if(account_status.IsActive())
{
// Para trabajar con las posiciones
2026-01-31 19:44:40 -05:00
account_status.UnregisterEvents(&this,
2026-01-28 13:02:22 -05:00
(ACCOUNT_STATUS_REG_FLAG_ON_OPEN_CLOSE_POSITION |
ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT |
ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT |
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS)
);
}
2026-01-31 19:44:40 -05:00
}
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
//| |
//+------------------------------------------------------------------+
void CRiskManagemet::OnInitNewPos(const ROnOpenClosePosition &position)
2025-09-22 09:09:20 -05:00
{
if(position.position.magic == this.magic_number || this.magic_number == NOT_MAGIC_NUMBER)
2025-11-26 07:03:20 -05:00
{
AddArrayNoVerification2(open_positions, position.position, RISK_MANAGEMENT_RESERVE_POS)
2025-09-22 09:09:20 -05:00
}
2025-11-26 07:03:20 -05:00
}
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
//| Function to check if the maximum profit per day was exceeded |
2025-09-24 14:00:58 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
__forceinline bool RiskMNormal_IsSuperatedProfit(const double value, const double saved_value, void* ptr)
2025-09-24 14:00:58 -05:00
{
2025-09-22 09:09:20 -05:00
return (account_status_curr_profit > value);
}
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
//| Boolean function to check if a loss was overcome |
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
2025-11-26 07:03:20 -05:00
__forceinline bool RiskMNormal_IsSuperatedLoss(const double value, const double saved_value, void* ptr)
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
{
2025-09-22 09:09:20 -05:00
return (-account_status_curr_profit) > value;
2025-09-24 14:00:58 -05:00
2025-11-26 07:03:20 -05:00
}
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
//#define MQLARTICLES_RM_MULTI_EA_MODE
2025-09-24 14:00:58 -05:00
// En caso se decida usar este bot en varias cuentas use el define: MQLARTICLES_RM_MULTI_EA_MODE
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
2025-09-24 14:00:58 -05:00
//| Funciones para obtener el tipo de fucnion a superar |
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
FuncionLossProfitSuperate CRiskManagemet::SuperateModeToFunctionProfit(ENUM_TYPE_LOSS_PROFIT type) const
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
{
2026-01-28 13:02:22 -05:00
#ifdef MQLARTICLES_RM_MULTI_EA_MODE
2025-11-26 07:03:20 -05:00
2026-01-28 13:02:22 -05:00
return CRiskManagemetBase::WraperIsSupertedProfit;
2025-09-22 09:09:20 -05:00
2026-01-28 13:02:22 -05:00
#else
return RiskMNormal_IsSuperatedProfit;
#endif
}
2026-01-31 19:44:40 -05:00
//+------------------------------------------------------------------+
2026-01-28 13:02:22 -05:00
// Si es GMLPO empty
FuncionLossProfitSuperate CRiskManagemet::SuperateModeToFunctionLoss(ENUM_TYPE_LOSS_PROFIT type) const
{
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
#ifdef MQLARTICLES_RM_MULTI_EA_MODE
return type == LP_GMLPO ? (FuncionLossProfitSuperate)LossProfitEmptyFuncionSup : (FuncionLossProfitSuperate)CRiskManagemetBase::WraperIsSupertedLoss;
#else
2026-01-31 19:44:40 -05:00
return type == LP_GMLPO ? (FuncionLossProfitSuperate)LossProfitEmptyFuncionSup : (FuncionLossProfitSuperate)RiskMNormal_IsSuperatedLoss;
2026-01-28 13:02:22 -05:00
#endif
}
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
2026-01-31 19:44:40 -05:00
//| SetLote function |
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
void CRiskManagemet::SetLote(CGetLote *lote_ptr)
{
if(!CheckPointer(lote_ptr))
{
LogError("El puntero a CGetlote* es invalido", FUNCION_ACTUAL);
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
return;
}
2026-01-31 19:44:40 -05:00
//---
2026-01-28 13:02:22 -05:00
if(CheckPointer(get_lote) == POINTER_DYNAMIC) // is not equal to 0 (POINTER_INVALID)
{
//---
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
RemoveLogger(get_lote);
delete get_lote;
2026-01-31 19:44:40 -05:00
//---
2026-01-28 13:02:22 -05:00
AddLogger(lote_ptr);
this.get_lote = lote_ptr;
}
2026-01-31 19:44:40 -05:00
2026-01-28 13:02:22 -05:00
else //Si es null
{
AddLogger(lote_ptr);
this.get_lote = lote_ptr;
2025-11-26 07:03:20 -05:00
}
}
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
2025-11-26 07:03:20 -05:00
//| Function that will be executed once all the |
2026-01-28 13:02:22 -05:00
//| Maximum profit and loss have been added |
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
void CRiskManagemet::EndAddProfitLoss()
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
{
if(is_init)
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
return;
LogInfo(StringFormat("The total size between maximum profit and loss is: %d", loss_profits_manager.SizeValids()), FUNCION_ACTUAL);
2026-01-28 13:02:22 -05:00
loss_profits_manager.SetValues();
2025-09-22 09:09:20 -05:00
2026-01-28 13:02:22 -05:00
this.is_init = true;
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
}
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
//| Function to add a maximum loss |
2025-09-24 14:00:58 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
bool CRiskManagemet::AddLoss(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, ENUM_RISK_CALCULATION_MODE _mode, ENUM_TYPE_LOSS_PROFIT type, bool strict,
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
bool is_dynamic = false, string percentages_to_activate = NULL, string risks_to_be_applied = NULL)
2025-09-24 14:00:58 -05:00
{
2026-01-28 13:02:22 -05:00
2025-09-24 14:00:58 -05:00
//---
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
if(_percentage <= 0.00)
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
{
2025-09-24 14:00:58 -05:00
LogWarning(StringFormat("Invalid percentage %.2f for lost profit %s, will not be added to the main array", _percentage, EnumToString(type)), FUNCION_ACTUAL);
2025-09-22 09:09:20 -05:00
return false;
2026-01-28 13:02:22 -05:00
2025-12-21 12:41:35 -05:00
}
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
//---
2025-09-22 09:09:20 -05:00
2026-01-28 13:02:22 -05:00
if(_percentage > 100.00 && _mode == percentage)
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
{
LogWarning(StringFormat("Percentage %.2f for %s exceeds 100%%, limiting to 100%%", _percentage, EnumToString(type)), FUNCION_ACTUAL);
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
_percentage = 100.00;
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
}
2026-01-28 13:02:22 -05:00
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-09-24 14:00:58 -05:00
const int index = int(type);
2025-09-22 09:09:20 -05:00
if(index > 5 || index < 0)
{
2025-09-24 14:00:58 -05:00
LogError(StringFormat("Invalid maximum loss type: %s (index: %d)", EnumToString(type), index), FUNCION_ACTUAL);
2025-09-22 09:09:20 -05:00
return false;
2026-03-05 12:10:29 -05:00
2025-09-24 14:00:58 -05:00
}
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
//--- Creamos
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
CLossProfit* new_loss = NULL;
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
CRiskManagemetBase* basic_risk = ((CRiskManagemetBase*)&this);
2025-12-21 12:41:35 -05:00
// Por tipo
if(_mode == money)
2026-03-05 12:10:29 -05:00
{
2025-12-21 12:41:35 -05:00
switch(index)
2025-09-22 09:09:20 -05:00
{
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
case LP_GMLPO:
{
CLossLossGmlpo<CLossProfitMoney<CLossProfit>>* temp = new CLossLossGmlpo<CLossProfitMoney<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
new_loss = temp;
break;
}
2026-01-29 08:19:03 -05:00
2025-09-24 14:00:58 -05:00
case LP_MDL:
2025-09-22 09:09:20 -05:00
{
CLossLossMaxDaily<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxDaily<CLossProfitMoney<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
break;
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
}
case LP_MWL:
{
2025-09-24 14:00:58 -05:00
CLossLossMaxWeekly<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxWeekly<CLossProfitMoney<CLossProfit>>(false, basic_risk);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-24 14:00:58 -05:00
new_loss = temp;
2025-09-22 09:09:20 -05:00
break;
}
case LP_MML:
{
2026-02-14 17:00:45 -05:00
CLossLossMaxMon<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxMon<CLossProfitMoney<CLossProfit>>(false, basic_risk);
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-11-26 07:03:20 -05:00
new_loss = temp;
break;
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
}
case LP_ML:
{
CLossLossMax<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMax<CLossProfitMoney<CLossProfit>>(false, basic_risk);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
2025-11-26 07:03:20 -05:00
break;
2025-09-22 09:09:20 -05:00
}
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
case LP_ML_PICO:
2026-02-14 17:00:45 -05:00
2025-09-22 09:09:20 -05:00
{
2026-01-29 10:49:55 -05:00
2026-01-31 19:44:40 -05:00
CLossLossMaxDesdeArriba<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxDesdeArriba<CLossProfitMoney<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2026-01-29 10:49:55 -05:00
2025-09-22 09:09:20 -05:00
new_loss = temp;
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
break;
}
}
2025-09-24 14:00:58 -05:00
}
2025-09-22 09:09:20 -05:00
else // percentage
{
switch(index)
{
case LP_GMLPO:
{
2025-12-21 12:41:35 -05:00
CLossLossGmlpo<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossGmlpo<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
new_loss = temp;
2025-09-22 09:09:20 -05:00
break;
2025-09-22 09:09:20 -05:00
}
2025-09-22 09:09:20 -05:00
case LP_MDL:
{
2026-03-05 12:10:29 -05:00
2025-09-22 09:09:20 -05:00
CLossLossMaxDaily<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxDaily<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
2026-02-14 17:00:45 -05:00
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
new_loss = temp;
break;
}
case LP_MWL:
{
CLossLossMaxWeekly<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxWeekly<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
new_loss = temp;
2025-09-22 09:09:20 -05:00
break;
}
case LP_MML:
{
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
CLossLossMaxMon<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxMon<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
new_loss = temp;
2025-09-22 09:09:20 -05:00
break;
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
}
case LP_ML:
2025-09-22 09:09:20 -05:00
{
2025-09-22 09:09:20 -05:00
CLossLossMax<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMax<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
new_loss = temp;
2026-03-05 12:10:29 -05:00
break;
2025-09-22 09:09:20 -05:00
2026-02-14 17:00:45 -05:00
}
2025-09-22 09:09:20 -05:00
case LP_ML_PICO:
{
CLossLossMaxDesdeArriba<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxDesdeArriba<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
new_loss = temp;
break;
}
2025-12-21 12:41:35 -05:00
}
2025-09-22 09:09:20 -05:00
}
2025-09-22 09:09:20 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
if(!loss_profits_manager.Add(new_loss))
{
2025-09-22 09:09:20 -05:00
delete new_loss;
2025-09-22 09:09:20 -05:00
return false;
}
2026-02-14 17:00:45 -05:00
2025-09-22 09:09:20 -05:00
//---
2026-01-29 10:49:55 -05:00
new_loss.SetPtrSuperated(GetPtrLossProfits());
2025-09-22 09:09:20 -05:00
//---
2026-02-14 17:00:45 -05:00
if(is_dynamic && percentages_to_activate != NULL && risks_to_be_applied != NULL)
2025-09-22 09:09:20 -05:00
2026-01-28 12:07:20 -05:00
{
2025-09-22 09:09:20 -05:00
if(!isCachedModifier[index])
{
new_loss.SetDynamic(percentages_to_activate, risks_to_be_applied, this.chosen_balance);
2026-02-14 17:00:45 -05:00
2025-09-22 09:09:20 -05:00
LogInfo(StringFormat("Dynamic maximum loss %s successfully configured", EnumToString(type)), FUNCION_ACTUAL);
2026-01-28 12:07:20 -05:00
}
2025-09-22 09:09:20 -05:00
else
2025-09-22 09:09:20 -05:00
{
LogError(StringFormat("Maximum loss %s already has an active modifier", EnumToString(type)), FUNCION_ACTUAL);
2026-01-28 13:02:22 -05:00
}
2025-09-22 09:09:20 -05:00
}
else
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
{
LogInfo(StringFormat("Maximum loss %s added: %.2f%s", EnumToString(type), _percentage, (_mode == money ? "money" : "%")), FUNCION_ACTUAL);
2025-09-22 09:09:20 -05:00
}
return true;
2025-11-26 07:03:20 -05:00
}
2025-09-22 09:09:20 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
//| Function to add a maximum gain |
//+------------------------------------------------------------------+
2025-11-26 07:03:20 -05:00
bool CRiskManagemet::AddProfit(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, ENUM_RISK_CALCULATION_MODE _mode, ENUM_TYPE_LOSS_PROFIT type, bool is_strict_,
2025-09-22 09:09:20 -05:00
bool is_dynamic = false, string percentages_to_activate = NULL, string risks_to_be_applied = NULL)
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
{
//---
if(_percentage <= 0.00)
{
LogWarning(StringFormat("Invalid percentage %.2f for maximum gain %s, will not be added to the main array", _percentage, EnumToString(type)), FUNCION_ACTUAL);
return false;
}
2026-02-14 17:00:45 -05:00
2025-09-22 09:09:20 -05:00
//---
2025-09-24 14:00:58 -05:00
if(_percentage > 100.00 && _mode == percentage)
{
LogWarning(StringFormat("Percentage %.2f for %s exceeds 100%%, limiting to 100%%", _percentage, EnumToString(type)), FUNCION_ACTUAL);
_percentage = 100.00;
2025-09-22 09:09:20 -05:00
}
//---
const int index = int(type);
2026-01-31 19:44:40 -05:00
if(index < 6 || index > 10) // Profits: LP_MDP=6 a LP_MP_BAJO=10
2025-09-22 09:09:20 -05:00
{
2025-09-24 14:00:58 -05:00
LogError(StringFormat("Invalid maximum gain type: %s (index: %d)", EnumToString(type), index), FUNCION_ACTUAL);
2025-09-22 09:09:20 -05:00
return false;
}
//--- Creamos
CLossProfit* new_profit = NULL;
CRiskManagemetBase* basic_risk = ((CRiskManagemetBase*)&this);
2025-11-26 07:03:20 -05:00
2026-01-28 13:02:22 -05:00
2025-11-26 07:03:20 -05:00
// Ajustar <EFBFBD>ndice para el switch (restar 6 para que LP_MDP=0, LP_MWP=1, etc.)
2025-09-22 09:09:20 -05:00
const int switch_index = index - 6;
2026-01-31 19:44:40 -05:00
2025-09-22 09:09:20 -05:00
// Por tipo
if(_mode == money)
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
{
switch(switch_index)
{
case 0: // LP_MDP
{
2026-03-19 18:23:16 -05:00
2025-09-22 09:09:20 -05:00
CLossProfitMaxDaily<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxDaily<CLossProfitMoney<CLossProfit>>(false, basic_risk);
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
break;
}
2025-11-26 07:03:20 -05:00
case 1: // LP_MWP
2025-09-22 09:09:20 -05:00
{
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
CLossProfitMaxWeekly<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxWeekly<CLossProfitMoney<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
}
2025-11-26 07:03:20 -05:00
case 2: // LP_MMP
2025-09-22 09:09:20 -05:00
{
CLossProfitMaxMon<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxMon<CLossProfitMoney<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
}
case 3: // LP_MP
{
2026-01-31 19:44:40 -05:00
2025-09-22 09:09:20 -05:00
CLossProfitMax<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMax<CLossProfitMoney<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
}
case 4: // LP_MP_BAJO
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
{
2026-01-07 11:00:48 -05:00
CLossProfitMaxDesdeBaajo<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxDesdeBaajo<CLossProfitMoney<CLossProfit>>(false, basic_risk);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2026-01-31 19:44:40 -05:00
2025-09-22 09:09:20 -05:00
new_profit = temp;
break;
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
}
}
}
else // percentage
2026-01-07 11:00:48 -05:00
{
switch(switch_index)
2026-01-31 19:44:40 -05:00
2026-01-07 11:00:48 -05:00
{
case 0: // LP_MDP
2025-09-22 09:09:20 -05:00
{
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
CLossProfitMaxDaily<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMaxDaily<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
new_profit = temp;
2026-01-28 13:02:22 -05:00
break;
2025-09-22 09:09:20 -05:00
}
2025-09-24 14:00:58 -05:00
case 1: // LP_MWP
2025-09-22 09:09:20 -05:00
{
CLossProfitMaxWeekly<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMaxWeekly<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2026-01-31 19:44:40 -05:00
2025-09-22 09:09:20 -05:00
new_profit = temp;
break;
}
case 2: // LP_MMP
{
CLossProfitMaxMon<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMaxMon<CLossProfitPercentage<CLossProfit>>(false, basic_risk);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
}
2025-11-10 09:33:30 -05:00
case 3: // LP_MP
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
{
2025-09-22 09:09:20 -05:00
CLossProfitMax<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMax<CLossProfitPercentage<CLossProfit>>(false, basic_risk);