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

orders.mq4

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

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

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

О программе

orders.mqh — библиотека исходного кода для MetaTrader 4, предоставляющая инструменты управления ордерами и позициями. Библиотека содержит класс COrders для открытия, закрытия, модификации ордеров и позиций, управления виртуальными стоп-лоссами и тейк-профитами, расчёта лотов, а также класс CGlobal для работы с глобальными переменными и профиля тестирования. Класс CSpeed используется для профилирования времени выполнения функций, а структура _global хранит именованные данные с временной меткой.

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

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

Классы
Класс class _global

Структура для хранения именованных данных (имя, числовое значение, временная метка), используемая внутри библиотеки для управления глобальными переменными.

Класс class CSpeed

Класс для профилирования времени выполнения функций в тестере и во время работы советника.

Класс class CGlobal

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

Класс class COrders

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

Методы и конструкторы
Конструктор · CSpeed CSpeed()

Создаёт экземпляр класса профилирования и запускает замер времени.

Конструктор · CSpeed CSpeed(bool bprint)

Создаёт экземпляр класса профилирования с указанием необходимости вывода результатов в журнал.

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

Уничтожает экземпляр класса профилирования.

Метод · CSpeed void Start(bool bprint)

Запускает замер времени выполнения с опциональным выводом результатов.

Метод · CSpeed void Stop(string sfunc,string sdop)

Останавливает замер и выводит затраченное время в микросекундах.

Метод · CSpeed void ReStart(string sfunc,string sdop)

Останавливает текущий замер, выводит результат и запускает новый замер.

Метод · CGlobal void OnInit(string symbol,string sexpert,long imagic)

Инициализирует класс глобальных переменных, устанавливая символ, имя эксперта и магический номер.

Метод · CGlobal void OnDeinit()

Освобождает ресурсы, очищая массив глобальных переменных.

Метод · CGlobal void UpdateTime()

Обновляет временные метки глобальных переменных, сбрасывая устаревшие значения.

Метод · CGlobal bool CheckGlobalParam(string name)

Проверяет наличие глобального параметра по имени с учётом привязки к эксперту и магическому номеру.

Метод · CGlobal double SaveGlobalParam(string name,double data)

Сохраняет числовое значение в глобальную переменную с формированием ключа из имени эксперта, магического номера и параметра.

Метод · CGlobal void DeleteGlobalParam(string name)

Удаляет глобальную переменную по имени с формированием ключа.

Метод · CGlobal double LoadGlobalParam(string name,double ddefault_data)

Загружает числовое значение из глобальной переменной, возвращая значение по умолчанию при отсутствии.

Метод · CGlobal double SaveParam(string name,double data)

Сохраняет числовой параметр в глобальную переменную с расширенным ключом, включающим имя символа.

Метод · CGlobal bool CheckParam(string name)

Проверяет наличие параметра в глобальных переменных по расширенному ключу.

Метод · CGlobal void DeleteParam(string name)

Удаляет параметр из глобальных переменных по расширенному ключу.

Метод · CGlobal double LoadParam(string name,double ddefault_data)

Загружает числовой параметр из глобальных переменных, возвращая значение по умолчанию при отсутствии.

Метод · CGlobal string SaveStringParam(string name,string data)

Сохраняет строковый параметр в глобальную переменную.

Метод · CGlobal string LoadStringParam(string name,string ddefault_data)

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

Метод · CGlobal bool DeleteStringParam(string name)

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

Метод · CGlobal int GlobalCopy(_global &dest[],_global &src[])

Копирует массив структур _global из исходного массива в целевой.

Метод · CGlobal int TesterFindIndexGlobal(string name)

Ищет индекс глобальной переменной по имени в массиве тестера.

Метод · CGlobal int GlobalVariablesTotal()

Возвращает общее количество глобальных переменных с учётом режима тестера.

Метод · CGlobal string GlobalVariableName(int index)

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

Метод · CGlobal datetime GlobalVariableTime(string sname)

Возвращает временную метку глобальной переменной по имени.

Метод · CGlobal double GlobalVariableGet(string name)

Возвращает числовое значение глобальной переменной по имени.

Метод · CGlobal datetime GlobalVariableSet(string name,double value)

Устанавливает числовое значение глобальной переменной по имени.

Метод · CGlobal bool GlobalVariableCheck(string name)

Проверяет существование глобальной переменной по имени.

Метод · CGlobal bool GlobalVariableDel(string name)

Удаляет глобальную переменную по имени.

Метод · COrders bool OnInitIndicators()

Вызывается при инициализации индикаторов советника, возвращает флаг успешности.

Метод · COrders bool OnDeinitIndicators()

Вызывается при деинициализации индикаторов советника, возвращает флаг успешности.

Метод · COrders int Signal()

Возвращает торговый сигнал (по умолчанию -1, требует переопределения в производном классе).

Метод · COrders void SetGlobal(CGlobal *ppglobal,bool bInit)

Привязывает экземпляр класса CGlobal к текущему объекту ордеров с опциональной инициализацией.

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

Выполняет очистку ресурсов при деинициализации советника.

Метод · COrders void Magic(long imagic)

Устанавливает магический номер для ордеров и сохраняет его в объекте.

Метод · COrders long Magic()

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

Метод · COrders void Symbol(string sname)

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

Метод · COrders bool Check(CPositionInfo &position,long imagic)

Проверяет позицию на соответствие символу и магическому номеру.

Метод · COrders bool Check(COrderInfo &order,long imagic)

Проверяет ордер на соответствие символу и магическому номеру.

Метод · COrders bool Check(CDealInfo &deal,long imagic)

Проверяет сделку на соответствие символу и магическому номеру.

Метод · COrders bool Check(string symbol,long imagic)

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

Метод · COrders bool CheckMagic(long imagic)

Устаревшая функция проверки магического номера; рекомендует использовать метод Check.

Метод · COrders bool OnInit(string sName,long iMagic,int islippage)

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

Метод · COrders bool IsPosition()

Возвращает флаг того, что текущий выбранный объект является позицией.

Метод · COrders bool IsWork(string sSymbol)

Проверяет возможность торговли: открыт ли рынок, есть ли баланс, разрешён ли торговый режим.

Метод · COrders bool IsNewDay()

Проверяет, начался ли новый торговый день.

Метод · COrders bool SelectByIndex(int i,bool is_position)

Выбирает позицию или ордер по индексу с проверкой по магическому номеру и символу.

Метод · COrders bool SelectAllMagic(int i,bool is_position)

Выбирает позицию или ордер по индексу без привязки к магическому номеру.

Метод · COrders void OnTick()

Основной обработчик тика: обновляет котировки, пересчитывает позиции и ордера, запускает виртуальный контроль.

Метод · COrders void doaction_OnTick()

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

Метод · COrders int Count(int itype)

Подсчитывает количество позиций и ордеров указанного типа.

Метод · COrders int Count(int itype,long imagic)

Подсчитывает количество позиций и ордеров указанного типа и магического номера.

Метод · COrders ulong getLastHistoryTicket(int itype,datetime tmhistory,bool bIN)

Ищет последний тикет сделки в истории по типу, времени и направлению входа.

Метод · COrders ulong getLastHistoryTicketByMagic(int itype,datetime tmhistory,long iMagic,bool bIN)

Ищет последний тикет сделки в истории по типу, времени, магическому номеру и направлению входа.

Метод · COrders ulong getHistoryOrderTicket(int itype,datetime tmhistory,bool bIN)

Возвращает тикет исторического ордера по типу и времени (обёртка над getLastHistoryTicket).

Метод · COrders ulong getHistoryOrderTicket(int itype,datetime tmhistory,long _iMagic,bool bIN)

Возвращает тикет исторического ордера по типу, времени и магическому номеру.

Метод · COrders int CloseOrdersOnBar(ENUM_TIMEFRAMES etf,int &iorders[])

Подсчитывает и возвращает количество закрытых ордеров на текущем баре указанного таймфрейма.

Метод · COrders int OpenOrdersOnBar(ENUM_TIMEFRAMES etf,int &iorders[])

Подсчитывает и возвращает количество открытых ордеров на текущем баре указанного таймфрейма.

Метод · COrders void DeleteVariables(string sfind)

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

Метод · COrders void virtual_init()

Инициализирует виртуальный контроль позиций, проверяя и закрывая позиции по виртуальным уровням.

Метод · COrders void virtual_show()

Отображает или удаляет графические линии виртуальных стоп-лоссов и тейк-профитов на графике.

Метод · COrders void virtual_set(ulong iticket,double dsl,double dtp)

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

Метод · COrders bool virtual_check(ulong iticket)

Проверяет наличие виртуальных уровней стоп-лосса или тейк-профита для указанного тикета.

Метод · COrders double virtual_get_tp(ulong iticket)

Возвращает виртуальный уровень тейк-профита для указанного тикета.

Метод · COrders double virtual_get_var(ulong iticket,string svar)

Возвращает произвольное числовое значение виртуальной переменной по тикету и имени.

Метод · COrders void virtual_set_var(ulong iticket,string svar,double dvar)

Устанавливает числовое значение виртуальной переменной по тикету и имени.

Метод · COrders double virtual_get_sl(ulong iticket)

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

Метод · COrders void virtual_set_levels(ulong iticket,double dsl_pt,double dtp_pt)

Устанавливает виртуальные уровни стоп-лосса и тейк-профита в пунктах от цены открытия позиции.

Метод · COrders double getLotByProcent(string m_name,ENUM_MM emm,double dprocent,double dstep)

Рассчитывает лот на основе указанного процента от баланса, эквити, свободной маржи или требуемой маржи.

Метод · COrders double getLotByProcent(ENUM_MM emm,double dprocent,double dstep)

Рассчитывает лот на основе указанного процента и шага без привязки к имени символа.

Метод · COrders double getLotBySL(double drisk,double dsl,double dbalance)

Рассчитывает лот на основе риска в денежном выражении и уровня стоп-лосса.

Метод · COrders double getLotBySL_valute(double drisk_valute,double dsl)

Рассчитывает лот на основе риска в валюте счёта и уровня стоп-лосса.

Метод · COrders double getLotBySL_valute(double drisk_valute,double dsl,double dcomission)

Рассчитывает лот с учётом комиссии, риска в валюте счёта и уровня стоп-лосса.

Метод · COrders double getLotNoLeverage(double dbalance,double dvaluerisk,double dsl,double dopen,double dstoprisk)

Рассчитывает лот без учёта кредитного плеча с ограничением по максимальному риску.

Метод · COrders bool CheckMaxSpread(double dMaxSpread)

Проверяет, не превышает ли текущий спред указанный максимальный уровень.

Метод · COrders double getMaxLot()

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

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

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

#ifndef __SOVETNIKOV_ORDERS_2sdfhgsd
#define __SOVETNIKOV_ORDERS_2sdfhgsd

#ifndef MYMATH
#define MYMATH
#endif

#include <sovetnikovNET\defines.mqh>
#include <sovetnikovNET\Draw.mqh>
/*
новое решение
*/

struct _global {
   string            name;
   double            data;
   datetime          time;
};

class CSpeed
{
protected:
   ulong             utimer;
   bool              bPrint;
public:

                     CSpeed()
   {
      Start(true);
   }

                     CSpeed(bool bprint)
   {
      Start(bprint);
   }

                    ~CSpeed()
   {
   }

   void              Start(bool bprint)
   {
      bPrint=bprint;
      if(bPrint)
         utimer=GetMicrosecondCount();
   }

   void              Stop(string sfunc,string sdop="")
   {
      if(!bPrint)
         return;  //выключено

      ulong msec=GetMicrosecondCount()-utimer;
      PrintFormat("CSpeed(%s): %s - %d microsec",sdop,sfunc,msec);
   }

   void              ReStart(string sfunc,string sdop="")
   {
      if(!bPrint)
         return;  //выключено

      ulong msec=GetMicrosecondCount()-utimer;
      PrintFormat("CSpeed(%s): %s - %d microsec",sdop,sfunc,msec);
      utimer=GetMicrosecondCount();
   }
};

class CGlobal
{
protected:
   string            m_name;
   string            m_expert;
   long              m_imagic;
   bool              IsTester;

   _global           m_cglobal[];

public:
   virtual void      OnInit(string symbol,string sexpert,long imagic)
   {
      // код доступен только после оплаты
   }

   virtual void      OnDeinit()
   {
      ArrayFree(m_cglobal); //очистим переменную глобальных перменных)
   }

   virtual void      UpdateTime()
   {
      if(!IsTester) {
         string spattern1=StringFormat("%s",m_expert);
         string spattern2="_tp";
         string spattern3="_sl";

         for(int i=0; i<GlobalVariablesTotal(); i++) {
            string svar=GlobalVariableName(i);
            if(StringFind(svar,spattern1)==0 || StringFind(svar,spattern2)>0 || StringFind(svar,spattern3)>0) {
               datetime tmUpdate=GlobalVariableTime(svar);

               if(tmUpdate>0 && (long)(TimeCurrent()-tmUpdate)>=3*604800) {
                  double dvar=GlobalVariableGet(svar);
                  GlobalVariableSet(svar,dvar);

               }
            }
         }
      }
   }

   virtual bool      CheckGlobalParam(string name)
   {
      string svar=StringFormat("%s.%d.%s",m_expert,m_imagic,name);
      return GlobalVariableCheck(svar);
   }

   virtual double    SaveGlobalParam(string name,double data)
   {
      GlobalVariableSet(StringFormat("%s.%d.%s",m_expert,m_imagic,name),data);
      return data;
   }

   virtual void      DeleteGlobalParam(string name)
   {
      GlobalVariableDel(StringFormat("%s.%d.%s",m_expert,m_imagic,name));
   }

   virtual double    LoadGlobalParam(string name,double ddefault_data=0)
   {
      double data=ddefault_data;
      data=GlobalVariableGet(StringFormat("%s.%d.%s",m_expert,m_imagic,name));

      if(data==0.0)
         data=ddefault_data;

      return (data);
   }

   virtual double    SaveParam(string name,double data)
   {

      string svar=StringFormat("%s.%s.%d.%s",m_expert,m_name,m_imagic,name);
      GlobalVariableSet(svar,data);

      return data;
   }

   virtual bool      CheckParam(string name)
   {
      string svar=StringFormat("%s.%s.%d.%s",m_expert,m_name,m_imagic,name);
      return GlobalVariableCheck(svar);
   }

   virtual void      DeleteParam(string name)
   {
      GlobalVariableDel(StringFormat("%s.%s.%d.%s",m_expert,m_name,m_imagic,name));
   }

   virtual double    LoadParam(string name,double ddefault_data=0)
   {
      double data=ddefault_data;
      string name_global=StringFormat("%s.%s.%d.%s",m_expert,m_name,m_imagic,name);

      if(GlobalVariableCheck(name_global)==false)
         data=ddefault_data;
      else
         data=(double)GlobalVariableGet(name_global);

      return data;
   }

   string            SaveStringParam(string name,string data)
   {
      GlobalVariableSet(StringFormat("%s.%d.%s=%s",m_expert,m_imagic,name,data),1);
      return data;
   }

   string            LoadStringParam(string name,string ddefault_data="")
   {
      string sfull_name=StringFormat("%s.%d.%s",m_expert,m_imagic,name);
      string sparam[];

      for(int i=0; i<GlobalVariablesTotal(); i++) {
         string svar=GlobalVariableName(i);
         string_explode("=",svar,sparam);

         if(ArraySize(sparam)==2 && StringCompare(sfull_name,sparam[0],false)==0) {
            return sparam[1]; //нашли
         }
      }

      return ddefault_data;
   }

   bool              DeleteStringParam(string name)
   {
      string sfull_name=StringFormat("%s.%d.%s",m_expert,m_imagic,name);
      string sparam[];
      bool bFind=false;

      for(int i=GlobalVariablesTotal()-1; i>=0; i--) {
         string svar=GlobalVariableName(i);
         string_explode("=",svar,sparam);

         if(ArraySize(sparam)==2 && StringCompare(sfull_name,sparam[0],false)==0) {
            GlobalVariableDel(svar);
            bFind=true;
         }
      }

      return bFind;
   }

   int               GlobalCopy(_global &dest[],_global &src[])
   {
      int isize=ArraySize(src);
      if(ArrayResize(dest,isize)!=-1) {
         for(int i=0; i<isize; i++) {
            dest[i].data=src[i].data;
            dest[i].name=src[i].name;
            dest[i].time=src[i].time;
         }

         return isize;
      }

      return false;
   }

   int               TesterFindIndexGlobal(string name)
   {
      int isize=ArraySize(m_cglobal);

      for(int i=isize-1; i>=0; i--) {
         if(StringCompare(m_cglobal[i].name,name,false)==0)
            return i; //найдем индекс
      }
      return -1;
   }

   int               GlobalVariablesTotal()
   {

      if(IsTester) {

         return ArraySize(m_cglobal);

      }

      return ::GlobalVariablesTotal();
   }

   string            GlobalVariableName(int index)
   {

      if(IsTester) {
         int isize=ArraySize(m_cglobal);
         if(index<0 || index>=isize)
            return "";

         return m_cglobal[index].name;
      }

      return ::GlobalVariableName(index);
   }

   datetime          GlobalVariableTime(string sname)
   {

      if(IsTester) {
         int index = TesterFindIndexGlobal(sname);
         if(index<0)
            return 0;//ошибка

         return m_cglobal[index].time;
      }

      return ::GlobalVariableTime(sname);
   }

   double            GlobalVariableGet(string name)
   {

      if(IsTester) {
         int index=TesterFindIndexGlobal(name);

         if(index==-1) {

            return false;
         }

         return m_cglobal[index].data;
      }

      return ::GlobalVariableGet(name);
   }

   datetime          GlobalVariableSet(string name,double value)
   {

      if(IsTester) {

         int index=TesterFindIndexGlobal(name);

         if(index!=-1) {

            m_cglobal[index].data=value;
            m_cglobal[index].time=TimeCurrent();
         } else if(index==-1 && name!="") {
            int isize=ArraySize(m_cglobal);

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

               m_cglobal[isize].name=name;
               m_cglobal[isize].data=value;
               m_cglobal[isize].time=TimeCurrent();

               isize=ArraySize(m_cglobal);
            } else {
               PrintFormat("(%d) Invalid resize m_cglobal error: %d",__LINE__,GetLastError());
               return 0; //ошибка
            }
         }

         return TimeCurrent();
      }

      return ::GlobalVariableSet(name,value);
   }

   bool              GlobalVariableCheck(string name)
   {

      if(IsTester) {
         int index=TesterFindIndexGlobal(name);
         if(index==-1)
            return false;
         return true;
      }

      return ::GlobalVariableCheck(name);
   }

   bool              GlobalVariableDel(string name)
   {

      if(IsTester) {
         int index=TesterFindIndexGlobal(name);
         if(index==-1) {

            return false;
         }

         _global newglobal[];
         int inewsize=0;
         int isize=ArraySize(m_cglobal);

         if(GlobalCopy(newglobal,m_cglobal)>0) {

            isize=0;
            ArrayResize(m_cglobal,0); //переформируем структуру

            inewsize=ArraySize(newglobal);

            for(int i=0; i<inewsize; i++) {
               if(newglobal[i].name!=name) {

                  if(ArrayResize(m_cglobal,isize+1)!=-1) {
                     m_cglobal[isize].name=newglobal[i].name;
                     m_cglobal[isize].data=newglobal[i].data;
                     m_cglobal[isize].time=newglobal[i].time;
                     isize++;
                  }
               }

            }

            return true;
         }

         return false;
      }

      return (bool)::GlobalVariableDel(name);
   }

};

class COrders
{
public:
   COrderInfo        m_order;
   CHistoryOrderInfo m_history;
   CPositionInfo     m_position;                   // object of CPositionInfo class
   CTrade            m_trade;                      // object of CTrade class
   CSymbolInfo       m_symbol;                     // object of CSymbolInfo class
   CAccountInfo      m_account;                    // object of CAccountInfo class
   CDealInfo         m_deal;                       // object of CDealInfo class
   CGlobal           *pglobal;

   CDraw             m_drawvirtual;
   double            p;
   int               ierrors;
   string            serrors;
   ulong             tmLastTick;

   CNewBar           m_newday;

   bool              IsTester;
   bool              IsDraw;

   string            m_name;
   long              m_imagic;
   int               m_islippage;
   int               m_all,orders[6];

   double            _Ask,_Bid;

   double            dTralProfit;
   bool              m_bClose;

   double            dBuProfit;
   bool              m_bBuClose;

   double            dProfit;

   double            dPositionCapital;

   bool              options_bNewDay; //включает новый день (авто включение если не задано)
   int               options_bTickPause; //включает паузу >0 при работе по тиках, когда точность тиковая не  критична, это ускоряет тест
   int               options_iPovtor; //кол-во поппыток при открытии ордера
   bool              options_bNoCheckPending; //отключает проверку лимиток на наличие денег
   bool              options_bCheckMargin; //проверять маржу при открытии
   bool              options_bVirtualControl;
   bool              options_bECN;

   bool              m_bposition;

   string            sWindowExpertName;

   virtual bool      OnInitIndicators()
   {
      return true;
   }

   virtual bool      OnDeinitIndicators()
   {
      return true;
   }

   virtual int       Signal()
   {

      return -1;
   }

   virtual void      SetGlobal(CGlobal *ppglobal,bool bInit=true)
   {

      if(bInit)
         ppglobal.OnInit(m_name,sWindowExpertName,m_imagic);
      pglobal=ppglobal;
   }

   virtual void      OnDeinit(const int reason=0)
   {
      OnDeinitIndicators();
      m_drawvirtual.OnDeinit();

   }

   virtual void      Magic(long imagic)
   {
      m_imagic=imagic;
      m_trade.SetExpertMagicNumber(m_imagic);
   }

   virtual long      Magic()
   {
      return m_imagic;
   }

   virtual void      Symbol(string sname)
   {
      m_name=sname;
      if(sname!=NULL) {
         m_symbol.Name(sname);
         m_symbol.Refresh(); //обновим данные по символу
         m_trade.SetTypeFillingBySymbol(sname);
         p=point(sname);
      }
   }

   virtual bool      Check(CPositionInfo &position,long imagic)
   {
      string symbol=position.Symbol();

      return Check(symbol,imagic);

   }

   virtual bool      Check(COrderInfo &order,long imagic)
   {
      string symbol=order.Symbol();

      return Check(symbol,imagic);

   }

   virtual bool      Check(CDealInfo &deal,long imagic)
   {
      string symbol=deal.Symbol();

      return Check(symbol,imagic);

   }

   virtual bool              Check(string symbol,long imagic)
   {

      if((m_name==NULL || symbol==m_name) && (m_imagic==-1 || m_imagic==imagic || imagic==-1)) {

         return true;
      }
      return false;
   }

   bool              CheckMagic(long imagic)
   {
      Print("Устаревшая функция. Использовать Check(position/order/deal,magic)");
      return false;
   }

   virtual bool              OnInit(string sName,long iMagic,int islippage)
   {
      // код доступен только после оплаты
   }

   bool              IsPosition()
   {
      return m_bposition;
   }

   bool              IsWork(string sSymbol=NULL)
   {
      if(options_bTickPause>0) {

         if((long)(TimeCurrent()-tmLastTick)<options_bTickPause && tmLastTick>0) {

            return false;
         }

         tmLastTick=TimeCurrent();
      }

      if(sSymbol==NULL)
         sSymbol=m_name;

      if(!checkMarketIsOpen(sSymbol)) {

         return false; //неторговое время (проверка на клиринг)
      }

      if(IsTester) {
         return true;
      }

      if(AccountInfoDouble(ACCOUNT_BALANCE)==0.0)
         return false;

      if(!work_check()) {

         return false;
      }

      if(!checkTradeMode(sSymbol)) {

         return false; //торговля по инструменту запрещена
      }

      return true;
   }

   bool              IsNewDay()
   {
      if(!options_bNewDay)
         options_bNewDay=true;
      return m_newday.isNewBar();
   }

   /*
   выбираем позицию или ордер, првоеряем их по меджику и инструменту, если ок то возвращаем true
   */
   virtual bool      SelectByIndex(int i,bool is_position)
   {
      if(is_position) {
         if(!m_position.SelectByIndex(i)) {

            return false;
         }

         if(Check(m_position,m_position.Magic())) {
            return true;
         }

      } else {
         if(!m_order.SelectByIndex(i))
            return false;

         if(m_order.OrderType()>=6)
            return false; //не пропустим ордера с нестандартным типом отложки и рыночные стандартные ордера обрабатываем только

         if(Check(m_order,m_order.Magic()))
            return true;
      }

      return false;
   }

   virtual bool      SelectAllMagic(int i,bool is_position)
   {
      if(is_position) {
         if(!m_position.SelectByIndex(i))
            return false;

         if(Check(m_position,-1))
            return true;
      } else {
         if(!m_order.SelectByIndex(i))
            return false;

         if(m_order.OrderType()>=6)
            return false; //не пропустим ордера с нестандартным типом отложки и рыночные стандартные ордера обрабатываем только

         if(Check(m_order,-1))
            return true;
      }

      return false;
   }

   /*
   Основной цикл обработки позиций и ордеров (если требуется подгрузить какие данные и будет за основу взять для закрытия и других функций)
   */
   virtual void      OnTick()
   {
      // код доступен только после оплаты
   }

   virtual void      doaction_OnTick()
   {

   }

   int               Count(int itype)
   {
      __COPYRIGHT__
      int iall=0;

      int  flag=toMyTypes(OP_BUY)&itype;

      if(toDefType(flag,itype)==OP_BUY)
         iall+=orders[OP_BUY];

      flag=toMyTypes(OP_SELL)&itype;
      if(toDefType(flag,itype)==OP_SELL)
         iall+=orders[OP_SELL];

      flag=toMyTypes(OP_SELLLIMIT)&itype;
      if(toDefType(flag,itype)==OP_SELLLIMIT)
         iall+=orders[OP_SELLLIMIT];

      flag=toMyTypes(OP_SELLSTOP)&itype;
      if(toDefType(flag,itype)==OP_SELLSTOP)
         iall+=orders[OP_SELLSTOP];

      flag=toMyTypes(OP_BUYLIMIT)&itype;
      if(toDefType(flag,itype)==OP_BUYLIMIT)
         iall+=orders[OP_BUYLIMIT];

      flag=toMyTypes(OP_BUYSTOP)&itype;
      if(toDefType(flag,itype)==OP_BUYSTOP)
         iall+=orders[OP_BUYSTOP];

      return iall;
   }

   int               Count(int itype,long imagic)
   {
      __COPYRIGHT__
      int ic=0;

      for(int i=0; i<PositionsTotal(); i++) {
         if(!m_position.SelectByIndex(i))
            continue; //если не выбирает, пропускаем

         if(this.OrderType(true)<2) {

            int  flag=toMyTypes(this.OrderType(true))&itype;
            if((imagic==-1 || imagic==this.OrderMagicNumber(true)) && (m_name==NULL || m_name==this.OrderSymbol(true))) {
               if(this.OrderType(true)==toDefType(flag,itype) || itype==ALL) {
                  ic++;
               }
            }
         }
      }

      for(int i=0; i<OrdersTotal(); i++) {
         if(!m_order.SelectByIndex(i))
            continue; //если не выбирает, пропускаем

         if(this.OrderType(false)>=2) {
            int  flag=toMyTypes(this.OrderType(false))&itype;

            if((imagic==-1 || imagic==this.OrderMagicNumber(false)) && (m_name==NULL || m_name==this.OrderSymbol(false))) {
               if(this.OrderType(false)==toDefType(flag,itype) || itype==ALL)
                  ic++;
            }
         }
      }

      return ic;
   }

   virtual ulong       getLastHistoryTicket(int itype,datetime tmhistory,bool bIN=true)
   {
      HistorySelect(tmhistory,TimeCurrent()); //загрузем историю последнего месяца

      if(!bIN) {
         itype=InverseSignal((ENUM_ORDER_TYPE)itype);
      }

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

         if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) {

            if((m_deal.Magic()==m_imagic || m_imagic==-1) && (m_deal.Symbol()==m_name || m_name==NULL)) {
               if(((m_deal.Entry()==DEAL_ENTRY_IN && bIN) || (m_deal.Entry()==DEAL_ENTRY_OUT && !bIN)) && (itype==ALL || itype==m_deal.DealType())) { //было открытие
                  if(m_deal.Time()>=tmhistory) {
                     return m_deal.Ticket();
                  }
               }
            }
         }
      }

      return 0;
   }

   virtual ulong       getLastHistoryTicketByMagic(int itype,datetime tmhistory,long iMagic,bool bIN=true)
   {
      HistorySelect(tmhistory,TimeCurrent()); //загрузем историю последнего месяца

      if(!bIN) {
         itype=InverseSignal((ENUM_ORDER_TYPE)itype);
      }

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

         if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) {

            if((m_deal.Magic()==iMagic) && (m_deal.Symbol()==m_name || m_name==NULL)) {
               if(((m_deal.Entry()==DEAL_ENTRY_IN && bIN) || (m_deal.Entry()==DEAL_ENTRY_OUT && !bIN)) && (itype==ALL || itype==m_deal.DealType())) { //было открытие
                  if(m_deal.Time()>tmhistory) {
                     return m_deal.Ticket();
                  }
               }
            }
         }
      }

      return 0;
   }

   virtual ulong       getHistoryOrderTicket(int itype,datetime tmhistory,bool bIN=true)
   {
      return getLastHistoryTicket(itype,tmhistory,bIN);
   }

   virtual ulong       getHistoryOrderTicket(int itype,datetime tmhistory,long _iMagic,bool bIN=true)
   {
      return getLastHistoryTicketByMagic(itype,tmhistory,_iMagic,bIN);
   }

   virtual int               CloseOrdersOnBar(ENUM_TIMEFRAMES etf,int &iorders[])
   {
      ArrayResize(iorders,10);
      ArrayInitialize(iorders,0);

      datetime tStart=iTime(m_name,etf,0);
      datetime tEnd=TimeCurrent();

      HistorySelect(tStart,tEnd);

      int itotal=HistoryDealsTotal();

      int icount=0;
      int itype=-1;

      for(int i=0; i<itotal; i++) {
         if(!m_deal.SelectByIndex(i))
            continue;

         if(Check(m_deal,m_deal.Magic())) {
            itype=(int)m_deal.DealType();

            datetime tmOpen=0;

            if(m_deal.Entry()==DEAL_ENTRY_OUT) {
               tmOpen=(datetime)m_deal.Time();

               if(tmOpen>0) {
                  int iBar=iBarShift(m_symbol.Name(),etf,tmOpen);

                  if(iBar==0) {

                     if(itype==OP_BUY)
                        iorders[OP_SELL]++;
                     if(itype==OP_SELL)
                        iorders[OP_BUY]++;
                     icount++;
                  }
               }
            }

         }

      }

      return            icount;
   }

   virtual int       OpenOrdersOnBar(ENUM_TIMEFRAMES etf,int &iorders[])
   {
      ArrayResize(iorders,10);
      ArrayInitialize(iorders,0);

      datetime tStart=iTime(m_name,etf,0);
      datetime tEnd=TimeCurrent();
      HistorySelect(tStart,tEnd);

      int itotal=HistoryDealsTotal();

      int icount=0;
      int itype=-1;

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

         if(Check(m_deal,m_deal.Magic())) {
            itype=(int)m_deal.DealType();

            datetime tmOpen=0;

            if(m_deal.Entry()==DEAL_ENTRY_IN) {
               tmOpen=(datetime)m_deal.Time();

               if(tmOpen>0) {
                  int iBar=iBarShift(m_deal.Symbol(),etf,tmOpen);
                  if(iBar==0) {
                     iorders[itype]++;
                     icount++;
                  }
               }
            }

         }

      }

      return            icount;
   }

   virtual void      DeleteVariables(string sfind)
   {

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return;

      int isize=pglobal.GlobalVariablesTotal();
      string sglobal="";
      for(int i=isize-1; i>=0; i--) {
         sglobal=pglobal.GlobalVariableName(i);

         if(sglobal=="" || sglobal==NULL)
            continue;

         if(StringFind(sglobal,StringFormat("_%s",sfind))<0)
            continue; //пропустим не наши

         string sret[];
         int j=string_explode("_",sglobal,sret);

         if(j==2) {
            ulong iticket=(ulong)StringToInteger(sret[0]);
            if(iticket>0) {

               if(!PositionSelectByTicket(iticket)) {
                  pglobal.GlobalVariableDel(sglobal); //удалим переменную закрытого ордера
               }

            }
         }
      }

   }

   virtual void      virtual_init()
   {
      if(CheckPointer(pglobal)==POINTER_INVALID)
         return;

      string param[],n;
      int i,itype=-1,isizeParam=0;

      int isize=0;

      isize=pglobal.GlobalVariablesTotal();

      for(i=isize-1; i>=0; i--) {
         string sglobal=pglobal.GlobalVariableName(i);

         if(sglobal=="" || sglobal==NULL)
            continue;

         if(StringFind(sglobal,"_sl")<0 && StringFind(sglobal,"_tp")<0) {
            continue; //пропустим не наши
         }

         string_explode("_",sglobal,param);

         isizeParam=ArraySize(param);

         if(isizeParam<2 && isizeParam>3)
            continue; //пропустим сразу неподходящие под наши правила

         if(isizeParam==2 && StringToInteger(param[0])>0) {
            ulong iticket=(ulong)StringToInteger(param[0]);//тикет

            if(iticket<=0)
               continue;
#ifdef __MQL5__
            if(!m_position.SelectByTicket(iticket)) {
               pglobal.GlobalVariableDel(sglobal);
               ObjectDelete(ChartID(),sglobal);

            }
#else
            if(::OrderSelect((int)iticket,SELECT_BY_TICKET,MODE_HISTORY)) {
               if(::OrderCloseTime()>0) {
                  pglobal.GlobalVariableDel(sglobal);
                  ObjectDelete(ChartID(),sglobal);
               }
            }
#endif

            if(m_position.SelectByTicket(iticket)) {

               itype=m_position.PositionType();
               n=m_position.Symbol();

               double pt=0;
               double dtp=0;
               double dsl=0;

               dtp=virtual_get_tp(iticket);
               dsl=virtual_get_sl(iticket);

               if(dtp==0 && dsl==0)
                  continue;

               MqlTick tick;
               SymbolInfoTick(n,tick);

               if(dtp!=0 && ((tick.bid>=dtp && itype==OP_BUY) || (tick.ask<=dtp && itype==OP_SELL))) {
                  if(OrderClose(iticket,0)) {
                     Print("Close by TP: ",iticket," tp=",dtp);
                     pglobal.GlobalVariableDel(sglobal);
                     m_drawvirtual.Delete(ChartID(),StringFormat("%lld_tp",iticket));
                     m_drawvirtual.Delete(ChartID(),StringFormat("%lld_sl",iticket));
                  }
               }//close by dtp

               if(dsl!=0 && ((tick.bid<=dsl && itype==OP_BUY) || (tick.ask>=dsl && itype==OP_SELL))) {
                  if(OrderClose(iticket,0)) {
                     Print("Close by SL: ",iticket," sl=",dsl);
                     pglobal.GlobalVariableDel(sglobal);
                     m_drawvirtual.Delete(ChartID(),StringFormat("%lld_tp",iticket));
                     m_drawvirtual.Delete(ChartID(),StringFormat("%lld_sl",iticket));
                  }
               }//close by dstop
            }

         }

      }

   }

   void              virtual_show()
   {

      if(!options_bVirtualControl)
         return;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return;

      string param[];
      int i,itype=-1,isizeParam=0;

      int isize=0;

      isize=pglobal.GlobalVariablesTotal();

      for(i=isize-1; i>=0; i--) {
         string sglobal=pglobal.GlobalVariableName(i);

         if(sglobal=="" || sglobal==NULL)
            continue;

         if(StringFind(sglobal,"_sl")<0 && StringFind(sglobal,"_tp")<0) {
            continue; //пропустим не наши
         }

         string_explode("_",sglobal,param);

         isizeParam=ArraySize(param);

         if(isizeParam<2 && isizeParam>3)
            continue; //пропустим сразу неподходящие под наши правила

         if(isizeParam==2 && StringToInteger(param[0])>0) {
            ulong iticket=(ulong)StringToInteger(param[0]);//тикет

            if(iticket<=0)
               continue;

            if(OrderSelect(iticket,true)) {
               datetime tmglobal=m_position.Time();

               double dstop=m_position.StopLoss();
               double dtake=m_position.TakeProfit();

               double dtp=0;
               double dsl=0;

               dtp=virtual_get_tp(iticket);
               dsl=virtual_get_sl(iticket);

               if(nd(dtp)==nd(dtake))
                  dtp=0;
               if(nd(dsl)==nd(dstop))
                  dsl=0;

               if(dtp>0)
                  m_drawvirtual.DrawLine(ChartID(),StringFormat("%lld_tp",iticket),0,tmglobal,dtp,TimeCurrent(),dtp,1,STYLE_DASHDOT,clrGreen,false,false,StringFormat("#%lld TP",iticket),true);
               else
                  m_drawvirtual.Delete(ChartID(),StringFormat("%lld_tp",iticket));

               if(dsl>0)
                  m_drawvirtual.DrawLine(ChartID(),StringFormat("%lld_sl",iticket),0,tmglobal,dsl,TimeCurrent(),dsl,1,STYLE_DASHDOT,clrRed,false,false,StringFormat("#%lld SL",iticket),true);
               else
                  m_drawvirtual.Delete(ChartID(),StringFormat("%lld_sl",iticket));

            } else {

               m_drawvirtual.Delete(ChartID(),StringFormat("%lld_tp",iticket));
               m_drawvirtual.Delete(ChartID(),StringFormat("%lld_sl",iticket));
            }

         }

      }

      for(i=ObjectsTotal(ChartID(),-1,-1)-1; i>=0; i--) {
         string sglobal=ObjectName(ChartID(),i,-1,-1);

         if(sglobal=="" || sglobal==NULL)
            continue;

         if(StringFind(sglobal,"_sl")<0 && StringFind(sglobal,"_tp")<0) {
            continue; //пропустим не наши
         }

         string_explode("_",sglobal,param);

         isizeParam=ArraySize(param);

         if(isizeParam==3 && StringToInteger(param[1])>0 && param[0]=="virtual") {
            ulong iticket=(ulong)StringToInteger(param[1]);//тикет

            if(iticket<=0)
               continue;

#ifdef __MQL5__
            if(!m_position.SelectByTicket(iticket)) {
               ObjectDelete(ChartID(),sglobal);

            }
#else
            if(::OrderSelect((int)iticket,SELECT_BY_TICKET,MODE_HISTORY)) {

               if(::OrderCloseTime()>0) {

                  ObjectDelete(ChartID(),sglobal);
               }
            }
#endif

         }
      }
   }

   void              virtual_set(ulong iticket,double dsl,double dtp)
   {
      if(iticket<=0)
         return;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return;

      string n;

      int idgt=digits(_Symbol);

      n=StringFormat("%lld_tp",iticket);
      if(dtp>=0)
         pglobal.GlobalVariableSet(n,dtp);
      else
         pglobal.GlobalVariableDel(n);

      n=StringFormat("%lld_sl",iticket);
      if(dsl>=0)
         pglobal.GlobalVariableSet(n,dsl);
      else
         pglobal.GlobalVariableDel(n);

   }

   bool              virtual_check(ulong iticket)
   {
      if(iticket<=0)
         return false;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return false;

      string n;

      n=StringFormat("%lld_tp",iticket);

      if(pglobal.GlobalVariableCheck(n))
         return  true;

      n=StringFormat("%lld_sl",iticket);

      if(pglobal.GlobalVariableCheck(n))
         return true;

      return false;
   }

   double            virtual_get_tp(ulong iticket)
   {
      if(iticket<=0)
         return 0;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return false;

      string n;

      n=StringFormat("%lld_tp",iticket);

      if(pglobal.GlobalVariableCheck(n))
         return pglobal.GlobalVariableGet(n);

      return 0;
   }

   double            virtual_get_var(ulong iticket,string svar)
   {
      if(iticket<=0)
         return 0;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return 0;

      string n;

      n=StringFormat("%lld_%s",iticket,svar);

      if(pglobal.GlobalVariableCheck(n))
         return pglobal.GlobalVariableGet(n);

      return 0;
   }

   void              virtual_set_var(ulong iticket,string svar,double dvar)
   {
      if(iticket<=0)
         return;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return;

      string n;

      if(dvar>=0) {
         n=StringFormat("%lld_%s",iticket,svar);

         pglobal.GlobalVariableSet(n,dvar);

      }
   }

   double            virtual_get_sl(ulong iticket)
   {
      if(iticket<=0)
         return 0;

      if(CheckPointer(pglobal)==POINTER_INVALID)
         return 0;

      string n;

      n=StringFormat("%lld_sl",iticket);

      if(pglobal.GlobalVariableCheck(n))
         return pglobal.GlobalVariableGet(n);

      return 0;
   }

   void              virtual_set_levels(ulong iticket,double dsl_pt,double dtp_pt)
   {

      if(iticket>0 && OrderSelect(iticket,true)) {
         string ssmb=m_position.Symbol();
         double dpp=point(ssmb);

         double dopen=m_position.PriceOpen();
         double dstop=0;
         double dtake=0;
         int itype=m_position.PositionType();

         if(itype==POSITION_TYPE_BUY) {
            if(dsl_pt>0)
               dstop=dopen-dsl_pt*dpp;
            if(dtp_pt>0)
               dtake=dopen+dtp_pt*dpp;
         }

         if(itype==POSITION_TYPE_SELL) {
            if(dsl_pt>0)
               dstop=dopen+dsl_pt*dpp;
            if(dtp_pt>0)
               dtake=dopen-dtp_pt*dpp;
         }

         virtual_set(iticket,dstop,dtake);
      }
   }

   static double     getLotByProcent(string m_name,ENUM_MM emm,double dprocent,double dstep)
   {
      double dlot=0;
      if(dprocent<=0)
         return 0;

      if(emm==MM_Balance) {
         dlot=NLot(0.01*(AccountBalance()*dprocent*0.001));
      } else if(emm==MM_Equity) {
         dlot=NLot(0.01*(AccountEquity()*dprocent*0.001));
      } else if(emm==MM_FreeMargin) {
         dlot=NLot(0.01*(AccountFreeMargin()*dprocent*0.001));
      } else if(emm==MM_MarginRequired) {
         double marginInit=SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL);

         if(marginInit>0)
            dlot=NLot(0.01*AccountBalance()*dprocent/marginInit);
         else
            dlot=0;
      } else if(emm==MM_BalanceStep && dstep>0) {
         dlot=NLot(AccountBalance()*dprocent/dstep);
      } else if(emm==MM_EquityStep && dstep>0) {
         dlot=NLot(AccountEquity()*dprocent/dstep);
      } else if(emm==MM_FreeMarginStep && dstep>0) {
         dlot=NLot(AccountFreeMargin()*dprocent/dstep);
      } else if(emm==MM_MarginProcent && dprocent>0 && dstep>0) {
         double initial_margin_rate=1,maintenance_margin_rate=0;

#ifdef __MQL5__
         SymbolInfoMarginRate(
            m_name,                     // символ
            ORDER_TYPE_BUY,
            initial_margin_rate,      // коэффициент взимания начальной маржи
            maintenance_margin_rate   // коэффициент взимания поддерживающей маржи
         );
#endif

         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_FOREX) {

            double dprice=1;

            if(StringFind(m_name,"GOLD")>=0 || StringFind(m_name,"XAU")>=0 || StringFind(m_name,"XAG")>=0)
               dprice=dstep;

            dlot=NLot(0.01*dprocent*AccountBalance()*AccountInfoInteger(ACCOUNT_LEVERAGE)/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate*dprice));
         }
#ifdef __MQL5__
         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE) {
            dlot=NLot(0.01*dprocent*AccountBalance()/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate));
         }
#endif
         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE)==SYMBOL_CALC_MODE_FUTURES) {
            double marginInit=SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL);

            dlot=NLot(0.01*dprocent*AccountBalance()/(marginInit*initial_margin_rate));
         }
         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_CFD) {

            dlot=NLot(0.01*dprocent*AccountBalance()/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate*dstep));
         }

         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_CFDLEVERAGE) {

            dlot=NLot(0.01*dprocent*AccountBalance()*AccountInfoInteger(ACCOUNT_LEVERAGE)/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate*dstep));
         }

      }

      return dlot;
   }

   virtual double    getLotByProcent(ENUM_MM emm,double dprocent,double dstep=0)
   {
      double dlot=0;
      if(dprocent<=0)
         return 0;

      if(emm==MM_Balance) {
         dlot=NLot(0.01*(AccountBalance()*dprocent*0.001));
      } else if(emm==MM_Equity) {
         dlot=NLot(0.01*(AccountEquity()*dprocent*0.001));
      } else if(emm==MM_FreeMargin) {
         dlot=NLot(0.01*(AccountFreeMargin()*dprocent*0.001));
      } else if(emm==MM_MarginRequired) {
         double marginInit=SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL);

         if(marginInit>0)
            dlot=NLot(0.01*AccountBalance()*dprocent/marginInit);
         else
            dlot=0;
      } else if(emm==MM_BalanceStep && dstep>0) {
         dlot=NLot(AccountBalance()*dprocent/dstep);
      } else if(emm==MM_EquityStep && dstep>0) {
         dlot=NLot(AccountEquity()*dprocent/dstep);
      } else if(emm==MM_FreeMarginStep && dstep>0) {
         dlot=NLot(AccountFreeMargin()*dprocent/dstep);
      } else if(emm==MM_MarginProcent && dprocent>0 && dstep>0) {
         double initial_margin_rate=1,maintenance_margin_rate=0;

#ifdef __MQL5__
         SymbolInfoMarginRate(
            m_name,                     // символ
            ORDER_TYPE_BUY,
            initial_margin_rate,      // коэффициент взимания начальной маржи
            maintenance_margin_rate   // коэффициент взимания поддерживающей маржи
         );
#endif

         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_FOREX) {

            double dprice=1;

            if(StringFind(m_name,"GOLD")>=0 || StringFind(m_name,"XAU")>=0 || StringFind(m_name,"XAG")>=0)
               dprice=dstep;

            dlot=NLot(0.01*dprocent*AccountBalance()*AccountInfoInteger(ACCOUNT_LEVERAGE)/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate*dprice));
         }
#ifdef __MQL5__
         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE) {
            dlot=NLot(0.01*dprocent*AccountBalance()/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate));
         }
#endif
         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE)==SYMBOL_CALC_MODE_FUTURES) {
            double marginInit=SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL);

            dlot=NLot(0.01*dprocent*AccountBalance()/(marginInit*initial_margin_rate));
         }
         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_CFD) {

            dlot=NLot(0.01*dprocent*AccountBalance()/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate*dstep));
         }

         if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_CFDLEVERAGE) {

            dlot=NLot(0.01*dprocent*AccountBalance()*AccountInfoInteger(ACCOUNT_LEVERAGE)/(SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE)*initial_margin_rate*dstep));
         }

      }

      return dlot;
   }

   virtual double    getLotBySL(double drisk,double dsl,double dbalance=0)
   {
      if(dsl==0.0)
         return (0.0);

      double dContractSize=SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE);
      double dTickValue=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE);
      double dTickSize=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_SIZE);
      double dStep=SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP);

      double _dpoint=SymbolInfoDouble(m_name,SYMBOL_POINT);
      if(_dpoint==0.0)
         return 0.0;

      double _sp=GetSpread(m_name);

      int d=int(point(m_name)/_dpoint);
      double bb=AccountBalance();

      if(dbalance>0)
         bb=dbalance;

      if(dsl*_dpoint*d==0)
         return 0;

      double m_lots=0;

      if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_FOREX)
         m_lots=MathFloor((bb*drisk*0.01)/(dsl*dTickValue)/dStep)*dStep;
      else
         m_lots=MathFloor((bb*drisk*0.01)/(dsl*dTickValue*_dpoint/dTickSize)/dStep)*dStep;

      return NLot(m_lots,m_name);
   }

   virtual double    getLotBySL_valute(double drisk_valute,double dsl)
   {
      if(dsl==0.0)
         return (0.0);

      double dpoint=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE);
      double dStep=SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP);
      double _dpoint=SymbolInfoDouble(m_name,SYMBOL_POINT);
      if(_dpoint == 0.0)
         return 0.0;

      int d=int(p/_dpoint);

      if(dsl*dpoint*d==0)
         return 0;

      double m_lots=MathFloor(drisk_valute/(dsl*dpoint*d)/dStep)*dStep;

      return NLot(m_lots);
   }

   virtual double    getLotBySL_valute(double drisk_valute,double dsl,double dcomission=0)
   {
      if(dsl==0.0)
         return (0.0);

      double dContractSize=SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE);
      double dTickValue=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE);
      double dTickSize=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_SIZE);
      double dStep=SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP);

      double _dpoint=SymbolInfoDouble(m_name,SYMBOL_POINT);
      if(_dpoint==0.0)
         return 0.0;

      double _sp=GetSpread(m_name);

      int d=int(point(m_name)/_dpoint);

      if(dsl*_dpoint*d==0)
         return 0;

      double m_lots=0;

      if(SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE) == SYMBOL_CALC_MODE_FOREX)
         m_lots=MathFloor(drisk_valute/(dsl*dTickValue)/dStep)*dStep;
      else
         m_lots=MathFloor(drisk_valute/(dsl*dTickValue*_dpoint/dTickSize)/dStep)*dStep;

      return NLot(m_lots,m_name);
   }

   virtual double    getLotNoLeverage(double dbalance,double dvaluerisk,double dsl,double dopen,double dstoprisk)
   {
      if(dsl<=0.0 || dstoprisk<=0 || dopen<=0)
         return 0.0;

      double dpoint=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE);
      double dStep=SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP);
      double dLotMin=SymbolInfoDouble(m_name,SYMBOL_VOLUME_MIN);
      double dLotMax=SymbolInfoDouble(m_name,SYMBOL_VOLUME_MAX);

      double _dpoint=SymbolInfoDouble(m_name,SYMBOL_POINT);
      if(_dpoint==0.0)
         return 0.0;

      int d=int(p/_dpoint);

      if(dsl*dpoint*d==0)
         return 0;

      double tick_value=SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE);
      double dContractSize=SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE);
      double m_lots=MathFloor((dbalance/(dopen*dContractSize))/dStep)*dStep;

      double dSummPosition=NormalizeDouble(m_lots*dopen*dContractSize,2);

      while(dSummPosition>dbalance) {
         m_lots-=dStep;
         if(m_lots<dLotMin)
            return 0;

         dSummPosition=NormalizeDouble(m_lots*dopen*dContractSize,2);
      }

      double dMaxRisk=ND2(dSummPosition*dstoprisk/100); //какую сумму потеряем максимум

      while(dMaxRisk>dvaluerisk) {
         m_lots-=dStep;
         if(m_lots<dLotMin)
            return 0;

         dSummPosition=NormalizeDouble(m_lots*dopen*dContractSize,2);
         dMaxRisk=ND2(dSummPosition*dstoprisk/100); //какую сумму потеряем максимум
      }

      return NLot(m_lots);
   }

   virtual bool      CheckMaxSpread(double dMaxSpread)
   {
      if(dMaxSpread==0)
         return true;

      double sp=GetSpread(m_name);

      if(sp>dMaxSpread)
         return false;

      return true;
   }

   virtual double    getMaxLot()
   {

      double dreturn_lot=0;

      int icount=PositionsTotal();

      for(int i=icount-1; i>=0; i--) {
         if(!SelectByIndex(i,true))
            continue;

         if(!Check(m_position,m_position.Magic()))
            continue;

         if(m_position.Volume()>dreturn_lot)
            dreturn_lot=m_position.Volume();
      }

      return dreturn_lot;
   }

   virtual double    getMaxLot(int itype)
   {

      double dreturn_lot=0;

      int icount=PositionsTotal();

      for(int i=icount-1; i>=0; i--) {
         if(!SelectByIndex(i,true))
            continue;

         if(!Check(m_position,m_position.Magic()))
            continue;

         if(itype==m_position.PositionType()) {

            if(m_position.Volume()>dreturn_lot)
               dreturn_lot=m_position.Volume();

         }
      }

      return dreturn_lot;
   }

   virtual double    getMaxLot(int itype,double &dopen)
   {
      dopen=0;
      double dreturn_lot=0;

      int icount=PositionsTotal();

      for(int i=icount-1; i>=0; i--) {
         if(!SelectByIndex(i,true))
            continue;

         if(!Check(m_position,m_position.Magic()))
            continue;

         if(itype==m_position.PositionType()) {

            if(m_position.Volume()>dreturn_lot) {
               dreturn_lot=m_position.Volume();
               dopen=m_position.PriceOpen();
            }

         }
      }

      return dreturn_lot;
   }

   virtual double    getMaxLotForUnlocker()
   {

      double dreturn_lot=0;

      double dbuy=0,dsell=0;

      int icount=PositionsTotal();

      for(int i=icount-1; i>=0; i--) {
         if(!SelectByIndex(i,true))
            continue;

         if(!Check(m_position,m_position.Magic()))
            continue;

         if(m_position.PositionType()==POSITION_TYPE_BUY)
            dbuy+=m_position.Volume();

         if(m_position.PositionType()==POSITION_TYPE_SELL)
            dsell+=m_position.Volume();

      }

      dreturn_lot=MathMax(dbuy,dsell);

      return dreturn_lot;
   }

   /*virtual double            getProfitAccount(int itype=ALL,datetime tmhistory=0)
     {

      int flag=0;
      double dProfit=0;

      int itotal=PositionsTotal();

      for(int i=itotal-1; i>=0; i--)
        {
         if(m_position.SelectByIndex(i))
           {

            if(m_position.PositionType()>=2)
               continue; //пропустим отложки

            flag=toMyTypes(m_position.PositionType())&itype;

            if(itype==ALL || m_position.PositionType()==toDefType(flag,itype))
              {
               dProfit+=m_position.Profit()+m_position.Swap()+m_position.Commission();
              }
           }
        }

      return dProfit;
     }
     */
   virtual double            getProfitAccount(int itype=ALL,datetime tmhistory=0,bool bhistory=false)
   {

      int flag=0;
      double dprofit=0;

      if(bhistory) {
         HistorySelect(tmhistory,TimeCurrent()); //загрузем историю последнего месяца

         ulong iticket=0;

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

            if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) {
               double MacroProfit=0;

               if(m_deal.Entry()==DEAL_ENTRY_IN) {
                  MacroProfit=m_deal.Commission(); //при открытии в мт5 списывает комиссию, если так надо учесть в расчетах
               }

               if(m_deal.Entry()==DEAL_ENTRY_OUT) {
                  MacroProfit=m_deal.Profit()+m_deal.Swap()+m_deal.Commission(); //при закрытии учесть надо все по сделке все комиссии , свопы и профит
               }

               datetime tmStart=(datetime)m_deal.Time();

               if(tmStart>tmhistory) {

                  dprofit+=MacroProfit;
               }

            }
         }
      }
      int itotal=PositionsTotal();

      for(int i=itotal-1; i>=0; i--) {
         if(m_position.SelectByIndex(i)) {

            if(m_position.PositionType()>=2)
               continue; //пропустим отложки

            flag=toMyTypes(m_position.PositionType())&itype;

            if(itype==ALL || m_position.PositionType()==toDefType(flag,itype)) {
               dprofit+=m_position.Profit()+m_position.Swap()+m_position.Commission();
            }
         }
      }

      return dprofit;
   }

   virtual double            getProfit(int itype=ALL,int imode=0,datetime tmhistory=0,long imagic=-1)
   {

      int flag=0;
      double dprofit=0;

      if(imode==0) {

         int itotal=PositionsTotal();

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

            if((imagic==-1 && Check(m_position,m_position.Magic())) ||
               (imagic!=-1 && m_position.Symbol()==m_name && m_position.Magic()==imagic)
              ) {
               flag=toMyTypes(m_position.PositionType())&itype;

               if(itype==ALL || m_position.PositionType()==toDefType(flag,itype)) {
                  dprofit+=m_position.Profit()+m_position.Swap()+m_position.Commission();
               }
            }
         }

      } else {

         HistorySelect(tmhistory,TimeCurrent()); //загрузем историю последнего месяца

         ulong iticket=0;

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

            if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) {

               if((imagic==-1 && Check(m_deal,m_deal.Magic())) ||
                  (imagic!=-1 && (m_deal.Symbol()==m_name || m_name==NULL) && m_deal.Magic()==imagic)) {
                  double MacroProfit=0;

                  if(m_deal.Entry()==DEAL_ENTRY_IN) {
                     MacroProfit=m_deal.Commission(); //при открытии в мт5 списывает комиссию, если так надо учесть в расчетах
                  }

                  if(m_deal.Entry()==DEAL_ENTRY_OUT) {
                     MacroProfit=m_deal.Profit()+m_deal.Swap()+m_deal.Commission(); //при закрытии учесть надо все по сделке все комиссии , свопы и профит
                  }

                  datetime tmStart=(datetime)m_deal.Time();

                  if(tmStart>tmhistory) {

                     dprofit+=MacroProfit;
                  }

               }
            }
         }

      }

      return dprofit;
   }

   virtual void            getProfit(double &dprofit_buy,double &dprofit_sell,datetime tmhistory=0,long imagic=-1)
   {

      dprofit_buy=0;
      dprofit_sell=0;

      int itotal=PositionsTotal();

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

         if((imagic==-1 && Check(m_position,m_position.Magic())) ||
            (imagic!=-1 && m_position.Symbol()==m_name && m_position.Magic()==imagic)
           ) {

            if(m_position.Time()>=tmhistory) {
               if(m_position.PositionType()==POSITION_TYPE_BUY) {
                  dprofit_buy+=m_position.Profit()+m_position.Swap()+m_position.Commission();
               }
               if(m_position.PositionType()==POSITION_TYPE_SELL) {
                  dprofit_sell+=m_position.Profit()+m_position.Swap()+m_position.Commission();
               }
            }
         }
      }

   }

   virtual bool      PartClose(double dpartclose_profit,double dpartclose_procent,bool bModeBU=false)
   {
      if(dpartclose_profit==0)
         return false;

      ulong iticket=0;

      m_symbol.Name(m_name);
      m_symbol.Refresh();
      m_symbol.RefreshRates();

      for(int i=PositionsTotal()-1; i>=0; i--) {
         if(!SelectByIndex(i,true))
            continue;

         ENUM_POSITION_TYPE etype=(ENUM_POSITION_TYPE)m_position.PositionType();

         if(etype==POSITION_TYPE_BUY || etype==POSITION_TYPE_SELL) {

            double dopen=m_position.PriceOpen();
            double dtake=m_position.TakeProfit();
            double dstop=m_position.StopLoss();

            double pr=0;

            if(etype==POSITION_TYPE_BUY)
               pr=ND1((m_symbol.Bid()-dopen)/p);
            else if(etype==POSITION_TYPE_SELL)
               pr=ND1((dopen-m_symbol.Ask())/p);

            double dLOT=NormalizeDouble(m_position.Volume(),2);
            double dlot=NLot(dLOT*dpartclose_procent/100); //часть лота

            if(ND2(dLOT-dlot)<m_symbol.LotsMin())
               continue; //пропуск если остаток меньше минимального лота или равен ему

            double dsummlots=0;

            if(pr>=dpartclose_profit) {

               iticket=m_position.Ticket();

               int part=get_part(iticket,dsummlots);

               if(part==0) {
                  if(bModeBU) {
                     m_trade.PositionModify(iticket,dopen,dtake);

                  }

                  return OrderClose(iticket,dlot);
               }

            }
         }

      }

      return false;
   }

   virtual ulong     GetNewTicket(ulong iticket)
   {

#ifdef __MQL4__
      ulong iticket_loop=0;
      for(int i=PositionsTotal()-1; i>=0; i--) {
         iticket_loop=PositionGetTicket(i);
         if(iticket_loop>0) {
            if(StringFormat("from #%lld",iticket)==PositionGetString(POSITION_COMMENT)) {
               return iticket_loop;
            }
         }

      }
#endif

      return iticket;
   }

   virtual void      Safe(double dplatsl,bool bbu=false,double dbu=0)
   {
      if(dplatsl==0)
         return;

      ulong iticket=0;

      m_symbol.Name(m_name);
      m_symbol.Refresh();
      m_symbol.RefreshRates();

      for(int i=PositionsTotal()-1; i>=0; i--) {
         if(!SelectByIndex(i,true))
            continue;

         ENUM_POSITION_TYPE etype=(ENUM_POSITION_TYPE)m_position.PositionType();

         if(etype==POSITION_TYPE_BUY || etype==POSITION_TYPE_SELL) {

            double dopen=m_position.PriceOpen();
            double dtake=m_position.TakeProfit();
            double dstop=m_position.StopLoss();

            if(dstop==0.0)
               continue;

            double dsl=0;
            double pr=0;

            if(etype==POSITION_TYPE_BUY) {
               pr=ND1((m_symbol.Bid()-dopen)/p);
               dsl=ND1((dopen-dstop)/p);
            } else if(etype==POSITION_TYPE_SELL) {
               pr=ND1((dopen-m_symbol.Ask())/p);
               dsl=ND1((dstop-dopen)/p);
            }

            if(dsl<=0.0)
               continue;  //стоп уже в бу

            double dLOT=NormalizeDouble(m_position.Volume(),2);
            double dlot=NLot(dLOT*0.5); //часть лота

            if(ND2(dLOT-dlot)<m_symbol.LotsMin())
               continue; //пропуск если остаток меньше минимального лота или равен ему

            double dsummlots=0;

            if(pr/dsl>=dplatsl) {

               iticket=m_position.Ticket();

               int part=get_part(iticket,dsummlots);

               if(part==0) {
                  if(dbu) {
                     if(etype==POSITION_TYPE_BUY)
                        OrderModify(iticket,dopen,dopen+dbu*p,dtake);
                     else
                        OrderModify(iticket,dopen,dopen-dbu*p,dtake);
                  }
                  OrderClose(iticket,dlot);
               }

            }
         }
      }
   }

   virtual int       get_part(ulong iticket,double &dsummlot,double &dprofit) //вспомогательная функция ищет кол-во частичных закрытий
   {

      dsummlot=0;
      dprofit=0;
      int part=-1;

      HistorySelectByPosition(iticket);      //выберем все сделки по позиции

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

         if(m_deal.Entry()==DEAL_ENTRY_IN) {
            dsummlot+=m_deal.Volume();
            dprofit+=m_deal.Commission();
         }

         if(m_deal.Entry()==DEAL_ENTRY_OUT) {
            dprofit+=m_deal.Profit()+m_deal.Swap()+m_deal.Commission();
            part++;
         }
      }

      if(part==-1)
         part=0;

      return part; //вернем сколько раз уже закрывались
   }

   virtual int       get_part(ulong iticket,double &dsummlot) //вспомогательная функция ищет кол-во частичных закрытий
   {

      dsummlot=0;
      int part=-1;

#ifdef __MQL5__
      part=0;
#endif

      HistorySelectByPosition(iticket);      //выберем все сделки по позиции

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

         if(m_deal.Entry()==DEAL_ENTRY_IN) {
            dsummlot+=m_deal.Volume();
         }

         if(m_deal.Entry()==DEAL_ENTRY_OUT) {
            part++;
         }

      }

      if(part==-1)
         part=0;
      return part; //вернем сколько раз уже закрывались
   }

   virtual double    get_lots(double &dlots[]) //подсчет лотов
   {
      double dlot=0.0;

      if(ArrayResize(dlots,2)!=-1) {
         ArrayInitialize(dlots,0);

         for(int i=0; i<PositionsTotal(); i++) {
            if(!SelectByIndex(i,true))
               continue;

            if(OrderType()<2) {
               dlots[(int)OrderType()]+=OrderLots();
            }

         }

         int idgt=LotDigits(m_name);
         dlots[0]=NormalizeDouble(dlots[0],idgt);
         dlots[1]=NormalizeDouble(dlots[1],idgt);

         dlot=dlots[0]-dlots[1];

         dlot=NormalizeDouble(dlot,idgt);
      }

      if(Abs(dlot)<m_symbol.LotsMin())
         return 0;

      return dlot;
   }

   virtual double    get_lots(int itype) //подсчет лотов по типу (бай или селл)
   {
      double dlot=0.0;

      if(itype<2) {

         for(int i=0; i<PositionsTotal(); i++) {
            if(!SelectByIndex(i,true))
               continue;

            if(m_position.PositionType()==itype) {
               dlot+=m_position.Volume();
            }

         }

      }

      return dlot;
   }

   virtual double    getLock(int &itype)
   {

      double dreturn_lot=0;
      itype=EMPTY;

      double dSaveLot[2]= {0};

      for(int i=0; i<PositionsTotal(); i++) {

         if(!SelectByIndex(i,true))
            continue; //если не выбирает, пропускаем

         if(OrderType()==OP_BUY)
            dSaveLot[0]+=OrderLots();
         if(OrderType()==OP_SELL)
            dSaveLot[1]+=OrderLots();

      }

      if(dSaveLot[0]>dSaveLot[1]) {
         itype=OP_SELL;//бай больше, надо ставить селл для лока!
         dreturn_lot=Abs(dSaveLot[0]-dSaveLot[1]);
      }

      if(dSaveLot[0]<dSaveLot[1]) {
         itype=OP_BUY;
         dreturn_lot=Abs(dSaveLot[1]-dSaveLot[0]);
      }

      if(dreturn_lot<m_symbol.LotsMin())
         return 0;

      return            dreturn_lot;
   }

   virtual void      OnTimer()
   {

   }
   virtual void      OnChartEvent(const int id,// идентификатор события
                                  const long& lparam,   // параметр события типа long
                                  const double& dparam, // параметр события типа double
                                  const string& sparam  // параметр события типа string
                                 )
   {

   }

   virtual void      Position()
   {

      dPositionCapital+=GetCapital();

   }

   virtual void      Order()
   {

   }

   virtual bool      OrderSelect(ulong iticket,bool bposition=true)
   {
      if(iticket<=0)
         return false;

      if(bposition) {
         bool bret=m_position.SelectByTicket(iticket);

         if(bret) {
            m_bposition=true;
            return true;
         }
      }

      bool bret=m_order.Select(iticket);

      m_bposition=!bret;

      return bret;
   }

   virtual string     OrderSymbol(bool bposition=true)
   {
      if(bposition)
         return m_position.Symbol();

      return m_order.Symbol();
   }

   virtual bool      OrderSelectHistory(ulong iticket)
   {
      if(iticket<=0)
         return false;

      m_history.Ticket(iticket);

      return true;
   }

   virtual double    OrderStep()
   {
      double dstep=0;

      double dopen=m_position.PriceOpen();
      long itype=m_position.PositionType();

      if(itype==POSITION_TYPE_BUY)
         dstep=ND1((m_symbol.Ask()-dopen)/p);
      if(itype==POSITION_TYPE_SELL)
         dstep=ND1((dopen-m_symbol.Bid())/p);

      return dstep;
   }

   virtual double    OrderProfitPoint()
   {
      double dstep=0;

      double dopen=m_position.PriceOpen();
      long itype=m_position.PositionType();

      if(itype==POSITION_TYPE_BUY)
         dstep=nd((m_symbol.Bid()-dopen)/p);
      if(itype==POSITION_TYPE_SELL)
         dstep=nd((dopen-m_symbol.Ask())/p);

      return dstep;
   }

   virtual double    OrderOpenPrice(bool bposition=true)
   {
      if(bposition)
         return m_position.PriceOpen();

      return m_order.PriceOpen();
   }

   virtual double    OrderOpenPrice(ulong positionId)
   {
      double dprice=0;
      datetime tmLast=0;

      if(positionId==0) {
         return 0;
      }

      HistorySelectByPosition(positionId);

      int iprice=0;

      for(int i=HistoryDealsTotal()-1; i>=0; i--) {
         ulong uticket=(ulong)HistoryDealGetTicket(i);//тикет не уникальный и связан с номером ордера (тикет позиции)
         if(uticket<=0)
            continue;

         if(HistoryDealGetInteger(uticket,DEAL_POSITION_ID)!=positionId)
            continue;

         if(HistoryDealGetInteger(uticket,DEAL_ENTRY)==DEAL_ENTRY_IN) { //тут надо самый последний
            if(HistoryDealGetInteger(uticket,DEAL_TIME)>tmLast || tmLast==0) {
               dprice+=HistoryDealGetDouble(uticket,DEAL_PRICE);
               iprice++;
               tmLast=(datetime)HistoryDealGetInteger(uticket,DEAL_TIME);
            }

         }
      }

      if(iprice>0)
         dprice/=iprice;

      return nd(dprice,m_name);

   }

   virtual double    OrderClosePrice(ulong positionId)
   {
      double dprice=0;
      datetime tmLast=0;

      if(positionId==0) {
         return 0;
      }

      HistorySelectByPosition(positionId);

      int iprice=0;

      for(int i=HistoryDealsTotal()-1; i>=0; i--) {
         ulong uticket=(ulong)HistoryDealGetTicket(i);//тикет не уникальный и связан с номером ордера (тикет позиции)
         if(uticket<=0)
            continue;

         if(HistoryDealGetInteger(uticket,DEAL_POSITION_ID)!=positionId)
            continue;

         if(HistoryDealGetInteger(uticket,DEAL_ENTRY)==DEAL_ENTRY_OUT) { //тут надо самый последний
            if(HistoryDealGetInteger(uticket,DEAL_TIME)>tmLast || tmLast==0) {
               dprice+=HistoryDealGetDouble(uticket,DEAL_PRICE);
               iprice++;
               tmLast=(datetime)HistoryDealGetInteger(uticket,DEAL_TIME);
            }

         }
      }

      if(iprice>0)
         dprice/=iprice;

      return nd(dprice,m_name);

   }

   virtual double    OrderOpenPriceRollover()
   {
      ulong id=m_position.Ticket();

      if(id>0) {

         if(HistorySelectByPosition(id)) {

            int itotals=HistoryDealsTotal();

            double dopenPrice=0;
            datetime tmDeal=0;

            for(int i=itotals-1; i>=0; i--) {
               double dopen=HistoryDealGetDouble(id,DEAL_PRICE);
               datetime tmdeal=(datetime)HistoryDealGetInteger(id,DEAL_TIME);

               if(tmDeal==0 || tmdeal<tmDeal) {
                  tmDeal=tmdeal;
                  dopenPrice=dopen;
               }
            }

            return nd(dopenPrice,m_name);
         }

      }

      return 0;
   }

   virtual datetime  OrderOpenTime(bool bposition=true)
   {
      if(bposition)
         return m_position.Time();

      return m_order.TimeSetup(); //время установки отложки
   }

   virtual datetime  OrderOpenTimeHistory()
   {

      HistoryDealSelect(m_history.Ticket());
      datetime tmLast=0;
      for(int i=0; i<HistoryDealsTotal(); i++) {
         ulong tdeal=HistoryDealGetTicket(i);
         ENUM_DEAL_ENTRY entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(tdeal,DEAL_ENTRY);
         if(entry==DEAL_ENTRY_IN || entry==DEAL_ENTRY_INOUT) { //открытие может быть и переворотом
            if(HistoryDealGetInteger(tdeal,DEAL_TIME)<tmLast || tmLast==0)
               tmLast=(datetime)HistoryDealGetInteger(tdeal,DEAL_TIME); //находим по последнему (более старый)
         }

      }

      return tmLast;
   }

   virtual datetime  OrderCloseTimeHistory()
   {

      HistoryDealSelect(m_history.Ticket());
      datetime tmLast=0;
      for(int i=0; i<HistoryDealsTotal(); i++) {
         ulong tdeal=HistoryDealGetTicket(i);
         ENUM_DEAL_ENTRY entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(tdeal,DEAL_ENTRY);
         if(entry==DEAL_ENTRY_OUT || entry==DEAL_ENTRY_INOUT || entry==DEAL_ENTRY_OUT_BY) { //отслеживаем перевороты, закрытие
            if(HistoryDealGetInteger(tdeal,DEAL_TIME)<tmLast || tmLast==0) //для закрытия самый ранний он первый
               tmLast=(datetime)HistoryDealGetInteger(tdeal,DEAL_TIME);
         }

      }

      return tmLast;
   }

   virtual double    OrderTakeProfit(bool bposition=true)
   {
      double dtake=0;

      if(bposition) {
         dtake=m_position.TakeProfit();
         if(dtake==0.0)
            dtake=virtual_get_tp(m_position.Ticket());
      } else {
  

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

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

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

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

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

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

Стоимость полного кода
9 079,10₽ ≈ $110.98