//+------------------------------------------------------------------+ //| 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" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // 1. Solo peude tener 1 tipo de perdida en el manager no mas.. // osea solo peudes tener un MDL en el manager no dos limites // 2. tamaños fijos de arrays para evitar el overhead de una rray dinamico // como el 1# punto se cumple (maximo podemos tener X puntos donde x se sabe en compilacion) por lo que podemos // tener ya el array al maximo tamaño que podra tener este.. // 3. Una vez que ya se agrega NO se peude quitar //--- class CLossProfitManager : public CAllClassEventsBasic { private: //--- CLossProfit* empty_obj; //--- CLossProfit* m_losses_profits[LOSS_PROFIT_COUNT]; // todos los punteros de losses profits bool m_is_add[LOSS_PROFIT_COUNT]; // Si esta añadido (solo uno de x tipo) //--- Indices validos // en este array se ubican todos los indices (referente a m_lossesesporifts) // que son validos (esto para evitar chekear con NULL) // osea es una lista de indices en la cual estan todos los indices validos int m_valid_indexes[LOSS_PROFIT_COUNT]; int m_valid_indexes_size; //--- Optimizaicon extra // Tambien para iterar rapido sobre profit\losses // tenemos arrays fijos //- CLossProfit* m_profits[LOSS_PROFIT_COUNT_MAXTYPE]; int m_profits_size; int m_last_idx_profit_sup; //- CLossProfit* m_losses[LOSS_PROFIT_COUNT_MAXTYPE]; 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]; } //--- Objeto vacio static CLossLossGmlpo> EMPTY_OBJ; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CLossLossGmlpo> CLossProfitManager::EMPTY_OBJ(true, NULL); //+------------------------------------------------------------------+ //| Contructor y Destructor | //+------------------------------------------------------------------+ CLossProfitManager::CLossProfitManager() : m_valid_indexes_size(0), m_profits_size(0), m_losses_size(0), m_last_idx_profit_sup(-1), m_last_idx_loss_sup(-1) { //--- for(int i = 0; i < LOSS_PROFIT_COUNT; i++) m_losses_profits[i] = NULL; //--- ArrayInitialize(m_is_add, 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 = 0; m_profits_size = 0; m_losses_size = 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; } //--- m_valid_indexes[m_valid_indexes_size++] = idx; //--- const ENUM_LOSS_PROFIT typelp = new_loss_profit.TypeLossProfit(); if(typelp == T_LOSS) { m_losses[m_losses_size++] = new_loss_profit; } else if(typelp == T_PROFIT) { m_profits[m_profits_size++] = new_loss_profit; } //--- 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 //+------------------------------------------------------------------+