Как не попасть в ловушки оптимизации?

Shashev Sergei | 1 ноября, 2006


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

Но в реальности создание надежной системы – путь проб и ошибок, на котором

какие-либо формы оптимизации неизбежны. Оптимизация присутствует всегда –

если не на поверхности, то в глубине процесса.

Дж. О. Кац, Д.Л. МакКормик. Энциклопедия торговых стратегий.


Что такое оптимизация торговой системы?


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

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

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

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

  • Возникновение идеи о том, на чем будет основана торговая система.
  • Выбор типа критериев или решающих правил.
  • Определение параметров системы.
  • Тестирование системы.
  • Возвращение к предыдущим пунктам при необходимости внесения изменений в систему.

Проблемы оптимизации второго рода


При разработке МТС все разработчики торговых систем используют оптимизацию, как первого, так и второго рода. Поиск критериев и решающих правил – работа для эвристических систем, вроде нейронных сетей, генетических алгоритмов и, конечно же, мозга человека - самой мощной из существующих на сегодняшний день систем. Это является оптимизацией первого рода, и поэтому вся ответственность за эту оптимизацию ложится на плечи трейдера.
Оптимизация второго рода – это поиск лучших параметров. Именно здесь возникают проблемы, поскольку очень легко можно подогнать данные под историю и получить "огромные прибыли". К сожалению, только на истории. Такой переоптимизации сложно избежать, и поэтому у некоторых трейдеров вырабатывается негативное отношение к ней. Из-за чего же?

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

Как решить проблему переоптимизации


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

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

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

К сожалению, в MetaTrader пока не встроен алгоритм, который будет сам искать области оптимальных решений. Одним из мощнейших алгоритмов, решающих задачи подобного типа, является KRAB. Его описание можно встретить в книге Загоруйко – «Прикладные методы анализа данных и знаний». Было бы неплохо, если бы он был реализован в следующих билдах.… Но не все так плохо!

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


Для трех параметров такую процедуру нам придется сделать
раза. Но уже для пяти параметров

и так далее. Так что, лучше количеством параметров не злоупотреблять.

При оптимизации двух параметров мы получаем график оптимизации, подобный этому:



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

Представленный ниже график не так однозначен, поскольку в нем мы видим две области с максимумами. Что выбрать?



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

Теперь попробуем исследовать какого-нибудь простенького эксперта – проанализируем оптимизацию трех параметров и найдем область оптимальных решений. Эксперт называется SP. Работает в зонах перекупленности и перепроданности с анализом моментума.

//+------------------------------------------------------------------+
//|                                                           SP.mq4 |
//|                      Copyright © 2006, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net"
 
//---- input parameters
extern int       TakeProfit=50;
extern int       StopLoss=30;
extern int       RsiLen=4;
extern int       KLen=8;
extern int       Momlength=10;
extern int       Lots=1;
extern int       rsi_oversold=39;
extern int       stoc_oversold=29;
extern int       rsi_overbought=60;
extern int       stoc_overbought=70;
extern int       Mom_Sell=-2;
extern int       Mom_Buy=2;
 
int expertBars;
double RSIlevel;
double Stoclevel;
double MomLevel;
double DLen=3;
 
//+------------------------------------------------------------------+
//| возвращает true если появлися новый бар, иначе false             |
//+------------------------------------------------------------------+
bool isNewBar()
  {
//----
   bool res=false; 
   if (expertBars!=Bars) 
      {
      expertBars=Bars;
      res=true;
      } 
//----
   return(res);
  }
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
  double price;
  double stop;
  double profit;
//----
   if ((isNewBar())&& (OrdersTotal()==0)&& (AccountBalance()>5000))
   {
      RSIlevel=iRSI(NULL,0,RsiLen,PRICE_CLOSE,0);
      Stoclevel=iStochastic(NULL,0,KLen,DLen,3,MODE_SMA,0,MODE_MAIN,0);
      MomLevel=100 - iMomentum(NULL,0,Momlength,PRICE_CLOSE,0);
      /*if (AccountBalance()>50000)
         {Lots=NormalizeDouble( AccountBalance()/10000,0)-4;}
      else 
         Lots=1;*/
      if ((RSIlevelrsi_oversold)&&(Stoclevelstoc_oversold)&&(MomLevel>Mom_Sell))
      {
         price=Ask;
         stop=NormalizeDouble(price-StopLoss*Point,Digits);
         profit=NormalizeDouble(price+TakeProfit*Point,Digits);
         OrderSend(Symbol(),OP_BUY,Lots,price,3,stop,profit,NULL,0,0,Green); 
         //Print(AccountBalance());          
      }
      if ((RSIlevel>rsi_overbought)&&(Stoclevel>stoc_overbought)&&(MomLevelMom_Buy))
      {
         price=Bid;
         stop=NormalizeDouble(price+StopLoss*Point,Digits);
         profit=NormalizeDouble(price-TakeProfit*Point,Digits);
         OrderSend(Symbol(),OP_SELL,Lots,price,3,stop,profit,NULL,0,0,Green); 
         //Print(AccountBalance());            
      }      
   } 
    
//----
   return(0);
  }
//+------------------------------------------------------------------+


Оптимизируем три параметра – периоды Stochastic и RSI, а также уровень StopLoss.

После оптимизации получаем три графика:



Зависимость прибыли от периодов Stochastic и RSI.


Зависимость прибыли от RSI м StopLoss.



Зависимость прибыли от Stochastic и StopLoss

Лучшие области:

  • 1 график – (4;5)&(3;6);
  • 2 график - (80;90)&(3;6);
  • 3 график - (80;90)&(4;5).

Их объединение дает нам решение – (5,4,80).


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

Заключение


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

В заключение несколько советов по оптимизации:

  • Выборка данных, на которых проводилась оптимизация, должна быть представительной. Для Daily – не меньше 3 лет.
  • Тестируйте стратегию вне оптимизируемой выборки – это позволит вам оценить выбранные параметры.
  • Не оптимизируйте одновременно очень много параметров – слишком велика вероятность подгонки под исторические данные.
  • Чтобы уменьшить время оптимизации, увеличьте шаг. Лучшая область не будет пропущена. Потом можно будет более подробно исследовать полученный кластер (метод сита).
  • Не сидите за оптимизацией часами – лучше модернизируйте алгоритм работы советника.
Надеюсь, что эта статья поможет Вам избежать «вредной оптимизации».