2026-07-28 09:08:36 -05:00
//+------------------------------------------------------------------+
//| RiskManagementBases.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
# property copyright " Copyright 2025, Leo. "
# property link " https://www.mql5.com "
# property strict
# ifndef MQLARTICLES_RM_RISKMGMTBASES_MQH
# define MQLARTICLES_RM_RISKMGMTBASES_MQH
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
# include "AccountStatus.mqh"
//+------------------------------------------------------------------+
//| Defines\Enums |
//+------------------------------------------------------------------+
//--- Risk management classes
class CRiskManagemetBase ; // Base class
class CRiskManagemet ; // Parent class
class CRiskManagemetPersonal ; // Class for personal risk management
class CRiskManagemetPropFirm ; // Class for prop firm risk management
class CRiskPointer ; // Class to obtain a pointer based on the selected risk management
//---
class CLossProfit ; // Class to handle maximum losses or gains
class CLossProfitManager ; // Container class to manage CLossProfit objects
//---
# define RISK_MANAGEMENT_RESERVE_POS 10
//---
# ifndef RISK_MANAGEMENT_BASES_MAX_POS_OPEN
# define RISK_MANAGEMENT_BASES_MAX_POS_OPEN ( 64 )
# endif // RISK_MANAGEMENT_BASES_MAX_POS_OPEN
//---
// m_positions aamcena posiciones directamente en el array de m_positioncs de las posiciones de la cuenta
// No amcena hashes ni nada
//+------------------------------------------------------------------+
//| Base Class CRiskManagement |
//+------------------------------------------------------------------+
class CRiskManagemetBase : public CAccountGestor
{
protected :
//---
CTrade trade ; //Instancia de ctrade
int m_positions [ RISK_MANAGEMENT_BASES_MAX_POS_OPEN ] ;
//---
ulong magic_number ; //Numero magico
double daily_profit , weekly_profit , monthly_profit , gross_profit ; //Profits de la cuenta
datetime last_day_time ;
datetime last_weekly_time ;
datetime last_monthly_time ;
datetime init_trade_time ;
double account_profit ; //Ganancia de la cuenta NETA, no confundir con ganancia BRUTA desde que inicio la cuenta
int m_positions_size ;
bool positions_open ;
//---
bool TryRemoveFromArrayOfPos ( const int global_pos_index ) ;
//---
void GetPositionsProfit ( ) ; // Function to get total profit from open positions
public :
CRiskManagemetBase ( const ulong magic_ ) ;
~ CRiskManagemetBase ( ) ;
//---
double m_pos_current_profit ;
//---
virtual double GetValorWithApplied ( double percentage_ , int type , ENUM_APPLIED_PERCENTAGES applied ) const = 0 ; // Function to get value based on max loss or gain type
//--- Function to set general class parameters
virtual void SetGeneralParameters ( MqlParam & params [ ] ) ;
//--- Getters
//- Magic number
inline ulong MagicNumber ( ) const { return this . magic_number ; }
//--- General profit retrieval
inline double GrossProfit ( ) const { return this . gross_profit ; }
inline double WeeklyProfit ( ) const { return this . weekly_profit ; }
inline double DailyProfit ( ) const { return this . daily_profit ; }
inline double MontlyProfit ( ) const { return monthly_profit ; }
//--- Functions to work with open positions
__forceinline int GetPositions ( uint flags ) const ; // Get total open positions filtered by flags
__forceinline int GetPositionsTotal ( ) const { return m_positions_size ; }
__forceinline void CloseAllPositions ( uint flags = FLAG_CLOSE_ALL_LOSS | FLAG_CLOSE_ALL_PROFIT | FLAG_POSITION_TYPE_BUY | FLAG_POSITION_TYPE_SELL ) ;
void CloseAllOrders ( uint flags ) ;
//---
__forceinline void CalcProfit ( ) { m_pos_current_profit = g_account_open_positions . GetProfitMask ( m_positions , m_positions_size ) ; }
//---
static __forceinline bool WraperIsSupertedLoss ( const double value , const double saved_value , void * ptr ) { return ( ( CRiskManagemetBase * ) ptr ) . m_pos_current_profit > value ; }
static __forceinline bool WraperIsSupertedProfit ( const double value , const double saved_value , void * ptr ) { return - ( ( ( CRiskManagemetBase * ) ptr ) . m_pos_current_profit ) > value ; }
} ;
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CRiskManagemetBase : : CRiskManagemetBase ( const ulong magic_ )
:
daily_profit ( 0.00 ) , weekly_profit ( 0.00 ) , monthly_profit ( 0.00 ) , gross_profit ( 0.00 ) , last_day_time ( 0 ) , last_weekly_time ( 0 ) , last_monthly_time ( 0 )
, init_trade_time ( 0 ) , account_profit ( 0.00 ) , positions_open ( false )
{
//---
m_positions_size = 0 ;
//---
trade . SetExpertMagicNumber ( magic_ ) ;
if ( magic_ = = NOT_MAGIC_NUMBER )
LogWarning ( " No magic number has been chosen, taking into account all the magic numbers and the user's trades " , FUNCION_ACTUAL ) ;
this . magic_number = magic_ ;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CRiskManagemetBase : : ~ CRiskManagemetBase ( )
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CRiskManagemetBase : : CloseAllOrders ( uint flags )
{
for ( int i = OrdersTotal ( ) - 1 ; i > = 0 ; i - - )
{
const ulong ticket = OrderGetTicket ( i ) ;
//---
ResetLastError ( ) ;
if ( OrderSelect ( ticket ) )
{
ENUM_ORDER_TYPE type_order = ( ENUM_ORDER_TYPE ) OrderGetInteger ( ORDER_TYPE ) ;
const ulong magic = OrderGetInteger ( ORDER_MAGIC ) ;
const int bandera = OrderTypeToFlag ( type_order ) ;
if ( ( bandera & flags ) ! = 0 & & ( magic = = this . magic_number | | this . magic_number = = NOT_MAGIC_NUMBER ) )
{
if ( type_order = = ORDER_TYPE_BUY | | type_order = = ORDER_TYPE_SELL )
trade . PositionClose ( ticket ) ;
else
trade . OrderDelete ( ticket ) ;
}
}
else
{
LogError ( StringFormat ( " Error al selecionar la order %I64u, ultimo error = %d " , ticket , GetLastError ( ) ) , FUNCION_ACTUAL ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CRiskManagemetBase : : TryRemoveFromArrayOfPos ( const int global_pos_index )
{
//--- Find
int index = -1 ;
for ( int i = 0 ; i < m_positions_size ; i + + )
{
if ( m_positions [ i ] = = global_pos_index )
{
index = i ;
break ;
}
}
//--- Check is invalid
if ( index = = -1 )
return false ;
//--- Reduce size
m_positions_size - - ;
//--- Move
for ( int i = index ; i < m_positions_size ; i + + )
{
m_positions [ i ] = m_positions [ i + 1 ] ; // Move the elements
}
//---
return true ;
}
//+------------------------------------------------------------------+
//| Function to obtain the number of open positions |
//+------------------------------------------------------------------+
__forceinline int CRiskManagemetBase : : GetPositions ( uint flags ) const
{
return g_account_open_positions . GetPositionsMask ( m_positions , m_positions_size , flags ) ;
}
//+---------------------------------------------------------------------------+
//| Function to close all positions opened by the magic number or by the user |
//+---------------------------------------------------------------------------+
__forceinline void CRiskManagemetBase : : CloseAllPositions ( uint flags = FLAG_CLOSE_ALL_LOSS | FLAG_CLOSE_ALL_PROFIT | FLAG_POSITION_TYPE_BUY | FLAG_POSITION_TYPE_SELL )
{
g_account_open_positions . CloseAllPositionMask ( m_positions , m_positions_size , trade , flags ) ;
}
//+------------------------------------------------------------------+
# endif // MQLARTICLES_RM_RISKMGMTBASES_MQH
//+------------------------------------------------------------------+