Блог им. HOME

— Вот не люблю я котов...
— Вы просто не умеете их готовить!
(не помню источник)
Так уж повелось в этой жизни, что человекам стало незазорно гулять по Невскому без штанов, а вот признать ошибки – никак. Хоть в штанах, хоть без оных.
Особенно разительным это свойство современного характера проявляется в правильном использовании чужого опыта.
Намедни завязалась беседа с одним из коллег по спекулянтскому цеху, и, среди прочего, вдруг всплыла тема трагического различия результатов бэктестирования торговой стратегии и торговли на живой трансляции котировок.
Короче, битый час общались, а понимания – ноль. Говорю, наконец, «покажи код своего бота, собака!»
Мялся-мялся горемычный, но всё-таки сдался. «Смотри, — говорит. – Только никому не показывай, пожалуйста.»
Да не нужны мне твои секреты! Тем более, что они – секреты Полишинеля.
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]
Успехов всем!
Вы неверно поняли смысл.
Во-первых, пересчета по всем свечкам в большинстве авторских ботов нет, т.к. боты работают по коллбэкам последнего бара. Во всех терминалах есть такая функция в API, чтобы не гонять траффик.
Во-вторых, в реальном времени бот (допустим, на фрейме 1 минута) получает данные ТЕКУЩЕГО бара, когда этот бар уже НАЧАЛ образовываться. До того момента, пока этот бар станет архивным и обретет точные и окончательные OHLC-цены, пройдет, как максимум, 1 минута, в течение которой торговая система уже выдаст торговый сигнал. Этот сигнал будет неверным по истечении срока тайм-фрейма для данного бара.
Т.е. ошибка состоит в использовании ТСистемой неокончательной, а промежуточной статистики. Но, как только Вы переведёте эту статистику в состояние архивной (как минимум через период времени, равный тайм-фрейму), эта статистика станет постоянной и готовой к использованию.
Поэтому и нужно пользоваться не index, а index-1.
Кстати, если Вы не пишете боты, а торгуете руками с экрана, Вы, сам того не осознавая, подтверждаете смысл моего поста, т.к. анализируете рынок по готовым, сложившимся барам, т.е. ставшим уже архивными. Ведь Вы же не совершаете операцию, пока бар не нарисовался окончательно?
т.е проверить что текущая свеча используется в расчетах очень легко...
Ты ставишь лимитник по цене ЗАКРЫТИЯ уже законченной свечи!!!
ЗА-КОН-ЧЕН-НОЙ!
У тебя есть такая возможность, т.к. ты ручками выставляешься.
А торговая система, заточенная на частоту опроса данных каждые 1-2-3… секунду, молотит по индексу index ТЕКУЩЕЙ свечи, которая уже началась, но ЕЩЕ не закончилась. Поэтому текущий CLOSE этой свечи не является окончательным. Он будет таковым по мере истечения тайм-фрейма. Не раньше.
А вот есть посложнее.
Ситуации когда заявка просто не исполнена, исполнена частично, когда сигнал работает при изменении чего-то, а заявка в этот момент не исполнилась, а на след. баре сигнала уже нет, и конечно сдвиги сработавших сигналов относительно теоретического исполнения из-за всего этого…
Решение её описано мной в посте про коллбэки своими руками.
У меня таких проблем нет.
Все ордеры исполняются. Обязательность исполнения ордеров вопреки всему!
Но возвращаясь к теме поста, хочу отметить, что самые, как Вы написали, простые проблемы чаще всего не замечаются. Вот только вопрос «Почему на бэктестах система показывает отличный результат, а в живой торговле сбоит?» встречается всякий раз, как только обсуждается построение эффективных систем.