English 中文 Español Deutsch 日本語 Português
Пример разработки спредовой стратегии на фьючерсах Московской биржи

Пример разработки спредовой стратегии на фьючерсах Московской биржи

MetaTrader 5Примеры | 29 ноября 2016, 09:57
12 746 41
MetaQuotes
MetaQuotes

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


Обратная корреляция символов Si и RTS

На Московской бирже торгуются фьючерсы вида Si-M.Y и RTS-M.Y, которые достаточно тесно между собой связаны. Здесь M.Y обозначают дату истечения контракта:

  • M — номер месяца
  • Y — две последние цифры года

Si  —  это фьючерсный контракт на курс доллар США/российский рубль, RTS  —  фьючерсный контракт на Индекс РТС, выраженный в долларах США.  Так как в Индекс РТС входят акции российских компаний, цены на которые выражены в рублях, то колебания курса USD/RUR отражаются также и на колебаниях индекса, выраженного в долларах США. На графиках этих инструментов видно, что при росте одного актива второй, как правило, падает.


Для лучшего представления мы наложили на оба графика канал стандартного отклонения.


Вычисляем линейную регрессию между Si и RTS

Мы можем выразить связь между двумя инструментами с помощью уравнения линейной регрессии вида Y(X)=A(X)+B. Для проверки напишем скрипт CalcShowRegression_script.mq5, который берет два массива цен закрытия, вычисляет коэффициенты и выводит диаграмму распределения с линией регрессии прямо на график.

Для вычисления коэффициентов регрессии используется функция из библиотеки ALGLIB, отрисовка делается графическими классами Стандартной библиотеки.



Строим индикатор спреда между Si и синтетикой

Мы получили коэффициенты линейной регрессии, и теперь можем строить синтетический график вида Y(RTS) = A*RTS+B. Разницу между оригинальным активом и синтетическим рядом назовем спредом. Эта разница будет меняться на каждом баре, от  положительных до отрицательных значений.

Для визуального представления спреда напишем индикатор TwoSymbolsSpread_Ind.mql5, который выводит в виде гистограммы спред на данных за последние 500 баров. Положительные значения спреда рисуются голубым цветом, отрицательные  —  желтым.

Индикатор обновляет и пишет в журнал Эксперты коэффициенты линейной регрессии при открытии каждого нового бара. При этом он дожидается того момента, когда новая свеча откроется на обоих инструментах — Si и RTS. Таким образом индикатор позволяет контролировать правильность и точность расчетов.


Строим график линейной регрессии на графике спредов за последние 100 баров

Индикатор спреда показывает, что разница между фьючерсом Si и синтетическим инструментом периодически меняется. Чтобы оценить текущую тенденцию, напишем индикатор SpreadRegression_Ind.mq5 (спред и линейная регрессия на нём), который строит трендовую линию на графике спреда. Параметры линии вычисляем опять же методом линейной регрессии.  Наложим оба индикатора на график для отладки.

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


Стратегия №1 — изменение наклона линейной регрессии на графике спреда

Значения спреда в индикаторе TwoSymbolsSpread_Ind.mql5 считаются как разность между Si и Y(RTS)=A*RTS + B. Вы можете легко проверить это, запустив индикатор под отладкой (кнопкой F5).


Сделаем простого советника, который отслеживает изменение угла наклона линейной регрессии, наложенной на график спреда. Угол наклона линии — это не что иное, как коэффициент A в уравнении Y=A*X+B. При положительном тренде на графике спреда A>0, при отрицательном A<0. Линейную регрессию мы считаем на последних 100 значениях графика спреда. Вот часть кода из советника Strategy1_AngleChange_EA.mq5.

#include <Trade\Trade.mqh>
//+------------------------------------------------------------------+
//| тип стратегии спреда                                             |
//+------------------------------------------------------------------+
enum SPREAD_STRATEGY
  {
   BUY_AND_SELL_ON_UP,  // Buy 1-st, Sell 2-nd
   SELL_AND_BUY_ON_UP,  // Sell 1-st, Buy 2-nd
  };
//---
input int       LR_length=100;                     // кол-во баров для регрессии на спреде
input int       Spread_length=500;                 // кол-во баров для расчета спреда
input ENUM_TIMEFRAMES  period=PERIOD_M5;           // таймфрейм
input string    symbol1="Si-12.16";                // первый символ пары
input string    symbol2="RTS-12.16";               // второй символ пары
input double    profit_percent=10;                 // сколько процентов прибыли фиксируем
input SPREAD_STRATEGY strategy=SELL_AND_BUY_ON_UP; // тип спредовой стратегии
//--- хендлы индикаторов
int ind_spreadLR,ind,ind_2_symbols;
//--- класс для торговых операций
CTrade trade;
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- коэффициент A наклона линейной регрессии на графике спреда Y(X)=A*X+B
   static double Spread_A_prev=0;
   if(isNewBar())
      PrintFormat("Новый бар %s открылся в %s",_Symbol,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS));
//--- дождемся, когда данные индикатора обновятся, так как он работает на двух символах
   if(BarsCalculated(ind_spreadLR)==Bars(_Symbol,_Period))
     {
      //--- получим значения линейной регрессии на графике спреда для баров с индексами 1 и 2 ("вчера" и "позавчера")
      double LRvalues[];
      double Spread_A_curr;
      int copied=CopyBuffer(ind_spreadLR,1,1,2,LRvalues);
      if(copied!=-1)
        {
         //--- коэффициент линейной регрессии на последнем завершенном ("вчерашнем") баре
         Spread_A_curr=LRvalues[1]-LRvalues[0];
         //--- если наклон регрессии сменился, то произведение текущего и предыдущего меньше нуля
         if(Spread_A_curr*Spread_A_prev<0)
           {
            PrintFormat("Линия LR сменила наклон, Spread_A_curr=%.2f, Spread_A_prev=%.2f: %s",
                        Spread_A_curr,Spread_A_prev,TimeToString(TimeCurrent(),TIME_SECONDS));
            //--- если открытых позиций нет, то войдем в рынок по двум символам
            if(PositionsTotal()==0)
               DoTrades(Spread_A_curr-Spread_A_prev>0,strategy,symbol1,1,symbol2,1);
            //--- есть открытые позиции, делаем переворот
            else
               ReverseTrades(symbol1,symbol2);
           }
         //--- наклон регрессии не изменился, проверим плавающую прибыль - может пора закрывать?
         else
           {
            double profit=AccountInfoDouble(ACCOUNT_PROFIT);
            double balance=AccountInfoDouble(ACCOUNT_BALANCE);
            if(profit/balance*100>=profit_percent)
              {
               //--- достигнут нужный уровень плавающей прибыли - фиксируем
               trade.PositionClose(symbol1);
               trade.PositionClose(symbol2);
              }
           }
         //--- запомним направление тренда для сравнения на открытии нового бара
         Spread_A_prev=Spread_A_curr;
        }
     }
  }

Чтобы не делать предположений, что нужно покупать, а что продавать при смене тренда, мы просто добавили в советника внешний параметр, который позволяет переворачивать торговые правила:

input SPREAD_STRATEGY strategy=SELL_AND_BUY_ON_UP; // тип спредовой стратегии

Теперь мы можем запустить тестирование и отладку советника.


Тестирование торговой Стратегии №1

Для отладки новой стратегии лучше всего использовать режим визуального тестирования. Для этого через меню Сервис-Настройки-Отладка задайте все необходимые данные:

  1. Символ
  2. Таймфрейм
  3. Интервал тестирования
  4. Режим торговли
  5. Размер депозита
  6. Режим генерации тиков

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

Торговый сервер MetaTrader 5 автоматически накапливает все пришедшие с биржи тики у себя и выдает в терминал всю тиковую историю по первому запросу.

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

После того, как код советника отлажен, можем провести оптимизацию параметров.


Оптимизация торговой Стратегии №1

В советнике Strategy1_AngleChange_EA.mq5 есть несколько внешних параметров, которые можно подбирать путем оптимизации (выделено желтым):

input int       LR_length=100;                     // кол-во баров для регрессии на спреде
input int       Spread_length=500;                 // кол-во баров для расчета спреда
input double    profit_percent=10;                 // сколько процентов прибыли фиксируем

input SPREAD_STRATEGY strategy=SELL_AND_BUY_ON_UP; // тип спредовой стратегии

Но мы в данном случае будем оптимизировать только параметр profit_percent для двух вариантов стратегии, чтобы понять, есть ли между ними разница. Иными словами, мы фиксируем значение параметра strategy и делаем оптимизацию по параметру profit_percent от 0.2 до 3.0%, чтобы увидеть общую картину для двух способов торговать на изменении наклона линии.

Для правила BUY_AND_SELL_ON_UP (покупаем первый актив, продаем второй), когда наклон линии меняется с отрицательного на положительный, оптимизация дает не очень хорошие результаты. В целом такой способ входа в рынок не выглядит привлекательным, мы чаще получаем убыток при тестировании на интервале в 2 месяца.


При использовании правила SELL_AND_BUY_ON_UP (продаем первый актив, покупаем второй) результаты оптимизации лучше — 5 из 15 проходов оптимизации показывают какую-то прибыль.


Оптимизация проводилась на истории с 1 августа по 30 сентября 2016 (интервал в два месяца). В целом, оба варианта торговли не выглядят многообещающими. Возможно, проблема в том, что для входов мы использовали достаточно запаздывающий показатель — наклон трендовой линии за последние 100 баров. Попробуем разработать второй вариант стратегии.


Стратегия №2 — смена знака спреда на завершенном баре

Во второй стратегии мы будем следить за изменениями знака спреда. Смотреть мы будем значения только на сформировавшихся барах, то есть на открытии нового "сегодняшнего" бара. Если спред на "позавчерашнем" баре был отрицательный, а на "вчерашнем" стал положительным, то мы считаем, что спред развернулся вверх (UP). Опять-таки в коде оставлена возможность торговать смену спреда в любую сторону  —  мы можем разворачивать направления входа с помощью параметра strategy. Вот блок кода советника Strategy2_SpreadSignChange_EA.mq5:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- предыдущее значение спреда как разности Symbol1 и Y(Symbol2)=A*Symbol2+B
   static double Spread_prev=0;
   if(isNewBar())
      PrintFormat("Новый бар %s открылся в %s",_Symbol,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS));
//--- дождемся, когда данные индикатора обновятся, так как он работает на двух символах
   if(BarsCalculated(ind_spreadLR)==Bars(_Symbol,_Period))
     {
      //--- получим значения спреда для баров с индексами 1 и 2 ("вчера" и "позавчера")
      double SpreadValues[];
      int copied=CopyBuffer(ind_spreadLR,0,1,2,SpreadValues);
      double Spread_curr=SpreadValues[1];
      if(copied!=-1)
        {
         //--- если знак спреда изменился, то произведение текущего и предыдущего меньше нуля
         if(Spread_curr*Spread_prev<0)
           {
            PrintFormat("Спред изменил знак, Spread_curr=%.2f, Spread_prev=%.2f: %s",
                        Spread_curr,Spread_prev,TimeToString(TimeCurrent(),TIME_SECONDS));
            //--- если открытых позиций нет, то войдем в рынок по двум символам
            if(PositionsTotal()==0)
               DoTrades(Spread_curr>0,strategy,symbol1,1,symbol2,1);
            //--- есть открытые позиции, делаем переворот
            else
               ReverseTrades(symbol1,symbol2);
           }
         //--- знак спреда не изменился, проверим плавающую прибыль - может, пора закрывать?
         else
           {
            double profit=AccountInfoDouble(ACCOUNT_PROFIT);
            double balance=AccountInfoDouble(ACCOUNT_BALANCE);
            if(profit/balance*100>=profit_percent)
              {
               //--- достигнут нужный уровень плавающей прибыли - фиксируем
               trade.PositionClose(symbol1);
               trade.PositionClose(symbol2);
              }
           }
         //--- запомним значение спреда для сравнения на открытии нового бара
         Spread_prev=Spread_curr;
        }
     }
  }

Сначала, как обычно, делаем отладку торгового робота в визуальном режиме тестирования, затем запускаем оптимизацию по параметру profit_percent, как и для первой стратегии. Результаты:



Как видим, для второй стратегии правило "Продаем первый актив и покупаем второй" даёт такие же неутешительные результаты тестирования, как и для первой. При этом правило "Покупаем первый  актив и продаем второй" на всех проходах даёт больше убытков.

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


Стратегия №3 — смена знака спреда на текущем баре с подтверждением на N тиках

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

Потребуем также, чтобы изменение знака спреда было устойчивым на последних N тиках — таким образом мы пытаемся избавиться от ложных сигналов. Для этого добавим в советника внешний параметр ticks_for_trade=10. Если на последних 10 тиках знак спреда отрицательный, а на предыдущем баре положительный, то мы входим в рынок. Вот так выглядит функция OnTick() советника Strategy3_SpreadSignOnTick_EA.mq5.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(isNewBar())
      PrintFormat("Новый бар %s открылся в %s",_Symbol,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS));
//--- дождемся, когда данные индикатора обновятся, так как он работает на двух символах
   if(BarsCalculated(ind_spreadLR)==Bars(_Symbol,_Period))
     {
      //--- получим значения спреда на текущем ("сегодня") и предыдущем ("вчера") барах
      double SpreadValues[];
      int copied=CopyBuffer(ind_spreadLR,0,0,2,SpreadValues);
      double Spread_curr=SpreadValues[1]; // спред на текущем баре развивающемся
      double Spread_prev=SpreadValues[0]; // спред на предыдущем завершенном баре
      if(copied!=-1)
        {
         //--- если изменение знака спреда сохраняется на последних ticks_for_trade тиках
         if(SpreadSignChanged(Spread_curr,Spread_prev,ticks_for_trade))
           {
            PrintFormat("Спред изменил знак, Spread_curr=%.2f, Spread_prev=%.2f: %s",
                        Spread_curr,Spread_prev,TimeToString(TimeCurrent(),TIME_SECONDS));
            //--- покажем на графике значения последних ticks_for_trade тиков по обоим символам
            ShowLastTicksComment(ticks_for_trade);
            //--- если открытых позиций нет, то войдем в рынок по двум символам
            if(PositionsTotal()==0)
               DoTrades(Spread_curr>0,strategy,symbol1,1,symbol2,1);
            //--- есть открытые позиции, делаем переворот
            else
               ReverseTrades(Spread_curr>0,positionstype,symbol1,symbol2);
           }
         //--- знак спреда не изменился, проверим плавающую прибыль - может, пора закрывать?
         else
           {
            double profit=AccountInfoDouble(ACCOUNT_PROFIT);
            double balance=AccountInfoDouble(ACCOUNT_BALANCE);
            if(profit/balance*100>=profit_percent)
              {
               //--- достигнут нужный уровень плавающей прибыли - фиксируем
               trade.PositionClose(symbol1);
               trade.PositionClose(symbol2);
               positionstype=0;
              }
           }
        }
     }
   }

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

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

"Покупаем 1-ый актив и продаем 2-ой"


"Продаем 1-ый актив и покупаем 2-ой"


Результаты при такой простой оптимизации не сильно улучшились.


Стратегия №4 — достижение спредом заданного значения в процентах

Создадим четвертую, последнюю, стратегию для торговли спредом. Она будет такой же простой как три предыдущие, а именно — торговый сигнал возникает в тот момент, когда спред составляет от цены первого актива заданное значение в процентах — spread_delta. Обработчик поступающих тиков OnInit() изменился незначительно, вот его код из советника Strategy4_SpreadDeltaPercent_EA.mq5.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(isNewBar())
      PrintFormat("Новый бар %s открылся в %s",_Symbol,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS));
//--- дождемся, когда данные индикатора обновятся, так как он работает на двух символах
   if(BarsCalculated(ind_spreadLR)==Bars(_Symbol,_Period))
     {
      //--- получим значение спреда на текущем ("сегодня")баре
      double SpreadValues[];
      int copied=CopyBuffer(ind_spreadLR,0,0,1,SpreadValues);
      double Spread_curr=SpreadValues[0]; // спред на текущем развивающемся баре
      if(copied!=-1)
        {
         MqlTick tick;
         SymbolInfoTick(symbol1,tick);
         double last=tick.last;
         double spread_percent=Spread_curr/last*100;
         //--- если спред в % достиг заданной величины spread_delta
         if(MathAbs(spread_percent)>=spread_delta)
           {
            PrintFormat("Спред достиг %.1f%% (%G) %s",
                        spread_percent,TimeToString(TimeCurrent(),TIME_SECONDS),
                        Spread_curr);
            //--- если открытых позиций нет, то войдем в рынок по двум символам
            if(PositionsTotal()==0)
               DoTrades(Spread_curr,strategy,symbol1,1,symbol2,1);
            //--- есть открытые позиции, делаем переворот
            else
               ReverseTrades(Spread_curr,positionstype,symbol1,symbol2);
           }
         //--- спред в пределах допустимого, проверим плавающую прибыль - может, пора закрывать?
         else
           {
            double profit=AccountInfoDouble(ACCOUNT_PROFIT);
            double balance=AccountInfoDouble(ACCOUNT_BALANCE);
            if(profit/balance*100>=profit_percent)
              {
               //--- достигнут нужный уровень плавающей прибыли - фиксируем
               trade.PositionClose(symbol1);
               trade.PositionClose(symbol2);
               positionstype=0;
              }
           }
        }
     }
  }

Закрывать позиции мы будем также по достижению заданного процента прибыли profit_percent=2, на этот раз сделаем его фиксированным. Запускаем оптимизацию по параметру spread_delta в диапазоне от 0.1 до 1%.

"Покупаем 1-ый актив и продаем 2-ой"


"Продаем 1-ый актив и покупаем 2-ой"


На этот раз первое правило "Покупаем 1-ый актив и продаем 2-ой" выглядит значительно лучше, чем второе. Оптимизацию по остальным параметрам вы можете сделать сами.


MetaTrader 5 — среда разработки торговых стратегий

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

Для разработчиков автоматических торговых систем тестер в MetaTrader 5 предлагает следующие удобные возможности:

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

Тестер торговых стратегий в данной статье использовался как инструмент исследования и поиска правильного направления — это делалось в виде оптимизации по одному параметру, чтобы быстро получать качественные выводы. Вы можете добавлять новые правила, модифицировать существующие и подвергнуть полученные советники тотальной оптимизации. Для ускорения массовых тяжелых вычислений используйте глобальную вычислительную сеть MQL5 Cloud Network, которая создана специально для платформы MetaTrader 5.


Необходимые замечания по стратегиям

Обычно при поиске символов для составления спреда используют не абсолютные значения цены, а приращения. То есть вместо ряда Close[i]  вычисляют Delta[i]=Close[i]-Close[i-1].

Для сбалансированной торговли необходимо подбирать объем для каждого символа спреда. В статье же при тестировании использовались только объемы в 1 лот на каждом символе.

При тестировании используются текущие настройки в спецификации контрактов Si и RTS. Необходимо отметить, что:

  • в основе фьючерса RTS-12.16 лежит доллар США,
  • цена тика фьючерса RTS-12.16 каждый день задается Московской биржей
  • и это значение равно 0.2 от индикативного курса доллара.

Методику расчета вы можете найти на сайте MOEX — http://fs.moex.com/files/3244. Поэтому нужно иметь в виду, что результаты оптимизации в тестере стратегий будут зависеть от курса доллара на момент проведения тестирования. В статье использованы скриншоты с результатами оптимизации, проведенными 25 октября 2016 года.

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

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

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

Не используется анализ стакана заявок, так как поток заявок в тестере MetaTrader 5 не эмулируется.

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

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


Статьи по теме:


Программы, используемые в статье:

#
 Имя
Тип
Описание
1
CalcShowRegression_script.mq5
Скрипт
Вычисляет коэфициенты линейной регрессии и выводит точечный график с линией тренда (используется класс СGraphic и функция из Alglib)
2
TwoSymbolsSpread_Ind.mql5
Индикатор
Индикатор, рисующий гистограмму спреда на двух символах
3
SpreadRegression_Ind.mq5
Индикатор Индикатор, рисующий график спреда и линию регрессии на нём
4
Strategy1_AngleChange_EA.mq5
Эксперт
Стратегия №1. Торговля на основе смены знака коэффициента А линейной регрессии в уравнении Y=A*X+B. Анализ и входы только на открытии нового бара
5
Strategy2_SpreadSignChange_EA.mq5 Эксперт Стратегия №2. Торговля на основе изменения знака в значении спреда. Анализ и входы только на открытии нового бара
6
Strategy3_SpreadSignOnTick_EA.mq5
Эксперт
Стратегия №3. Торговля на основе изменения знака в значении спреда. Анализ и входы внутри текущего бара, изменение знака должно сохраняться на последних N тиках
7 Strategy4_SpreadDeltaPercent_EA.mq5 
Эксперт
Стратегия №4. Торговля на основе достижения заданного в процентах значения спреда. Анализ и входы внутри текущего бара при первом же подходящем тике.

Прикрепленные файлы |
MQL5.zip (24.5 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (41)
Rashid Umarov
Rashid Umarov | 23 февр. 2017 в 07:54
prostotrader:

 Не понятно где и как рассчитывается lot1 и lot2

Нигде не рассчитывается, об ограничениях сказано в самой статье в отдельном разделе.
Rashid Umarov
Rashid Umarov | 23 февр. 2017 в 07:55
prostotrader:

Не очень удачно выбран пример Si - RTS, так как RTS не пропорционально зависит от Si,

большое влияние на RTS может оказывать MIX(MXI), ведь RTS - отражение индекса ММВБ в валюте. 

Гораздо интереснее рассмотреть SBRF  - SBPR разные фьючерсы на один и тот же актив.

Добавлено

Или рассмотреть RTS VS MIX без учёта хеджированием Si, так как в клиринг пересчитывается не весь контракт RTS, а

только разница между ценой покупки и ценой клиринга. 

MIX = RTS * USD_INDEX * LOT_RTS = 10 * 0.02

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

Спасибо за замечания, это интересно всем.
Maxim Dmitrievsky
Maxim Dmitrievsky | 16 окт. 2017 в 13:22

Как можно получить F-statistic и p -value из построенной регр модели через алглиб, мб кто-то уже делал? Там есть только AVGerr и RMSerr

Roman Konopelko
Roman Konopelko | 16 окт. 2017 в 15:10
Maxim Dmitrievsky:

Как можно получить F-statistic и p -value из построенной регр модели через алглиб, мб кто-то уже делал? Там есть только AVGerr и RMSerr

В классе CAlglib есть статический метод для F теста:

//+------------------------------------------------------------------+
//| Two-sample F-test                                                |
//| This test checks three hypotheses about dispersions of the given |
//| samples.                                                         |
//| Input parameters:                                                |
//|     X   -   sample 1. Array whose index goes from 0 to N-1.      |
//|     N   -   sample size.                                         |
//|     Y   -   sample 2. Array whose index goes from 0 to M-1.      |
//|     M   -   sample size.                                         |
//| Output parameters:                                               |
//|     BothTails   -   p-value for two-tailed test.                 |
//|                     If BothTails is less than the given          |
//|                     significance level the null hypothesis is    |
//|                     rejected.                                    |
//|     LeftTail    -   p-value for left-tailed test.                |
//|                     If LeftTail is less than the given           |
//|                     significance level, the null hypothesis is   |
//|                     rejected.                                    |
//|     RightTail   -   p-value for right-tailed test.               |
//|                     If RightTail is less than the given          |
//|                     significance level the null hypothesis is    |
//|                     rejected.                                    |
//+------------------------------------------------------------------+
static void CAlglib::FTest(const double &x[],const int n,const double &y[],
                           const int m,double &bothTails,double &leftTail,
                           double &rightTail)
Maxim Dmitrievsky
Maxim Dmitrievsky | 16 окт. 2017 в 16:10
Roman Konopelko:

В классе CAlglib есть статический метод для F теста:


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

Автоматическое нахождение экстремумов на основе заданного ценового перепада Автоматическое нахождение экстремумов на основе заданного ценового перепада
При автоматизации торговых стратегий, использующих графические модели, необходимо находить экстремумы на графиках для дальнейшей обработки и интерпретации. Существующие инструменты не всегда дают возможность это сделать. Представленные в статье алгоритмы позволяют находить все экстремумы на чартах. Разработанные инструменты одинаково эффективны как для работы на трендовом рынке, так и на боковом движении. Полученные результаты слабо зависят от выбранного таймфрейма и определяются только заданным масштабом.
Паттерны, доступные при торговле корзинами валют Паттерны, доступные при торговле корзинами валют
В продолжение прошлой статьи о принципах торговли корзинами валют, рассмотрены паттерны, которые может обнаружить трейдер. Рассмотрены положительные и отрицательные стороны каждого паттерна, даны рекомендации по их использованию. В качестве инструмента анализа применены индикаторы, построенные на основе осциллятора Вильямса.
Графические интерфейсы X: Элемент "Время", элемент "Список из чекбоксов" и сортировка таблицы (build 6) Графические интерфейсы X: Элемент "Время", элемент "Список из чекбоксов" и сортировка таблицы (build 6)
Продолжаем развивать библиотеку для создания графических интерфейсов. На этот раз будут представлены такие элементы, как «Время» и «Список из чекбоксов». Кроме этого, в класс таблицы типа CTable добавлена возможность сортировать данные по возрастанию и убыванию.
Универсальный осциллятор с графическим интерфейсом Универсальный осциллятор с графическим интерфейсом
В статье описывается создание универсального индикатора на основе всех осцилляторов терминала с собственным графическим интерфейсом. Это позволит быстро и удобно менять параметры каждого отдельного осциллятора прямо из окна графика (а не открывая окно свойств), сравнивать их показатели и выбирать оптимальный для себя вариант под конкретную задачу.