Запрашиваем в TSLab открытые позиции ПРАВИЛЬНО 3!
В предыдущей статье, чтобы подогреть интерес к вопросу, я снова показывал не самый правильный способ того, как запрашивать у TSLab открытые позиции. Результаты получились довольно интересными даже для меня самого, а для вас, дорогие мои читатели, они были, возможно, целым открытием в TSLab. Наконец, долгожданная статья с самым правильным способом работы с позициями. Данный способ отлично работает на версии 1.2.xx. Насчет версии 1.3.xx загадывать не будем. На 1.1 данный способ вообще не существует, так как появился только в 1.2.
3 способа, как запросить у TSLab открытые позиции.
3. ПРАВИЛЬНЫЙ способ
Описание всей сути укладывается в одно предложение: ВЕЗДЕ где возможно используйте МЕТОДЫ у которых можно указать НОМЕР БАРА в качестве аргумента. Если есть два метода в одном из которых есть возможность указать номер бара, а в другом нет, то используйте тот, в котором можно указать номер бара. Вот и весь секрет. Следуйте ему и никогда не будете шокированы неадекватной работой ваших торговых роботов.
Укажу сразу несколько стандартных методов, наиболее активно используемых при написании торговых роботов:
// Возвращает последнюю активную позицию для заданного сигнала или null НА ЗАДАННОМ БАРЕ IPosition GetLastActiveForSignal(string signalName, int barNum); // Последняя позиция в списке для заданного сигнала открытия или null НА ЗАДАННОМ БАРЕ IPosition GetLastForSignal(string signalName, int barNum); // Последняя позиция в списке для заданного сигнала закрытия или null НА ЗАДАННОМ БАРЕ IPosition GetLastForCloseSignal(string signalName, int barNum); // Последняя закрытая позиция или null НА ЗАДАННОМ БАРЕ IPosition GetLastPositionClosed(int barNum);
Как можно заметить, сигнатура методов очень похожа на методы из прошлой статьи, только добавился номер бара. Ну, а результат использования именно этих методов довольно серьезно отличается от результатов прошлых статей.
Скрипт с простой логикой я сразу пропускаю, так как там ничего интересного. Он отлично работает во всех режимах и в логе НЕ БУДЕТ записей о попытке закрыть позицию на баре хх. Все потому, что вышеописанные методы возвращают данные по позиции с учетом номера бара, и для бара 10 они не вернут позицию открытую на баре 100, даже если она реальная. Сразу переходим к нашему контрольному скрипту на котором все ломалось.
using RusAlgo.Helper; using TSLab.Script; using TSLab.Script.Handlers; namespace test.Статьи { public class PositionGet5 : IExternalScript { public void Execute(IContext ctx, ISecurity sec) { var center = new double[ctx.BarsCount]; center[0] = sec.ClosePrices[0]; for (int i = 1; i < ctx.BarsCount; i++) { // запросим у TSLab закрытые позиции var x = sec.Positions.GetLastPositionClosed(i); center[i] = x != null ? x.ExitPrice : center[i - 1]; // запросим у TSLab открытые позиции на баре i для LE var le = sec.Positions.GetLastActiveForSignal("LE", i); if (le == null) { sec.Positions.BuyAtPrice(i + 1, 1, center[i] * 0.9985, "LE"); } else { if (i - le.EntryBarNum > 5) le.CloseAtMarket(i+1, "LX"); } // запросим у TSLab открытые позиции на баре i для SE var se = sec.Positions.GetLastActiveForSignal("SE", i); if (se == null) { sec.Positions.SellAtPrice(i + 1, 1, center[i] * 1.0015, "SE"); } else { if (i - se.EntryBarNum > 5) se.CloseAtMarket(i + 1, "SX"); } } var pane = ctx.First; var gl = pane.AddList("center", center, ListStyles.LINE, new Color(), LineStyles.SOLID, PaneSides.RIGHT); gl.Thickness = 3; } } }
Результат работы скрипта в лаборатории стандартно показывает правильную картинку.
Рисунок 1. Результат в лаборатории.
В режиме агента без реальных позиций тоже все нормально. Пока.
Рисунок 2. Результат в агенте, без реальных позиций.
После входа в первую реальную позицию все снова ломается и снова хочется воскликнуть: “TSLab must die!”. Куда делись все виртуальные позиции по шорту??? Мы ведь вошли только в лонг и шортовые виртуальные позиции должны быть на месте и изломы должны были остаться. Но их нет!
Рисунок 3. Результат в агенте, с открытой реальной позицией.
На самом деле плакать рано. Все достаточно просто объясняется. Так как входы в виртуальные лонговые позиции в начале графика запрещены и не происходят, то центральная линия остается на уровне цены закрытия первой свечи. В тех местах где должны быть шорты, заявка болтается НАД толстой черной линией и просто не может быть исполнена. Поэтому шорты просто пропадают вследствие изменения положения центральной линии. Вот и все. Дальше увидим более интересный момент.
Рисунок 4. Результат в агенте, с закрытой реальной позицией.
После закрытия реальной позиции картинка совершенно адекватная. Тут тоже все так как и должно быть. Центральная линия перемещается в новую цену закрытия только там где положено, а не на всем графике.
Рисунок 5. Пропустили вход в лонг. Получили виртуальную позицию.
На рисунке 5 можно наблюдать излом центральной линии, но входа и выхода не видно. Суть в том, что вход в позицию был намеренно пропущен и позиция стала виртуальной. То есть, без реального входа и выхода. Ну, а так как на баре входа в эту виртуальную позицию мы не имеем открытых позиций ПОСЛЕ этого бара, то вход в виртуальную позицию совершенно не возбраняется и вполне может иметь место быть.
Рисунок 6. Пропустили вход в лонг. После вошли в шорт.
Вход в шорт никак не влияет на нашу виртуальную позицию. Потому, что реальная позиция была для сигнала SE, а виртуальная позиция для сигнала LE. Как результат, виртуальный лонг не был выброшен и остался на графике. С похожей ситуацией столкнулся человек работая через визуальный редактор. Вот эта тема форума.
Рисунок 7. Пропустили вход в лонг. После вошли в лонг.
На рисунке 7 видно исчезновение виртуальной лонговой позиции. Это нормально. Ведь у нас есть реальная позиция ПОСЛЕ точки где должна была открыться виртуальная лонговая позиция. В результате смещения центральной линии вы можете получать сигналы о пропущенных входах, и если включено автооткрытие, то оно может сработать там где не нужно. Нужно быть внимательным.
Даже для правильного способа есть некоторые моменты, требующие внимательного отношения и понимания. Важно не допускать пропущенных входов иначе вся логика может пойти совершенно не так как в лаборатории. При запуске скрипта нужно ожидать исчезновения виртуальных сделок при появлении реальных. Это тоже может привести к различиям между реалом и лабораторией.
Логика скрипта, разобранная во всех статьях, применяется для написания любого скриптов с мартингейлом. Поэтому, не стоит думать, что пример взят сферический в вакууме и к жизни не имеет никакого отношения. Еще как имеет, если вспомнить сколько алгоритмов делается с мартингейлом.
плюсы
Перечислим плюсы данного способа запрашивать у TSLab открытые позиции:
- способ работает
- можно работать с разными сигналами
- разработчики настоятельно РЕКОМЕНДУЮТ использовать его
минусы:
- так же подвержен проблеме с виртуальными позициями
- самый медленный способ из всех разобранных (подтверждение в статье “Тормозят скрипты TSLab? Ускоряемся“)
Вывод
Использование правильного способа запрашивать у TSLab открытые позиции не избавляет вас от необходимости включать голову. Так же могут быть интересные ситуации кажущиеся багом программы, но таковым не являющиеся. Описанный метод работает вполне адекватно и предсказуемо, что позволяет создавать торговые роботы с предсказуемым поведеним.
PS: вот и все ребята. Вопросы? Задавайте их в комментариях!