//+------------------------------------------------------------------+ //| RiskManagementBases.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Leo." #property link "https://www.mql5.com" #property strict #ifndef RISK_MANAGEMENT_BASES_MQH #define RISK_MANAGEMENT_BASES_MQH #include "AccountStatus.mqh" //--- 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 //+------------------------------------------------------------------+ //| Base Class CRiskManagement | //+------------------------------------------------------------------+ class CRiskManagemetBase : public CAccountGestor { protected: CTrade trade; //Instancia de ctrade Position open_positions[]; //Tickets abiertos por el maic 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 bool positions_open; // double curr_profit; int8_t c; // Identifier void GetPositionsProfit(); // Function to get total profit from open positions public: CRiskManagemetBase(ulong magic_); //--- virtual double GetValorWithApplied(double percentage_, ENUM_TYPE_LOSS_PROFIT type, ENUM_APPLIED_PERCENTAGES applied) const = 0; // Function to get value based on max loss or gain type //--- virtual double GetExtraValueForLossProfit() { return 0; } //--- Function to set general class parameters virtual void SetGeneralParameters(MqlParam ¶ms[]); inline int8_t d() const { return c; } //--- 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 int GetPositions(uint flags) const; // Get total open positions filtered by flags inline int16_t GetPositionsTotal() const { return (int16_t)open_positions.Size(); } void CloseAllPositions(uint flags = FLAG_CLOSE_ALL_LOSS | FLAG_CLOSE_ALL_PROFIT | FLAG_POSITION_TYPE_BUY | FLAG_POSITION_TYPE_SELL); void CloseAllOrders(uint flags); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CRiskManagemetBase::CRiskManagemetBase(ulong magic_) { ArrayResize(open_positions, 0, RISK_MANAGEMENT_RESERVE_POS); 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_; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CRiskManagemetBase::CloseAllOrders(uint flags) { for(int i = OrdersTotal() - 1; i >= 0; i--) { ulong ticket = OrderGetTicket(i); ResetLastError(); if(OrderSelect(ticket)) { ENUM_ORDER_TYPE type_order = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); ulong magic = OrderGetInteger(ORDER_MAGIC); 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); } } } //+------------------------------------------------------------------+ //| Function to obtain the number of open positions | //+------------------------------------------------------------------+ int CRiskManagemetBase::GetPositions(uint flags) const { int count = 0; for(int16_t i = 0; i < (int16_t)open_positions.Size() ; i++) { ENUM_POSITION_TYPE type = this.open_positions[i].type; if((flags & FLAG_POSITION_TYPE_BUY) != 0) if(type == POSITION_TYPE_BUY) count++; if((flags & FLAG_POSITION_TYPE_SELL) != 0) if(type == POSITION_TYPE_SELL) count++; } return count; } //+---------------------------------------------------------------------------+ //| Function to close all positions opened by the magic number or by the user | //+---------------------------------------------------------------------------+ void CRiskManagemetBase::CloseAllPositions(uint flags = FLAG_CLOSE_ALL_LOSS | FLAG_CLOSE_ALL_PROFIT | FLAG_POSITION_TYPE_BUY | FLAG_POSITION_TYPE_SELL) { for(int i = (int)this.open_positions.Size() - 1; i >= 0; i--) { bool close = false; if(!PositionSelectByTicket(this.open_positions[i].ticket)) continue; // Si no se puede seleccionar la posición, continuar double profit = PositionGetDouble(POSITION_PROFIT); ENUM_POSITION_TYPE type = this.open_positions[i].type; // Verificar si el tipo de posición está en los flags if((type == POSITION_TYPE_BUY && (flags & FLAG_POSITION_TYPE_BUY) == 0) || (type == POSITION_TYPE_SELL && (flags & FLAG_POSITION_TYPE_SELL) == 0)) continue; if((flags & FLAG_CLOSE_ALL_PROFIT) != 0 && profit > 0) { close = trade.PositionClose(this.open_positions[i].ticket); } else if((flags & FLAG_CLOSE_ALL_LOSS) != 0 && profit < 0) { close = trade.PositionClose(this.open_positions[i].ticket); } } } //+------------------------------------------------------------------+ #endif //+------------------------------------------------------------------+