Скачать MetaTrader 5

Трейдминатор 3: восстание торговых роботов

18 января 2012, 08:27
Roman Zamozhnyy
8
6 564

Пролог

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

Используя его, я во второй статье попытался применить его для написания самооптимизирующего эксперта. Написание статьи завершено постановкой следующей задачи: создать эксперт (самооптимизирующийся, само собой разумеется), который может не только подобрать оптимальные параметры для какой-то определенной торговой системы, но и выбрать саму оптимальную стратегию из числа уже написанных стратегий. Посмотрим же, возможно ли это сделать, и если возможно - то как?

Сказки торговых роботов

Итак, сформулируем общие требования к самооптимизирующемуся экперту.

Он должен уметь (на исторических данных):

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

Далее, в реальной жизни он должен уметь:

  • открывать и закрывать позиции;
  • выбирать размер позиции;
  • принимать решение о необходимости новой оптимизации.

На рисунке ниже предложена принципиальная схема такого эксперта.


Детальная схема со связями во вложении в архиве MQL5Article.zip файл MQLArticle.pdf

Помня, что нельзя объять необъятное, сразу же узаботимся внесением ограничений в логику эксперта. Договоримся, что (ВАЖНО):

  1. Принимать торговые решения эксперт будет при наступлении нового бара (на любом, выбраном нами таймфрейме).
  2. Исходя из п.1, но не только, эксперт будет закрывать сделки только по сигналам индикаторов, не используя TakeProfit и StopLoss и, соответственно, не используя TralingStop.
  3. Условие для начала новой оптимизации: просадка по балансу более установленного на этапе инициализации уровня. Здесь важно понимать, что это лично моё условие и каждый из Вас волен написать своё условие.
  4. Фитнесс-функция моделирует торговлю на истории и максимизирует смоделированный баланс при условии того, что относительная просадка по балансу смоделированных торгов ниже какого-то задаваемого уровня. Здесь также важно понимать, что это лично моя фитнесс-функция и каждый из Вас волен написать свою.
  5. Ограничим количество оптимизируемых параметров кроме трёх общих (стратегия, инструмет, доля депо) пятью для параметров индикаторных буферов. Такое ограничение логически вытекает из максимального количества индикаторных буферов для встроенных технических индикаторов. Если Вы собираетесь описывать стратегии, использующие пользовательские индикаторы с большим количеством индикаторных буферов, просто измените переменную OptParamCount в файле main.mq5 на нужное количество.

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

Начнём с функции, где всё крутится.

void OnTick()
{
  if(isNewBars()==true)
  {
    trig=false;
    switch(strat)
    {
      case  0: {trig=NeedCloseMA()   ; break;};                      //Количество строк case должно быть равным количеству стратегий
      case  1: {trig=NeedCloseSAR()  ; break;};
      case  2: {trig=NeedCloseStoch(); break;};
      default: {trig=NeedCloseMA()   ; break;};
    }
    if(trig==true)
    {
      if(GetRelDD()>maxDD)                                           //Если просадка баланса превысила допустимую:
      {
        GA();                                                        //Вызываем функцию генетической оптимизации
        GetTrainResults();                                           //Получаем оптимизированные параметры
        maxBalance=AccountInfoDouble(ACCOUNT_BALANCE);               //Отсчет просадки будем теперь вести не от максимума баланса,...
                                                                     //...а от текущего баланса
      }
    }
    switch(strat)
    {
      case  0: {trig=NeedOpenMA()   ; break;};                       //Количество строк case должно быть равным количеству стратегий
      case  1: {trig=NeedOpenSAR()  ; break;};
      case  2: {trig=NeedOpenStoch(); break;};
      default: {trig=NeedOpenMA()   ; break;};
    }
    Print(TimeToString(TimeCurrent()),";","Main:OnTick:isNewBars(true)",
          ";","strat=",strat);
  }
}

Что здесь? Как и нарисовано на схеме, смотрим на каждом тике, не случился ли новый бар? Если случился, то, зная, какая сейчас выбрана стратегия, вызываем характерную именно для этой стратегии функцию проверки наличия открытой позиции и, при необходимости, её закрытие. Допустим, сейчас наилучшая стратегия на пробой SAR, соответственно, вызовется и функция NeedCloseSAR:

bool NeedCloseSAR()
{
  CopyBuffer(SAR,0,0,count,SARBuffer);
  CopyOpen(s,tf,0,count,o);
  Print(TimeToString(TimeCurrent()),";","StrategySAR:NeedCloseSAR",
        ";","SAR[0]=",SARBuffer[0],";","SAR[1]=",SARBuffer[1],";","Open[0]=",o[0],";","Open[1]=",o[1]);
  if((SARBuffer[0]>o[0]&&SARBuffer[1]<o[1])||
     (SARBuffer[0]<o[0]&&SARBuffer[1]>o[1]))
  {
    if(PositionsTotal()>0)
    {
      ClosePosition();
      return(true);
    }
  }
  return(false);
}

Любая функция закрытия позиции должна быть булевой и при закрытии позиции возвращать true. Это позволит следующему блоку кода функции OnTick() принять решение о необходимости начала новой оптимизации:

    if(trig==true)
    {
      if(GetRelDD()>maxDD)                                           //Если просадка баланса превысила допустимую:
      {
        GA();                                                        //Вызываем функцию генетической оптимизации
        GetTrainResults();                                           //Получаем оптимизированные параметры
        maxBalance=AccountInfoDouble(ACCOUNT_BALANCE);               //Отсчет просадки будем теперь вести не от максимума баланса,...
                                                                     //...а от текущего баланса
      }
    }

Получаем текущую просадку по балансу, сравниваем с максимально возможной, если превысила - новая оптимизация (GA()). Функция GA() в свою очередь вызовет сердце всего эксперта - фитнесс-функцию FitnessFunction(int chromos) модуля GAModule.mqh:

void FitnessFunction(int chromos)                                    //Фитнесс-функция для генетического оптимизатора:...
                                                                     //...выбирает стратегию, инструмент, долю депо,...
                                                                     //...параметры индикаторных буфферов;...
                                                                     //...можно оптимизировать что-угодно, но...
                                                                     //...необходимо внимательно следить за количествами генов
{
  double ff=0.0;                                                     //Непосредственно фитнесс-функция
  strat=(int)MathRound(Colony[GeneCount-2][chromos]*StratCount);     //ГА выбирает стратегию
//Для режима прогона советника в тестере используем следующий код...
  z=(int)MathRound(Colony[GeneCount-1][chromos]*3);                  //ГА выбирает инструмент
  switch(z)
  {
    case  0: {s="EURUSD"; break;};
    case  1: {s="GBPUSD"; break;};
    case  2: {s="USDCHF"; break;};
    case  3: {s="USDJPY"; break;};
    default: {s="EURUSD"; break;};
  }
//..а для реального режима предыдущий код комментим, а нижеследующий раскомментим (выбор инструментов происходит в окне MarketWatch)
/*
  z=(int)MathRound(Colony[GeneCount-1][chromos]*(SymbolsTotal(true)-1));//ГА выбирает инструмент
  s=SymbolName(z,true);
*/
  optF=Colony[GeneCount][chromos];                                   //ГА выбирает долю депо
  switch(strat)
  {
    case  0: {ff=FFMA(   Colony[1][chromos],                         //Количество строк case должно быть равным количеству стратегий
                         Colony[2][chromos],
                         Colony[3][chromos],
                         Colony[4][chromos],
                         Colony[5][chromos]); break;};
    case  1: {ff=FFSAR(  Colony[1][chromos],
                         Colony[2][chromos],
                         Colony[3][chromos],
                         Colony[4][chromos],
                         Colony[5][chromos]); break;};
    case  2: {ff=FFStoch(Colony[1][chromos],
                         Colony[2][chromos],
                         Colony[3][chromos],
                         Colony[4][chromos],
                         Colony[5][chromos]); break;};
    default: {ff=FFMA(   Colony[1][chromos],
                         Colony[2][chromos],
                         Colony[3][chromos],
                         Colony[4][chromos],
                         Colony[5][chromos]); break;};
  }
  AmountStartsFF++;
  Colony[0][chromos]=ff;
  Print(TimeToString(TimeCurrent()),";","GAModule:FitnessFunction",
        ";","strat=",strat,";","s=",s,";","optF=",optF,
        ";",Colony[1][chromos],";",Colony[2][chromos],";",Colony[3][chromos],";",Colony[4][chromos],";",Colony[5][chromos]);
}

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

double FFStoch(double par1,double par2,double par3,double par4,double par5)
{
  int    b;
  bool   FFtrig=false;                                               //Есть открытая позиция?
  string dir="";                                                     //Направление открытой позиции
  double OpenPrice;                                                  //Цена открытия позиции
  double t=cap;                                                      //Текущий баланс
  double maxt=t;                                                     //Максимальный баланс
  double aDD=0.0;                                                    //Абсолютная просадка
  double rDD=0.000001;                                               //Относительная просадка
  Stoch=iStochastic(s,tf,(int)MathRound(par1*MaxStochPeriod)+1,
                         (int)MathRound(par2*MaxStochPeriod)+1,
                         (int)MathRound(par3*MaxStochPeriod)+1,MODE_SMA,STO_CLOSECLOSE);
  StochTopLimit   =par4*100.0;
  StochBottomLimit=par5*100.0;
  dig=MathPow(10.0,(double)SymbolInfoInteger(s,SYMBOL_DIGITS));
  leverage=AccountInfoInteger(ACCOUNT_LEVERAGE);
  contractSize=SymbolInfoDouble(s,SYMBOL_TRADE_CONTRACT_SIZE);
  b=MathMin(Bars(s,tf)-1-count-MaxMAPeriod,depth);
  for(from=b;from>=1;from--)                                         //Откуда начинаем копировать историю
  {
    CopyBuffer(Stoch,0,from,count,StochBufferMain);
    CopyBuffer(Stoch,1,from,count,StochBufferSignal);
    if((StochBufferMain[0]>StochBufferSignal[0]&&StochBufferMain[1]<StochBufferSignal[1])||
       (StochBufferMain[0]<StochBufferSignal[0]&&StochBufferMain[1]>StochBufferSignal[1]))
    {
      if(FFtrig==true)
      {
        if(dir=="BUY")
        {
          CopyOpen(s,tf,from,count,o);
          if(t>0) t=t+t*optF*leverage*(o[1]-OpenPrice)*dig/contractSize; else t=0;
          if(t>maxt) {maxt=t; aDD=0;} else if((maxt-t)>aDD) aDD=maxt-t;
          if((maxt>0)&&(aDD/maxt>rDD)) rDD=aDD/maxt;
        }
        if(dir=="SELL")
        {
          CopyOpen(s,tf,from,count,o);
          if(t>0) t=t+t*optF*leverage*(OpenPrice-o[1])*dig/contractSize; else t=0;
          if(t>maxt) {maxt=t; aDD=0;} else if((maxt-t)>aDD) aDD=maxt-t;
          if((maxt>0)&&(aDD/maxt>rDD)) rDD=aDD/maxt;
        }
        FFtrig=false;
      }
   }
    if(StochBufferMain[0]>StochBufferSignal[0]&&StochBufferMain[1]<StochBufferSignal[1]&&StochBufferMain[1]>StochTopLimit)
    {
      CopyOpen(s,tf,from,count,o);
      OpenPrice=o[1];
      dir="SELL";
      FFtrig=true;
    }
    if(StochBufferMain[0]<StochBufferSignal[0]&&StochBufferMain[1]>StochBufferSignal[1]&&StochBufferMain[1]<StochBottomLimit)
    {
      CopyOpen(s,tf,from,count,o);
      OpenPrice=o[1];
      dir="BUY";
      FFtrig=true;
    }
  }
  Print(TimeToString(TimeCurrent()),";","StrategyStoch:FFStoch",
        ";","K=",(int)MathRound(par1*MaxStochPeriod)+1,";","D=",(int)MathRound(par2*MaxStochPeriod)+1,
        ";","Slow=",(int)MathRound(par3*MaxStochPeriod)+1,";","TopLimit=",StochTopLimit,";","BottomLimit=",StochBottomLimit,
        ";","rDD=",rDD,";","Cap=",t);
  if(rDD<=trainDD) return(t); else return(0.0);
}

Фитнесс-функция стохастика вернёт значение смоделированного баланса основной функции, та передаст их Генетическому алгоритму. В какой то момент времени ГА примет решение об окончании оптимизации и функцией GetTrainResults() мы вернем основной программе оптимальные в текущий момент значения стратегии (допустим - скользящие средние), инструмента, доли депо и параметров индикаторых буферов, а также создадим для дальнейшей работы в реале индикаторы:

void GetTrainResults()                                               //Получаем лучшие параметры
{
  strat=(int)MathRound(Chromosome[GeneCount-2]*StratCount);          //Запоминаем лучшую стратегию
//Для режима прогона советника в тестере используем следующий код...
  z=(int)MathRound(Chromosome[GeneCount-1]*3);                       //Запоминаем лучший инструмент
  switch(z)
  {
    case  0: {s="EURUSD"; break;};
    case  1: {s="GBPUSD"; break;};
    case  2: {s="USDCHF"; break;};
    case  3: {s="USDJPY"; break;};
    default: {s="EURUSD"; break;};
  }
//..а для реального режима предыдущий код комментим, а нижеследующий раскомментим (выбор инструментов происходит в окне MarketWatch)
/*
  z=(int)MathRound(Chromosome[GeneCount-1]*(SymbolsTotal(true)-1));  //Запоминаем лучший инструмент
  s=SymbolName(z,true);
*/
  optF=Chromosome[GeneCount];                                        //Запоминаем лучшую долю депо
  switch(strat)
  {
    case  0: {GTRMA(   Chromosome[1],                                //Количество строк case должно быть равным количеству стратегий
                       Chromosome[2],
                       Chromosome[3],
                       Chromosome[4],
                       Chromosome[5]) ; break;};
    case  1: {GTRSAR(  Chromosome[1],
                       Chromosome[2],
                       Chromosome[3],
                       Chromosome[4],
                       Chromosome[5]) ; break;};
    case  2: {GTRStoch(Chromosome[1],
                       Chromosome[2],
                       Chromosome[3],
                       Chromosome[4],
                       Chromosome[5]) ; break;};
    default: {GTRMA(   Chromosome[1],
                       Chromosome[2],
                       Chromosome[3],
                       Chromosome[4],
                       Chromosome[5]) ; break;};
  }
  Print(TimeToString(TimeCurrent()),";","GAModule:GetTrainResults",
        ";","strat=",strat,";","s=",s,";","optF=",optF,
        ";",Chromosome[1],";",Chromosome[2],";",Chromosome[3],";",Chromosome[4],";",Chromosome[5]);
}

void GTRMA(double par1,double par2,double par3,double par4,double par5)
{
  MAshort=iMA(s,tf,(int)MathRound(par1*MaxMAPeriod)+1,0,MODE_SMA,PRICE_OPEN);
  MAlong =iMA(s,tf,(int)MathRound(par2*MaxMAPeriod)+1,0,MODE_SMA,PRICE_OPEN);
  CopyBuffer(MAshort,0,from,count,ShortBuffer);
  CopyBuffer(MAlong, 0,from,count,LongBuffer );
  Print(TimeToString(TimeCurrent()),";","StrategyMA:GTRMA",
        ";","MAL=",(int)MathRound(par2*MaxMAPeriod)+1,";","MAS=",(int)MathRound(par1*MaxMAPeriod)+1);
}

Теперь всё возвращается в то место, где всё крутится (OnTick()): зная, какая стратегия сейчас наилучшая, проверяется, не пора ли в рынок:

bool NeedOpenMA()
{
  CopyBuffer(MAshort,0,0,count,ShortBuffer);
  CopyBuffer(MAlong, 0,0,count,LongBuffer );
  Print(TimeToString(TimeCurrent()),";","StrategyMA:NeedOpenMA",
        ";","LB[0]=",LongBuffer[0],";","LB[1]=",LongBuffer[1],";","SB[0]=",ShortBuffer[0],";","SB[1]=",ShortBuffer[1]);
  if(LongBuffer[0]>LongBuffer[1]&&ShortBuffer[0]>LongBuffer[0]&&ShortBuffer[1]<LongBuffer[1])
  {
    request.type=ORDER_TYPE_SELL;
    OpenPosition();
    return(false);
  }
  if(LongBuffer[0]<LongBuffer[1]&&ShortBuffer[0]<LongBuffer[0]&&ShortBuffer[1]>LongBuffer[1])
  {
    request.type=ORDER_TYPE_BUY;
    OpenPosition();
    return(false);
  }
  return(true);
}

Круг замкнулся.

Проверим, как работает? Вот отчет за 2011 год на часовках по четырём мажорам: EURUSD, GBPUSD, USDCHF, USDJPY:

Отчет Тестера стратегий
InstaForex-Server (Build 567)
Настройки
Советник: Main
Символ: EURUSD
Период: H1 (2011.01.01 - 2011.12.31)
Входные параметры: trainDD=0.50000000
maxDD=0.20000000
Брокер: InstaForex Companies Group
Валюта: USD
Начальный депозит: 10 000.00
Плечо: 1:100
Результаты
Качество истории: 100%
Бары: 6197 Тики: 1321631
Чистая прибыль: -538.74 Общая прибыль: 3 535.51 Общий убыток: -4 074.25
Прибыльность: 0.87 Матожидание выигрыша: -89.79 Уровень маржи: 85.71%
Фактор восстановления: -0.08 Коэффициент Шарпа: 0.07 Результат OnTester: 0
Просадка баланса:
Абсолютная просадка по балансу: 4 074.25 Максимальная просадка по балансу: 4 074.25 (40.74%) Относительная просадка по балансу: 40.74% (4 074.25)
Просадка средств:
Абсолютная просадка по средствам: 4 889.56 Максимальная просадка по средствам: 6 690.90 (50.53%) Относительная просадка по средствам: 50.53% (6 690.90)
Всего трейдов: 6 Короткие трейды (% выигравших): 6 (16.67%) Длинные трейды (% выигравших): 0 (0.00%)
Всего сделок: 12 Прибыльные трейды (% от всех): 1 (16.67%) Убыточные трейды (% от всех): 5 (83.33%)
Самый большой прибыльный трейд: 3 535.51 Самый большой убыточный трейд: -1 325.40
Средний прибыльный трейд: 3 535.51 Средний убыточный трейд: -814.85
Максимальное количество непрерывных выигрышей (прибыль): 1 (3 535.51) Максимальное количество непрерывных проигрышей (убыток): 5 (-4 074.25)
Максимальная непрерывная прибыль (число выигрышей): 3 535.51 (1) Максимальная непрерывный убыток (число проигрышей): -4 074.25 (5)
Средний непрерывный выигрыш: 1 Средний непрерывный проигрыш: 5


 

Ордера
Время открытия Ордер Символ Тип Объем Цена S / L T / P Время Состояние Комментарий
2011.01.03 01:002USDCHFsell28.21 / 28.210.93212011.01.03 01:00filled
2011.01.03 03:003USDCHFbuy28.21 / 28.210.93652011.01.03 03:00filled
2011.01.03 06:004USDCHFsell24.47 / 24.470.93522011.01.03 06:00filled
2011.01.03 09:005USDCHFbuy24.47 / 24.470.93722011.01.03 09:00filled
2011.01.03 13:006USDCHFsell22.99 / 22.990.93522011.01.03 13:00filled
2011.01.03 16:007USDCHFbuy22.99 / 22.990.93752011.01.03 16:00filled
2011.01.03 18:008USDJPYsell72.09 / 72.0981.572011.01.03 18:00filled
2011.01.03 21:009USDJPYbuy72.09 / 72.0981.662011.01.03 21:00filled
2011.01.04 01:0010USDJPYsell64.54 / 64.5481.672011.01.04 01:00filled
2011.01.04 02:0011USDJPYbuy64.54 / 64.5481.782011.01.04 02:00filled
2011.10.20 21:0012USDCHFsell56.30 / 56.300.89642011.10.20 21:00filled
2011.10.21 12:0013USDCHFbuy56.30 / 56.300.89082011.10.21 12:00filled
Сделки
Время Сделка Символ Тип Направление Объем Цена Ордер Комиссия Своп Прибыль Баланс Комментарий
2011.01.01 00:001balance0.000.0010 000.0010 000.00
2011.01.03 01:002USDCHFsellin28.210.932120.000.000.0010 000.00
2011.01.03 03:003USDCHFbuyout28.210.936530.000.00-1 325.408 674.60
2011.01.03 06:004USDCHFsellin24.470.935240.000.000.008 674.60
2011.01.03 09:005USDCHFbuyout24.470.937250.000.00-522.198 152.41
2011.01.03 13:006USDCHFsellin22.990.935260.000.000.008 152.41
2011.01.03 16:007USDCHFbuyout22.990.937570.000.00-564.027 588.39
2011.01.03 18:008USDJPYsellin72.0981.5780.000.000.007 588.39
2011.01.03 21:009USDJPYbuyout72.0981.6690.000.00-794.536 793.86
2011.01.04 01:0010USDJPYsellin64.5481.67100.000.000.006 793.86
2011.01.04 02:0011USDJPYbuyout64.5481.78110.000.00-868.115 925.75
2011.10.20 21:0012USDCHFsellin56.300.8964120.000.000.005 925.75
2011.10.21 12:0013USDCHFbuyout56.300.8908130.00-3.783 539.299 461.26
0.00 -3.78 -534.96 9 461.26
Copyright 2001-2011, MetaQuotes Software Corp.

Поясню зоны, выделенные на графике (пояснялки взяты из анализа логов):

  1. После старта советника Генетический алгоритм выбрал стратегию Пробой SAR на валютной паре USDCHF с долей депо в торговле 28%, поторговал до вечера третьего января, слил более 20% баланса и начал повторную оптимизацию.
  2. Теперь советник решил торговать Пробой SAR по USDJPY, но уже на весь депо (98%). Понятное дело, на долго его не хватило и уже четвертого утром он начал уже третью оптимизацию.
  3. Теперь его решение - торговать золотой и мёртвый крест по скользящим средним на USDCHF опять же на весь депо. И ждал он первый мёртвый крест аж до 20-го октября, и продал по максимуму, и отыграл все убытки. После этого до конца года условий на вход советник более не видел...

Продолжение следует?

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

Предупреждение о рисках:

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

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

Лицензии:

Модуль UGAlib.mqh написан и распространяется на условиях лицензии BSD Андреем Дик aka joo.

Эксперт, вспомогательные модули, прилагаемые к этой статье, написаны и распространяются на условиях BSD автором Roman Rich. Текст лицензии в файле Lic.txt.

Прикрепленные файлы |
main.mq5 (4.94 KB)
gamodule.mqh (7.31 KB)
ugalib.mqh (32.55 KB)
strategyma.mqh (5.13 KB)
strategystoch.mqh (6.03 KB)
strategysar.mqh (4.09 KB)
lic.txt (3.06 KB)
mql5article.zip (45.3 KB)
musthave.mqh (7.74 KB)
Anatoli Kazharski
Anatoli Kazharski | 29 янв 2012 в 16:40
ivandurak:
Понятно , что в статье рассказано не все . Вопрос простой стоит копать в этом направлении, есть там устойчивая на форварде ТС,  или нет только мираж.
В статьях, как правило, показывают схему. ТС должен каждый разработать сам и попробовать через описанный метод усовершенствовать её. Кто же готовую систему выложит? Так не честно будет по отношению к себе. :)
Roman Zamozhnyy
Roman Zamozhnyy | 29 янв 2012 в 20:21
ivandurak:
Понятно , что в статье рассказано не все . Вопрос простой стоит копать в этом направлении, есть там устойчивая на форварде ТС,  или нет только мираж.
Попробуйте к ГА прикрутить различные НС, для образца возмите НС из предыдущей статьи.
Alexey
Alexey | 30 янв 2012 в 11:13
tol64:
В статьях, как правило, показывают схему. ТС должен каждый разработать сам и попробовать через описанный метод усовершенствовать её. Кто же готовую систему выложит? Так не честно будет по отношению к себе. :)
Никто не просит готовую систему. Спрашиваю, авторам удалось создать на этой технологии устойчивый советник да или нет. Этого достаточно для продолжения собственных исследований, в целях экономии времени  или есть смысл копать в другом направлении. 
Anatoli Kazharski
Anatoli Kazharski | 30 янв 2012 в 17:17
ivandurak:
Никто не просит готовую систему. Спрашиваю, авторам удалось создать на этой технологии устойчивый советник да или нет. Этого достаточно для продолжения собственных исследований, в целях экономии времени  или есть смысл копать в другом направлении. 
Тоже было бы интересно мнение любого, кто этим занимается. Для себя я сделал выводы исходя из проведённых многочисленных тестов (около 10000) вручную. При чём для сокращения времени я просто не дожидался окончания теста, ограничив 1 тест 5-тью минутами, а стратегия для теста была довольно простая и несмотря на это получился положительный результат. Так что, думаю, попробовать стоит эту схему.
Иван Корнилов
Иван Корнилов | 21 мар 2012 в 14:58
Идея интересная, но есть проблемы - генетические алгоритмы плохо подходят для оптимизации торговых системе, вы множите упустить много удачных параметров. Ничего не мешает вам сделать полный прогон в том случае, если вы торгуете только на открытии бара. Не очень понравились торговые сигналы которые вы пытаетесь оптимизировать. Сейчас на мой взгляд есть куда более удачные сигнальные системы для оптимизации.
Преобразование Бокса-Кокса Преобразование Бокса-Кокса

Статья призвана познакомить читателя с преобразованием Бокса-Кокса (Box-Cox Transformation). В статье кратко затрагиваются вопросы, связанные с его использованием и приводятся примеры, позволяющие оценить эффективность данного преобразования по отношению к случайным последовательностям и реальным котировкам.

Создание советников при помощи Expert Advisor Visual Wizard Создание советников при помощи Expert Advisor Visual Wizard

Программа Expert Advisor Visual Wizard предоставляет интуитивно понятную графическую среду с полным набором готовых торговых блоков, которые позволят вам за несколько минут создавать советники. Знания программирования и языка MQL5 не требуется. Подход "click, drag and drop" позволяет вам создавать визуальные представления торговых стратегий и сигналов. Эти торговые диаграммы автоматически анализируются генератором MQL5-кода, который преобразует их в готовые к работе советники. Интерактивная графическая среда упрощает процесс проектирования и избавляет от необходимости написания кода на MQL5.

Интервью с Александром Арашкевичем (ATC 2011) Интервью с Александром Арашкевичем (ATC 2011)

Наконец улеглись страсти, мы можем перевести дух и начинать переосмысливать еще раз его результаты. И у нас есть еще один победитель Александр Арашкевич (AAA777) из Белоруссии, который получил специальный приз от Главного спонсора Automated Trading Championship 2011 - бесплатную поездку на соревнование Формулы-1 в 2012 году. Мы не могли упустить такой возможности пообщаться с ним.

Избавляемся от балласта самодельных DLL Избавляемся от балласта самодельных DLL

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