//+------------------------------------------------------------------+ //| Accounts.mqh | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "Account.mqh" //+------------------------------------------------------------------+ //| Класс-коллекция аккаунтов | //+------------------------------------------------------------------+ class CAccounts : public CObject { private: CArrayObj m_list; // Список объектов-аккаунтов CAccount m_tmp; // Временный объект-аккаунт для поиска protected: //--- Создаёт новый объект-аккаунт и добавляет его в список CAccount *Add(const long login, const string server); public: //--- Создаёт новый объект-аккаунт bool Create(const long login, const string server); //--- Возвращает указатель на указанный объект-аккаунт по (1) логину и серверу, (2) индексу в списке CAccount *Get(const long login, const string server); CAccount *Get(const int index) const { return this.m_list.At(index); } //--- Объединяет списки позиций аккаунтов и возвращает общий CArrayObj *GetCommonPositionsList(void); //--- Возвращает список позиций указанного аккаунта CArrayObj *GetAccountPositionsList(const long login, const string server); //--- Возвращает количество хранимых аккаунтов int Total(void) const { return this.m_list.Total(); } //--- Обновляет списки позиций указанного аккаунта bool PositionsRefresh(const long login, const string server); //--- Конструктор/деструктор CAccounts(); ~CAccounts(); }; //+------------------------------------------------------------------+ //| Конструктор | //+------------------------------------------------------------------+ CAccounts::CAccounts() { this.m_list.Sort(); } //+------------------------------------------------------------------+ //| Деструктор | //+------------------------------------------------------------------+ CAccounts::~CAccounts() { this.m_list.Clear(); } //+------------------------------------------------------------------+ //| Создаёт новый объект-аккаунт и добавляет его в список | //+------------------------------------------------------------------+ CAccount *CAccounts::Add(const long login,const string server) { //--- Создаём новый объект-аккаунт CAccount *account=new CAccount(login, server); if(account==NULL) return NULL; //--- Если созданный объект не добавлен в список - удаляем его и возвращаем NULL if(!this.m_list.Add(account)) { delete account; return NULL; } //--- Возвращаем указатель на созданный объект return account; } //+------------------------------------------------------------------+ //| Создаёт новый объект-аккаунт | //+------------------------------------------------------------------+ bool CAccounts::Create(const long login,const string server) { //--- Во временный объект-аккаунт устанавливаем логин и сервер this.m_tmp.SetLogin(login); this.m_tmp.SetServer(server); //--- Списку объектов-аккаунтов устанавливаем флаг сортированного списка и //--- получаем индекс объекта в списке, имеющего те же логин и сервер, что и у временного объекта this.m_list.Sort(); int index=this.m_list.Search(&this.m_tmp); //--- Возвращаем флаг успешного добавления объекта в список (результат работы метода Add), либо false, если объект в списке уже есть return(index==WRONG_VALUE ? this.Add(login, server)!=NULL : false); } //+------------------------------------------------------------------+ //| Возвращает указатель на указанный объект-аккаунт | //+------------------------------------------------------------------+ CAccount *CAccounts::Get(const long login,const string server) { //--- Во временный объект-аккаунт устанавливаем логин и сервер this.m_tmp.SetLogin(login); this.m_tmp.SetServer(server); //--- Списку объектов-аккаунтов устанавливаем флаг сортированного списка и //--- получаем индекс объекта в списке, имеющего те же логин и сервер, что и у временного объекта this.m_list.Sort(); int index=this.m_list.Search(&this.m_tmp); //--- Возвращаем указатель на объект в списке по индексу, либо NULL, если индекс равен -1 return this.m_list.At(index); } //+------------------------------------------------------------------+ //| Обновляет списки позиций указанного аккаунта | //+------------------------------------------------------------------+ bool CAccounts::PositionsRefresh(const long login, const string server) { //--- Получаем указатель на объект-аккаунт с указанными логином и сервером CAccount *account=this.Get(login, server); if(account==NULL) return false; //--- Если полученный объект - не текущий аккаунт, if(account.Login()!=::AccountInfoInteger(ACCOUNT_LOGIN) || account.Server()!=::AccountInfoString(ACCOUNT_SERVER)) { //--- сообщаем, что обновление данных не текущего аккаунта приведёт к некорректным данным и возвращаем false ::Print("Error. Updating the list of positions for a non-current account will result in incorrect data."); return false; } //--- Возвращаем результат обновления данных текущего аккаунта return account.PositionsRefresh(); } //+------------------------------------------------------------------+ //| Объединяет списки позиций аккаунтов и возвращает общий | //+------------------------------------------------------------------+ CArrayObj *CAccounts::GetCommonPositionsList(void) { //--- Создаём новый список и сбрасываем для него флаг управления памятью CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); //--- В цикле по списку аккаунтов int total=this.m_list.Total(); for(int i=0; i