Секреты TSLab | Торговые роботы | События
12 Май

Тормозят скрипты TSLab? Ускоряемся!

При написании скриптов в TSLab, визуальный то редактор или TSLab API, мы всегда работаем с позициями. А это за собой влечет проверку существования  позиции на текущий момент. Исходя из парадигмы TSLab прежде чем совершить покупку или продажу, нам необходимо проверить текущую ситуацию. Есть ли у нас позиция, нет ли у нас  позиции мы можем узнать только сделав запрос позиций. В TSLab есть несколько вариаций запроса позиции. Первый и наиболее старый способ – запросить последнюю активную позицию. Второй и более новый способ – запросить активную позицию только на текущем баре. От того как вы используете запрос позиций будет влиять прямым образом на ваши скрипты TSLab. Я не буду рассматривать остальную кучу способов, которые в общем и целом всегда сводятся к одной из двух модификаций рассмотренных ниже. Да и в 90% случаев я примняю только два этим способа запроса позиций когда разрабатываю скрипты TSLab. И разница в скорости работы этих способов разительна.

Почему скрипты TSLab медленно работают?

Иногда после запуска скрипта в лаборатории вы видите картинку наподобие той, что изображена ниже. Процессор перегружен, кулера гудят и складывается ощущение что ваш компьютер собирается взлетать. Для просмотра информации о загрузке процессора использована программа process explorer, без которой как без рук.

почему скрипты tslab медленно работают

Рисунок 1. Скрипт скушал весь процессор.

Причин этому может быть много и моей фантазии не хватит чтобы назвать их все. Но можно разделить их на несколько категорий.

  • Плохо написан ваш скрипт. Много лишних расчетов загружают процессор.
  • Ваш скрипт производит сложные расчеты для принятия решения.
  • Медленно работают функции TSLab API, потребляя много ресурсов.

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

    /// <summary>
    /// Последняя активная позиция по названию сигнала
    /// </summary>
    /// <param name="signalName">Имя сигнала</param>
    /// <returns>
    /// Возвращает позицию или null
    /// </returns>
    IPosition GetLastActiveForSignal(string signalName);

    /// <summary>
    /// Последняя активная позиция по названию сигнала
    /// </summary>
    /// <param name="signalName">Имя сигнала</param>
    /// <param name="barNum"/>
    /// <returns>
    /// Возвращает позицию или null
    /// </returns>
    IPosition GetLastActiveForSignal(string signalName, int barNum);

Вот эти функции и будем тестировать по скорости работы.

Тестирование скорости запроса позиций.

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

Каждый скрипт состоит из двух частей. Первая часть скрипта намерено генерирует большое число позиций (чтобы было чего запрашивать у TSLab). Вторая часть начинает запрашивать текущую позицию для каждого бара. Замеряем время выполнения второй части скрипта и выводим все это в окно сообщений. Собственно скрипты TSLab ниже:

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

namespace Медленно_работает_скрипт_TSLab
{
    public class GetLastSpeedTest : IExternalScript
    {
        public void Execute(IContext ctx, ISecurity sec)
        {
            for (int i = 0; i < ctx.BarsCount; i+=100)
            {
                sec.Positions.BuyAtMarket(i+1, 1, "LE");
                var le = sec.Positions.GetLastActiveForSignal("LE");
                le.CloseAtMarket(i+2, "LX");
            }

            var beginTime = DateTime.Now;

            var counter = 0;
            for (int i = 0; i < ctx.BarsCount; i++)
            {
                var le = sec.Positions.GetLastActiveForSignal("LE");
                if (le != null)
                    counter++;
                else
                    counter--;
            }
            ctx.Log(counter.ToString(), new Color());
            var duration = DateTime.Now - beginTime;
            ctx.Log(duration.TotalMilliseconds.ToString(), new Color(),true);
        }
    }
}
using System;
using TSLab.Script;
using TSLab.Script.Handlers;

namespace Медленно_работает_скрипт_TSLab
{
    public class GetLastSpeedTest : IExternalScript
    {
        public void Execute(IContext ctx, ISecurity sec)
        {
            for (int i = 0; i < ctx.BarsCount; i+=100)
            {
                sec.Positions.BuyAtMarket(i+1, 1, "LE");
                var le = sec.Positions.GetLastActiveForSignal("LE");
                le.CloseAtMarket(i+2, "LX");
            }

            var beginTime = DateTime.Now;

            var counter = 0;
            for (int i = 0; i < ctx.BarsCount; i++)
            {
                var le = sec.Positions.GetLastActiveForSignal("LE",i);
                if (le != null)
                    counter++;
                else
                    counter--;
            }
            ctx.Log(counter.ToString(), new Color());
            var duration = DateTime.Now - beginTime;
            ctx.Log(duration.TotalMilliseconds.ToString(), new Color(),true);
        }
    }
}

Как видно, отличие только в строке 23. Все остальное совершенно идентично. В коде применены приемы, позволяющие избежать оптимизации компилятора который может удалять бесполезный код. Так что отличия тут только в функции запроса позиции.

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

  1. С запросом номера бара: 139 мсек
  2. Без запроса номера бара: 101 мсек

Разница в 40% значительна и заслуживает того, чтобы обратить на нее внимание. Проведем небольшой анализ результатов и сделаем выводы.

Что делать?

Главное отличие функции без номера бара от другой состоит в том, что она просто берет последнюю позицию и возвращает ее нам. Вторая функция ищет те позиции которые активны на заданном номере бара. Ищет она их, естественно, в каком-то списке или хэш таблице или еще где-то. Логично предположить, что просто “взять и вернуть” будет работать намного быстрее чем “найти взять и вернуть”. Главная проблема в слове “найти”. И чем больше у вас позиций на истории, тем дольше будет работать  поиск нужных нам позиций для заданного бара. В то время как функция первая, не зависит от числа позиций вообще. Следовательно, чем больше позиций, тем больше разница в скорости работы обоих функций.

Когда мы создаем скрипты TSLab в визуальном редакторе, автоматически используется функция с номером бара. А это значит, что мы может сделать скрипт в значительно шустрее чем в визуальном редакторе! Для этого всего лишь нужно использовать функцию БЕЗ номера бара. Это ускорит ваш скрипт, но в некоторых случаях может создать проблемы (смотрите “Альтернативный метод для пересчета пок/прод”). Чаще всего никаких проблем нет. Главное помнить о том, что функция GetLastActiveForSignal(“LE”) возвращает активную позицию не для текущего бара, а вообще самую последнюю активную позицию, то есть открытую позже остальных. Разработчики рекомендуют использовать везде функцию с номером бара, поэтому, в некотором будущем, могут удалить возможность запрашивать позицию без номера бара.


comments powered by HyperComments

Иван
2017-01-01 03:28:07
Секс знакомства http://bit.ly/2hkF2s9
14
Июл
2017

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

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

11
Июн
2017

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

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

7
Май
2017

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

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

2
Апр
2017

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

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

7
Мар
2017

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

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