![Кроссплатформенный торговый советник: Мани-менеджмент](https://c.mql5.com/i/articles/overlay.png)
Кроссплатформенный торговый советник: Мани-менеджмент
Оглавление
- Введение
- Цели
- Базовый класс
- Классы и типы мани-менеджмента
- Контейнер объектов мани-менеджмента
- Пример
- Заключение
Введение
Мани-менеджмент (управление капиталом) — распространенная функция в торговых советниках. Она позволяет эксперту динамически определять размер лота для следующей сделки, в которую он войдет. В этой статье представлены несколько классов мани-менеджмента, которые позволят нам автоматизировать весь процесс расчета торгового объема в советнике.
Цели
- Понимать и применять наиболее распространенные методы управления капиталом, используемые в трейдинге
- Разрешить эксперту выбирать из списка доступных методов мани-менеджмента
- Обеспечить совместимость с 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); };
Поскольку этот объект разработан, чтобы содержать многочисленные объекты мани-менеджмента, требуются как минимум два метода, чтобы сделать объект доступным к использованию в разрабатываемом советнике:
- Выбор, или способность динамически переключаться между методами мани-менеджмента
- Использование выбранного объекта мани-менеджмента и получение рассчитанного для него объема сделки
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 Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/3280
![Тестирование паттернов, возникающих при торговле корзинами валютных пар. Часть I](https://c.mql5.com/2/28/articles_234__1.png)
![Графические интерфейсы XI: Нарисованные элементы управления (build 14.2)](https://c.mql5.com/2/28/av.png)
![Графические интерфейсы XI: Поля ввода и комбо-боксы в ячейках таблицы (build 15)](https://c.mql5.com/2/28/MQL5-avatar-XI-build_15.png)
![Использование облачных хранилищ для обмена данными между терминалами](https://c.mql5.com/2/28/7l8-fbt8.png)
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования