//+------------------------------------------------------------------+ //| SymbolTrade.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" #define DIRECTORY "TradingByHistoryDeals" #define FILE_NAME "HistoryDealsData.bin" #define PATH DIRECTORY+"\\"+FILE_NAME #include #include //+------------------------------------------------------------------+ //| Структура сделки. Используется для создания файла истории сделок| //+------------------------------------------------------------------+ struct SDeal { ulong ticket; // Тикет сделки long order; // Ордер, на основании которого была открыта сделка long pos_id; // Идентификатор позиции long time_msc; // Время в миллисекундах datetime time; // Время double volume; // Объём double price; // Цена double profit; // Прибыль double commission; // Комиссия по сделке double swap; // Накопленный своп при закрытии double fee; // Оплата за проведение сделки, начисляется сразу после совершения сделки double sl; // Уровень Stop Loss double tp; // Уровень Take Profit ENUM_DEAL_TYPE type; // Тип ENUM_DEAL_ENTRY entry; // Способ изменения позиции ENUM_DEAL_REASON reason; // Причина или источник проведения сделки long magic; // Идентификатор эксперта int digits; // Digits символа ushort symbol[16]; // Символ ushort comment[64]; // Комментарий к сделке ushort external_id[256]; // Идентификатор сделки во внешней торговой системе (на бирже) //--- Установка строковых свойств bool SetSymbol(const string deal_symbol) { return(::StringToShortArray(deal_symbol, symbol)==deal_symbol.Length()); } bool SetComment(const string deal_comment) { return(::StringToShortArray(deal_comment, comment)==deal_comment.Length()); } bool SetExternalID(const string deal_external_id) { return(::StringToShortArray(deal_external_id, external_id)==deal_external_id.Length()); } //--- Возврат строковых свойств string Symbol(void) { return(::ShortArrayToString(symbol)); } string Comment(void) { return(::ShortArrayToString(comment)); } string ExternalID(void) { return(::ShortArrayToString(external_id)); } }; //--- Типы сортировки сделок enum ENUM_DEAL_SORT_MODE { SORT_MODE_DEAL_TICKET = 0, // Режим сравнения/сортировки по тикету сделки SORT_MODE_DEAL_ORDER, // Режим сравнения/сортировки по ордеру, на основание которого выполнена сделка SORT_MODE_DEAL_TIME, // Режим сравнения/сортировки по времени совершения сделки SORT_MODE_DEAL_TIME_MSC, // Режим сравнения/сортировки по времени совершения сделки в миллисекундах SORT_MODE_DEAL_TYPE, // Режим сравнения/сортировки по типу сделки SORT_MODE_DEAL_ENTRY, // Режим сравнения/сортировки по направлению сделки SORT_MODE_DEAL_MAGIC, // Режим сравнения/сортировки по Magic number сделки SORT_MODE_DEAL_REASON, // Режим сравнения/сортировки по причине или источнику проведения сделки SORT_MODE_DEAL_POSITION_ID, // Режим сравнения/сортировки по идентификатору позиции SORT_MODE_DEAL_VOLUME, // Режим сравнения/сортировки по объему сделки SORT_MODE_DEAL_PRICE, // Режим сравнения/сортировки по цене сделки SORT_MODE_DEAL_COMMISSION, // Режим сравнения/сортировки по комиссии SORT_MODE_DEAL_SWAP, // Режим сравнения/сортировки по накопленному свопу при закрытии SORT_MODE_DEAL_PROFIT, // Режим сравнения/сортировки по финансовому результату сделки SORT_MODE_DEAL_FEE, // Режим сравнения/сортировки по оплате за проведение сделки SORT_MODE_DEAL_SL, // Режим сравнения/сортировки по уровню Stop Loss SORT_MODE_DEAL_TP, // Режим сравнения/сортировки по уровню Take Profit SORT_MODE_DEAL_SYMBOL, // Режим сравнения/сортировки по имени символа, по которому произведена сделка SORT_MODE_DEAL_COMMENT, // Режим сравнения/сортировки по комментарию к сделке SORT_MODE_DEAL_EXTERNAL_ID, // Режим сравнения/сортировки по идентификатору сделки во внешней торговой системе SORT_MODE_DEAL_TICKET_TESTER, // Режим сравнения/сортировки по тикету сделки в тестере SORT_MODE_DEAL_POS_ID_TESTER, // Режим сравнения/сортировки по идентификатору позиции в тестере }; //+------------------------------------------------------------------+ //| Класс сделки. Используется для торговли в тестере стратегий | //+------------------------------------------------------------------+ class CDeal : public CObject { protected: //--- Целочисленные свойства ulong m_ticket; // Тикет сделки. Уникальное число, которое присваивается каждой сделке long m_order; // Ордер, на основание которого выполнена сделка datetime m_time; // Время совершения сделки long m_time_msc; // Время совершения сделки в миллисекундах с 01.01.1970 ENUM_DEAL_TYPE m_type; // Тип сделки ENUM_DEAL_ENTRY m_entry; // Направление сделки – вход в рынок, выход из рынка или разворот long m_magic; // Magic number для сделки (смотри ORDER_MAGIC) ENUM_DEAL_REASON m_reason; // Причина или источник проведения сделки long m_pos_id; // Идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка //--- Вещественные свойства double m_volume; // Объем сделки double m_price; // Цена сделки double m_commission; // Комиссия по сделке double m_swap; // Накопленный своп при закрытии double m_profit; // Финансовый результат сделки double m_fee; // Оплата за проведение сделки, начисляется сразу после совершения сделки double m_sl; // Уровень Stop Loss double m_tp; // Уровень Take Profit //--- Строковые свойства string m_symbol; // Имя символа, по которому произведена сделка string m_comment; // Комментарий к сделке string m_external_id; // Идентификатор сделки во внешней торговой системе (на бирже) //--- Дополнительные свойства int m_digits; // Digits символа double m_point; // Point символа ulong m_ticket_tester; // Тикет позиции в тестере long m_pos_id_tester; // Идентификатор позиции в тестере public: //--- Установка свойств сделки void SetTicket(const ulong ticket) { this.m_ticket=ticket; } void SetOrder(const long order) { this.m_order=order; } void SetTime(const datetime time) { this.m_time=time; } void SetTimeMsc(const long value) { this.m_time_msc=value; } void SetType(const ENUM_DEAL_TYPE type) { this.m_type=type; } void SetEntry(const ENUM_DEAL_ENTRY entry) { this.m_entry=entry; } void SetMagic(const long magic) { this.m_magic=magic; } void SetReason(const ENUM_DEAL_REASON reason) { this.m_reason=reason; } void SetPositionID(const long id) { this.m_pos_id=id; } void SetVolume(const double volume) { this.m_volume=volume; } void SetPrice(const double price) { this.m_price=price; } void SetCommission(const double commission) { this.m_commission=commission; } void SetSwap(const double swap) { this.m_swap=swap; } void SetProfit(const double profit) { this.m_profit=profit; } void SetFee(const double fee) { this.m_fee=fee; } void SetSL(const double sl) { this.m_sl=sl; } void SetTP(const double tp) { this.m_tp=tp; } void SetSymbol(const string symbol) { this.m_symbol=symbol; } void SetComment(const string comment) { this.m_comment=comment; } void SetExternalID(const string ext_id) { this.m_external_id=ext_id; } void SetTicketTester(const ulong ticket) { this.m_ticket_tester=ticket; } void SetPosIDTester(const long pos_id) { this.m_pos_id_tester=pos_id; } //--- Возврат свойств сделки ulong Ticket(void) const { return this.m_ticket; } long Order(void) const { return this.m_order; } datetime Time(void) const { return this.m_time; } long TimeMsc(void) const { return this.m_time_msc; } ENUM_DEAL_TYPE TypeDeal(void) const { return this.m_type; } ENUM_DEAL_ENTRY Entry(void) const { return this.m_entry; } long Magic(void) const { return this.m_magic; } ENUM_DEAL_REASON Reason(void) const { return this.m_reason; } long PositionID(void) const { return this.m_pos_id; } double Volume(void) const { return this.m_volume; } double Price(void) const { return this.m_price; } double Commission(void) const { return this.m_commission; } double Swap(void) const { return this.m_swap; } double Profit(void) const { return this.m_profit; } double Fee(void) const { return this.m_fee; } double SL(void) const { return this.m_sl; } double TP(void) const { return this.m_tp; } string Symbol(void) const { return this.m_symbol; } string Comment(void) const { return this.m_comment; } string ExternalID(void) const { return this.m_external_id; } int Digits(void) const { return this.m_digits; } double Point(void) const { return this.m_point; } ulong TicketTester(void) const { return this.m_ticket_tester; } long PosIDTester(void) const { return this.m_pos_id_tester; } //--- Сравнивает два объекта между собой по указанному в mode свойству virtual int Compare(const CObject *node, const int mode=0) const { const CDeal *obj=node; switch(mode) { case SORT_MODE_DEAL_TICKET : return(this.Ticket() > obj.Ticket() ? 1 : this.Ticket() < obj.Ticket() ? -1 : 0); case SORT_MODE_DEAL_ORDER : return(this.Order() > obj.Order() ? 1 : this.Order() < obj.Order() ? -1 : 0); case SORT_MODE_DEAL_TIME : return(this.Time() > obj.Time() ? 1 : this.Time() < obj.Time() ? -1 : 0); case SORT_MODE_DEAL_TIME_MSC : return(this.TimeMsc() > obj.TimeMsc() ? 1 : this.TimeMsc() < obj.TimeMsc() ? -1 : 0); case SORT_MODE_DEAL_TYPE : return(this.TypeDeal() > obj.TypeDeal() ? 1 : this.TypeDeal() < obj.TypeDeal() ? -1 : 0); case SORT_MODE_DEAL_ENTRY : return(this.Entry() > obj.Entry() ? 1 : this.Entry() < obj.Entry() ? -1 : 0); case SORT_MODE_DEAL_MAGIC : return(this.Magic() > obj.Magic() ? 1 : this.Magic() < obj.Magic() ? -1 : 0); case SORT_MODE_DEAL_REASON : return(this.Reason() > obj.Reason() ? 1 : this.Reason() < obj.Reason() ? -1 : 0); case SORT_MODE_DEAL_POSITION_ID : return(this.PositionID() > obj.PositionID() ? 1 : this.PositionID() < obj.PositionID() ? -1 : 0); case SORT_MODE_DEAL_VOLUME : return(this.Volume() > obj.Volume() ? 1 : this.Volume() < obj.Volume() ? -1 : 0); case SORT_MODE_DEAL_PRICE : return(this.Price() > obj.Price() ? 1 : this.Price() < obj.Price() ? -1 : 0); case SORT_MODE_DEAL_COMMISSION : return(this.Commission() > obj.Commission() ? 1 : this.Commission() < obj.Commission() ? -1 : 0); case SORT_MODE_DEAL_SWAP : return(this.Swap() > obj.Swap() ? 1 : this.Swap() < obj.Swap() ? -1 : 0); case SORT_MODE_DEAL_PROFIT : return(this.Profit() > obj.Profit() ? 1 : this.Profit() < obj.Profit() ? -1 : 0); case SORT_MODE_DEAL_FEE : return(this.Fee() > obj.Fee() ? 1 : this.Fee() < obj.Fee() ? -1 : 0); case SORT_MODE_DEAL_SL : return(this.SL() > obj.SL() ? 1 : this.SL() < obj.SL() ? -1 : 0); case SORT_MODE_DEAL_TP : return(this.TP() > obj.TP() ? 1 : this.TP() < obj.TP() ? -1 : 0); case SORT_MODE_DEAL_SYMBOL : return(this.Symbol() > obj.Symbol() ? 1 : this.Symbol() < obj.Symbol() ? -1 : 0); case SORT_MODE_DEAL_COMMENT : return(this.Comment() > obj.Comment() ? 1 : this.Comment() < obj.Comment() ? -1 : 0); case SORT_MODE_DEAL_EXTERNAL_ID : return(this.ExternalID() >obj.ExternalID() ? 1 : this.ExternalID() obj.TicketTester()? 1 : this.TicketTester()obj.PosIDTester() ? 1 : this.PosIDTester() =time); } //--- Обработчик OnTester. Возвращает количество обработанных тестером сделок double OnTester(void) { ::PrintFormat("Symbol %s: Total deals: %d, number of processed deals: %d", this.Symbol(), this.DealsTotal(), this.NumProcessedDeals()); return this.m_deals_processed; } //--- Сравнивает два объекта между собой (сравнение только по символу) virtual int Compare(const CObject *node, const int mode=0) const { const CSymbolTrade *obj=node; return(this.Symbol()>obj.Symbol() ? 1 : this.Symbol()WRONG_VALUE) return true; //--- Добавляем указатель на сделку в список в порядке сортировки по времени в миллисекундах this.m_list_deals.Sort(SORT_MODE_DEAL_TIME_MSC); if(!this.m_list_deals.InsertSort(deal)) { ::PrintFormat("%s: Failed to add deal", __FUNCTION__); return false; } //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CSymbolTrade::Возвращает объект сделки по времени в секундах | //+------------------------------------------------------------------+ CDeal* CSymbolTrade::GetDealByTime(const datetime time) { DealTmp.SetTime(time); this.m_list_deals.Sort(SORT_MODE_DEAL_TIME_MSC); int index=this.m_list_deals.Search(&DealTmp); return this.m_list_deals.At(index); } //+------------------------------------------------------------------+ //|CSymbolTrade::Возвращает сделку открытия по идентификатору позиции| //+------------------------------------------------------------------+ CDeal *CSymbolTrade::GetDealInByPosID(const long pos_id) { int total=this.m_list_deals.Total(); for(int i=0; i