Как правильно тестировать советников.

Опубликовано: 01.01.2007

Множество споров ведется о том, как правильно тестировать советников. Возможно, множество хороших советников загублено по причине ошибок при тестировании. Многие, увидев в отчете тестера строку - Качество моделирования n/a, даже не будут смотреть остальные результаты тестирования. Такое отношение является лишь результатом незнания того, как происходит тестирование в MetaTrader 4. Многие, написав на MQL4 советника, не задумываясь, запускают его на тестирование и, получив отрицательные результаты, грешат на тестер или пытаются исправить код MQL4-программы. Но это не самое страшное, самое страшное – это, по ошибке, получить положительные результаты и выставить эксперта на реал. В этом случае результаты торговли могут быть крайне плачевными.
Данной статьей я хочу подтолкнуть трейдеров к тому, чтобы они задумались над тем, что они тестируют, и как они это делают. Тестер – это лишь инструмент, а инструмент в неумелых руках...

Для того чтобы правильно тестировать советников в MetaTrader 4 необходимо разобраться в том, как он проводит тестирование. Важность понимания этого проиллюстрирую следующим примером:
Протестируем на дневках EUR/USD D1 простую систему, которая открывает длинную позицию в начале каждого дня. Выход из позиции происходит по стоплосс или тейкпрофит равные 20 пунктов каждый. Вот код этого эксперта на MQL4:

#property copyright "Smirnov Pavel"
#property link      "www.autoforex.ru"

int StopLoss=20; // уровень стоплосса в пунктах
int TakeProfit=20; // уровень тейкпрофита в пунктах
datetime day=0; // переменная-флаг используется для определения наступления нового 
дня
int ticket=0; // этой переменной присваивается номер открытого ордера (не 
используется)

int start()
{
  if(OrdersTotal()<1) // проверяем, что ни 
одной позиции еще не открыто
    if(TimeDay(TimeCurrent())!=day) // если текущий день 
не совпадает с переменной day,
                                    // то значит наступил новый день.
    {
      day=TimeDay(TimeCurrent()); // переменной day присваиваем значение текущего дня.

      ticket=OrderSend(Symbol(),OP_BUY,0.1,Ask,10,Ask-StopLoss*Point, // 
открываем длинную позицию
                       Ask+TakeProfit*Point,"test",12345,0,Red);
    }
  return(0);
}

// функции init() и deinit() в нашем примере не используются,
// но они, все-равно должны присутствовать в эксперте.
int init()
{
  return(0);
}

int deinit()
{
  return(0);
}

Давайте посмотрим результаты тестирования этого эксперта на EUR/USD D1 за промежуток времени с 28 по 29 октября 2005 года, т.е. в течение одного дня. При тестировании используется модель по ценам открытия:

ВремяТипОрдерЛотыЦенаS / LT / PПрибыль Баланс
12005.10.28 00:00buy10.101.21411.21211.2161
22005.10.28 23:59s/l10.101.21211.21211.2161-20.009999980.00

За этот промежуток времени была совершена одна сделка. На рисунке слева отмечен бар, на котором происходит вход в рынок. Этот бар имеет следующие характеристики (Bid):

Open=1.2139
High=1.2173
Low=1.2048
Close=1.2066

EUR/USD D1 график. www.autoforex.ru - Механические Торговые Системы на рынке Форекс

А вот результаты тестирования того же эксперта, на том же промежутке, при тех же условиях, но при использовании модели все тики (в исторических данных присутствовали минутные котировки за период тестирования):

ВремяТипОрдерЛотыЦенаS / LT / PПрибыль Баланс
12005.10.28 00:00buy10.101.21411.21211.2161
22005.10.28 08:37t/p10.101.21611.21211.216120.0010000020.00

Т.е. получили прямо противоположный результат!
Какой же результат правильный? Давайте разберемся, почему различные модели тестирования дают различные результаты.

Для начала открываем руководство пользователя MetaTrader 4 (Справка -> Вызов справки), затем выбираем закладку Содержание, там Автотрейдинг -> Тестирование стратегий -> Настройка и читаем все, что касается тестирования советников и методов моделирования.

Теперь давайте посмотрим, как происходит тестирование советника по ценам открытия на дневном таймфрейме EUR/USD D1. Перед тестированием происходит генерация fxt-файла, который будет состоять из дневных котировок. Именно этот файл и будет использован тестером как источник котировок при тестировании. Более подробно об этих файлах можно почитать в справке по MetaTrader 4.

Во время тестирования первым делом моделируется открытие бара (28.10.2005 на дневках) у которого Open=High=Low=Close=1.2139 (бар 0 на рисунке). Этот смоделированный бар становится текущим, нулевым баром в тестере. В этот момент запускается функция start() эксперта. Заметьте, что бар, который на самом деле есть в исторических данных, еще не сформирован.

EUR/USD D1 график. www.autoforex.ru - Механические Торговые Системы на рынке Форекс

Если теперь, внутри функции start() нашего эксперта, запросить значение цены High, Low или Close для текущего бара с помощью предопределенных переменных High[0], Low[0] и Close[0], то все они дадут не верное значение равное 1.2139, потому что бар еще не сформирован, а лишь смоделирован. Единственное значение цены, которое будет соответствовать действительности это значение цены открытия - Open[0]=1.2139. Значения других переменных также будут привязаны к цене открытия, например текущая цена Bid в тестере будет равна 1.2139, Ask = 1.2139 + SPREAD и т.д. Потому и называется данный метод моделирования - по ценам открытия.

Итак, функция start() нашего эксперта запущена, при этом выполняются все условия для совершения сделки, и позиция открывается, при этом выставляются значения StopLoss = 1.2121 и TakeProfit = 1.2161 (20 пунктов каждый).
Затем, когда выполнение функции start() закончено, тестер достраивает текущий бар до его полного размера. И теперь, когда у тестера есть полностью сформированный бар, он может проверить были ли достигнуты StopLoss или TakeProfit на этом баре, чтобы, в этом случае, закрыть сделку.

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

Далее в тестере происходит моделирование следующего бара (29.10.2005 на дневках), который автоматически становится текущим (нулевым) баром. Бывший нулевой бар становится первым баром, первый становится вторым и т.д. Эта ситуация показана на рисунке справа. Когда новый бар смоделирован, он имеет значения Open=High=Low=Close=1.2063, и тестер снова может запускать на выполнение функцию start() нашего эксперта. Но этого, в нашем случае, не происходит, потому что мы выбрали диапазон тестирования с 28 по 29 октября 2005, поэтому MetaTrader 4 остановится и закончит тестирование нашего эксперта.

EUR/USD D1 график. www.autoforex.ru - Механические Торговые Системы на рынке Форекс

Давайте разберемся с моделью тестирования все тики.
Из справки МетаТрейдера:

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

Таким образом, модель все тики позволяет нам приблизить тестирование эксперта к реальной торговле.

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

Давайте посмотрим на то, как вела себя цена 28.10.2005, именно на этом баре проходило тестирование нашего советника. Используем для этого часовой график EUR/USD H1. Справа, на рисунке, видно как менялась цена в течение дня. При этом прекрасно видно, что сначала был достигнут TakeProfit на баре, отмеченном стрелкой, а уже затем достигнут StopLoss, так же отмечен стрелкой.
Таким образом, при тестировании нашего эксперта, тестер смог, используя информацию меньших таймфреймов, определить, что в 8.37 был, достигнут уровень выставленного тейкпрофита и закрыл сделку с прибылью.

EUR/USD D1 график. www.autoforex.ru - Механические Торговые Системы на рынке Форекс

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

Каждая представленная в тестере модель предназначена для своих целей.
Начнем с того, что самый быстрый метод тестирования – по ценам открытия. Именно этот метод я использую для оптимизации советников. Единственное, надо понимать, что при этом возможны случаи, когда при тестировании советника вместо тейкпрофита срабатывает стоплосс. Это ухудшает показатели тестируемой системы, но лучше уж показатели будут занижены, а в реальной торговле покажут лучший результат, чем наоборот. При этом такая ситуация, на самом деле, не так часто случается. Например, если TakeProfit=200, а StopLoss=100, то необходимо, чтобы размер свечи High – Low равнялся 300 пунктов. Такие свечи встречаются, разве что на дневках. Поэтому, тестируя советника с такими значениями TakeProfit и StopLoss на часовых данных H1, проблем не возникнет. Посмотрите, например, на эксперта "20/200 pips", который тестировался по ценам открытия именно из этих соображений. Результаты же тестирования этого эксперта, используя модель все тики, лишь немногим отличаются от тестов по ценам открытия.

Модель все тики самая медленная. Эта модель требует наличие минутных котировок за период тестирования, иначе теряются все преимущества данной модели. Чем меньше минутных котировок в истории, тем больше будет "синтетических", смоделированных тиков в тестере и тем хуже будет качество моделирования и достоверность результатов. Поэтому перед тем, как тестировать советника, используя модель все тики, позаботьтесь о наличии минутных котировок за период тестирования. Лично я использую данную модель тестирования крайне редко, только когда эксперт уже оптимизирован и требуется более детальное исследование его свойств.

Есть, в MetaTrader 4 еще одна модель тестирования – контрольные точки. Это более грубый метод, нежели метод все тики, который использует данные ближайшего меньшего таймфрейма, для того, чтобы смоделировать изменение цены внутри бара. Например, если тестировать советника на дневном периоде D1, нам необходимо наличие котировок Н4 (четырехчасовок). Если тестируем на периоде Н4, нам необходимо наличие котировок H1 и т.д. Этот метод тестирования значительно быстрее, чем метод все тики, и дает более достоверные результаты, чем метод по ценам открытия. Лично я никогда не пользуюсь этим методом, по простой причине – я почти всегда, на стадии разработки, использую метод по ценам открытия, а затем, когда советник написан и готов к работе тестирую его по всем тикам.

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

Избежать ошибок при тестировании советников можно лишь одним способом – понять, как происходит тестирование в МетаТрейдере. Тестируйте и набирайтесь опыта.

Напоследок несколько простых советов:

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