Секреты TSLab | Торговые роботы | События
16 Апр

Стоп на свече входа. Как?

Часто, пользователи программы TSLab спрашивают: “Как выставить стоп на свече входа сразу же после входа в позицию?”. Данный вопрос повторяется снова и снова и, вероятно, будет повторяться много раз в будущем. Так как в TSLab инструкция по этим вопросам отсутствует, разберем в статье этот момент на примерах.

Стоп на свече входа. Как?

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

  1. Использовать сжатие/разжатие в скрипте.
  2. Использовать пересчет пок/прод, пок/прод(без объема), сделка.

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

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

Используем сжатие и разжатие.

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

using TSLab.Script;
using TSLab.Script.Handlers;

namespace test
{
    public class OneCandleEntExCompress : IExternalScript
    {
        public void Execute(IContext ctx, ISecurity sec)
        {
            for (int i = 0; i < ctx.BarsCount; i++)
            {
                var le = sec.Positions.GetLastActiveForSignal("LE", i);
                if (le == null)
                {
                    if (sec.Bars[i].Close > sec.Bars[i].Open)
                        sec.Positions.BuyAtMarket(i+1, 1, "LE");
                }
                else
                {
                    var take = le.EntryPrice*(1 + 0.01);
                    var stop = le.EntryPrice*(1 - 0.005);
                    le.CloseAtStop(i+1, stop, "LXS");
                    le.CloseAtProfit(i+1, take, "LXP");
                }
            }

            if (ctx.IsOptimization)
                return;

            var color = new Color(System.Drawing.Color.Black.ToArgb());
            var pane = ctx.CreatePane(sec.Symbol, 100, false);
            pane.AddList(sec.Symbol, sec, CandleStyles.BAR_CANDLE, color, PaneSides.RIGHT);
        }
    }
}

Результатом работы данного скрипта будет следующая картинка:

стоп на свече входа. как?

Рисунок 1. Задержка в выставлении стопа и тейка.

Как видим, есть вполне четкая и осязаемая задержка в установке тейка и стопа, которая может быть очень опасной. Если работать на часовиках, то часовой лаг в выставлении стопа может быть причиной больших убытков. Переработаем скрипт и введем в него сжатие. В качестве базового таймфрейма выберем минутки, а в качестве рабочего выбираем часовой таймфрейм. Смотрим что получилось на выходе:

using TSLab.DataSource;
using TSLab.Script;
using TSLab.Script.Handlers;

namespace test
{
    public class OneCandleEntExCompress : IExternalScript
    {
        public void Execute(IContext ctx, ISecurity sec)
        {
            var compressed = sec.CompressTo(new Interval(60, DataIntervals.MINUTE));
            var hSignal = new double[compressed.Bars.Count];
            for (int i = 0; i < compressed.Bars.Count; i++)
                hSignal[i] = compressed.Bars[i].Close > compressed.Bars[i].Open ? 1 : 0;

            var signal = compressed.Decompress(hSignal);

            for (int i = 0; i < ctx.BarsCount; i++)
            {
                var le = sec.Positions.GetLastActiveForSignal("LE", i);
                if (le == null)
                {
                    if (signal[i] > 0)
                        sec.Positions.BuyAtMarket(i+1, 1, "LE");
                }
                else
                {
                    var take = le.EntryPrice*(1 + 0.01);
                    var stop = le.EntryPrice*(1 - 0.005);
                    le.CloseAtStop(i+1, stop, "LXS");
                    le.CloseAtProfit(i+1, take, "LXP");
                }
            }

            if (ctx.IsOptimization)
                return;

            var color = new Color(System.Drawing.Color.Black.ToArgb());
            var pane = ctx.CreatePane(sec.Symbol, 100, false);
            pane.AddList(sec.Symbol, sec, CandleStyles.BAR_CANDLE, color, PaneSides.RIGHT);

            pane = ctx.CreatePane(sec.Symbol, 50, false);
            pane.AddList(compressed.Symbol, compressed, CandleStyles.BAR_CANDLE, color, PaneSides.RIGHT);

            color = new Color(System.Drawing.Color.LightGray.ToArgb());
            pane.AddList("signal", signal, ListStyles.HISTOHRAM, color, LineStyles.SOLID, PaneSides.LEFT);
        }
    }
}

В результате работы скрипта картинка получится вот такая:

стоп на свече входа. как?

Рисунок 2. Простановка стопа и тейка в течение одной свечи.

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

Используем пересчет пок/прод

Как уже было сказано выше, такой способ работы лишает нас возможности протестировать скрипт на исторических данных. Тестироваться то скрипт будет, но вот стоп на свече входа без модификации скрипта мы получить не  сможем. Увидим его только в режиме Агента. Для анализа такого способа мы используем такой же скрипт что и ранее, только оптимизируем под пересчет “пок/прод”.

using TSLab.Script;
using TSLab.Script.Handlers;

namespace test
{
    public class OneCandleEntExBuySell : IExternalScript
    {
        public void Execute(IContext ctx, ISecurity sec)
        {
            var count = ctx.BarsCount; 
            for (int i = 0; i < count; i++)
            {
                var le = sec.Positions.GetLastActiveForSignal("LE", i);
                if (le == null)
                {
                    if (sec.Bars[i].Close > sec.Bars[i].Open)
                    {
                        // для последней завершенной свечи логика входа будет особой
                        // сигналы на вход учитываем только ОТ ЗАВЕРШЕННЫХ свечек
                        if (i == count-2)  
                        {
                            // при пересчете пок/прод сигнал нельзя ставить на формирующуюся свечку не пойдет в рынок.
                            sec.Positions.BuyAtPrice(i + 2, 1, sec.Bars[i].Close - 1, "LE");
                        }
                        // для исторических свечек логика входа будет стандартной
                        else if (i < count - 2)
                        {
                            sec.Positions.BuyAtPrice(i + 1, 1, sec.Bars[i].Close - 1, "LE");
                        }
                    }
                }
                else
                {
                    var take = le.EntryPrice*(1 + 0.01);
                    var stop = le.EntryPrice*(1 - 0.005);
                    le.CloseAtStop(i+1, stop, "LXS");
                    le.CloseAtProfit(i+1, take, "LXP");
                }
            }

            if (ctx.IsOptimization)
                return;

            var color = new Color(System.Drawing.Color.Black.ToArgb());
            var pane = ctx.CreatePane(sec.Symbol, 100, false);
            pane.AddList(sec.Symbol, sec, CandleStyles.BAR_CANDLE, color, PaneSides.RIGHT);
        }
    }
}

В получившемся скрипте можно заметить особую логику входа для сформированных и еще не сформированных свечек. Это связано с особенностью TSLab (очень неудобной для меня), запрещающей ставить сигнал на формирующуюся свечку в пересчете “пок/прод”. Сигнал нужно ставить только на свечку которой еще нет. То есть  мы должны посчитать сигнал по уже сформированным свечкам, а выставить сигнал можем только на несуществующую свечку что обычно представляет собой i+2, вместо обычного i+1. Вот такая особенность. Только на пересчете “интервал+сделка” можно ставить сигнал на формируемую свечку.

ВАЖНО: если вы сформируете в визуальном редакторе скрипт работающий на пересчете “пок/прод”, то он будет использовать для входов сигналы посчитанные по формирующейся свече. Индикаторы будут рассчитаны и использованы для формирования сигнала. Может получаться, что в течение свечи, которая формируется, у вас сигнал будет то появляться то пропадать. Это на самом деле проблема!

стоп на свече входа. как?

Рисунок 3. На истории для пересчета “пок/прод” картинка мало отличается от пересчета “интервал”.

Если вы запустите скрипт в режиме Агента, то картинка не будет отличаться от обычной картинки скрипта с пересчетом “интервал”. Отличие будет только в том, что скрипт будет пересчитываться постоянно и стоп с тейком выставятся сразу же после того как сигнал LE будет отработан и скриптом будет взята на грудь  позиция.

Выводы

На текущий момент установить стоп на свече входа можно двумя способами. Наиболее оптимальный и универсальный способ – использовать сжатие в больший таймфрейм. Данный способ позволяет не только проводить тестирование скрипта на  исторических данных, но и не требует модификации скрипта для запуска в режиме агента.

14
Июл
2017

Доверительное управление. Результаты в июне 2017 года.

Доверительное управление. Результаты в июне 2017 года. Июнь индекс РТС вновь провел преимущественно в боковых движениях, а… »

11
Июн
2017

Доверительное управление. Результаты в мае 2017 года.

Доверительное управление. Результаты в мае 2017 года. В мае “болтанка” индекса РТС продолжилась, на паре… »

7
Май
2017

Доверительное управление. Результаты в апреле 2017 года.

Доверительное управление. Результаты в апреле 2017 года. В апреле мы наблюдали очередной месяц “боковика” по… »

2
Апр
2017

Доверительное управление. Результаты в марте 2017 года.

Доверительное управление. Результаты в марте 2017 года. В марте волатильность на рынке несущественно выросла. Все… »

7
Мар
2017

Доверительное управление. Результаты в феврале 2017 года.

Доверительное управление. Результаты в феврале 2017 года. Февраль был самым коротким торговым месяцем, к тому же… »