
— Вот не люблю я котов...
— Вы просто не умеете их готовить!
(не помню источник)
Так уж повелось в этой жизни, что человекам стало незазорно гулять по Невскому без штанов, а вот признать ошибки – никак. Хоть в штанах, хоть без оных.
Особенно разительным это свойство современного характера проявляется в правильном использовании чужого опыта.
Намедни завязалась беседа с одним из коллег по спекулянтскому цеху, и, среди прочего, вдруг всплыла тема трагического различия результатов бэктестирования торговой стратегии и торговли на живой трансляции котировок.
Короче, битый час общались, а понимания – ноль. Говорю, наконец, «покажи код своего бота, собака!»
Мялся-мялся горемычный, но всё-таки сдался. «Смотри, — говорит. – Только никому не показывай, пожалуйста.»
Да не нужны мне твои секреты! Тем более, что они – секреты Полишинеля.
5 минут изучаю, 10 минут…
И замечаю одну старую-престарую ошибку. В смысле, я-то определился с ней еще в начале пути при разработке своего первого бота лет 20 назад. Вот уж не думал, что она до сих пор жива и терзает молодые умы.
Итак, суть ошибки.
Так сталось, что при написании ТС (торговой системы) автор не делает различия между завершенным фреймом и текущим фреймом.
В большинстве случаев, используя индексацию баров (применительно к QUIK, хотя это справедливо для любых терминалов), разработчики ссылаются на системный индекс index. Этот индекс используется в Руководстве QLUA и прописан во всех индикаторах библиотеки терминала:

Каждый знает, что он из себя представляет:
Однако, нигде не отмечается, что этот индекс присваивается бару по мере формирования его первой цены Open(index). Это происходит в начале тайм-фрейма. Внимание: В НАЧАЛЕ! Т.е. ДО момента окончания периода тайм-фрейма.
Теперь зададимся вопросом: а на каких барах строится бэк-тест?
Опять же – правильно! На ПОЛНОСТЬЮ СФОРМИРОВАННЫХ БАРАХ, т.к. в момент прогонки теста вся база баров УЖЕ сложилась, и в ней нет ни одного незаконченного бара в выбранном тайм-фрейме!
Итак, подытожим:
Очевидно, что между двумя этими наборами параметров бара в 99% случаев имеются огромные различия.
Вот эти различия и убивают результаты тестирования в попытках использовать найденные параметры для живой торговли.
Как решается эта проблема?
Очень просто. Вместо index нужно использовать (index – 1) и, соответственно, все индексы нужно сдвинуть на -1.
Получится, например, что пересечение ma1 = SМА(С, 5) и ma2 = SМА(С, 9):
- БЫЛО: ma1[index-1] < ma2[index-1] AND ma1[index] > ma2[index]
- СТАЛО: ma1[index-2] < ma2[index-2] AND ma1[index-1] > ma2[index-1]
Самое интересное, что применение такого индексирования покажется плохим, т.к. только что успешный тест вдруг становится убыточным. Цирк?..
Из личного опыта: ранее я писал о способах управления текущей базой котировок. Так вот, кроме «обрезания хвостов» я перестраиваю базу так, что в начале нужного периода первый бар имеет индекс 1, а не системный 19017 (на вчерашних торгах).
В таком случае, вышеприведенный пример пересечения «средних» у меня выглядит так:
ma1[#ma1-2] < ma2[#ma2-2] AND ma1[#ma1-1] > ma2[#ma2-1]
Успехов всем!
А вот есть посложнее.
Ситуации когда заявка просто не исполнена, исполнена частично, когда сигнал работает при изменении чего-то, а заявка в этот момент не исполнилась, а на след. баре сигнала уже нет, и конечно сдвиги сработавших сигналов относительно теоретического исполнения из-за всего этого…