Скачать MetaTrader 5

Кроссплатформенный торговый советник: Мани-менеджмент

11 июля 2017, 16:35
Enrico Lambino
0
2 810

Оглавление

  1. Введение
  2. Цели
  3. Базовый класс
  4. Классы и типы мани-менеджмента
  5. Контейнер объектов мани-менеджмента
  6. Пример
  7. Заключение

Введение

Мани-менеджмент (управление капиталом) — распространенная функция в торговых советниках. Она позволяет эксперту динамически определять размер лота для следующей сделки, в которую он войдет. В этой статье представлены несколько классов мани-менеджмента, которые позволят нам автоматизировать весь процесс расчета торгового объема в советнике.

Цели

  • Понимать и применять наиболее распространенные методы управления капиталом, используемые в трейдинге
  • Разрешить эксперту выбирать из списка доступных методов мани-менеджмента
  • Обеспечить совместимость с MQL4 и MQL5

Базовый класс

Базовый родительский класс для всех классов мани-менеджмента, описанных в этой статье — СMoney, производный от CMoneyBase. Класс CMoneyBase определен в нижеследующем фрагменте кода:

class CMoneyBase : public CObject
  {
protected:
   bool              m_active;
   double            m_volume;
   double            m_balance;
   double            m_balance_inc;
   int               m_period;
   bool              m_equity;
   string            m_name;
   CSymbolManager   *m_symbol_man;
   CSymbolInfo      *m_symbol;
   CAccountInfo     *m_account;
   CEventAggregator *m_event_man;
   CObject          *m_container;
public:
                     CMoneyBase(void);
                    ~CMoneyBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_MONEY;}
   //--- инициализация
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   bool              InitAccount(CAccountInfo*);
   bool              InitSymbol(CSymbolManager*);
   CObject          *GetContainer(void);
   void              SetContainer(CObject*);
   virtual bool      Validate(void);
   //--- методы получения и установки
   bool              Active(void) const;
   void              Active(const bool);
   void              Equity(const bool);
   bool              Equity(void) const;
   void              LastUpdate(const datetime);
   datetime          LastUpdate(void) const;
   void              Name(const string);
   string            Name(void) const;
   double            Volume(const string,const double,const ENUM_ORDER_TYPE,const double);
   void              Volume(const double);
   double            Volume(void) const;
protected:
   virtual void      OnLotSizeUpdated(void);
   virtual bool      UpdateLotSize(const string,const double,const ENUM_ORDER_TYPE,const double);
  };

Большинство методов класса отвечают либо за получение, либо за установку различных членов класса, и поэтому не требуют подробных пояснений. В практическом применении реальное значение имеют три метода: UpdateLotSize, OnLotSizeUpdated и Volume.

В методе UpdateLotSize происходит фактический расчет торгового объема. Это тоже основной метод, расширенный из базового класса, и следовательно, большая часть различий между классами мани-менеджмента находится именно в нем. Для базового класса CMoneyBase метод можно считать виртуальным, потому что единственное его назначение здесь — возвращать значение true:

bool CMoneyBase::UpdateLotSize(const string,const double,const ENUM_ORDER_TYPE,const double)
  {
   return true;
  }

Иногда после расчета торгового объема нужно обновить определенные значения, которые будут использоваться для последующих вычислений. В таких случаях используется метод OnLotSizeUpdated. Он автоматически вызывается внутри метода UpdateLotSize:

void CMoneyBase::OnLotSizeUpdated(void)
  {
   m_symbol=m_symbol_man.Get();
   double maxvol=m_symbol.LotsMax();
   double minvol=m_symbol.LotsMin();
   if(m_volume<minvol)
      m_volume=minvol;
   if(m_volume>maxvol)
      m_volume=maxvol;
  }

Чтобы получить текущее значение торгового объема, уже рассчитанное посредством мани-менеджмента, советнику не надо вызывать ни UpdateLotSize, ни OnLotSizeUpdated. Вместо этого вызывается метод Volume класса. Этот метод автоматически вызовет внутри себя остальные два.

double CMoneyBase::Volume(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   if(!Active())
      return 0;
   if(UpdateLotSize(symbol,price,type,sl))
      OnLotSizeUpdated();
   return m_volume;
  }

Методы мани-менеджмента


Фиксированный лот

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

В этом типе мани-менеджмента нам нужен только фиксированный объем. Таким образом, его основное отличие от CMoney/CMoneyBase — в конструкторе, где мы определяем фиксированный размер лота:

CMoneyFixedLotBase::CMoneyFixedLotBase(double volume)
  {
   Volume(volume);
  }

Если нам нужно динамически изменить результат работы этого метода управления капиталом, мы просто изменяем его член класса m_volume вызовом метода Volume.

Фиксированно-фракционный метод

Фиксированно-фракционный метод (или метод фиксированного риска) подразумевает выделение определенного процента от баланса или эквити в качестве риска на каждую сделку. Этот метод реализован в стандартной библиотеке: CmoneyFixedRisk.  Если сделка закрывается в убытке, этот убыток не превышает установленного процента от баланса счета ко времени входа в сделку. Убыток здесь определяется как максимальная потеря, которую может понести трейдер в конкретной сделке — когда условия сделки доходят до стоп-лосса. Применение метода требует, чтобы стоп-лосс не был равен нулю.

Вычисление процента риска выражается в следующей формуле:

Volume = (balance * account_percentage / ticks) / tick_value

гдe:

  • balance — баланс или эквити счета
  • account_percentage — процент максимального риска (диапазон: 0.0-1.0)
  • ticks — значение стоп-лосса, выраженное в тиках
  • tick_value — стоимость тика в валюте депозита (на 1 полный лот)

Тик определяется как самое маленькое возможное движение цены для данного инструмента или валютной пары. К примеру, EURUSD у брокера, использующего пятизначные котировки, будет иметь стоимость тика 0,00001. Это наименьшее возможное движение по этой валютной паре. Если значение стоп-лосса выражено в пунктах или пипсах, результатом будет разница между входной ценой сделки и стоп-лоссом в пунктах или пипсах.

По той же валютной паре размер тика для брокера с четырехзначной котировкой будет отличаться от пятизначной. Причина в том, что при 4 знаках 1 тик эквивалентен 1 пункту (или пипсу), а при использовании пятизначной котировки пипс равен 10 пунктам.

В качестве примера мани-менеджмента с фиксированным риском предположим, что мы работаем с брокером, использующим пятизначные котировки, у нас на балансе есть $ 1 000, а заданный предел риска составляет 5% на одну сделку. Предположим, что стоимость тика 0,1, а стоп-лосс —  200 пунктов (20 пипсов):

Volume = (1000 * 0.05 / 200) / 0.1 = 2.5 лота

Вычисленный объем лота увеличивается в зависимости от процента риска и доступного баланса, а уменьшается на основании размера стоп-лосса и тикового значения. Баланс счета, риск и стоимость тика, как правило, постоянны, а вот стоп-лосс нередко бывает переменным и вычисляется динамически. Поэтому фиксированный риск не подходит для стратегий, где нет верхнего лимита на разницу между входной ценой и стоп-лоссом. Рассчитанный размер лота может оказаться слишком маленьким, и брокер может его отклонить. С другой стороны, слишком маленький стоп-лосс приведет к очень большому размеру лота, и это тоже может повлечь за собой проблемы: некоторые брокеры устанавливают настройку, ограничивающую максимальный лот. Эта проблема практически решена в MetaTrader 5, где ордера разбиваются на несколько сделок, если объем лота слишком велик. Однако в MetaTrader 4 такой функции нет — объем сделки должен быть подготовлен заранее (при необходимости разбит на несколько мелких сделок), чтобы она смогла состояться, даже если ее размер превышает максимально допустимый уровень.

Формула, которая используется в расчетах, находится внутри метода UpdateLotSize:

bool CMoneyFixedFractionalBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();
      double ticks=0;
      if(price==0.0)
        {
         if(type==ORDER_TYPE_BUY)
            ticks=MathAbs(m_symbol.Bid()-sl)/m_symbol.TickSize();
         else if(type==ORDER_TYPE_SELL)
            ticks=MathAbs(m_symbol.Ask()-sl)/m_symbol.TickSize();
        }
      else ticks=MathAbs(price-sl)/m_symbol.TickSize();
      m_volume=((balance*(m_risk/100))/ticks)/m_symbol.TickValue();
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }

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

Фиксированно-пропорциональный метод

Фиксированно-пропорциональный метод управления капиталом — вычисление объема лота в пропорции к текущему балансу счета. Его можно рассматривать как частный случай фиксированного лота, за исключением того, что здесь размер лота настраивается автоматически, а не вручную самим трейдером. Если счет растет, размер лота тоже будет увеличиваться после прохождения определенного порога. Если баланс уменьшается, соответственно будет уменьшаться и размер лота.

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

Объем сделки для этого метода мани-менеджмента рассчитывается по формуле:

Volume = base_volume + (balance / balance_increase) * volume_increment

гдe:

  • base_volume — базовый объем лота, который будет в любом случае добавлен к общему объему, вне зависимости от характеристик счета
  • balance — текущий баланс на счете
  • balance_increase — порог увеличения баланса на счете, после которого будет происходить шаг приращения размера лота
  • volume_increment — шаговый объем, который будет добавлен к лоту после достижения порога (или, соответственно, вычтен из него).

К примеру, возьмем за базовый объем нулевой лот. Он будет увеличиваться на 0,1 на каждые 1000 долларов на счёте. В данный момент на нашем счете $2,500. Общий объем будет рассчитан следующим образом:

Volume = 0 + (2500 / 1000) * 0.1 = 0.25 лота

У этого метода есть множество вариаций. Одна из них — метод, где размер лота обновляется только на определенных уровнях, пошагово. В вышеприведенном примере рассчитанный объем лота равен 0,25. В ином случае он может определенное время оставаться на уровне 0,2 лота, а потом сразу вырасти до 0,3 (как только баланс достигнет $3,000).

Для этого случая метод UpdateLotSize будет реализован так:

bool CMoneyFixedRatioBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();      
      m_volume=m_volume_base+((int)(balance/m_balance_inc))*m_volume_inc;
      m_balance=balance;
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }


Фиксированный риск на один пункт

Фиксированный риск на один пункт работает так, что каждый пункт стоп-лосса стоит определенную сумму в валюте депозита. Алгоритм вычисления размера лота основывается на том, какая стоимость тика нужна трейдеру. К примеру, если зафиксировать на долларовом счёте риск на пункт 2.0, каждый пункт стоп-лосса будет стоить $2. Если стоп-лосс на сделку составляет 200 пунктов, максимальный риск для такой сделки составит $400 (то есть, $400 будет потеряно, если рынок достигнет уровня стоп-лосса сделки).

Для обычного трейдера использование этого типа мани-менеджмента — очень просто для понимания, потому что риск выражается в денежном значении, в валюте депозита. Трейдеру просто нужно установить требуемую стоимость тика, и торговый объем будет рассчитан автоматически. Стоимость тика, или изменение в прибыли/убытке на минимальное движение цены, будет оставаться одинаковым, но общий риск будет зависеть от размера стоп-лосса сделки.

С использованием формулы для этого типа мани-менеджмента метод UpdateLotSize будет реализован так:

bool CMoneyFixedRiskPerPointBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();
      m_volume=(m_risk/m_symbol.TickValue());
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }


Фиксированный риск (Фиксированная маржа)

Фиксированный риск по марже — аналог класса CMoneyFixedMargin из Стандартной библиотеки MQL5. Фактически, это частный случай описанного выше способа мани-менеджмента — фиксированного риска на пункт. Однако, в отличие от фиксированного риска на пункт, этот метод учитывает при расчете объема сделки всю величину стоп-лосса, поэтому вне зависимости от размера стоп-лосса, риск остается таким же. В предыдущем примере у нас был установлен стоп-лосс в 200 пунктов, и $400 — максимальный риск. Если уменьшить стоп-лосс до 100 пунктов, максимальный риск на сделку при использовании фискированного риска на пункт тоже уменьшится вдвое, а при использовании просто фиксированного риска (фиксированной маржи) максимальный риск останется все тем же — $400.

Используя эту формулу, мы можем реализовать метод UpdateLotSize следующим образом:

bool CMoneyFixedRiskBase::UpdateLotSize(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl)
  {
   m_symbol=m_symbol_man.Get(symbol);
   double last_volume=m_volume;
   if(CheckPointer(m_symbol))
     {
      double balance=m_equity==false?m_account.Balance():m_account.Equity();
      double ticks=0;
      if(price==0.0)
        {
         if(type==ORDER_TYPE_BUY)
            ticks=MathAbs(m_symbol.Bid()-sl)/m_symbol.TickSize();
         else if(type==ORDER_TYPE_SELL)
            ticks=MathAbs(m_symbol.Ask()-sl)/m_symbol.TickSize();
        }
      else ticks=MathAbs(price-sl)/m_symbol.TickSize();
      m_volume=(m_risk/m_symbol.TickValue())/ticks;
     }
   return NormalizeDouble(last_volume-m_volume,2)==0;
  }

Формула, которая здесь используется, практически аналогична фиксированному риску на пункт, за исключением того, что нам надо получить тиковое значение стоп-лосса, и потом определять результат по предыдущей формуле с этим значением.


Контейнер объектов мани-менеджмента

Как и классы сигналов, рассмотренные в предыдущей статье, наши объекты мани-менеджмента тоже будут иметь контейнеры. Это позволит советнику динамически выбирать из списка доступных объектов мани-менеджмента, загруженных в платформу. В идеале этот контейнер будет выступать как посредник между классами мани-менеджмента и остальным кодом советника. Базовый класс для этого объекта — CMoneysBase, его определение продемонстрировано ниже:

class CMoneysBase : public CArrayObj
  {
protected:
   bool              m_active;
   int               m_selected;
   CEventAggregator *m_event_man;
   CObject          *m_container;
public:
                     CMoneysBase(void);
                    ~CMoneysBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_MONEYS;}
   //--- инициализация
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   CObject          *GetContainer(void);
   void              SetContainer(CObject*);
   virtual bool      Validate(void) const;
   //--- методы установки и получения
   virtual bool      Active(void) const;
   virtual void      Active(const bool);
   virtual int       Selected(void) const;
   virtual void      Selected(const int);
   virtual bool      Selected(const string);
   //--- вычисление объема
   virtual double    Volume(const string,const double,const ENUM_ORDER_TYPE,const double);
  };

Поскольку этот объект разработан, чтобы содержать многочисленные объекты мани-менеджмента, требуются как минимум два метода, чтобы сделать объект доступным к использованию в разрабатываемом советнике:

  1. Выбор, или способность динамически переключаться между методами мани-менеджмента
  2. Использование выбранного объекта мани-менеджмента и получение рассчитанного для него объема сделки
Выбор можно реализовать двумя путями: через присвоение индекса объекту мани-менеджмента в массиве объектов (CMoneysBase расширяет CArrayObj), или через нахождение выбранного объекта по имени (метод Name, принадлежащий классу CMoneyBase/CMoney). Ниже показана перегрузка метода Selected, который принимает целочисленный аргумент (или индекс):
CMoneysBase::Selected(const int value)
  {
   m_selected=value;
  }

А вот как выглядит перегруженный метод Selected, который принимает строковый аргумент (имя объекта мани-менеджмента). Обратите внимние, что он принимает не пустое имя объекта мани-менеджмента, которое присваивается методом Name.

bool CMoneysBase::Selected(const string select)
  {
   for(int i=0;i<Total();i++)
     {
      CMoney *money=At(i);
      if(!CheckPointer(money))
         continue;
      if(StringCompare(money.Name(),select))
        {
         Selected(i);
         return true;
        }
     }
   return false;
  }

Третья перегрузка метода вообще не содержит аргументов. Она просто возвращает индекс выбранного объекта мани-менеджмента, когда нужно выяснить, какой метод выбран на данный момент.

int CMoneysBase::Selected(void) const
  {
   return m_selected;
  }
Текущий объем рассчитывается через этот объект его методом Volume. Метод сначала получает указатель на выбранный объект мани-менеджмента, а потом вызывает его собственный метод Volume. Код метода Volume для класса CMoneysBase продемонстрирован ниже:
double CMoneysBase::Volume(const string symbol,const double price,const ENUM_ORDER_TYPE type,const double sl=0)
  {
   CMoney *money=At(m_selected);
   if(CheckPointer(money))
      return money.Volume(symbol,price,type,sl);
   return 0;
  }

Здесь метод обращается к объекту через массив объектов и сохраняет его в указателе. Чтобы избежать ошибок, нужно убедиться, что текущий элемент, на который ссылается индекс, действительно существует внутри массива объектов.

Пример

В качестве примера мы будем использовать последний пример из предыдущей статьи. Модифицируем его: включим в него классы мани-менеджмента, описанные в этой статье, поместим их в отдельный контейнер, и потом добавим в менеджер ордеров. Большинство дополнений будут иметь дело только с функцией советника OnInit, которая продемонстрирована ниже:

int OnInit()
  {
//--- 
   order_manager=new COrderManager();
   money_manager = new CMoneys();
   CMoney *money_fixed= new CMoneyFixedLot(0.05);
   //CMoney *money_ff= new CMoneyFixedFractional(5);
   CMoney *money_ratio= new CMoneyFixedRatio(0,0.1,1000);
   //CMoney *money_riskperpoint= new CMoneyFixedRiskPerPoint(0.1);
   //CMoney *money_risk= new CMoneyFixedRisk(100);
   
   money_manager.Add(money_fixed);
   //money_manager.Add(money_ff);
   money_manager.Add(money_ratio);
   //money_manager.Add(money_riskperpoint);
   //money_manager.Add(money_risk);
   order_manager.AddMoneys(money_manager);
   //order_manager.Account(money_manager);
   symbol_manager=new CSymbolManager();
   symbol_info=new CSymbolInfo();
   if(!symbol_info.Name(Symbol()))
      Print("symbol not set");
   symbol_manager.Add(GetPointer(symbol_info));
   order_manager.Init(symbol_manager,new CAccountInfo());

   MqlParam params[1];
   params[0].type=TYPE_STRING;
#ifdef __MQL5__
   params[0].string_value="Examples\\Heiken_Ashi";
#else
   params[0].string_value="Heiken Ashi";
#endif
   SignalHA *signal_ha=new SignalHA(Symbol(),0,1,params,signal_bar);
   SignalMA *signal_ma=new SignalMA(Symbol(),(ENUM_TIMEFRAMES) Period(),maperiod,0,mamethod,maapplied,signal_bar);
   signals=new CSignals();
   signals.Add(GetPointer(signal_ha));
   signals.Add(GetPointer(signal_ma));
   signals.Init(GetPointer(symbol_manager),NULL);
//--- 
   return(INIT_SUCCEEDED);
  }

Сюда включены строки кода, отвечающие за использование фиксированно-фракционного типа мани-менеджмента, фиксированного риска и фиксированного риска на пункт. Однако на данный момент наш советник входит только в сделки с нулевыми стоп-лоссами, а все эти методы требуют ненулевого.  Поэтому воздержимся от их применения. Будем использовать только методы, основанные на фиксированном лоте и фиксированно-пропорциональном управлении капиталом. Если эти объекты возвращают невалидный стоп-лосс (меньше нуля), менеджер ордеров будет использовать объем лота по умолчанию (0.1, он доступен в члене m_lotsize класса CorderManager/COrderManagerBase).

У COrderManager есть свой собственный член класса, который является указателем на контейнер мани-менеджмента (CMoney). Таким образом, использование COrderManager тоже приведет к тому, что заголовочные файлы мани-менеджмента будут включены в исходный код. Если в советнике не используется COrderManager, тогда директива #include для классов мани-менеджмента должна быть указана в исходном коде.

Для функции OnTick мы изменяем советник следующим образом: для длинных позиций советник будет использовать фиксированный размер лота, а для коротких — рассчитывать размер лота с использованием фиксированного соотношения. Этого можно добиться, изменив выбранный тип мани-менеджмента методом Selected (класс CMoneys) перед тем, как менеджер ордеров вызовет метод TradeOpen:

void OnTick()
  {
//--- 
   if(symbol_info.RefreshRates())
     {
      signals.Check();
      if(signals.CheckOpenLong())
        {
         close_last();
         //Print("Entering buy trade..");
         money_manager.Selected(0);
         order_manager.TradeOpen(Symbol(),ORDER_TYPE_BUY,symbol_info.Ask());
        }
      else if(signals.CheckOpenShort())
        {
         close_last();
         //Print("Entering sell trade..");
         money_manager.Selected(1);
         order_manager.TradeOpen(Symbol(),ORDER_TYPE_SELL,symbol_info.Bid());
        }
     }
  }

Поскольку мани-менеджмент, по сути своей, — просто чистые расчеты, мы ожидаем, что вычисленный размер лота будет одинаковым в обеих версиях терминала. Ниже показан результат тестов советника в MetaTrader 4 (первые 10 сделок):

# Время Тип Ордер Объем Цена S / L T / P Прибыль Баланс
1. 2017.01.02 00:00 продажа 1. 1.00 1.05100 0.00000 0.00000
2 2017.01.03 03:00 Закрытие 1. 1.00 1.04679 0.00000 0.00000 419.96 10419.96
3 2017.01.03 03:00 Покупка 2 0.05 1.04679 0.00000 0.00000
4 2017.01.03 10:00 Закрытие 2 0.05 1.04597 0.00000 0.00000 -4.10 10415.86
5 2017.01.03 10:00 продажа 3 1.00 1.04597 0.00000 0.00000
6 2017.01.03 20:00 Закрытие 3 1.00 1.04285 0.00000 0.00000 312.00 10727.86
7 2017.01.03 20:00 Покупка 4 0.05 1.04285 0.00000 0.00000
8 2017.01.03 22:00 Закрытие 4 0.05 1.04102 0.00000 0.00000 -9.15 10718.71
9 2017.01.03 22:00 продажа 5 1.00 1.04102 0.00000 0.00000
10 2017.01.04 02:00 Закрытие 5 1.00 1.04190 0.00000 0.00000 -89.04 10629.67
11 2017.01.04 02:00 Покупка 6 0.05 1.04190 0.00000 0.00000
12 2017.01.04 03:00 Закрытие 6 0.05 1.03942 0.00000 0.00000 -12.40 10617.27
13 2017.01.04 03:00 продажа 7 1.00 1.03942 0.00000 0.00000
14 2017.01.04 06:00 Закрытие 7 1.00 1.04069 0.00000 0.00000 -127.00 10490.27
15 2017.01.04 06:00 Покупка 8 0.05 1.04069 0.00000 0.00000
16 2017.01.05 11:00 Закрытие 8 0.05 1.05149 0.00000 0.00000 54.05 10544.32
17 2017.01.05 11:00 продажа 9 1.00 1.05149 0.00000 0.00000
18 2017.01.05 16:00 Закрытие 9 1.00 1.05319 0.00000 0.00000 -170.00 10374.32
19 2017.01.05 16:00 Покупка 10 0.05 1.05319 0.00000 0.00000
20 2017.01.06 05:00 Закрытие 10 0.05 1.05869 0.00000 0.00000 27.52 10401.84

В MetaTrader 5 мы можем видеть следующие результаты (режим хеджирования, первые 10 сделок):














Ордера
Время открытия Ордер Символ Тип Объём Цена S / L T / P Время Состояние Комментарий
2017.01.02 00:00:00 2 EURUSD продажа 1.00 / 1.00 1.05100

2017.01.02 00:00:00 заполнение
2017.01.03 03:00:00 3 EURUSD Покупка 1.00 / 1.00 1.04669

2017.01.03 03:00:00 заполнение
2017.01.03 03:00:00 4 EURUSD Покупка 0.05 / 0.05 1.04669

2017.01.03 03:00:00 заполнение
2017.01.03 10:00:00 5 EURUSD продажа 0.05 / 0.05 1.04597

2017.01.03 10:00:00 заполнение
2017.01.03 10:00:00 6 EURUSD продажа 1.00 / 1.00 1.04597

2017.01.03 10:00:00 заполнение
2017.01.03 20:00:00 7 EURUSD Покупка 1.00 / 1.00 1.04273

2017.01.03 20:00:00 заполнение
2017.01.03 20:00:00 8 EURUSD Покупка 0.05 / 0.05 1.04273

2017.01.03 20:00:00 заполнение
2017.01.03 22:00:00 9 EURUSD продажа 0.05 / 0.05 1.04102

2017.01.03 22:00:00 заполнение
2017.01.03 22:00:00 10 EURUSD продажа 1.00 / 1.00 1.04102

2017.01.03 22:00:00 заполнение
2017.01.04 02:00:00 11 EURUSD Покупка 1.00 / 1.00 1.04180

2017.01.04 02:00:00 заполнение
2017.01.04 02:00:00 12 EURUSD Покупка 0.05 / 0.05 1.04180

2017.01.04 02:00:00 заполнение
2017.01.04 03:00:00 13 EURUSD продажа 0.05 / 0.05 1.03942

2017.01.04 03:00:00 заполнение
2017.01.04 03:00:00 14 EURUSD продажа 1.00 / 1.00 1.03942

2017.01.04 03:00:00 заполнение
2017.01.04 06:00:00 15 EURUSD Покупка 1.00 / 1.00 1.04058

2017.01.04 06:00:00 заполнение
2017.01.04 06:00:00 16 EURUSD Покупка 0.05 / 0.05 1.04058

2017.01.04 06:00:00 заполнение
2017.01.05 11:00:00 17 EURUSD продажа 0.05 / 0.05 1.05149

2017.01.05 11:00:00 заполнение
2017.01.05 11:00:00 18 EURUSD продажа 1.00 / 1.00 1.05149

2017.01.05 11:00:00 заполнение
2017.01.05 16:00:00 19 EURUSD Покупка 1.00 / 1.00 1.05307

2017.01.05 16:00:00 заполнение
2017.01.05 16:00:00 20 EURUSD Покупка 0.05 / 0.05 1.05307

2017.01.05 16:00:00 заполнение
2017.01.06 05:00:00 21 EURUSD продажа 0.05 / 0.05 1.05869

2017.01.06 05:00:00 заполнение

Поскольку менеджер ордеров уже позаботился о разнице между двумя платформами (и языками), метод и результат расчета размера лота будет одинаковым.

Заключение

В статье показано, как в кроссплатформенном торговом советнике можно применять мани-менеджмент. Представлены 5 различных типов управления капиталом. Также представлен пользовательский объект-контейнер для указателей на объекты, который используется для динамического выбора метода мани-менеджмента.

Перевод с английского произведен MetaQuotes Software Corp.
Оригинальная статья: https://www.mql5.com/en/articles/3280

Прикрепленные файлы |
mm_ha_ma.zip (1038.69 KB)
tester_results.zip (292.36 KB)
Графические интерфейсы XI: Нарисованные элементы управления (build 14.2) Графические интерфейсы XI: Нарисованные элементы управления (build 14.2)

В новой версии библиотеки все элементы библиотеки будут рисоваться на отдельных графических объектах типа OBJ_BITMAP_LABEL. Также продолжим описывать оптимизацию кода: рассмотрим изменения в классах, которые являются ядром библиотеки.

Использование облачных хранилищ для обмена данными между терминалами Использование облачных хранилищ для обмена данными между терминалами

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

Тестирование паттернов, возникающих при торговле корзинами валютных пар. Часть I Тестирование паттернов, возникающих при торговле корзинами валютных пар. Часть I

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

Графические интерфейсы XI: Поля ввода и комбо-боксы в ячейках таблицы (build 15) Графические интерфейсы XI: Поля ввода и комбо-боксы в ячейках таблицы (build 15)

В этом обновлении библиотеки элемент "Таблица" (класс CTable) пополнится новыми опциями. Расширим линейку элементов в ячейках таблицы и на этот раз добавим в неё поля ввода и комбо-боксы. В качестве дополнения в это обновление была добавлена возможность управлять размерами окна пользователем MQL-приложения во время её выполнения.