Блог им. mirovan

Граальные ловушки при построении торговых систем

При проектировании торговых систем очень важно не только создать рабочую стратегию, приносящую прибыль, но и избежать ошибок в коде, потому что именно эти ошибки могут привести к так называемой «граальной» ловушке.
 
1 ловушка – подглядывание в будущее при входе в позицию
Впервые с такой ловушкой я столкнулся при разработке трендовой системы на основе индикаторов ADX+CCI. Найти эту ошибку мне помог Игорь Чечет, за что ему большое спасибо.
 
Кратко рассмотрим данную торговую систему.
 
Вход в лонг осуществляется при росте индикатора ADX, который показывает наличие тренда, и пересечении индикатором CCI значения +100, который показывает момент входа в позицию. В шорт соответственно наоборот.
Приведу часть кода, которая была изначально:
//Сравниваем значение ADX на текущем баре и предыдущем
if (ADX.Series(Bars,ADXperiod)[bar] > ADX.Series(Bars,ADXperiod)[bar — 1]) {
	if (CCI.Series(Bars,CCIperiod)[bar] > 100) { 	//Открытие позиции в Long
		BuyAtMarket(bar);
	}
	else if (CCI.Series(Bars,CCIperiod)[bar] < -100)		//Открытие позиции в Short
	{
		ShortAtMarket(bar);
	}
}


В результате выполнения данного кода получилась очень красивая кривая доходности:
Граальные ловушки при построении торговых систем
 
Ошибка здесь заключается в следующем. Вход в позицию осуществляется по рыночной цене на свече bar — BuyAtMarket(bar). Но если посмотреть правило, по которому осуществляется этот вход то становиться очевидно, что допущена ошибка – так называемое подглядывание в будущее. А именно, сравнивается значение индикатора ADX на текущей свече и предыдущей:
if (ADX.Series(Bars,ADXperiod)[bar] > ADX.Series(Bars,ADXperiod)[bar — 1])
Но дело в том что пока свеча не закрылась, мы не права имеем обращаться к значению индикатора на текущей свече. Соответственно, не имеем права входить в позицию на текущей свече. Таким образом, необходимо входить строго на следующей свече, по правилу BuyAtMarket(bar+1). В результате получим следующую кривую доходности:
Граальные ловушки при построении торговых систем



 
2 ловушка – подглядывание в будущее при выходе из позиции
Подглядывание в будущее, на мой взгляд, одна из самых часто встречающихся ошибок, и при недостаточном анализе кода после построения торговой системы, увидеть ошибку бывает довольно тяжело. Так случилось с моей недавней системой на основе пробоя максимума/минимума за N свечей. Ситуация входа в позицию ошибки не содержала, но код выходы из позиции как раз подглядывал в будущее:
Граальные ловушки при построении торговых систем
Рис 3. Кривая доходности для системы с ошибкой в коде при выходе из позиции
Изначально я думал, что ошибка в коде у меня всё же есть, но найти у меня её не получалось.
Скептически относясь к таким сумасшедшим результатам, я обратился за помощью к Дмитрию Власову, который указал на мою ошибку в коде. Дословная цитата — Подробнее
 
 
3 ловушка – синтаксическая ошибка в коде
Программирую не только торговые системы очень часто встречаются ошибки синтаксиса в коде. Так, например в Си-подобных языках программирования (C++, C#, Java), есть два оператора «=» (равно) и «==» (сравнение), которые выполняют совершенно разные функции. Оператор «=» (равно) используется для присвоения переменной некоторого значения, а  оператор «==» (сравнение) сравнивает две переменные.
Приведу пример кода с ошибкой:
if ( Close[bar] = Close[bar-1]  )
{

}
Такой код, безусловно, выполнится, и в результате в массиве Close, элементу с номером bar (т.е. Close[bar]) будет присвоено значение элемента c номеров bar-1. Поэтому для исправления этой ошибки нужно использовать оператор сравнение «==».
Эта ошибка довольно часто встречается, когда разработчик может просто опечататься.

 
4 ловушка – ошибка типов данных в коде
Довольно очевидная, на первый взгляд ошибка, но не всегда заметная при тестировании торговой стратегии, ошибка вычисления при использовании определенного типа данных.
Например, пусть в системе есть такой параметр как стоп-лосс, который составляет 0,3% риска на сделку и рассчитывается по формуле:
double stopLoss = price / 100 * 97;
Однако в данной строчке допущена ошибка, а именно результат деления — price / 100 – даст целое положительное число, а нам требуется вещественное (т.е. дробное), поэтому правильным вариантом будет использование оператора приведения типов:
double stopLoss = (double) price / 100 * 97;


 
5 ловушка – открытие/закрытие позиции на первой внутридневной свече
Часто при проектировании торговых систем вход осуществляется внутри дня, а позиция удерживается в течение нескольких дней, пока не сработает правило для выхода из позиции или стоп-лосс. Как мы все знаем, рынок, в большинстве случаев открывается гепом в одну или другую сторону, соответственно на первой свече (допустим минутной) происходим очень большое количество заявок, в том числе может сработать и стоп-заявка торговой системы. Однако, при тестировании торговой системы программы подобные Wealth Lab не учитывают скорость движения цены на такой свече, и вполне вероятно, что тестер стратегии закроют позицию по стоп-лосу именно по цене стоп-приказа. Понятно, что это будет не совсем верно, т.к. большое проскальзывание в реале не даст закрыть позицию.
 
5 ловушка – порядок выполнения приказов в торговой системе
Для пессимистичного сценария результатов торговой системы, рекомендуется выполнять код обработки сигнала выхода из позиции перед приказом входа
//Если позиция открыта
if (IsLastPositionActive)
{
            //Правила для выхода
}
else        //Если позиция закрыта
{
            //Правила для входа
}
Причем если используются одновременно в системе сигналы выхода из позиции по стоп-лосу и тейк-профиту, необходимо исполнять стоп-лосс именно перед тейк-профитом, т.к. данные сигналы могут возникнуть на одной свече.


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


7 ловушка – некорректные данные для анализа
Одной из причин неудовлетворительного тестирования торговой системы, могут служить некорректные данные по какому-либо инструменту для тестирования. Это могут быть либо неверные свечи, либо аномально длинные тени свечей, которые в рабочей стратегии могут давать убыточные результаты при срабатывании стоп-лоссов.
Граальные ловушки при построении торговых систем





8 ловушка – переоптимизация торговой системы
Приведу в пример систему, которую я разрабатывал одной из первых. В системе использовались такие индикаторы как CCI, ADX и набор SMA. В результате получилась система с очень большим количеством параметров. Путем оптимизации я добился прибыльной торговой системы на истории





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


Посмотреть полный оригинал статьи
★40
10 комментариев
Так и есть. Но демо граале творцам не доказать же. Поголовное большинство граалей с бешеной доходностью на истории — подглядывание в будущее.
avatar
+ respect, bro
отличная работа
даже не используя робота
все равно допускаем ряд ошибок, подмеченных автром
sergey-110, на самом деле, можно классифицировать еще большее количество ошибок. Но это, на мой взгляд основный, на которые я сам постоянно натыкаюсь.
При анализе торговых систем (когда глаз «замылен» и уже не видишь своих багов), часто помогают другие разработчики в поиске таких ошибок.
Максим Милованов, ага
со стороны чужие ошибки виднее
Максим. Пробовали делать системы в состав которых входят независимые друг от друга индикаторы? Поведение таких индикаторов можно предугадать по отдельности каждый- тогда можно предвидеть поведение системы в целом.
Пример простой: Вы берете 4 средних, расчет 1- по open, 2- high, 3- low, 4- close и анализируете. Поведение первых трех будут изменяться внутри свечи только в одном направлении… это поможет убить ложную прибыль системе при тесте и большее соответствие с реалом… Удачи
avatar
RusTrend, «независимые друг от друга индикаторы» — ну ведь так или иначе индикаторы зависят от цены, поэтому они не такие уж и не зависимые. Я правильно вас понял?
Максим, отличная статья
avatar
нет Максим, не правильно. Цена критерий общий и нейтральный (кроме close). т.е. внутри свечи… открылась — МА по открытий получила своё значение и его уже не поменяет, далее цена росла и образовала HIGH — МА по high сформировалась и если цена внутри свечи пойдем вниз эта МА не уменьшится а идет формирование МА по LOW и только в одном направлении… в результате мы имеем три индикатора независимых друг от друга но реакцию на движение каждого мы можем определить и оценить поведение системы… на пример в ходе этой свечи наш high пробил МА по high и мы вошли в лонг, при этом МА по OPEN выше чем по LOW… это не конкретный торговый пример… это сама идея, если поменять ма на пробой канала — будет уже простая система… что я хотел объяснить — при таких независимых индикаторах работающих в одну сторону можно создавать системы с минимумом подгонки… останется только определится с проскальзыванием… я к примеру использую на фьюче ртс — на вход 300 на выход 100… не весть бог что но чем могу…
avatar
Максим Милованов, плюсанул и добавил в избр.!)
avatar

теги блога Максим Милованов

....все тэги



UPDONW
Новый дизайн