198 lines
16 KiB
MQL5
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|