MQLArticles/RM/RiskManagement.mqh

1161 lines
90 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 |
//+------------------------------------------------------------------+
2025-09-24 14:00:58 -05:00
class CRiskManagemet : public CRiskManagemetBase
2025-12-21 12:41:35 -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
2025-11-26 07:03:20 -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-01-28 17:12:28 -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
2025-11-26 07:03:20 -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
//--- Update profits function
void UpdateProfit(const double &profit, const double& acc_total_profit);
2026-01-29 10:49:55 -05:00
2026-01-28 12:07:20 -05:00
virtual void OnOpenTrade() { }
2026-01-28 13:02:22 -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-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
2025-09-24 14:00:58 -05:00
public:
2025-09-22 09:09:20 -05:00
//--- Constructor and Destructor
2026-01-28 17:12:28 -05:00
CRiskManagemet(const ulong& _magic, const ENUM_GET_LOT& type_get_lot_, const bool& is_global);
2025-09-22 09:09:20 -05:00
~CRiskManagemet();
2025-09-22 09:09:20 -05:00
//--- Set
void EndAddProfitLoss();
virtual void SetGeneralParameters(MqlParam &params[]) = 0;
2026-01-28 12:07:20 -05:00
void SetLote(CGetLote* lote_ptr);
inline void SetStopLoss(double dist_open_sl) { this.StopLoss = (long)ConvertPriceToPoints(_Symbol, dist_open_sl); }
2026-01-28 13:02:22 -05:00
inline void SetStopLoss(long _sl_point_) { this.StopLoss = _sl_point_; }
2026-01-28 12:07:20 -05:00
//--- Get losses and profits
const CLossProfit* const GetLossOrProfit(const ENUM_TYPE_LOSS_PROFIT _type) const { return loss_profits_manager[_type]; }
2026-01-28 13:02:22 -05:00
2026-01-28 12:07:20 -05:00
2025-09-22 09:09:20 -05:00
//--- Superated funcionts
const CLossProfitManager* GetLossProfitManager() const { return loss_profits_manager; }
2026-01-29 08:19:03 -05:00
2025-12-21 12:41:35 -05:00
//--- Add
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
// Modificators
2026-01-29 08:19:03 -05:00
bool AddModificator(CExtraModifications* modificator); // Modificator pointer
2025-09-22 09:09:20 -05:00
__forceinline bool AddModificator(CExtraModifications &modificator) { return AddModificator(&modificator); }
2026-01-28 12:07:20 -05:00
2025-09-22 09:09:20 -05:00
2026-01-28 12:07:20 -05:00
2025-09-22 09:09:20 -05:00
// Hook
2026-01-28 12:07:20 -05:00
bool AddRmHook(IRiskManagementHook* hook);
__forceinline bool AddRmHook(IRiskManagementHook& hook) { return AddRmHook(&hook); }
// Loss
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
2025-09-22 09:09:20 -05:00
// Profit
bool AddProfit(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, ENUM_RISK_CALCULATION_MODE _mode, ENUM_TYPE_LOSS_PROFIT type, bool is_strict_,
bool is_dynamic = false, string percentages_to_activate = NULL, string risks_to_be_applied = NULL); // Profit
2026-01-28 17:12:28 -05:00
//--- Functions inherited from CAccountGestor
2025-09-22 09:09:20 -05:00
2026-01-28 17:12:28 -05:00
// Basic events
void OnNewDay(const datetime& curr_time) override;
void OnNewWeek(const datetime& curr_time) override;
void OnNewMonth(const datetime& curr_time) override;
// Account status
void OnNewProfit(const ROnOpenClosePosition &profit, const datetime& curr_time) override;
void OnOpenClosePosition(const ROnOpenClosePosition &pos) override;
2025-09-22 09:09:20 -05:00
void OnWithdrawalDeposit(const double& value) override;
2026-01-28 12:07:20 -05:00
void OnInitNewPos(const ROnOpenClosePosition &position) override;
//--- Get the lot using GMPLO and type_get_lot
double GetLote(ENUM_ORDER_TYPE type, double entry_price, ulong deviation, ulong stop_limit);
//--- 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
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
//--- Functions for working with the get lot size mod
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
void TypeGetLot(ENUM_GET_LOT new_get_mode) { this.type_get_lot = new_get_mode; }
inline ENUM_GET_LOT TypeGetLot() const { return this.type_get_lot; }
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
//--- Magic number
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
inline ulong MagicNumber() const { return this.magic_number; }
2026-01-28 13:02:22 -05:00
2025-11-26 07:03:20 -05:00
//--- Risk management type
2025-11-26 07:03:20 -05:00
virtual inline ENUM_MODE_RISK_MANAGEMENT ModeRiskManagement() const = 0;
};
2026-01-28 13:02:22 -05:00
2025-11-26 07:03:20 -05:00
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
2025-11-26 07:03:20 -05:00
//| Constructor |
2025-09-22 09:09:20 -05:00
2025-09-24 14:00:58 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
CRiskManagemet::CRiskManagemet(const ulong& _magic, const ENUM_GET_LOT& type_get_lot_, const bool& is_global)
2026-01-28 13:02:22 -05:00
: CRiskManagemetBase(_magic, is_global)
2025-09-22 09:09:20 -05:00
{
2025-09-24 14:00:58 -05:00
//---
2026-01-29 08:19:03 -05:00
2025-09-22 09:09:20 -05:00
this.chosen_balance = AccountInfoDouble(ACCOUNT_BALANCE);
2026-01-29 08:19:03 -05:00
for(int i = 0 ; i < LOSS_PROFIT_COUNT; i++)
2025-09-22 09:09:20 -05:00
2026-01-29 08:19:03 -05:00
{
isCachedModifier[i] = false;
2025-09-22 09:09:20 -05:00
}
2026-01-29 08:19:03 -05:00
2025-09-22 09:09:20 -05:00
//---
const bool ac_i = account_status.IsInitialized();
2025-09-24 14:00:58 -05:00
//--- Registramos la clase para recibir eventos
2025-09-22 09:09:20 -05:00
// Basicos
CBasicEvents::Register(&this, BASICEVENT_REG_ALL_FLAG); // OnNewDay, Week, Month
2025-09-22 09:09:20 -05:00
// Para trabajar con las posiciones
account_status.RegisterEvents(&this,
2025-09-24 14:00:58 -05:00
(ACCOUNT_STATUS_REG_FLAG_ON_OPEN_CLOSE_POSITION |
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -05:00
ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT |
2025-09-22 09:09:20 -05:00
ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT |
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
(ac_i ? 0 : ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS)
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
//---
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
this.type_get_lot = type_get_lot_;
2025-09-24 14:00:58 -05:00
//---
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
loss_profits_manager = new CLossProfitManager(is_global); // Le pasamos is_global
2025-09-24 14:00:58 -05:00
2025-11-26 07:03:20 -05:00
m_hooks = new CRiskManagemeHookManager();
2025-09-22 09:09:20 -05:00
//---
2025-11-26 07:03:20 -05:00
2026-01-28 13:02:22 -05:00
AddLogger(loss_profits_manager, true); // Si pertenece..
AddLogger(m_hooks, false);
2025-11-26 07:03:20 -05:00
2026-01-28 13:02:22 -05:00
//---
if(ac_i) // Se crea luego de que se inicie
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
2026-01-28 17:12:28 -05:00
ulong position_ticket = PositionGetTicket(i);
2026-01-28 13:02:22 -05:00
if(!PositionSelectByTicket(position_ticket))
continue;
2026-01-28 17:12:28 -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-28 17:12:28 -05:00
if(position_magic == _magic || _magic == NOT_MAGIC_NUMBER)
2026-01-28 13:02:22 -05:00
{
Position new_pos;
new_pos.type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
new_pos.ticket = position_ticket;
new_pos.profit = GetTotalPositionProfitNoCurrent(new_pos.ticket);
new_pos.magic = _magic;
2026-01-28 17:12:28 -05:00
AddArrayNoVerification2(open_positions, new_pos, RISK_MANAGEMENT_RESERVE_POS)
2026-01-28 13:02:22 -05:00
}
}
}
}
//+------------------------------------------------------------------+
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
//| Destructor |
//+------------------------------------------------------------------+
CRiskManagemet::~CRiskManagemet()
2026-01-28 17:12:28 -05:00
{
2026-01-28 13:02:22 -05:00
//---
CleanItems("RiskManagement");
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
//--- Solo desregistrase si no es global (se elimina antes)
if(!m_is_global)
{
2026-01-28 17:12:28 -05:00
//--- Registramos la clase para recibir eventos
2026-01-28 13:02:22 -05:00
// Basicos
CBasicEvents::Unregister(&this, BASICEVENT_REG_ALL_FLAG); // OnNewDay, Week, Month
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
// Para trabajar con las posiciones
account_status.UnregisterEvents(&this,
(ACCOUNT_STATUS_REG_FLAG_ON_OPEN_CLOSE_POSITION |
2026-01-28 17:12:28 -05:00
ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT |
2026-01-28 13:02:22 -05:00
ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT |
ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS)
);
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-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
void CRiskManagemet::OnInitNewPos(const ROnOpenClosePosition &position)
2025-09-22 09:09:20 -05:00
{
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
if(position.position.magic == this.magic_number || this.magic_number == NOT_MAGIC_NUMBER)
{
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
AddArrayNoVerification2(open_positions, position.position, RISK_MANAGEMENT_RESERVE_POS)
}
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
//+------------------------------------------------------------------+
2025-09-24 14:00:58 -05:00
//| Function to check if the maximum profit per day was exceeded |
2025-09-22 09:09:20 -05:00
2025-11-26 07:03:20 -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
{
2025-09-24 14:00:58 -05:00
return (account_status_curr_profit > value);
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-09-24 14:00:58 -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
__forceinline bool RiskMNormal_IsSuperatedLoss(const double& value, const double& saved_value, void* ptr)
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-11-26 07:03:20 -05:00
return (-account_status_curr_profit) > value;
2025-09-22 09:09:20 -05:00
}
2026-01-28 13:02:22 -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
//+------------------------------------------------------------------+
2026-01-28 13:02:22 -05:00
//| Funciones para obtener el tipo de fucnion a superar |
//+------------------------------------------------------------------+
FuncionLossProfitSuperate CRiskManagemet::SuperateModeToFunctionProfit(ENUM_TYPE_LOSS_PROFIT type) const
{
return RiskMNormal_IsSuperatedProfit;
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
}
//+------------------------------------------------------------------+
2026-01-28 17:12:28 -05:00
// Si es GMLPO empty
2026-01-28 13:02:22 -05:00
FuncionLossProfitSuperate CRiskManagemet::SuperateModeToFunctionLoss(ENUM_TYPE_LOSS_PROFIT type) const
{
return type == LP_GMLPO ? (FuncionLossProfitSuperate)LossProfitEmptyFuncionSup : (FuncionLossProfitSuperate)RiskMNormal_IsSuperatedLoss;
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
}
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
//+------------------------------------------------------------------+
//| SetLote function |
//+------------------------------------------------------------------+
2026-01-28 17:12:28 -05:00
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);
return;
2026-01-28 17:12:28 -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-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
{
//---
delete get_lote;
2026-01-28 17:12:28 -05:00
RemoveLogger(get_lote);
2026-01-28 13:02:22 -05:00
//---
AddLogger(lote_ptr, false);
2026-01-28 17:12:28 -05:00
2026-01-28 13:02:22 -05:00
this.get_lote = lote_ptr;
}
else //Si es null
2026-01-28 17:12:28 -05:00
{
2026-01-28 13:02:22 -05:00
AddLogger(lote_ptr, false);
this.get_lote = lote_ptr;
}
}
2025-11-26 07:03:20 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
//| Function that will be executed once all the |
2025-11-26 07:03:20 -05:00
//| Maximum profit and loss have been added |
//+------------------------------------------------------------------+
2026-01-28 13:02:22 -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
{
2025-09-24 14:00:58 -05:00
if(is_init)
2025-09-22 09:09:20 -05:00
return;
2025-09-24 14:00:58 -05:00
LogInfo(StringFormat("The total size between maximum profit and loss is: %d", loss_profits_manager.SizeValids()), FUNCION_ACTUAL);
2025-09-22 09:09:20 -05:00
loss_profits_manager.SetValues();
this.is_init = true;
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
}
2026-01-28 13:02:22 -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
//| Function to add a maximum loss |
2025-09-22 09:09:20 -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
bool CRiskManagemet::AddLoss(double _percentage, ENUM_APPLIED_PERCENTAGES _applied, ENUM_RISK_CALCULATION_MODE _mode, ENUM_TYPE_LOSS_PROFIT type, bool 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-09-24 14:00:58 -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
2026-01-28 13:02:22 -05:00
if(_percentage <= 0.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
2025-12-21 12:41:35 -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;
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
if(_percentage > 100.00 && _mode == percentage)
2025-09-22 09:09:20 -05:00
{
2026-01-28 13:02:22 -05:00
2025-12-21 12:41:35 -05:00
LogWarning(StringFormat("Percentage %.2f for %s exceeds 100%%, limiting to 100%%", _percentage, EnumToString(type)), FUNCION_ACTUAL);
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
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
const int index = int(type);
2025-09-24 14:00:58 -05:00
if(index > 5 || index < 0)
2025-09-22 09:09:20 -05:00
{
LogError(StringFormat("Invalid maximum loss type: %s (index: %d)", EnumToString(type), index), FUNCION_ACTUAL);
return false;
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-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
//--- Creamos
2025-09-22 09:09:20 -05:00
CLossProfit* new_loss = NULL;
2025-12-21 12:41:35 -05:00
CRiskManagemetBase* basic_risk = ((CRiskManagemetBase*)&this);
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
// Por tipo
if(_mode == money)
{
switch(index)
{
2025-09-22 09:09:20 -05:00
case LP_GMLPO:
2025-12-21 12:41:35 -05:00
{
2025-09-22 09:09:20 -05:00
CLossLossGmlpo<CLossProfitMoney<CLossProfit>>* temp = new CLossLossGmlpo<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
2025-09-24 14:00:58 -05:00
break;
2025-09-22 09:09:20 -05:00
}
case LP_MDL:
2026-01-29 08:19:03 -05:00
{
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
CLossLossMaxDaily<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxDaily<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
break;
}
2025-09-24 14:00:58 -05:00
case LP_MWL:
2025-09-22 09:09:20 -05:00
{
CLossLossMaxWeekly<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxWeekly<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
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;
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
}
case LP_MML:
{
CLossLossMaxMon<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxMon<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
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-24 14:00:58 -05:00
2025-11-26 07:03:20 -05:00
break;
}
2025-09-22 09:09:20 -05:00
case LP_ML:
2025-11-26 07:03:20 -05:00
{
CLossLossMax<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMax<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
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_PICO:
2025-09-24 14:00:58 -05:00
{
2025-09-22 09:09:20 -05:00
2026-01-29 10:49:55 -05:00
CLossLossMaxDesdeArriba<CLossProfitMoney<CLossProfit>>* temp = new CLossLossMaxDesdeArriba<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
2025-09-22 09:09:20 -05:00
2026-01-29 10:49:55 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
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
}
}
else // percentage
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
{
switch(index)
{
case LP_GMLPO:
{
CLossLossGmlpo<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossGmlpo<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
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;
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
}
2025-09-22 09:09:20 -05:00
case LP_MDL:
{
2025-09-22 09:09:20 -05:00
CLossLossMaxDaily<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxDaily<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
2025-12-21 12:41:35 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
new_loss = temp;
break;
2025-09-22 09:09:20 -05:00
}
case LP_MWL:
{
CLossLossMaxWeekly<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxWeekly<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
2025-12-21 12:41:35 -05:00
break;
2025-09-22 09:09:20 -05:00
}
2025-09-22 09:09:20 -05:00
case LP_MML:
{
CLossLossMaxMon<CLossProfitPercentage<CLossProfit>>* temp = new CLossLossMaxMon<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
2025-11-26 07:03:20 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
2025-09-22 09:09:20 -05:00
new_loss = temp;
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
}
2025-11-26 07:03: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, m_is_global);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
2025-09-22 09:09:20 -05:00
break;
}
2025-12-21 12:41:35 -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, m_is_global);
temp.Init(_percentage, _applied, strict, SuperateModeToFunctionLoss(type));
new_loss = temp;
2025-09-22 09:09:20 -05:00
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
if(!loss_profits_manager.Add(new_loss))
2025-11-26 07:03:20 -05:00
{
2025-09-22 09:09:20 -05:00
delete new_loss;
2025-09-22 09:09:20 -05:00
return false;
}
2025-09-22 09:09:20 -05:00
//---
2026-01-28 12:07:20 -05:00
new_loss.SetPtrSuperated(GetPtrLossProfits());
2025-09-22 09:09:20 -05:00
2026-01-29 10:49:55 -05:00
2025-12-21 12:41:35 -05:00
//---
2025-09-22 09:09:20 -05:00
if(is_dynamic && percentages_to_activate != NULL && risks_to_be_applied != NULL)
{
2026-01-28 12:07:20 -05:00
if(!isCachedModifier[index])
2025-09-22 09:09:20 -05:00
2026-01-28 12:07:20 -05:00
{
2025-09-22 09:09:20 -05:00
new_loss.SetDynamic(percentages_to_activate, risks_to_be_applied, this.chosen_balance);
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
2026-01-28 12:07:20 -05:00
{
2025-09-22 09:09:20 -05:00
LogError(StringFormat("Maximum loss %s already has an active modifier", EnumToString(type)), FUNCION_ACTUAL);
2025-09-22 09:09:20 -05:00
}
}
2026-01-28 13:02:22 -05:00
else
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-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
}
return true;
2025-09-22 09:09:20 -05:00
}
2025-11-26 07:03:20 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:09:20 -05:00
//| Function to add a maximum gain |
//+------------------------------------------------------------------+
2025-09-22 09:09: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_,
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
//---
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;
}
//---
if(_percentage > 100.00 && _mode == percentage)
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
{
2025-09-24 14:00:58 -05:00
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);
if(index < 6 || index > 10) // Profits: LP_MDP=6 a LP_MP_BAJO=10
{
2026-01-28 17:12:28 -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;
2025-09-24 14:00:58 -05:00
}
2025-09-22 09:09:20 -05:00
//--- Creamos
CLossProfit* new_profit = NULL;
CRiskManagemetBase* basic_risk = ((CRiskManagemetBase*)&this);
// Ajustar <EFBFBD>ndice para el switch (restar 6 para que LP_MDP=0, LP_MWP=1, etc.)
2025-11-26 07:03:20 -05:00
const int switch_index = index - 6;
2026-01-28 13:02:22 -05:00
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
// Por tipo
2026-01-28 17:12:28 -05:00
if(_mode == money)
2025-09-22 09:09:20 -05:00
{
switch(switch_index)
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
{
case 0: // LP_MDP
{
CLossProfitMaxDaily<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxDaily<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2025-12-21 12:41:35 -05:00
2025-09-22 09:09:20 -05:00
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
2025-09-22 09:09:20 -05:00
case 1: // LP_MWP
{
2025-11-26 07:03:20 -05:00
CLossProfitMaxWeekly<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxWeekly<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2025-11-26 07:03:20 -05:00
2025-09-22 09:09:20 -05:00
new_profit = temp;
break;
}
case 2: // LP_MMP
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
{
2025-11-26 07:03:20 -05:00
CLossProfitMaxMon<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxMon<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
}
case 3: // LP_MP
{
CLossProfitMax<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMax<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
2026-01-28 17:12:28 -05:00
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2026-01-28 17:12:28 -05:00
new_profit = temp;
2025-09-22 09:09:20 -05:00
break;
}
case 4: // LP_MP_BAJO
{
CLossProfitMaxDesdeBaajo<CLossProfitMoney<CLossProfit>>* temp = new CLossProfitMaxDesdeBaajo<CLossProfitMoney<CLossProfit>>(false, basic_risk, m_is_global);
2025-09-24 14:00:58 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2025-09-22 09:09:20 -05:00
new_profit = temp;
2026-01-07 11:00:48 -05:00
2025-09-22 09:09:20 -05:00
break;
2026-01-28 17:12:28 -05:00
}
2025-09-22 09:09:20 -05:00
}
2026-01-28 13:02:22 -05:00
}
2025-09-22 09:09:20 -05:00
else // percentage
{
switch(switch_index)
2026-01-07 11:00:48 -05:00
{
case 0: // LP_MDP
2026-01-28 17:12:28 -05:00
{
2026-01-07 11:00:48 -05:00
CLossProfitMaxDaily<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMaxDaily<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2025-09-22 09:09:20 -05:00
2026-01-28 13:02:22 -05:00
new_profit = temp;
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
case 1: // LP_MWP
2026-01-28 13:02:22 -05:00
2025-09-22 09:09:20 -05:00
{
CLossProfitMaxWeekly<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMaxWeekly<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
2025-09-24 14:00:58 -05:00
2025-09-22 09:09:20 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
2026-01-28 17:12:28 -05:00
}
2025-09-22 09:09:20 -05:00
case 2: // LP_MMP
2026-01-28 17:12:28 -05:00
{
2025-09-22 09:09:20 -05:00
CLossProfitMaxMon<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMaxMon<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
new_profit = temp;
break;
}
case 3: // LP_MP
{
CLossProfitMax<CLossProfitPercentage<CLossProfit>>* temp = new CLossProfitMax<CLossProfitPercentage<CLossProfit>>(false, basic_risk, m_is_global);
2025-11-10 09:33:30 -05:00
temp.Init(_percentage, _applied, is_strict_, SuperateModeToFunctionProfit(type));
2025-09-22 09:09:20 -05:00
2025-12-21 12:41:35 -05:00
new_profit = temp;
2025-09-22 09:09:20 -05:00
break;