Создаем мультивалютный советник

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Создаем мультивалютный советник

Сообщение Kalkin » 25 фев 2017, 16:00

В этой теме затронем нюансы написания мультивалютного советника для Метатрейдера 4. Мультивалютники я писал еще в 2009 - 2010-м году, так что некоторый опыт имеется, хоть и последние несколько лет я ими не занимался.
Мультивалютным называется такой советник, который устанавливается на один график, а торговые операции выполняет с двумя и более инструментами. Надо различать мультивалютный советник и тот, который устанавливается на множество графиков - это просто совместная работа нескольких экземпляров обыкновенного моновалютного советника.
Сразу скажу, что ничего сложного в мультивалютных советниках нету, нужно просто соблюдать некоторые правила, которые ниже рассмотрим.

1. Перечень торгуемых инструментов.
Есть несколько способов задания наименований всех инструментов, которыми собираемся торговать.
Самый простой способ - в настройках советника предусмотреть отдельные параметры для каждого инструмента:
Код: выделить все
input string Sym1 = "EURUSD"; // имя 1-й пары
input string Sym2 = "GBPUSD"; // имя 2-й пары
input string Sym3 = "AUDUSD"; // имя 3-й пары
input string Sym4 = "USDJPY"; // имя 4-й пары
input string Sym5 = "USDCAD"; // имя 5-й пары

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

Второй способ - перечислить торгуемые инструменты в каком-то параметре в настройках советника:
Код: выделить все
input string Symbols = "EURUSD,GBPUSD,AUDUSD,USDJPY,USDCAD,USDCHF,NZDUSD"; // перечень торгуемых символов

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

Также немаловажный аспект: советник будет запускаться по тикам того инструмента, на графике которого он стоит. Если установили на EURUSD, то только когда будет тик именно на EURUSD, советник сможет проанализировать все другие пары. Поэтому мультивалютный советник следует устанавливать на самую ликвидную валютную пару.
ВАЖНО: в "Обзоре рынка" МТ4 должны присутствовать все инструменты, по которым должна вестись торговля.

2. Доступ к таймсериям
Если необходимо определить значение цены открытия, закрытия, хая, лоу, количество баров, время открытия, тиковые объемы, то в обычном моновалютном советнике мы используем предопределенные массивы-таймсерии Open[], Close[], High[], Low[], Time[] и т.д. В мультивалютном советнике об этом можно забыть. Для доступа к таймсериям используются соответствующие функции с явным указанием инструмента, таймфрейма и номера бара:
Код: выделить все
double  iOpen(
   string           symbol,          // символ
   int              timeframe,       // период
   int              shift            // сдвиг
   );

double  iClose(
   string           symbol,          // символ
   int              timeframe,       // период
   int              shift            // сдвиг
   );

double  iHigh(
   string           symbol,          // символ
   int              timeframe,       // период
   int              shift            // сдвиг
   );

double  iLow(
   string           symbol,          // символ
   int              timeframe,       // период
   int              shift            // сдвиг
   );



3. Работа с предопределенными переменными
Речь идет о таких предопределенных переменных, как последняя известная цена продажи (запрашиваемая цена) Ask, последняя известная цена покупки (предложение на покупку) Bid, Размер пункта Point, количество цифр после десятичной точки в цене Digits и тому подобных.
Для мультивалютных советников необходимо все эти значения брать с помощью функции MarketInfo(...). Из справки MQL4:
Код: выделить все
double  MarketInfo(
   string           symbol,     // символ инструмента
   int              type        // тип информации
   );
 
Параметры
symbol
   [in]  Имя символа.
type
   [in] Идентификатор запроса, определяющий тип возвращаемой информации. Может быть любым из значений идентификаторов запроса.

Возвращаемое значение
Информация о финансовом инструменте. Часть информации о текущем финансовом инструменте хранится в предопределенных переменных.

Пример:
   double vbid    = MarketInfo("EURUSD",MODE_BID);
   double vask    = MarketInfo("EURUSD",MODE_ASK);
   double vpoint  = MarketInfo("EURUSD",MODE_POINT);
   int    vdigits = (int)MarketInfo("EURUSD",MODE_DIGITS);
   int    vspread = (int)MarketInfo("EURUSD",MODE_SPREAD);



А теперь перейдем к примеру простого мультивалютного советника.
Последний раз редактировалось Kalkin 25 фев 2017, 19:10, всего редактировалось 1 раз.
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Создаем мультивалютный советник

Сообщение Kalkin » 25 фев 2017, 17:06

Alexandeer писал(а):На самом деле не важно какой советник. Допустим алгоритм такой: Если нет открытых ордеров, то открывать ордер с тейком и стопом 50, причем открывать сразу на 5 парах.
Получается пользователь запускает его на 1 графике, а бот открывает ордера на нескольких, думаю для этого нужно окошечко оформить где вся инфа бы появлялась, правда я не знаю как. Но как его тестить? Я еще не разу мультивалютный не видел, ну во всяком случае простой и понятный.


Вот примерно по такому заданию и напишем. Предупреждаю, что сильно упростил многие моменты, их можно будет наверстать потом, если тема получит развитие. Напишем советник, который при отсутствии открытых позиций вводит позиции по трем различным инструментам. В настройках для каждого инструмента введем свой блок параметров, в которых укажем наименование торгуемого инструмента, направление торгов (покупка/продажа), величину лота и размер стоп-лоссов и тейк-профитов. Получится примерно следующее:
Код: выделить все
input string            s1 = "СИМВОЛ 1 :";                   // -------
input string            Symbol_1 = "EURUSD";       // Символ
input TPosType          OrderType_1 = OP_BUY;      // Тип ордера
input double            Lot_1 = 0.1;               // Лот
input int               StopLossPips_1 = 200;      // Stop Loss в пунктах
input int               TakeProfitPips_1 = 100;    // Take Profit в пунктах
input string            s2 = "СИМВОЛ 2 :";                   // -------
input string            Symbol_2 = "USDJPY";       // Символ
input TPosType          OrderType_2 = OP_BUY;      // Тип ордера
input double            Lot_2 = 0.1;               // Лот
input int               StopLossPips_2 = 200;      // Stop Loss в пунктах
input int               TakeProfitPips_2 = 100;    // Take Profit в пунктах
input string            s3 = "СИМВОЛ 3 :";                   // -------
input string            Symbol_3 = "EURJPY";       // Символ
input TPosType          OrderType_3 = OP_SELL;     // Тип ордера
input double            Lot_3 = 0.2;               // Лот
input int               StopLossPips_3 = 200;      // Stop Loss в пунктах
input int               TakeProfitPips_3 = 100;    // Take Profit в пунктах


Для удобства выбора типа ордера в программу введен перечислимый тип TPosType:
Код: выделить все
enum TPosType
{
   TP_BUY = OP_BUY, // покупать (buy)
   TP_SELL = OP_SELL // продавать (sell)
};


Тело советника простое: при отсутствии открытых позиций поочередно для каждого инструмента вызывается функция открытия позиции, в которую каждый раз передаются параметры для каждого из инструментов:
Код: выделить все
void OnTick()
  {
//---
     if (OrdersTotal()==0) // если нет открытых позиций
     {
        // открываем позиции по трем инструментам
        OpenPosition(Symbol_1, OrderType_1, Lot_1, StopLossPips_1, TakeProfitPips_1);
        OpenPosition(Symbol_2, OrderType_2, Lot_2, StopLossPips_2, TakeProfitPips_2);
        OpenPosition(Symbol_3, OrderType_3, Lot_3, StopLossPips_3, TakeProfitPips_3);
     }
  }


Функция открытия позиций должна удовлетворять требованиям, указанным в первом посте. Цену для открытия позиции в зависимости от направления (покупки или продажи), величину пункта, количество цифр после запятой определяем с помощью функции MarketInfo(), в которую передаем наименование торгуемого инструмента из фактических параметров функции. Структура функции может быть и другой, но для минимального набора необходимо определить цену открытия позиции, вычислить уровни стоп-лоссов и тейк-профитов и, собственно, вызвать торговую функцию для открытия позиции:
Код: выделить все
//+------------------------------------------------------------------+
//| Открытие позиции                                                  |
//+------------------------------------------------------------------+
void OpenPosition(string Sym, int type, double lot, int sl, int tp)
{
//----
   double openprice=0; // цена открытия позиции
   double StopLoss = 0;
   double TakeProfit = 0;
   if (type == OP_BUY)
   {
      openprice = MarketInfo(Sym,MODE_ASK); // покупка идет по цене ASK
      if (sl>0) StopLoss = openprice - sl*MarketInfo(Sym,MODE_POINT);      // определяем стоп-лосс для покупок
      if (tp>0) TakeProfit = openprice + tp*MarketInfo(Sym,MODE_POINT);    // определяем тейк-профит для покупок
   }
   else if (type == OP_SELL)
   {
      openprice = MarketInfo(Sym,MODE_BID); // продажа идет по цене BID
      if (sl>0) StopLoss = openprice + sl*MarketInfo(Sym,MODE_POINT);      // определяем стоп-лосс для продаж
      if (tp>0) TakeProfit = openprice - tp*MarketInfo(Sym,MODE_POINT);    // определяем тейк-профит для продаж
   }
   //нормализуем стопы и тейки
   StopLoss = NormalizeDouble(StopLoss, (int)MarketInfo(Sym, MODE_DIGITS));
   TakeProfit = NormalizeDouble(TakeProfit, (int)MarketInfo(Sym, MODE_DIGITS));
   
   if (OrderSend(Sym, type, lot, openprice, 10, StopLoss, TakeProfit, "", 0))
      Print("Открыта позиция ",Sym," ", type," ",lot, " лот");
   else
      Print("Ошибка при открытии позиции ",Sym," ", type," ",lot, " лот");
}


Сам советник - во вложении ниже.

MyMultiEA.mq4
(9.04 KB) Скачиваний: 154
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Создаем мультивалютный советник

Сообщение Kalkin » 25 фев 2017, 17:19

Протестировать такой советник в тестере стратегий все-таки надо, хоть полноценного теста и не получится. Все дело в том, что при попытке открытия позиции по отличному от выбранного для тестирования символу генерируется ошибка исполнения с кодом 4107 - "Неправильный параметр цены для торговой функции" и никакого открытия не происходит. Тем не менее, для отсеивания грубых логических ошибок необходимо провести такие тесты по отдельности для каждого инструмента.
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Создаем мультивалютный советник

Сообщение Paramon » 25 фев 2017, 17:31

Kalkin писал(а):Протестировать такой советник в тестере стратегий все-таки надо, хоть полноценного теста и не получится. Все дело в том, что при попытке открытия позиции по отличному от выбранного для тестирования символу генерируется ошибка исполнения с кодом 4107 - "Неправильный параметр цены для торговой функции" и никакого открытия не происходит. Тем не менее, для отсеивания грубых логических ошибок необходимо провести такие тесты по отдельности для каждого инструмента.


А что же покажет тест который даже не запустится из-за ошибки?
Аватар пользователя
Paramon
 
Сообщений: 730
Зарегистрирован: 15 авг 2013, 07:55
Средств на руках: 147.03 Доллар
Награды: 1
Ветеран II (1)
Группа: Базовая
Благодарил (а): 224 раз.
Поблагодарили: 75 раз.

Создаем мультивалютный советник

Сообщение Kalkin » 25 фев 2017, 19:03

Paramon писал(а):
Kalkin писал(а):Протестировать такой советник в тестере стратегий все-таки надо, хоть полноценного теста и не получится. Все дело в том, что при попытке открытия позиции по отличному от выбранного для тестирования символу генерируется ошибка исполнения с кодом 4107 - "Неправильный параметр цены для торговой функции" и никакого открытия не происходит. Тем не менее, для отсеивания грубых логических ошибок необходимо провести такие тесты по отдельности для каждого инструмента.


А что же покажет тест который даже не запустится из-за ошибки?


Позиции по тестируемому символу будут открываться, вот их и проверяем. На этом этапе не исследуются мультивалютные свойства советника, а проверяется его принципиальная работоспособность по каждой паре. Затем - демо-тест на VPS.
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Создаем мультивалютный советник

Сообщение ВЯЧЕСЛАВПЕТРОВ » 27 фев 2017, 16:12

Вопрос как можно взять значения индикаторов на трех парах. На каждой паре по индикатору.
Вот индикатор возможно не весь код.
TradersDynamicIndex.mq4
(9.09 KB) Скачиваний: 66
Аватар пользователя
ВЯЧЕСЛАВПЕТРОВ
 
Сообщений: 1522
Зарегистрирован: 06 сен 2016, 21:28
Средств на руках: 90.40 Доллар
Награды: 2
Ветеран I (1) Медаль за эрудицию (1)
Группа: Базовая
Благодарил (а): 3574 раз.
Поблагодарили: 434 раз.
Автор Вячеслав Петров. Возьму капитал или счет в управление. В лс.
Мониторинг трех счетной системы. Первый.Второй. Третий.
Четвертый.

Создаем мультивалютный советник

Сообщение Kalkin » 27 фев 2017, 19:41

ВЯЧЕСЛАВПЕТРОВ писал(а):Вопрос как можно взять значения индикаторов на трех парах. На каждой паре по индикатору.
Вот индикатор возможно не весь код.
TradersDynamicIndex.mq4

Значение буфера внешнего индикатора берется при помощи функции iCustom():
Код: выделить все
double  iCustom(
   string       symbol,           // имя символа
   int          timeframe,        // таймфрейм
   string       name,             // папка/имя_пользовательского индикатора
   ...                            // список входных параметров индикатора
   int          mode,             // источник данных
   int          shift             // сдвиг
   );


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

В предложенном примере в разделе входных параметров советника необходимо ввести перечень параметров, такой же, как в самом индикаторе. Необходимо это сделать для того, чтобы из советника можно было бы подставлять различные параметры индикатора (для той же оптимизации).
Код: выделить все
extern string IndicatorName = "TradersDynamicIndex"; // Имя индикатора
extern int RSI_Period = 13;         //8-25
extern int RSI_Price = MODE_CLOSE;           //0-6
extern int Volatility_Band = 34;    //20-40
extern int RSI_Price_Line = 2;     
extern int RSI_Price_Type = MODE_SMA;      //0-3
extern int Trade_Signal_Line = 7;   
extern int Trade_Signal_Type = MODE_SMA;   //0-3
extern bool UseAlerts = false;


Потом определяем индексы буферов индикатора, которые хотим прочитать. Например, базовая линия индикатора (желтая) имеет индекс 2, линия RSI - индекс 0, сигнальная линия - индекс 1.
Прочитать базовую линию индикатора:
Код: выделить все
      double Base_1 = iCustom(Symbol_1, 0, IndicatorName,RSI_Period,RSI_Price,Volatility_Band,RSI_Price_Line,RSI_Price_Type,Trade_Signal_Line,Trade_Signal_Type,UseAlerts,2,0);
      double Base_2 = iCustom(Symbol_2, 0, IndicatorName,RSI_Period,RSI_Price,Volatility_Band,RSI_Price_Line,RSI_Price_Type,Trade_Signal_Line,Trade_Signal_Type,UseAlerts,2,0);
      double Base_3 = iCustom(Symbol_3, 0, IndicatorName,RSI_Period,RSI_Price,Volatility_Band,RSI_Price_Line,RSI_Price_Type,Trade_Signal_Line,Trade_Signal_Type,UseAlerts,2,0);


А если перечислять все символы в одном из параметров настроек через запятую, то не нужно 100500 раз прописывать вызов функции для каждой пары, а делать это в цикле, подставляя каждый раз наименование пары из массива.
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Создаем мультивалютный советник

Сообщение ВЯЧЕСЛАВПЕТРОВ » 28 фев 2017, 16:07

Мне очень нравятся ваши ответы. Я хотел написать самостоятельно советник из моей темы .
Треугольный арбитраж на базе КиД «купи и держи».
Знаний у меня пока не достаточно. Могу я в этой теме задавать конкретные вопросы связные с написанием этого мультивалютного в советника и наедятся на вашу помощь в ключевых вопросах?
Аватар пользователя
ВЯЧЕСЛАВПЕТРОВ
 
Сообщений: 1522
Зарегистрирован: 06 сен 2016, 21:28
Средств на руках: 90.40 Доллар
Награды: 2
Ветеран I (1) Медаль за эрудицию (1)
Группа: Базовая
Благодарил (а): 3574 раз.
Поблагодарили: 434 раз.
Автор Вячеслав Петров. Возьму капитал или счет в управление. В лс.
Мониторинг трех счетной системы. Первый.Второй. Третий.
Четвертый.

Создаем мультивалютный советник

Сообщение Kalkin » 28 фев 2017, 19:45

ВЯЧЕСЛАВПЕТРОВ писал(а):Мне очень нравятся ваши ответы. Я хотел написать самостоятельно советник из моей темы .
Треугольный арбитраж на базе КиД «купи и держи».
Знаний у меня пока не достаточно. Могу я в этой теме задавать конкретные вопросы связные с написанием этого мультивалютного в советника и наедятся на вашу помощь в ключевых вопросах?

Собственно, ради этого тема и затеяна, чтобы помочь всякими советами :-): , так что чем сможем - поможем, спрашивайте.
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Создаем мультивалютный советник

Сообщение ВЯЧЕСЛАВПЕТРОВ » 10 мар 2017, 16:35

Есть такой алгоритм который бы вычислял стоимость одного пункта каждой валюты в терминале?
Стал создавать советник и понял что нужно сделать расчеты рисков после открытия или закрытия ордера в мультивалютном советнике для КИД.
Спасибо за буфера обмена из индикатора то я долго думал как их найти , но так и не понял. Просто скопировал ваш код.
Аватар пользователя
ВЯЧЕСЛАВПЕТРОВ
 
Сообщений: 1522
Зарегистрирован: 06 сен 2016, 21:28
Средств на руках: 90.40 Доллар
Награды: 2
Ветеран I (1) Медаль за эрудицию (1)
Группа: Базовая
Благодарил (а): 3574 раз.
Поблагодарили: 434 раз.
Автор Вячеслав Петров. Возьму капитал или счет в управление. В лс.
Мониторинг трех счетной системы. Первый.Второй. Третий.
Четвертый.


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 48

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения