//+------------------------------------------------------------------+ //| Manager.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_MANAGERS_MQH #define MQLARTICLES_RM_LOSSPROFIT_MANAGERS_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include "Basic\\MaxLosses.mqh" #include "Basic\\MaxProfits.mqh" //+------------------------------------------------------------------+ //| Manager class to work with different poses | //+------------------------------------------------------------------+ // NOTA: // Esta clase no recibe EVENTOS de ningun tipo.. solo se heredo de CAllClassEventsBasic, para propagar logs.. // Y el estado global //--- class CLossProfitManager : public CAllClassEventsBasic { private: //--- CLossProfit* empty_obj; //--- CLossProfit* m_losses_profits[LOSS_PROFIT_COUNT]; bool m_is_add[LOSS_PROFIT_COUNT]; // Si esta añadido //--- Indices validos int m_valid_indexes[]; int m_valid_indexes_size; //--- CLossProfit* m_profits[]; int m_profits_size; int m_last_idx_profit_sup; //--- CLossProfit* m_losses[]; int m_losses_size; int m_last_idx_loss_sup; public: ~CLossProfitManager(); CLossProfitManager(); //--- __forceinline int SizeValids() const { return m_valid_indexes_size; } __forceinline int GetIndexValid(const int index) { return m_valid_indexes[index]; } //--- inline bool IsAdd(const ENUM_TYPE_LOSS_PROFIT type) const { return m_is_add[type]; } //--- Clear void Clear(); //--- Add bool Add(CLossProfit * new_loss_profit); // Add CLossProfit //--- Is Superated // Index __forceinline int GetLastIndexSuperatedProfit() const { return m_last_idx_profit_sup; } __forceinline int GetLastIndexSuperatedLoss() const { return m_last_idx_loss_sup; } // Ptr const CLossProfit* const GetLastLossSuperated() const { return m_losses[m_last_idx_loss_sup]; } const CLossProfit* const GetLastProfitSuperated() const { return m_profits[m_last_idx_profit_sup]; } // Type __forceinline int GetLastLossSuperatedType() const { return m_losses[m_last_idx_loss_sup].Type(); } __forceinline int GetLastProfitSuperatedType() const { return m_profits[m_last_idx_profit_sup].Type(); } // Main bool MaxProfitIsSuperated() const; bool MaxLossIsSuperated() const; //--- On void SetNewChossenBalanceForDynamicsAndSet(double _chosen_balance, bool update); void SetValues(); // Setear valores void SetValuesAndDynamic(); // Valores y dinamicos void CheckDynamic(); //--- void Summary() const; //--- CLossProfit* operator[](const ENUM_TYPE_LOSS_PROFIT type) const; CLossProfit* operator[](const int index) const { return m_losses_profits[index]; } }; //+------------------------------------------------------------------+ //| Contructor y Destructor | //+------------------------------------------------------------------+ CLossProfitManager::CLossProfitManager() { //--- m_valid_indexes_size = ArrayResize(m_valid_indexes, 0); m_profits_size = ArrayResize(m_profits, 0); m_losses_size = ArrayResize(m_losses, 0); m_last_idx_profit_sup = -1; m_last_idx_loss_sup = -1; //--- empty_obj = new CLossLossGmlpo>(true, NULL); for(int i = 0; i < LOSS_PROFIT_COUNT; i++) { m_losses_profits[i] = NULL; m_is_add[i] = false; } } //+------------------------------------------------------------------+ CLossProfitManager::~CLossProfitManager(void) { #ifdef MORE_INFO_LOSS_PROFIT_DEFINE FastLog(FUNCION_ACTUAL, INFO_TEXT, "Eliminado en CLossProfitManager"); #endif delete empty_obj; Clear(); // Eliminamos todos los punteros } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLossProfitManager::Summary(void) const { Print("------------"); Print("Number of losses to revise: ", m_losses_size); Print("Number of profits to revise: ", m_profits_size); Print("Total losses and profits: ", SizeValids()); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CLossProfitManager::MaxProfitIsSuperated(void) const { for(int i = 0; i < m_profits_size; i++) { if(m_profits[i].IsSuperated()) { ((CLossProfitManager*)&this).m_last_idx_profit_sup = i; return true; } } return false; } //+------------------------------------------------------------------+ bool CLossProfitManager::MaxLossIsSuperated(void) const { for(int i = 0; i < m_losses_size; i++) { if(m_losses[i].IsSuperated()) { ((CLossProfitManager*)&this).m_last_idx_loss_sup = i; return true; } } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLossProfitManager::SetValues() { for(int i = 0; i < m_valid_indexes_size; i++) { const int k = m_valid_indexes[i]; m_losses_profits[k].Set(); // Setea el valor m_losses_profits[k].SetSavedValue(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLossProfitManager::SetValuesAndDynamic() { for(int i = 0; i < m_valid_indexes_size; i++) { const int key = m_valid_indexes[i]; m_losses_profits[key].Set(); // Setea el valor if(m_losses_profits[key].IsDynamicMode()) // Check si es dinamico m_losses_profits[key].CheckAndModifyThePercentage(); // Modificamos } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLossProfitManager::SetNewChossenBalanceForDynamicsAndSet(double _chosen_balance, bool update) { for(int i = 0; i < m_valid_indexes_size; i++) { const int key = m_valid_indexes[i]; m_losses_profits[key].Set(); if(m_losses_profits[key].IsDynamicMode()) // Check si es dinamico { m_losses_profits[key].SetDynamic(_chosen_balance); // Modificamos if(update) m_losses_profits[key].CheckAndModifyThePercentage(); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLossProfitManager::CheckDynamic(void) { for(int i = 0; i < m_valid_indexes_size; i++) { const int key = m_valid_indexes[i]; if(m_losses_profits[key].IsDynamicMode()) // Check si es dinamico m_losses_profits[key].CheckAndModifyThePercentage(); // Modificamos } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLossProfitManager::Clear(void) { //--- ArrayInitialize(m_is_add, false); //--- m_valid_indexes_size = ArrayResize(m_valid_indexes, 0); m_profits_size = ArrayResize(m_profits, 0); m_losses_size = ArrayResize(m_losses, 0); //--- CleanItems("CLossProfitManager"); // Delete pointers (m_losses_profits (m_loggers) } //+------------------------------------------------------------------+ //| operator[] | //+------------------------------------------------------------------+ CLossProfit* CLossProfitManager::operator[](const ENUM_TYPE_LOSS_PROFIT type) const { return m_is_add[type] ? m_losses_profits[type] : empty_obj; } //+------------------------------------------------------------------+ //| Function that is executed every time a new item is added | //+------------------------------------------------------------------+ // check_duplicate: No tiene efecto bool CLossProfitManager::Add(CLossProfit * new_loss_profit) { //--- if(!CheckPointer(new_loss_profit)) { LogFatalError("The pointer to CLossProfit* is invalid", FUNCION_ACTUAL); Remover(); return false; } //--- const int idx = new_loss_profit.Type(); if(m_is_add[idx]) { LogWarning(StringFormat("The loss or gain %s has already been added, it will not be added.", new_loss_profit.Name()), FUNCION_ACTUAL); return false; } //--- ArrayResize(m_valid_indexes, m_valid_indexes_size + 1); m_valid_indexes[m_valid_indexes_size] = idx; m_valid_indexes_size++; //--- if(new_loss_profit.TypeLossProfit() == T_LOSS) { ArrayResize(m_losses, m_losses_size + 1); m_losses[m_losses_size] = new_loss_profit; m_losses_size++; } else if(new_loss_profit.TypeLossProfit() == T_PROFIT) { ArrayResize(m_profits, m_profits_size + 1); m_profits[m_profits_size] = new_loss_profit; m_profits_size++; } //--- m_is_add[idx] = true; m_losses_profits[idx] = new_loss_profit; //--- AddLogger(new_loss_profit); // Si son descendientes de CAllBasicClass return true; } //--- /* ADVERTENCIA: - Al momento de añadir items a esta clase, esta si son dinamicos las eliminara cuidado. - El unico que maneja esta clase es CRiskManagement, por lo que no se puede remover elementos WARNINGS: - When adding items to this class, if they are dynamic, be careful. - The only one that handles this class is CRiskManagement, so elements cannot be removed. */ #endif //+------------------------------------------------------------------+