2026-08-31 20:49:50 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| AccountStatus.mqh |
|
| | | //| Copyright 2025, Niquel Mendoza. |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2025, Niquel Mendoza."
|
| | | #property link "https://www.mql5.com"
|
| | | #property strict
|
| | |
|
| | | #ifndef MQLARTICLES_RM_ACCOUNTSTATUS_MQH
|
| | | #define MQLARTICLES_RM_ACCOUNTSTATUS_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-06 20:42:03 -05:00 | | | // #define MQLARTICLES_RM_USE_HASHMAP_TICKESTABLE
|
| | |
|
2026-09-12 19:41:52 -05:00 | | | #ifdef MQLARTICLES_RM_USE_HASHMAP_TICKESTABLE
|
2026-08-31 20:49:50 -05:00 | | | #include "TicketsTable.mqh"
|
2026-09-06 20:42:03 -05:00 | | | #else // MQLARTICLES_RM_USE_HASHMAP_TICKESTABLE
|
| | | #include "TinyTicketsTable.mqh"
|
| | |
|
| | | //--- defines explicitos.. para mismo comportamiento esperado en ambos
|
| | | #include <TSN\\GCol\\HashMap.mqh>
|
| | | #include <TSN\\GCol\\GenericHashes.mqh>
|
| | | #endif // MQLARTICLES_RM_USE_HASHMAP_TICKESTABLE
|
| | |
|
2026-08-31 20:49:50 -05:00 | | | //#include <Math/Stat/Stat.mqh>
|
| | |
|
2026-09-12 19:41:52 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
2026-08-31 20:49:50 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Defines |
|
| | | //+------------------------------------------------------------------+
|
| | | //--- Events
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION (4)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION (8)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY (16)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_ORDER_ADD (32)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_ORDER_UPDATE (64)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_ORDER_DELETE (128)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT (256)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT (512)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS (1024)
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ON_LOSS_PROFIT (2048)
|
| | |
|
| | | //--- All events
|
| | | #define ACCOUNT_STATUS_REG_FLAG_ALL (ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_ORDER_ADD | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_ORDER_UPDATE | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_ORDER_DELETE | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS | \
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_LOSS_PROFIT)
|
| | |
|
| | | //---
|
| | | #define ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_TP 1
|
| | | #define ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_SL 2
|
| | | #define ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_TP_SL (ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_TP|ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_SL)
|
| | |
|
| | | //---
|
| | | #define ACCOUNT_STATUS_FLAG_FREE (1)
|
| | | #define ACCOUNT_STATUS_FLAG_INIT (2)
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Global Variables |
|
| | | //+------------------------------------------------------------------+
|
| | | double account_status_curr_profit; // Profit en flotante - profit in float
|
| | | bool account_status_positions_open; // Flag indicating if there are open positions in the account
|
2026-09-12 19:41:52 -05:00 | | | CTicketsTable g_account_open_positions; // CTicketsTable type object for efficient ticket management
|
2026-08-31 20:49:50 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Class for account management |
|
| | | //+------------------------------------------------------------------+
|
| | | class CAccountStatus : public CAllClassEventsBasic
|
| | | {
|
| | | private:
|
| | | //--- Event Subscribers Arrays
|
| | | CAccountGestor* m_on_close_position[];
|
| | | int m_on_close_position_size;
|
| | |
|
| | | CAccountGestor* m_on_open_position[];
|
| | | int m_on_open_position_size;
|
| | |
|
| | | CAccountGestor* m_on_position_modify[];
|
| | | int m_on_position_modify_size;
|
| | |
|
| | | CAccountGestor* m_on_order_add[];
|
| | | int m_on_order_add_size;
|
| | |
|
| | | CAccountGestor* m_on_order_update[];
|
| | | int m_on_order_update_size;
|
| | |
|
| | | CAccountGestor* m_on_order_delete[];
|
| | | int m_on_order_delete_size;
|
| | |
|
| | | CAccountGestor* m_on_new_profit[];
|
| | | int m_on_new_profit_size;
|
| | |
|
| | | CAccountGestor* m_on_withdrawal_deposit[];
|
| | | int m_on_withdrawal_deposit_size;
|
| | |
|
| | | CAccountGestor* m_on_init_new_pos[];
|
| | | int m_on_init_new_pos_size;
|
| | |
|
| | | CAccountGestor* m_on_loss_profit[];
|
| | | int m_on_loss_profit_size;
|
| | |
|
| | |
|
| | | //---
|
| | | uint8_t m_flags;
|
| | |
|
| | | //---
|
| | | double account_daily_profit; // Account profit (adding EAs and user etc, total) daily
|
| | | double account_weekly_profit; // Account profit (adding EAs and user etc, total) weekly
|
| | | double account_monthly_profit; // Account profit (adding EAs and user etc, total) monthly
|
| | | double account_gross_profit; // Account profit (adding EAs and user etc, total) total
|
| | |
|
| | | //---
|
| | | ROrder last_order_struct;
|
| | |
|
| | | //--- Most recent structure of the opened or closed position
|
| | | ROnClosePosition last_struct;
|
| | |
|
| | | // Variables that store a property of the last deal (when adding a deal, TRADE_TRANSACTION_DEAL_ADD)
|
| | | ulong last_deal_ticket; // Ticket
|
| | | ENUM_DEAL_TYPE last_deal_type; // Deal type
|
| | | ulong last_deal_magic; // Magic
|
| | |
|
| | | // Variable that stores the last symbol for specific events (TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_ORDER_DELETE)
|
| | | string last_trans_symbol; // Symbol
|
| | |
|
| | | //--- Function to update profits
|
| | | void UpdateProfitInit();
|
| | | void UpdateProfit(const double new_profit);
|
| | |
|
| | | //---
|
| | | void RemoveFromArrayFast(CAccountGestor* &array[], int &size, CAccountGestor* &ptr);
|
| | |
|
| | | public:
|
| | | CAccountStatus();
|
| | | ~CAccountStatus();
|
| | |
|
| | | //--- Tipos (publcios para facil acceso.. recuerda NO modificar)
|
| | | datetime last_day_time; // Opening time of the current daily candle
|
| | | datetime last_weekly_time; // Opening time of the current weekly candle
|
| | | datetime last_monthly_time; // Opening time of the current monthly candle
|
| | |
|
| | | //--- Event Registration Method
|
| | | void RegisterEvents(CAccountGestor* ptr, const int flags);
|
| | | void UnregisterEvents(CAccountGestor* ptr, const int flags);
|
| | | void UnregisterEvent(CAccountGestor* ptr, const int event);
|
| | | void RegisterEvent(CAccountGestor* ptr, const int event);
|
| | |
|
| | | //--- Getter
|
| | | //- Profits
|
| | | inline double AccountGrossProfit() const { return account_gross_profit; }
|
| | | inline double AccountDailyProfit() const { return account_daily_profit; }
|
| | | inline double AccountWeeklyProfit() const { return account_weekly_profit; }
|
| | | inline double AccountMonthlyProfit() const { return account_monthly_profit; }
|
| | |
|
| | | //- Esta iniciado ?
|
| | | __forceinline bool IsInitialized() const { return (m_flags & ACCOUNT_STATUS_FLAG_INIT) != 0; }
|
| | |
|
| | | //- Aun esta activo?? (util para deinciacion en destrucotr de herederos de CAccountGestor)
|
| | | __forceinline bool IsActive() const { return (m_flags & ACCOUNT_STATUS_FLAG_FREE) == 0; }
|
| | |
|
| | | //- Ultima transaccion
|
| | | inline string LastTransctionSymbol() const { return last_trans_symbol; }
|
| | | __forceinline Position LastPosition() const { return last_struct.position; }
|
| | |
|
| | | //- Deals (solo en DEAL_TRANSACTION_ADD)
|
| | | __forceinline ulong LastDealMagic() const { return last_deal_magic; }
|
| | | __forceinline ulong LastDealTicket() const { return last_deal_ticket; }
|
| | |
|
| | | //--- Events
|
| | | void OnTradeTransactionEvent(const MqlTradeTransaction& trans); // Should be executed in OnTradeTransaction
|
| | | void OnInitEvent(); // Should be executed in OnInit, at the end
|
| | | void OnNewDay(const datetime curr_time) override final; // The function should be called every new day
|
| | | void OnNewWeek(const datetime curr_time) override final; // The function should be called every new week
|
| | | void OnNewMonth(const datetime curr_time) override final; // The function should be called every new month
|
| | |
|
| | | //--- Info functions
|
| | | void PrintLastOrder();
|
| | | void PrintLastPosition();
|
| | |
|
| | | //---
|
| | | void Deinit(const int reason);
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Constructor |
|
| | | //+------------------------------------------------------------------+
|
| | | CAccountStatus::CAccountStatus(void)
|
| | | :
|
| | | account_daily_profit(0.00), account_weekly_profit(0.00), account_gross_profit(0.00), account_monthly_profit(0.00),
|
| | | m_on_close_position_size(0), m_on_open_position_size(0), m_on_position_modify_size(0), m_on_order_add_size(0), m_on_order_update_size(0),
|
| | | m_on_order_delete_size(0), m_on_new_profit_size(0), m_on_withdrawal_deposit_size(0), m_on_init_new_pos_size(0), m_on_loss_profit_size(0),
|
| | | m_flags(0)
|
| | | {
|
| | | //---
|
| | | account_status_curr_profit = 0.00;
|
| | | account_status_positions_open = false;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Destructor |
|
| | | //+------------------------------------------------------------------+
|
| | | CAccountStatus::~CAccountStatus()
|
| | | {
|
| | | //Print("Entrando");
|
| | | //CleanItems("AccountStatus");
|
| | | // CBasicEvents::Unregister(CAllClassEventsBasic *ptr,const uchar flags) no tiene sentido. dado que es global...
|
| | | // Entonces es eliminar cuando se elimina... asi que dejemos que mql5 haga loq eu tenga que hacer
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | __forceinline void CAccountStatus_Deinit(const int reason)
|
| | | {
|
| | | // WRapper para poder pasarlo
|
| | | account_status.Deinit(reason);
|
| | | }
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::Deinit(const int reason)
|
| | | {
|
| | | //--- Limpiamos todos los arrays
|
| | | // SOlo ejecutamos en caso la clase solo tenga la benadera de incilzaicon
|
| | | // En caso tenga otra bandera como free entonces no se ejeucta
|
| | | if((m_flags & ACCOUNT_STATUS_FLAG_INIT) == ACCOUNT_STATUS_FLAG_INIT)
|
| | | {
|
| | | //---
|
| | | m_on_close_position_size = ArrayResize(m_on_close_position, 0);
|
| | | m_on_open_position_size = ArrayResize(m_on_open_position, 0);
|
| | | m_on_position_modify_size = ArrayResize(m_on_position_modify, 0);
|
| | | m_on_order_add_size = ArrayResize(m_on_order_add, 0);
|
| | | m_on_order_update_size = ArrayResize(m_on_order_update, 0);
|
| | | m_on_order_delete_size = ArrayResize(m_on_order_delete, 0);
|
| | | m_on_new_profit_size = ArrayResize(m_on_new_profit, 0);
|
| | | m_on_withdrawal_deposit_size = ArrayResize(m_on_withdrawal_deposit, 0);
|
| | | m_on_init_new_pos_size = ArrayResize(m_on_init_new_pos, 0);
|
| | | m_on_loss_profit_size = ArrayResize(m_on_loss_profit, 0);
|
| | |
|
| | | //---
|
| | | m_flags |= ACCOUNT_STATUS_FLAG_FREE;
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Registro y De-Registro |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::RegisterEvents(CAccountGestor* ptr, const int flags)
|
| | | {
|
| | | //---
|
| | | if(!CheckPointer(ptr))
|
| | | {
|
| | | LogFatalError("Puntero invalido registrado", FUNCION_ACTUAL);
|
| | | Remover();
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION) != 0)
|
| | | m_on_open_position[ArrayResize(m_on_open_position, (++m_on_open_position_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION) != 0)
|
| | | m_on_close_position[ArrayResize(m_on_close_position, (++m_on_close_position_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY) != 0)
|
| | | m_on_position_modify[ArrayResize(m_on_position_modify, (++m_on_position_modify_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_ORDER_ADD) != 0)
|
| | | m_on_order_add[ArrayResize(m_on_order_add, (++m_on_order_add_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_ORDER_UPDATE) != 0)
|
| | | m_on_order_update[ArrayResize(m_on_order_update, (++m_on_order_update_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_ORDER_DELETE) != 0)
|
| | | m_on_order_delete[ArrayResize(m_on_order_delete, (++m_on_order_delete_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT) != 0)
|
| | | m_on_new_profit[ArrayResize(m_on_new_profit, (++m_on_new_profit_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT) != 0)
|
| | | m_on_withdrawal_deposit[ArrayResize(m_on_withdrawal_deposit, (++m_on_withdrawal_deposit_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS) != 0)
|
| | | m_on_init_new_pos[ArrayResize(m_on_init_new_pos, (++m_on_init_new_pos_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_LOSS_PROFIT) != 0)
|
| | | m_on_loss_profit[ArrayResize(m_on_loss_profit, (++m_on_loss_profit_size)) - 1] = ptr;
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::RegisterEvent(CAccountGestor* ptr, const int event)
|
| | | {
|
| | | //---
|
| | | if(!CheckPointer(ptr))
|
| | | {
|
| | | LogFatalError("Puntero invalido registrado", FUNCION_ACTUAL);
|
| | | Remover();
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION)
|
| | | m_on_close_position[ArrayResize(m_on_close_position, (++m_on_close_position_size)) - 1] = ptr;
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION)
|
| | | m_on_open_position[ArrayResize(m_on_open_position, (++m_on_open_position_size)) - 1] = ptr;
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY)
|
| | | m_on_position_modify[ArrayResize(m_on_position_modify, (++m_on_position_modify_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_ORDER_ADD)
|
| | | m_on_order_add[ArrayResize(m_on_order_add, (++m_on_order_add_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_ORDER_UPDATE)
|
| | | m_on_order_update[ArrayResize(m_on_order_update, (++m_on_order_update_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_ORDER_DELETE)
|
| | | m_on_order_delete[ArrayResize(m_on_order_delete, (++m_on_order_delete_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT)
|
| | | m_on_new_profit[ArrayResize(m_on_new_profit, (++m_on_new_profit_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT)
|
| | | m_on_withdrawal_deposit[ArrayResize(m_on_withdrawal_deposit, (++m_on_withdrawal_deposit_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS)
|
| | | m_on_init_new_pos[ArrayResize(m_on_init_new_pos, (++m_on_init_new_pos_size)) - 1] = ptr;
|
| | |
|
| | | //---
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_LOSS_PROFIT)
|
| | | m_on_loss_profit[ArrayResize(m_on_loss_profit, (++m_on_loss_profit_size)) - 1] = ptr;
|
| | | }
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| De-Suscribirse |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::UnregisterEvents(CAccountGestor* ptr, const int flags)
|
| | | {
|
| | | if(!CheckPointer(ptr))
|
| | | {
|
| | | LogError("Invalid pointer for unregister", FUNCION_ACTUAL);
|
| | | return;
|
| | | }
|
| | |
|
| | | //--- OnClosePosition
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION) != 0)
|
| | | RemoveFromArrayFast(m_on_close_position, m_on_close_position_size, ptr);
|
| | |
|
| | | //--- OnOpenPosition
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION) != 0)
|
| | | RemoveFromArrayFast(m_on_open_position, m_on_open_position_size, ptr);
|
| | |
|
| | | //--- OnPositionModify
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY) != 0)
|
| | | RemoveFromArrayFast(m_on_position_modify, m_on_position_modify_size, ptr);
|
| | |
|
| | | //--- OnOrderAdd
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_ORDER_ADD) != 0)
|
| | | RemoveFromArrayFast(m_on_order_add, m_on_order_add_size, ptr);
|
| | |
|
| | | //--- OnOrderUpdate
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_ORDER_UPDATE) != 0)
|
| | | RemoveFromArrayFast(m_on_order_update, m_on_order_update_size, ptr);
|
| | |
|
| | | //--- OnOrderDelete
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_ORDER_DELETE) != 0)
|
| | | RemoveFromArrayFast(m_on_order_delete, m_on_order_delete_size, ptr);
|
| | |
|
| | | //--- OnNewProfit
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT) != 0)
|
| | | RemoveFromArrayFast(m_on_new_profit, m_on_new_profit_size, ptr);
|
| | |
|
| | | //--- OnWithdrawalDeposit
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT) != 0)
|
| | | RemoveFromArrayFast(m_on_withdrawal_deposit, m_on_withdrawal_deposit_size, ptr);
|
| | |
|
| | | //--- OnInitNewPos
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS) != 0)
|
| | | RemoveFromArrayFast(m_on_init_new_pos, m_on_init_new_pos_size, ptr);
|
| | |
|
| | | //--- OnLossProfit
|
| | | if((flags & ACCOUNT_STATUS_REG_FLAG_ON_LOSS_PROFIT) != 0)
|
| | | RemoveFromArrayFast(m_on_loss_profit, m_on_loss_profit_size, ptr);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::UnregisterEvent(CAccountGestor* ptr, const int event)
|
| | | {
|
| | | if(!CheckPointer(ptr))
|
| | | {
|
| | | LogError("Invalid pointer for unregister", FUNCION_ACTUAL);
|
| | | return;
|
| | | }
|
| | |
|
| | | //--- OnOpenPosition
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION)
|
| | | RemoveFromArrayFast(m_on_open_position, m_on_open_position_size, ptr);
|
| | |
|
| | | //--- OnClosePosition
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION)
|
| | | RemoveFromArrayFast(m_on_close_position, m_on_close_position_size, ptr);
|
| | |
|
| | | //--- OnPositionModify
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY)
|
| | | RemoveFromArrayFast(m_on_position_modify, m_on_position_modify_size, ptr);
|
| | |
|
| | | //--- OnOrderAdd
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_ORDER_ADD)
|
| | | RemoveFromArrayFast(m_on_order_add, m_on_order_add_size, ptr);
|
| | |
|
| | | //--- OnOrderUpdate
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_ORDER_UPDATE)
|
| | | RemoveFromArrayFast(m_on_order_update, m_on_order_update_size, ptr);
|
| | |
|
| | | //--- OnOrderDelete
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_ORDER_DELETE)
|
| | | RemoveFromArrayFast(m_on_order_delete, m_on_order_delete_size, ptr);
|
| | |
|
| | | //--- OnNewProfit
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_NEW_PROFIT)
|
| | | RemoveFromArrayFast(m_on_new_profit, m_on_new_profit_size, ptr);
|
| | |
|
| | | //--- OnWithdrawalDeposit
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_WITHDRAWAL_DEPOSIT)
|
| | | RemoveFromArrayFast(m_on_withdrawal_deposit, m_on_withdrawal_deposit_size, ptr);
|
| | |
|
| | | //--- OnInitNewPos
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS)
|
| | | RemoveFromArrayFast(m_on_init_new_pos, m_on_init_new_pos_size, ptr);
|
| | |
|
| | | //--- OnLossProfit
|
| | | else
|
| | | if(event == ACCOUNT_STATUS_REG_FLAG_ON_LOSS_PROFIT)
|
| | | RemoveFromArrayFast(m_on_loss_profit, m_on_loss_profit_size, ptr);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::RemoveFromArrayFast(CAccountGestor* &array[], int &size, CAccountGestor* &ptr)
|
| | | {
|
| | | for(int i = 0; i < size; i++)
|
| | | {
|
| | | if(array[i] == ptr)
|
| | | {
|
| | | array[i] = array[size - 1];
|
| | | ArrayResize(array, (--size));
|
| | |
|
| | | //LogInfo(StringFormat("Event subscriber removed (size now: %d)", size), FUNCION_ACTUAL);
|
| | | return;
|
| | | }
|
| | | }
|
| | | //LogWarning("Pointer not found in event array", FUNCION_ACTUAL);
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function that executes every new day |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::OnNewDay(const datetime curr_time)
|
| | | {
|
| | | this.last_day_time = curr_time - (curr_time % 86400);
|
| | | this.account_daily_profit = 0.0;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function that executes every new month |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::OnNewMonth(const datetime curr_time)
|
| | | {
|
| | | if((m_flags & ACCOUNT_STATUS_FLAG_INIT) == 0)
|
| | | {
|
| | | LogError("Account status no INICIADO", FUNCION_ACTUAL);
|
| | | Remover();
|
| | | return;
|
| | | }
|
| | | this.last_monthly_time = curr_time;
|
| | | this.account_monthly_profit = 0.0;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function that executes weekly |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::OnNewWeek(const datetime curr_time)
|
| | | {
|
| | | this.last_weekly_time = curr_time;
|
| | | this.account_weekly_profit = 0.0;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function that executes in OnInit |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::OnInitEvent()
|
| | | {
|
| | | //---
|
| | | if((m_flags & ACCOUNT_STATUS_FLAG_INIT) != 0)
|
| | | {
|
| | | LogWarning("Clase ya iniciada", FUNCION_ACTUAL);
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | const datetime curr_time = TimeCurrent();
|
| | |
|
| | | //--- Initialize the profit collection variables
|
| | | this.last_day_time = curr_time - (curr_time % 86400);
|
| | | this.last_weekly_time = CTimeUtils::StartOfWeek(curr_time);
|
| | | this.last_monthly_time = CTimeUtils::StartOfMonth(curr_time);
|
| | | this.m_flags |= ACCOUNT_STATUS_FLAG_INIT;
|
| | |
|
| | | //--- Registramos para que reciba el evento
|
| | | CBasicEvents::Register(&this, BASICEVENT_REG_ALL_FLAG);
|
| | |
|
| | | //--- Initialize the managers with the new profit
|
| | | UpdateProfitInit();
|
| | |
|
| | | //---
|
| | | ROnOpenPosition profit;
|
| | | profit.account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
| | | profit.account_profit_diario = this.account_daily_profit;
|
| | | profit.account_profit_mensual = this.account_monthly_profit;
|
| | | profit.account_profit_semanal = this.account_weekly_profit;
|
| | | profit.account_profit_total = this.account_gross_profit;
|
| | |
|
| | | //--- Notify OnNewProfit subscribers
|
| | | for(int i = 0; i < m_on_new_profit_size; i++)
|
| | | m_on_new_profit[i].OnNewProfit(profit, curr_time);
|
| | |
|
| | | //--- Check if there are open trades
|
| | | const int pos_total = PositionsTotal();
|
| | |
|
| | | //--- If there are open positions we add them
|
| | | if(pos_total > 0)
|
| | | {
|
| | | for(int i = pos_total - 1; i >= 0; i--)
|
| | | {
|
| | | const ulong position_ticket = PositionGetTicket(i);
|
| | | if(!PositionSelectByTicket(position_ticket))
|
| | | continue;
|
| | |
|
| | | //---
|
| | | last_trans_symbol = PositionGetString(POSITION_SYMBOL);
|
| | |
|
| | | //---
|
| | | static Position new_pos;
|
| | | new_pos.type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
| | | new_pos.ticket = position_ticket;
|
2026-09-12 19:41:52 -05:00 | | | new_pos.profit = CRmFunctions::GetTotalPositionProfitNoCurrent(position_ticket);
|
2026-08-31 20:49:50 -05:00 | | | new_pos.magic = (ulong)PositionGetInteger(POSITION_MAGIC);
|
| | | new_pos.tp = PositionGetDouble(POSITION_TP);
|
| | | new_pos.sl = PositionGetDouble(POSITION_SL);
|
| | | new_pos.open_time = (datetime)PositionGetInteger(POSITION_TIME);
|
| | | new_pos.open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
| | | new_pos.volume = PositionGetDouble(POSITION_VOLUME);
|
2026-09-03 15:35:10 -05:00 | | | g_account_open_positions.Add(new_pos);
|
2026-08-31 20:49:50 -05:00 | | |
|
| | | //---
|
| | | profit.position = new_pos;
|
| | |
|
| | | //--- Notify OnInitNewPos subscribers
|
| | | for(int k = 0; k < m_on_init_new_pos_size; k++)
|
| | | m_on_init_new_pos[k].OnInitNewPos(profit);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function to update profits |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::UpdateProfit(const double new_profit)
|
| | | {
|
| | | //---
|
| | | this.account_gross_profit += new_profit;
|
| | | this.account_daily_profit += new_profit;
|
| | | this.account_weekly_profit += new_profit;
|
| | | this.account_monthly_profit += new_profit;
|
| | |
|
| | | //---
|
| | | if(IsInfoLogEnabled())
|
| | | {
|
| | | FastLog(FUNCION_ACTUAL, INFO_TEXT, "New profits:");
|
| | | Print("Daily profit: ", this.account_daily_profit);
|
| | | Print("Weekly profit: ", this.account_weekly_profit);
|
| | | Print("Monthly profit: ", this.account_monthly_profit);
|
| | | Print("Gross profit: ", this.account_gross_profit);
|
| | | }
|
| | |
|
| | | //--- Notify OnLossProfit subscribers
|
| | | for(int i = 0; i < m_on_loss_profit_size; i++)
|
| | | m_on_loss_profit[i].OnLossProfit(new_profit);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::UpdateProfitInit()
|
| | | {
|
| | | //---
|
2026-09-12 19:41:52 -05:00 | | | this.account_gross_profit = CRmFunctions::GetNetProfitSince(true, 0, D'1972.01.01 00:00');
|
| | | this.account_daily_profit = CRmFunctions::GetNetProfitSince(true, 0, this.last_day_time);
|
| | | this.account_weekly_profit = CRmFunctions::GetNetProfitSince(true, 0, this.last_weekly_time);
|
| | | this.account_monthly_profit = CRmFunctions::GetNetProfitSince(true, 0, this.last_monthly_time);
|
2026-08-31 20:49:50 -05:00 | | |
|
| | | //---
|
| | | if(IsInfoLogEnabled())
|
| | | {
|
| | | FastLog(FUNCION_ACTUAL, INFO_TEXT, "New profits:");
|
| | | Print("Daily profit: ", this.account_daily_profit);
|
| | | Print("Weekly profit: ", this.account_weekly_profit);
|
| | | Print("Monthly profit: ", this.account_monthly_profit);
|
| | | Print("Gross profit: ", this.account_gross_profit);
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function to execute in OnTick |
|
| | | //+------------------------------------------------------------------+
|
2026-09-12 19:41:52 -05:00 | | | #define CAccountStatus_OnTickEvent TSN::account_status_curr_profit = AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE);
|
2026-08-31 20:49:50 -05:00 | | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| OnTradeTransaction event |
|
| | | //+------------------------------------------------------------------+
|
| | | //--- Activa el evento de OnOrderAdd
|
| | | //#define CACCOUNT_STATUS_ACTIVE_ON_ORDER_ADD
|
| | |
|
| | | //--- Activa el evento de OnOrderUpdate
|
| | | //#define CACCOUNT_STATUS_ACTIVE_ON_ORDER_UPDATE
|
| | |
|
| | | //--- Activa el evento de OnOrderDelete
|
| | | //#define CACCOUNT_STATUS_ACTIVE_ON_ORDER_DELETE
|
| | |
|
| | | //--- Activa el evento de OnPositionModifed
|
| | | //#define CACCOUNT_STATUS_ACTIVE_ON_POSITION_MODIFIED
|
| | |
|
| | | //--- En los evenots de ordenes, su definicion activa que tamiben cuenten las ordenes de compra y venta
|
| | | //#define CACCOUNT_STATUS_COUNT_ORDERS_BUY_SELL
|
| | |
|
| | | //---
|
| | | void CAccountStatus::OnTradeTransactionEvent(const MqlTradeTransaction &trans)
|
| | | {
|
| | | //---
|
| | | switch(trans.type)
|
| | | {
|
| | | //---
|
| | | case TRADE_TRANSACTION_ORDER_ADD: // 0
|
| | | {
|
| | | #ifdef CACCOUNT_STATUS_ACTIVE_ON_ORDER_ADD
|
| | |
|
| | | #ifndef CACCOUNT_STATUS_COUNT_ORDERS_BUY_SELL
|
2026-09-12 19:41:52 -05:00 | | | if(!MQLArticles_IsPendingOrder[trans.order_type])
|
2026-08-31 20:49:50 -05:00 | | | return;
|
| | | #endif // CACCOUNT_STATUS_COUNT_ORDERS_BUY_SELL
|
| | |
|
| | | //---
|
| | | if(OrderSelect(trans.order))
|
| | | {
|
| | | //---
|
| | | last_trans_symbol = trans.symbol;
|
| | |
|
| | | //---
|
| | | last_order_struct.order_open_price = trans.price;
|
| | | last_order_struct.order_stop_loss = trans.price_sl;
|
| | | last_order_struct.order_take_profit = trans.price_tp;
|
| | | last_order_struct.order_magic = OrderGetInteger(ORDER_MAGIC);
|
| | | last_order_struct.order_ticket = trans.order;
|
| | | last_order_struct.order_time_expiration = trans.time_expiration;
|
| | | last_order_struct.order_reason = (ENUM_ORDER_REASON)OrderGetInteger(ORDER_REASON);
|
| | | last_order_struct.order_type = trans.order_type;
|
| | | last_order_struct.order_state = trans.order_state;
|
| | | last_order_struct.order_type_time = trans.time_type;
|
| | |
|
| | | //--- Notify OnOrderAdd subscribers
|
| | | for(int i = 0; i < m_on_order_add_size; i++)
|
| | | m_on_order_add[i].OnOrderAdd(last_order_struct);
|
| | | }
|
| | | else
|
| | | {
|
| | | LogError(StringFormat("Error al seleccionar la orden %I64u", trans.order), FUNCION_ACTUAL);
|
| | | }
|
| | |
|
| | | #endif // CACCOUNT_STATUS_ACTIVE_ON_ORDER_ADD
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_ORDER_UPDATE: // 1
|
| | | {
|
| | | #ifdef CACCOUNT_STATUS_ACTIVE_ON_ORDER_UPDATE
|
| | |
|
| | | #ifndef CACCOUNT_STATUS_COUNT_ORDERS_BUY_SELL
|
2026-09-12 19:41:52 -05:00 | | | if(!MQLArticles_IsPendingOrder[trans.order_type])
|
2026-08-31 20:49:50 -05:00 | | | return;
|
| | | #endif // CACCOUNT_STATUS_COUNT_ORDERS_BUY_SELL
|
| | |
|
| | | //---
|
| | | if(OrderSelect(trans.order))
|
| | | {
|
| | | //---
|
| | | last_trans_symbol = trans.symbol;
|
| | |
|
| | | //---
|
| | | last_order_struct.order_open_price = trans.price;
|
| | | last_order_struct.order_stop_loss = trans.price_sl;
|
| | | last_order_struct.order_take_profit = trans.price_tp;
|
| | | last_order_struct.order_magic = OrderGetInteger(ORDER_MAGIC);
|
| | | last_order_struct.order_ticket = trans.order;
|
| | | last_order_struct.order_time_expiration = trans.time_expiration;
|
| | | last_order_struct.order_reason = (ENUM_ORDER_REASON)OrderGetInteger(ORDER_REASON);
|
| | | last_order_struct.order_type = trans.order_type;
|
| | | last_order_struct.order_state = trans.order_state;
|
| | | last_order_struct.order_type_time = trans.time_type;
|
| | |
|
| | | //--- Notify OnOrderUpdate subscribers
|
| | | for(int i = 0; i < m_on_order_update_size; i++)
|
| | | m_on_order_update[i].OnOrderUpdate(last_order_struct);
|
| | | }
|
| | | else
|
| | | {
|
| | | LogError(StringFormat("Error al seleccionar la orden %I64u", trans.order), FUNCION_ACTUAL);
|
| | | }
|
| | |
|
| | | #endif // CACCOUNT_STATUS_ACTIVE_ON_ORDER_UPDATE
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_ORDER_DELETE: // 2
|
| | | {
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_HISTORY_ADD: // 3
|
| | | {
|
| | | #ifdef CACCOUNT_STATUS_ACTIVE_ON_ORDER_DELETE
|
| | |
|
| | | //---
|
2026-09-12 19:41:52 -05:00 | | | if(MQLArticles_IsPendingOrder[trans.order_type])
|
2026-08-31 20:49:50 -05:00 | | | {
|
| | | if(HistoryOrderSelect(trans.order))
|
| | | {
|
| | | // Se llama antes que historyadd
|
| | | //---
|
| | | last_trans_symbol = trans.symbol;
|
| | |
|
| | | //---
|
| | | last_order_struct.order_open_price = trans.price;
|
| | | last_order_struct.order_stop_loss = trans.price_sl;
|
| | | last_order_struct.order_take_profit = trans.price_tp;
|
| | | last_order_struct.order_magic = HistoryOrderGetInteger(trans.order, ORDER_MAGIC);
|
| | | last_order_struct.order_ticket = trans.order;
|
| | | last_order_struct.order_time_expiration = trans.time_expiration;
|
| | | last_order_struct.order_reason = (ENUM_ORDER_REASON)HistoryOrderGetInteger(trans.order, ORDER_REASON);
|
| | | last_order_struct.order_type = trans.order_type;
|
| | | last_order_struct.order_state = trans.order_state;
|
| | | last_order_struct.order_type_time = trans.time_type;
|
| | |
|
| | | //--- Notify OnOrderDelete subscribers
|
| | | for(int i = 0; i < m_on_order_delete_size; i++)
|
| | | m_on_order_delete[i].OnOrderDelete(last_order_struct);
|
| | | }
|
| | | else
|
| | | {
|
| | | LogError(StringFormat("Error al seleccionar la orden %I64u", trans.order), FUNCION_ACTUAL);
|
| | | }
|
| | | }
|
| | | #endif // CACCOUNT_STATUS_ACTIVE_ON_ORDER_DELETE
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_HISTORY_UPDATE: // 4
|
| | | {
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_HISTORY_DELETE: // 5
|
| | | {
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_DEAL_ADD: // 6
|
| | | {
|
| | | //---
|
| | | last_deal_type = trans.deal_type;
|
| | | last_deal_ticket = trans.deal;
|
| | | last_trans_symbol = trans.symbol;
|
| | |
|
| | | //---
|
| | | if(last_deal_type == DEAL_TYPE_BUY || last_deal_type == DEAL_TYPE_SELL)
|
| | | {
|
| | | HistoryDealSelect(trans.deal);
|
| | | const ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(last_deal_ticket, DEAL_ENTRY);
|
| | | last_deal_magic = (ulong)HistoryDealGetInteger(last_deal_ticket, DEAL_MAGIC);
|
| | | const ulong position_ticket = trans.position;
|
| | |
|
| | | //---
|
| | | const double deal_profit = HistoryDealGetDouble(last_deal_ticket, DEAL_PROFIT); // Get deal profit
|
| | | const double deal_commission = HistoryDealGetDouble(last_deal_ticket, DEAL_COMMISSION); // Get commission
|
| | |
|
| | | //---
|
| | | if(entry == DEAL_ENTRY_IN && PositionSelectByTicket(trans.position))
|
| | | {
|
| | | //---
|
| | | LogInfo(StringFormat("Position %I64u opened with magic %I64u", position_ticket, last_deal_magic), FUNCION_ACTUAL);
|
| | |
|
| | | //--- Activate open positions flag
|
| | | account_status_positions_open = true;
|
| | |
|
| | | //--- Calculate the profit
|
| | | const double deal_net_profit = deal_profit + deal_commission; // Calculate net profit
|
| | | UpdateProfit(deal_net_profit); //Update the profit
|
| | |
|
| | | //--- Create a new position to add to the tickets
|
| | | last_struct.position.type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
| | | last_struct.position.ticket = position_ticket;
|
| | | last_struct.position.magic = last_deal_magic;
|
| | | last_struct.position.profit = deal_net_profit;
|
| | | last_struct.position.open_time = (datetime)PositionGetInteger(POSITION_TIME);
|
| | | last_struct.position.open_price = trans.price;
|
| | | last_struct.position.sl = trans.price_sl;
|
| | | last_struct.position.tp = trans.price_tp;
|
| | | last_struct.position.volume = trans.volume;
|
| | |
|
| | | //--- Add to positions array
|
2026-09-03 15:35:10 -05:00 | | | g_account_open_positions.Add(last_struct.position);
|
2026-08-31 20:49:50 -05:00 | | |
|
| | | //--- Extra
|
| | | // Account
|
| | | last_struct.account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
| | | last_struct.account_profit_diario = account_daily_profit;
|
| | | last_struct.account_profit_total = account_gross_profit;
|
| | | last_struct.account_profit_mensual = account_monthly_profit;
|
| | | last_struct.account_profit_semanal = account_weekly_profit;
|
| | |
|
| | | // Deal
|
| | | last_struct.deal_entry_type = entry;
|
| | | last_struct.deal_ticket = last_deal_ticket;
|
| | | last_struct.deal_profit = deal_net_profit;
|
| | | last_struct.deal_reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(last_deal_ticket, DEAL_REASON);
|
| | |
|
| | | // Extra
|
| | | last_struct.magic_number_closed = 0;
|
| | |
|
| | | //--- Notify OnOpenClosePosition subscribers
|
| | | for(int i = 0; i < m_on_open_position_size; i++)
|
| | | m_on_open_position[i].OnOpenPosition(last_struct);
|
| | |
|
| | | //---
|
| | | return;
|
| | | }
|
| | |
|
| | | if(entry != DEAL_ENTRY_OUT)
|
| | | break;
|
| | |
|
| | | //---
|
| | | #define ACCOUNT_STATUS_MIN_VOL 0.00000001
|
| | |
|
| | | //---
|
| | | int pos_idx;
|
| | | if(g_account_open_positions.GetByTicket(position_ticket, last_struct.position, pos_idx))
|
| | | {
|
| | | // Print("Vol: ", DoubleToString(trans.volume));
|
| | |
|
| | | //---
|
| | | if((last_struct.position.volume - trans.volume) < ACCOUNT_STATUS_MIN_VOL) // Cierre completo
|
| | | {
|
| | | //---
|
| | | g_account_open_positions.DeleteByIndex(pos_idx);
|
| | |
|
| | | //---
|
| | | LogCaution(StringFormat("Position with ticket %I64u has been closed", position_ticket), FUNCION_ACTUAL);
|
| | |
|
| | | //--- Get the most recent profit
|
| | | const double deal_swap = HistoryDealGetDouble(last_deal_ticket, DEAL_SWAP); // Get swap fees
|
| | | const double deal_net_profit = deal_profit + deal_commission + deal_swap; // Calculate net profit
|
| | |
|
| | | //---
|
| | | if(g_account_open_positions.Count() == 0)
|
| | | account_status_positions_open = false;
|
| | |
|
| | | //--- Update its profit
|
| | | last_struct.position.profit += deal_net_profit;
|
| | |
|
| | | //--- Update the general profit
|
| | | UpdateProfit(deal_net_profit);
|
| | |
|
| | | //--- Set the new structure
|
| | | // Ya se hace
|
| | |
|
| | | // Account
|
| | | last_struct.account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
| | | last_struct.account_profit_diario = account_daily_profit;
|
| | | last_struct.account_profit_total = account_gross_profit;
|
| | | last_struct.account_profit_mensual = account_monthly_profit;
|
| | | last_struct.account_profit_semanal = account_weekly_profit;
|
| | |
|
| | | // Deal
|
| | | last_struct.deal_entry_type = entry; //market entry type (ENTRY_OUT)
|
| | | last_struct.deal_ticket = last_deal_ticket; //Closing deal ticket
|
| | | last_struct.deal_profit = deal_net_profit; //Net profit (excluding commissions)
|
| | | last_struct.deal_reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(last_deal_ticket, DEAL_REASON);
|
| | |
|
| | | // Extra
|
| | | last_struct.magic_number_closed = last_deal_magic; //Ticket with which the position was closed
|
| | |
|
| | | //--- Notify OnOpenClosePosition subscribers
|
| | | for(int i = 0; i < m_on_close_position_size; i++)
|
| | | m_on_close_position[i].OnClosePosition(last_struct, pos_idx);
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | else
|
| | | {
|
| | | //---
|
| | | LogCaution(StringFormat("Possible partial closure of the position: %I64u", position_ticket), FUNCION_ACTUAL);
|
| | |
|
| | | //---
|
| | | const double deal_swap = HistoryDealGetDouble(last_deal_ticket, DEAL_SWAP); // Get swap fees
|
| | | const double deal_net_profit = deal_profit + deal_commission + deal_swap; // Calculate net profit
|
| | |
|
| | | //---
|
| | | g_account_open_positions.UpdatePositionPartial(deal_net_profit, trans.volume, pos_idx); //Update the profit of the position that partially closed
|
| | |
|
| | | //---
|
| | | UpdateProfit(deal_net_profit);
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | }
|
| | | else
|
| | | if(last_deal_type == DEAL_TYPE_BALANCE || last_deal_type == DEAL_TYPE_CHARGE) // Withdrawal or deposit
|
| | | {
|
| | | HistoryDealSelect(last_deal_ticket);
|
| | | const double deal_profit = HistoryDealGetDouble(last_deal_ticket, DEAL_PROFIT); // Get deal profit
|
| | |
|
| | | //---
|
| | | if(fabs(deal_profit) < 0.0000000001)
|
| | | break;
|
| | |
|
| | | //--- Notify OnWithdrawalDeposit subscribers
|
| | | for(int i = 0; i < m_on_withdrawal_deposit_size; i++)
|
| | | m_on_withdrawal_deposit[i].OnWithdrawalDeposit(deal_profit);
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_DEAL_UPDATE: // 7
|
| | | {
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_DEAL_DELETE: // 8
|
| | | {
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_POSITION: // 9
|
| | | {
|
| | | #ifdef CACCOUNT_STATUS_ACTIVE_ON_POSITION_MODIFIED
|
| | | const ulong t = trans.position;
|
| | | if(g_account_open_positions.GetByTicket(t, last_struct.position))
|
| | | {
|
| | | //---
|
| | | last_trans_symbol = trans.symbol;
|
| | |
|
| | | //---
|
| | | uint8_t f = 0;
|
| | |
|
| | | //--- Cambio tp
|
| | | const double new_tp = trans.price_tp;
|
| | | if(last_struct.position.tp != new_tp)
|
| | | {
|
| | | g_account_open_positions.UpdateTp(new_tp, t);
|
| | | last_struct.position.tp = new_tp;
|
| | | f |= ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_TP;
|
| | | }
|
| | |
|
| | | //--- Cambio sl
|
| | | const double new_sl = trans.price_sl;
|
| | | if(last_struct.position.sl != new_sl)
|
| | | {
|
| | | g_account_open_positions.UpdateSl(new_sl, t);
|
| | | last_struct.position.sl = new_sl;
|
| | | f |= ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_SL;
|
| | | }
|
| | |
|
| | | //--- Notify OnPositionModify subscribers
|
| | | if(f)
|
| | | for(int i = 0; i < m_on_position_modify_size; i++)
|
| | | m_on_position_modify[i].OnPositionModify(last_struct.position, f);
|
| | | }
|
| | | #endif // CACCOUNT_STATUS_ACTIVE_ON_POSITION_MODIFIED
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TRADE_TRANSACTION_REQUEST: // 10
|
| | | {
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Print last order values |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::PrintLastOrder(void)
|
| | | {
|
| | | Print("--- Last Order ---");
|
| | | Print("Ticket: ", last_order_struct.order_ticket);
|
| | | Print("Type: ", EnumToString(last_order_struct.order_type));
|
| | | Print("State: ", EnumToString(last_order_struct.order_state));
|
| | | Print("Magic: ", last_order_struct.order_magic);
|
| | | Print("Open Price: ", last_order_struct.order_open_price);
|
| | | Print("Stop Loss: ", last_order_struct.order_stop_loss);
|
| | | Print("Take Profit: ", last_order_struct.order_take_profit);
|
| | | Print("Expiration: ", last_order_struct.order_time_expiration);
|
| | | Print("Time Type: ", EnumToString(last_order_struct.order_type_time));
|
| | | Print("Reason: ", EnumToString(last_order_struct.order_reason));
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Print last position values |
|
| | | //+------------------------------------------------------------------+
|
| | | void CAccountStatus::PrintLastPosition(void)
|
| | | {
|
| | | Print("--- Last Position ---");
|
| | | Print("Ticket: ", last_struct.position.ticket);
|
| | | Print("Type: ", EnumToString(last_struct.position.type));
|
| | | Print("Magic: ", last_struct.position.magic);
|
| | | Print("Open Price: ", last_struct.position.open_price);
|
| | | Print("Open Time: ", last_struct.position.open_time);
|
| | | Print("Stop Loss: ", last_struct.position.sl);
|
| | | Print("Take Profit: ", last_struct.position.tp);
|
| | | Print("Profit: ", last_struct.position.profit);
|
| | | }
|
| | |
|
| | |
|
| | | // Nota importante:
|
| | | // En versiones antiguas los obejtos agregados (regisrados) SE ELIMINABAN de la clase.. ahora YA NO
|
| | | // La clase ya no gestiona los LOGS NI elimina los obejtos agregados a ella, solo da los eventos
|
| | |
|
| | | CAccountStatus account_status;
|
2026-09-12 19:41:52 -05:00 | | | }
|
2026-08-31 20:49:50 -05:00 | | | #endif // MQLARTICLES_RM_ACCOUNTSTATUS_MQH
|
| | | //+------------------------------------------------------------------+
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //+------------------------------------------------------------------+
|