← К каталогу
Исходный код · ID 3524

ordersevents.mqh

Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Библиотека ordersevents.mqh предназначена для работы с данными ордеров и позиций в среде MetaTrader 4. Она обеспечивает загрузку, сохранение и синхронизацию информации о торговых операциях между мастер- и слейв-счетами через CSV-файлы.

Класс COrderData представляет структуру данных отдельного ордера, включая тикет, символ, тип, лот, цены, время и комментарий. Класс COrderEvents управляет массивами ордеров и позиций, предоставляет методы загрузки и сохранения данных, а также набор виртуальных методов-обработчиков для реагирования на изменения.

Библиотека поддерживает автоматическое отслеживание изменений в позициях, ордерах и истории сделок, включая частичное закрытие. Данные о состоянии торгового счета сохраняются в файлы для последующей передачи на клиентские терминалы.

Состав библиотеки

Классов: 2 · методов: 38 · конструкторов: 2 · деструкторов: 1 · отдельных функций: 0

Классы
Класс class COrderData

Класс, представляющий структуру данных отдельного ордера: тикет, символ, тип, лот, цены открытия и закрытия, стоп-лосс, тейк-профит, время, магик, комментарий и состояние.

Класс class COrderEvents

Основной класс библиотеки, управляющий массивами ордеров и позиций, загрузкой и сохранением данных, а также синхронизацией между мастер- и слейв-счетами.

Методы и конструкторы
Метод · COrderData void Reset()

Сбрасывает все поля объекта-ордера в значения по умолчанию.

Конструктор · COrderData COrderData()

Конструктор класса, создающий объект ордера с инициализацией значений по умолчанию через метод Reset.

Метод · COrderData void operator=(const int nil)

Присваивание нулевой инициализации объекту ордера (сброс всех полей).

Метод · COrderData void operator=(const COrderData &data)

Копирование данных одного объекта ордера в другой.

Метод · COrderData bool Load(long laccount,string &sdata[],long time_offset)

Загрузка данных ордера из строкового массива с парсингом полей из CSV-формата.

Метод · COrderData long GetMagic(long iaccount)

Возвращает магический номер ордера для указанного аккаунта.

Метод · COrderData void Print()

Выводит информацию об ордере в журнал для отладки.

Метод · COrderEvents void Reset()

Сбрасывает все внутренние поля и массивы объекта в начальные значения.

Конструктор · COrderEvents COrderEvents()

Конструктор класса, создающий объект с инициализацией через метод Reset.

Деструктор · COrderEvents ~COrderEvents()

Деструктор, вызывающий деинициализацию и освобождение массивов.

Метод · COrderEvents bool do_action_filedata_order(COrderData &order)

Виртуальный метод-обработчик, вызываемый при обработке данных ордера из файла; по умолчанию возвращает true.

Метод · COrderEvents void do_event_init()

Виртуальный метод, вызываемый при инициализации событий; используется для пользовательской инициализации.

Метод · COrderEvents void OnInit(string sversion,string sCopierPath,string sFilePrefix)

Инициализирует версию, путь и префикс файла, сбрасывает состояние и вызывает do_event_init.

Метод · COrderEvents void OnDeinit(const int reason)

Вызывается при деинициализации для освобождения массивов ордеров и позиций.

Метод · COrderEvents void FilterComment(string &comment)

Заменяет запрещённый символ-разделитель (точку с запятой) в комментарии ордера на двоеточие.

Метод · COrderEvents ulong ConvertTicket(ulong thist)

Преобразует тикет, очищая старший бит (специфика MQL4).

Метод · COrderEvents bool do_filter_filedata_update(bool bupdate)

Виртуальный фильтр, определяющий необходимость обновления данных; по умолчанию пропускает запрос без изменений.

Метод · COrderEvents void do_event_change_type(CPositionInfo &tmp)

Виртуальный обработчик изменения типа позиции (CPositionInfo).

Метод · COrderEvents void do_event_change_volume(CPositionInfo &tmp)

Виртуальный обработчик изменения объёма позиции (CPositionInfo).

Метод · COrderEvents void do_event_change_open(CPositionInfo &tmp)

Виртуальный обработчик изменения цены открытия позиции (CPositionInfo).

Метод · COrderEvents void do_event_change_stop(CPositionInfo &tmp)

Виртуальный обработчик изменения стоп-лосса позиции (CPositionInfo).

Метод · COrderEvents void do_event_change_take(CPositionInfo &tmp)

Виртуальный обработчик изменения тейк-профита позиции (CPositionInfo).

Метод · COrderEvents void do_event_change_type(COrderInfo &tmp)

Виртуальный обработчик изменения типа ордера (COrderInfo).

Метод · COrderEvents void do_event_change_volume(COrderInfo &tmp)

Виртуальный обработчик изменения объёма ордера (COrderInfo).

Метод · COrderEvents void do_event_change_open(COrderInfo &tmp)

Виртуальный обработчик изменения цены открытия ордера (COrderInfo).

Метод · COrderEvents void do_event_change_stop(COrderInfo &tmp)

Виртуальный обработчик изменения стоп-лосса ордера (COrderInfo).

Метод · COrderEvents void do_event_change_take(COrderInfo &tmp)

Виртуальный обработчик изменения тейк-профита ордера (COrderInfo).

Метод · COrderEvents void do_event_change_state(COrderInfo &tmp)

Виртуальный обработчик изменения состояния ордера (COrderInfo).

Метод · COrderEvents void do_event_change_type(CHistoryOrderInfo &tmp)

Виртуальный обработчик изменения типа исторического ордера (CHistoryOrderInfo).

Метод · COrderEvents void do_event_change_close(CHistoryOrderInfo &tmp)

Виртуальный обработчик закрытия исторического ордера (CHistoryOrderInfo).

Метод · COrderEvents void do_action_loadfile_version(string &sdata[])

Виртуальный обработчик, вызываемый при загрузке данных версии из файла.

Метод · COrderEvents void do_action_loadfile_account(string &sdata[])

Виртуальный обработчик, вызываемый при загрузке данных аккаунта из файла.

Метод · COrderEvents void do_action_loadfile_position(string &sdata[])

Виртуальный обработчик, вызываемый при загрузке данных позиции из файла.

Метод · COrderEvents void Master(long imaster_account)

Настраивает мастер-аккаунт, определяет режим счета (хедж/фикс), обновляет массивы ордеров и позиций из текущего состояния терминала.

Метод · COrderEvents void Slave(ulong iAccountNumber)

Загружает данные с указанного слейв-счёта из CSV-файла, проверяя актуальность по времени последнего обновления.

Метод · COrderEvents void ClearTicket(ulong tclear)

Удаляет ордер из массива по указанному тикету, если он уже закрыт.

Метод · COrderEvents void Save()

Сохраняет текущие данные об ордерах и позициях в CSV-файл мастер-аккаунта с учётом смещения времени.

Метод · COrderEvents int LoadFile(string sfile,ulong iAccountNumber)

Загружает и парсит данные из CSV-файла слейв-аккаунта, заполняя массивы ордеров и позиций; поддерживает версию, аккаунт и позиционные данные.

Метод · COrderEvents enum_type_data GetData(string &sstring,string &sdata[])

Определяет тип данных строки (версия, аккаунт или позиция) и разбивает её на массив значений.

Метод · COrderEvents bool NettingPosition(COrderData &data)

Управляет расчётом лота для неттинг-счёта при добавлении нового ордера, суммируя объёмы по символу.

Метод · COrderEvents double NettingPositionMaster(string sSymbol,ENUM_ORDER_TYPE &etype)

Возвращает суммарный лот и направление позиции мастера по указанному символу для неттинг-счёта.

Получить полный код

Поиск по коду файла

#ifndef __SOVETNIKOV_ORDEREVENTS__
#define __SOVETNIKOV_ORDEREVENTS__ ""

#include <SovetnikovNET/Copier.mqh>

class COrderData
  {

public:
   ulong             master_ticket; //тикет на мастере
   ulong             first_ticket;
   string            master_symbol; //имя инструмента
   int               type; //4 тип
   double            lot; //8 лот
   double            lotout; //8 Лот закрытый
   double            open; //8 цена открытие ордера
   double            close; //8 цена закрытие ордера
   double            stop; //8 стоп
   double            take; //8 тейк
   datetime          tmOpen;//8 открытие
   datetime          tmClose;//8 закрытие
   long              magic; //4 меджик - на клиенте тут формируется (int)(master_ticket+account), если это мт5, то там формировать будет (long)(master_ticket+account)
   double            real_open; //реальная цена открытия на клиенте
   long              master_magic; //меджик мастера (при загрузке на клиенте данных от мастера) mt5
   string            comment;
   long              state;
   bool              history;

   void              Reset()
     {
      master_ticket=0; //тикет на мастере
      first_ticket=0;
      master_symbol=""; //имя инструмента
      type=0; //4 тип
      lot=0; //8 лот
      lotout=0; //8 лот закрытый
      open=0; //8 цена открытие ордера
      real_open=0; //реальная цена открытия на слейв
      close=0; //8 цена закрытие ордера
      stop=0; //8 стоп
      take=0; //8 тейк
      tmOpen=0;//8 открытие
      tmClose=0;//8 закрытие
      magic=0; //4 меджик - у мастера тут свой меджик, на клиенте тут храним меджик для контроля ордера
      comment="";
      state=0;
      history=false; //открытый ордер по умолчанию
     }
                     COrderData()
     {
      Reset();
     }

   void              operator=(const int nil=NULL) //нулевая инициализация переменных
     {
      Reset();
     }

   void              operator=(const COrderData &data)//простое копирование
     {
      master_ticket=data.master_ticket; //тикет на мастере
      first_ticket=data.first_ticket;
      master_symbol=data.master_symbol; //имя инструмента
      type=data.type; //4 тип
      lot=data.lot; //8 лот
      lotout=data.lotout;
      open=data.open; //8 цена открытие ордера
      real_open=data.real_open;
      close=data.close; //8 цена закрытие ордера
      stop=data.stop; //8 стоп
      take=data.take; //8 тейк
      tmOpen=data.tmOpen;//8 открытие
      tmClose=data.tmClose;//8 закрытие
      magic=data.magic; //4 меджик (будем такой же ставить)
      comment=data.comment;
      state=data.state;
      history=data.history;
     }

   bool              Load(long laccount,string &sdata[],long time_offset)
     {
      if(ArraySize(sdata)==16)
        {

         /*//по умолчанию точность double 6 цифр после запятой, сделал поддержку до 8 цифр на случай появления криптовалют с такой точностью
                   swrite=StringFormat("%s;%lld;%lld;%s;%d;%.8f;%.8f;%.8f;%.8f;%.8f;%lld;%lld;%lld;%ls;%d\n\r",
                                     orders[i].history?"closed":"open",//0
                                     orders[i].master_ticket,//1
                                     orders[i].first_ticket,//2
                                     orders[i].master_symbol,//3
                                     orders[i].type,//4
                                     orders[i].lot,//5
                                     orders[i].open,//6
                                     orders[i].close,//7
                                     orders[i].stop,//8
                                     orders[i].take,//9
                                     orders[i].tmOpen>0?orders[i].tmOpen:0,//10
                                     orders[i].tmClose>0?orders[i].tmClose:0,//11
                                     orders[i].magic,//12
                                     orders[i].comment,//13
                                     orders[i].state);//14
                                     */
         history=false;
         if(sdata[0]=="closed")
            history=true;

         master_ticket=StringToInteger(sdata[1]);
         first_ticket=StringToInteger(sdata[2]); //эти данные мастер заполняет если было частичное закрытие и тут будет ордер первый до частичного закрытия

         master_symbol=sdata[3];

         type=(int)StringToInteger(sdata[4]);
         lot=StringToDouble(sdata[5]);
         lotout=StringToDouble(sdata[6]);
         open=StringToDouble(sdata[7]);
         close=StringToDouble(sdata[8]);
         stop=StringToDouble(sdata[9]);
         take=StringToDouble(sdata[10]);
         tmOpen=(datetime)StringToInteger(sdata[11]);
         tmClose=(datetime)StringToInteger(sdata[12]);

         /*if(tmOpen>0)
            tmOpen=(datetime)(tmOpen-ltime_offset);
         if(tmClose>0)
            tmClose=(datetime)(tmClose-ltime_offset);
         */

#ifdef  __MQL5__
         master_magic=StringToInteger(sdata[13]); //сохраним на будущее меджик с мастера
         magic=(ulong)(master_magic-laccount);//mt5

#else
         master_magic=int(StringToInteger(sdata[13])); //сохраним на будущее меджик с мастера
         magic=(int)(master_magic-laccount);//mt5

#endif

         comment=sdata[14];
         state=StringToInteger(sdata[15]);

         return true; //загрузка успешная
        }

      return false; //неверные данные
     }

   long              GetMagic(long iaccount)
     {
      return magic;
     }

   void              Print()
     {
      if(master_ticket<=0)
         return;

      PrintFormat("Print: %s;%lld;%lld;Master=%s;%d;%.8f;%.8f;%.8f;%.8f;%.8f;%.8f;%.8f;%s;%s;%lld;%ls;%d",
                  history?"closed":"open",//0
                  master_ticket,//1
                  first_ticket,//2
                  master_symbol,//3
                  type,//4
                  lot,//5
                  lotout,//6
                  open,//7
                  real_open, //real open
                  close,//8
                  stop,//9
                  take,//10
                  tmOpen>0?TimeToString(tmOpen,TIME_DATE|TIME_MINUTES|TIME_SECONDS):"",//11
                  tmClose>0?TimeToString(tmClose,TIME_DATE|TIME_MINUTES|TIME_SECONDS):"",//12
                  magic,//13
                  comment,//14
                  state);//15
     }
  };

class COrderEvents
  {
public:
   int               ierror;
   long              ilasttotal;
   bool              is_hedge,is_fifo; //тип счета неттинг или хедж
   datetime          time;
   bool              bRestart; //при рестарте ставим флаг true для сохранения файла даже без сделок

   ulong             lastupdate; //последнее обновлене тик таймер
   bool              is_save; //возможность выключить сохранение в файл

   COrderData        orders[];//ордера открытые  и закрытые
   COrderData        position[]; //для нет счета

   bool              bLoad; //флаг успешной загрузки данных

   ulong             m_master_account;
   string            sCopirName,sfile_prefix,sVersion;
   ulong             tm_last_open_file;
   long              time_offset;

   virtual void              Reset()
     {
      is_hedge=false;
      is_fifo=false;
      lastupdate=0;
      is_save=true;
      ilasttotal=0;
      bLoad=false;
      tm_last_open_file=0;
      ArrayResize(orders,0,500);
      ArrayResize(position,0,500);
      ierror=0;
      sVersion="1.00";
      time_offset=0;
      sfile_prefix="";

      m_master_account=0;
     }
                     COrderEvents()
     {
      Reset();
     }

                    ~COrderEvents()
     {
      this.OnDeinit();
     }

   virtual bool      do_action_filedata_order(COrderData &order)
     {

      return true;
     }

   virtual void      do_event_init()
     {
     }

   virtual void              OnInit(string sversion,string sCopierPath,string sFilePrefix)
     {
      // код доступен только после оплаты
   }

   virtual void              OnDeinit(const int reason=0)
     {
      ArrayFree(orders);
      ArrayFree(position);

     }

   void              FilterComment(string &comment)
     {
      StringReplace(comment,";",":"); //запрещенный символ, его заменяем т.к. используется для разделителя

     }

#ifdef __MQL4__
   ulong               ConvertTicket(ulong thist)
     {
      if((thist & 0x8000000000000000) != 0)
        {
         thist &=~0x8000000000000000;
        }

      return thist;
     }
#else
   ulong               ConvertTicket(ulong thist)
     {
      return thist;
     }
#endif

   virtual bool      do_filter_filedata_update(bool bupdate)
     {
      return bupdate;
     }

   /*
   обработчики виртуальные для работы с изменениями позиций, ордеров и закрытых\отмененных
   */
   virtual void      do_event_change_type(CPositionInfo &tmp) {}
   virtual void      do_event_change_volume(CPositionInfo &tmp) {}
   virtual void      do_event_change_open(CPositionInfo &tmp) {}
   virtual void      do_event_change_stop(CPositionInfo &tmp) {}
   virtual void      do_event_change_take(CPositionInfo &tmp) {}

   virtual void      do_event_change_type(COrderInfo &tmp) {}
   virtual void      do_event_change_volume(COrderInfo &tmp) {}
   virtual void      do_event_change_open(COrderInfo &tmp) {}
   virtual void      do_event_change_stop(COrderInfo &tmp) {}
   virtual void      do_event_change_take(COrderInfo &tmp) {}
   virtual void      do_event_change_state(COrderInfo &tmp) {}

   virtual void      do_event_change_type(CHistoryOrderInfo &tmp) {}
   virtual void      do_event_change_close(CHistoryOrderInfo &tmp) {}

   virtual void      do_action_loadfile_version(string &sdata[]) {}
   virtual void      do_action_loadfile_account(string &sdata[]) {}
   virtual void      do_action_loadfile_position(string &sdata[]) {}

   virtual void              Master(long imaster_account)
     {
      m_master_account=imaster_account;

#ifdef __MQL5__
      is_hedge=AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING;
      is_fifo=AccountInfoInteger(ACCOUNT_FIFO_CLOSE);
#else
      is_hedge=true;
      is_fifo=false;
#endif

      lastupdate=GetMicrosecondCount();

      int isize=ArraySize(orders);

      CPositionInfo  pos;
      COrderInfo ord;
      CHistoryOrderInfo hist;

      bool bUpdate=false;      //если структура пустая, то обновляем ее
      int jorders=0;

      for(int i=isize-1; i>=0; i--)
        {
         if(orders[i].master_ticket==0)
           {
            continue;
           }

         bool bFind=false;

         if(!bUpdate && orders[i].history==false &&  pos.SelectByTicket(orders[i].master_ticket))
           {

            int iDigit=(int)SymbolInfoInteger(pos.Symbol(),SYMBOL_DIGITS);
            int iLotDigits=LotDigits(pos.Symbol());

            if(orders[i].type!=pos.PositionType())
              {
               bUpdate=true;
               do_event_change_type(pos);

              }
            if(NormalizeDouble(orders[i].lot,iLotDigits)!=NormalizeDouble(pos.Volume(),iLotDigits))
              {
               bUpdate=true;
               do_event_change_volume(pos);

              }
            if(NormalizeDouble(orders[i].open,iDigit)!=NormalizeDouble(pos.PriceOpen(),iDigit))
              {
               bUpdate=true;
               do_event_change_open(pos);

              }
            if(NormalizeDouble(orders[i].stop,iDigit)!=NormalizeDouble(pos.StopLoss(),iDigit))
              {
               bUpdate=true;
               do_event_change_stop(pos);

              }
            if(NormalizeDouble(orders[i].take,iDigit)!=NormalizeDouble(pos.TakeProfit(),iDigit))
              {
               bUpdate=true;
               do_event_change_take(pos);

              }

            bFind=true;
           }

         if(!bFind && !bUpdate && orders[i].history==false && ord.Select(orders[i].master_ticket))
           {

            int iDigit=(int)SymbolInfoInteger(ord.Symbol(),SYMBOL_DIGITS);
            int iLotDigits=LotDigits(ord.Symbol());

            if(orders[i].type!=ord.OrderType())
              {
               bUpdate=true;
               do_event_change_type(ord);

              }
            if(NormalizeDouble(orders[i].lot,iLotDigits)!=NormalizeDouble(ord.VolumeInitial(),iLotDigits))
              {
               bUpdate=true;
               do_event_change_volume(ord);

              }
            if(NormalizeDouble(orders[i].open,iDigit)!=NormalizeDouble(ord.PriceOpen(),iDigit))
              {
               bUpdate=true;
               do_event_change_open(ord);

              }
            if(NormalizeDouble(orders[i].stop,iDigit)!=NormalizeDouble(ord.StopLoss(),iDigit))
              {
               bUpdate=true;
               do_event_change_stop(ord);

              }
            if(NormalizeDouble(orders[i].take,iDigit)!=NormalizeDouble(ord.TakeProfit(),iDigit))
              {
               bUpdate=true;
               do_event_change_take(ord);

              }

            if(orders[i].state!=ord.State())
              {
               bUpdate=true;
               do_event_change_state(ord);

              }

            bFind=true;
           }

         if(!bUpdate && !bFind && orders[i].history==false)
           {

            ulong iticket=orders[i].first_ticket>0?orders[i].first_ticket:orders[i].master_ticket;
#ifdef __MQL4__
            if(OrderSelect((int)iticket,SELECT_BY_TICKET))
#else
            if(HistoryOrderSelect(iticket))
#endif
              {

#ifdef __MQL4__
               if(::OrderCloseTime()==0)
                 {
                  orders[i].history=false;
                  continue;
                 }
#endif

               hist.Ticket(iticket);

               if(orders[i].type!=hist.OrderType())
                 {
                  bUpdate=true;
                  do_event_change_type(hist);

                 }

               if(orders[i].tmClose!=hist.TimeDone())
                 {
                  bUpdate=true;
                  do_event_change_close(hist);

                 }

               bFind=true;
              }
           }

         if(bUpdate)
            break; //если хоть один ордер нужно обновить, то обновим и не будем првоерять остальные
        }

      bUpdate=do_filter_filedata_update(bUpdate);

      if(!bUpdate)
        {

         HistorySelect(0,TimeCurrent());

#ifdef __MQL5__
         long itotal=HistoryDealsTotal()+PositionsTotal()+OrdersTotal();
#else
         long itotal=HistoryOrdersTotal()+OrdersTotal();
#endif

         if(itotal!=ilasttotal)
           {
            if(ilasttotal!=0)
               Print("Update data, last count: ",ilasttotal," new count:",itotal);
            bUpdate=true;
            ilasttotal=itotal;

           }

        }

      if(bUpdate || bRestart)
        {

         bRestart=false;

         ArrayFree(orders);

         isize=0;

#ifdef __MQL5__
         for(int i=PositionsTotal()-1; i>=0; i--)
#else
         for(int i=OrdersTotal()-1; i>=0; i--)
#endif
           {

            if(!pos.SelectByIndex(i))
               continue;

            if(pos.PositionType()>=2)
               continue; //проверим по типу, пригодиться для мт4

            isize=ArraySize(orders);

            if(ArrayResize(orders,isize+1)!=-1)
              {
               orders[isize].history=false;
               orders[isize].master_ticket=pos.Ticket();
               orders[isize].master_symbol=pos.Symbol();
               orders[isize].magic=pos.Magic();
               orders[isize].lot=pos.Volume();
               orders[isize].lotout=0; //сюда надо будет записать значение объема на который были закрыты сделки
               orders[isize].type=pos.PositionType();
               orders[isize].open=pos.PriceOpen();
               orders[isize].stop=pos.StopLoss();
               orders[isize].take=pos.TakeProfit();
               orders[isize].tmOpen=pos.Time();
               orders[isize].tmClose=0;
               orders[isize].comment=pos.Comment();
               orders[isize].close=0;
               orders[isize].state=0;
               FilterComment(orders[isize].comment);
              }

           }

         for(int i=OrdersTotal()-1; i>=0; i--)
           {

            if(!ord.SelectByIndex(i))
               continue;

            if(ord.OrderType()>=0 && (ord.OrderType()<2 || ord.OrderType()>=6))
               continue; //првоерим по типу, пригодиться для мт4

            isize=ArraySize(orders);

            if(ArrayResize(orders,isize+1)!=-1)
              {
               orders[isize].history=false;
               orders[isize].master_ticket=ord.Ticket();
               orders[isize].master_symbol=ord.Symbol();
               orders[isize].magic=ord.Magic();
               orders[isize].lot=ord.VolumeCurrent();
               orders[isize].lotout=0;
               orders[isize].type=ord.OrderType();
               orders[isize].open=ord.PriceOpen();
               orders[isize].stop=ord.StopLoss();
               orders[isize].take=ord.TakeProfit();
               orders[isize].tmOpen=ord.TimeSetup();
               orders[isize].tmClose=0;
               orders[isize].comment=ord.Comment();
               orders[isize].close=0;
               orders[isize].state=ord.State();
               FilterComment(orders[isize].comment);

              }

           }

         datetime tmDay1=iTime(_Symbol,PERIOD_D1,3);

         HistorySelect(tmDay1,TimeCurrent()); //загрузим историю за прошлый день, потребуется для отметки если был ордер закрыт

#ifdef __MQL5__
         CDealInfo deal;

         if(HistoryDealsTotal()>0)
           {
            for(int i=HistoryDealsTotal()-1; i>=0; i--)
              {
               if(!deal.SelectByIndex(i))
                  continue;

               if(deal.Entry()==DEAL_ENTRY_INOUT || deal.Entry()==DEAL_ENTRY_OUT)
                 {
                  ulong tdeal=deal.Ticket();
                  long thist=deal.PositionId();

                  ENUM_DEAL_TYPE etype=deal.DealType();

                  if(etype==DEAL_TYPE_BUY || etype==DEAL_TYPE_SELL)
                    {
                     if(etype==DEAL_TYPE_BUY)
                        etype=DEAL_TYPE_SELL;
                     else
                        if(etype==DEAL_TYPE_SELL)
                           etype=DEAL_TYPE_BUY;

                     if(thist>0)
                       {
                        if(pos.SelectByTicket(ConvertTicket(thist)))
                          {
                           if(pos.Time()==0)
                              continue; //если этот оредр еще в рынке, то он не в истории!!
                          }
                        else
                          {

                           bool bfind=false;
                           for(int iisize=ArraySize(orders)-1; iisize>=0; iisize--)
                             {

                              if(orders[iisize].master_ticket==thist)
                                {
                                 orders[iisize].history=true; //пометим  что уже закрыт
                                 bfind=true;
                                 break;
                                }
                             }

                           if(!bfind && thist>0)
                             {
                              isize=ArraySize(orders);

                              if(ArrayResize(orders,isize+1)!=-1)
                                {

                                 orders[isize].history=true;
                                 orders[isize].master_ticket=thist;
                                 orders[isize].master_symbol=deal.Symbol();
                                 orders[isize].magic=deal.Magic();
                                 orders[isize].type=etype;
                                 orders[isize].stop=0;
                                 orders[isize].take=0;
                                 orders[isize].lot=deal.Volume();
                                 orders[isize].lotout=0;

                                 orders[isize].open=0;
                                 orders[isize].close=deal.Price();
                                 orders[isize].comment=deal.Comment();
                                 orders[isize].state=4;
                                 orders[isize].tmOpen=deal.Time();
                                 orders[isize].tmClose=deal.Time();

                                 HistorySelectByPosition(thist);

                                 CDealInfo deal2;
                                 double dsummlot=0.0;
                                 double dlot=0.0,dlotout=0.0;

                                 for(int j=0; j<HistoryDealsTotal(); j++)
                                   {
                                    if(!deal2.SelectByIndex(j))
                                       continue;

          

Показано первые 50% кода (символов: 25120)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
2 512₽ ≈ $30.71