Article-15346-MQL5-Trade-Mo.../Accounts.mqh
2026-03-23 13:19:06 +07:00

198 lines
16 KiB
MQL5

//+------------------------------------------------------------------+
//| 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<total; i++)
{
//--- получаем очередной объект-аккаунт
CAccount *account=this.m_list.At(i);
if(account==NULL)
continue;
//--- Получаем список закрытых позиций аккаунта
CArrayObj *src=account.GetPositionsList();
if(src==NULL)
continue;
//--- Если это первый аккаунт в списке
if(i==0)
{
//--- копируем в новый список элементы из списка позиций аккаунта
if(!list.AssignArray(src))
{
delete list;
return NULL;
}
}
//--- Если это не первый аккаунт в списке
else
{
//--- добавляем в конец нового списка элементы из списка позиций аккаунта
if(!list.AddArray(src))
continue;
}
}
//--- Отправляем новый список в хранилище
if(!ListStorage.Add(list))
{
delete list;
return NULL;
}
//--- Возвращаем указатель на созданный и заполненный список
return list;
}
//+------------------------------------------------------------------+
//| Возвращает список позиций указанного аккаунта |
//+------------------------------------------------------------------+
CArrayObj *CAccounts::GetAccountPositionsList(const long login,const string server)
{
CAccount *account=this.Get(login, server);
return(account!=NULL ? account.GetPositionsList() : NULL);
}
//+------------------------------------------------------------------+