Максим Милованов
Максим Милованов личный блог
03 сентября 2012, 13:59

Торговая система на основе уровней Вуди. Часть 3. Создание торгового робота с использованием библиотеки Stock#

Продолжая тему о создании робота на основе уровней Вуди, настало время разработки робота на языке C# с помощью библиотеки для создания торговых роботов Stock#.
Напомню алгоритм робота с учетом специфики языка Qpile (Рис 1). Суть при программировании на C# данного алгоритма почти не меняется.

 Торговая система на основе уровней Вуди. Часть 3. Создание торгового робота с использованием библиотеки Stock#

 
В качестве терминала мы будем использовать терминал самый распространенный терминал Quik. Для экспорта свечей из Quik в нашу программу необходимо заранее создать таблицу-портфель для Quik. Рекомендуется использовать определенный набор таблиц для экспорта данных через DDE (Рис 2).
Торговая система на основе уровней Вуди. Часть 3. Создание торгового робота с использованием библиотеки Stock#



Рассмотрим такой нюанс Stock# как событийная модель. Код, основанный на данной модели, получается компактным и оперативно реагирует на рыночные события за счет мгновенного вызова.
Для того чтобы робот понял, что ему передаются свечи, создадим класс QuikCandle

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ecng.Common;
using Ecng.Serialization;

using StockSharp.Quik;

namespace SkeletonRobotQuik
{
    [DdeCustomTable("Исторические свечки")]
    class QuikCandle
    {
        [Identity]
        [InnerSchema]
        public QuikCandleDateTime DateTime { get; set; }

        [DdeCustomColumn("Цена открытия", Order = 2)]
        public decimal OpenPrice { get; set; }

        [DdeCustomColumn("Максимальная цена", Order = 3)]
        public decimal HighPrice { get; set; }

        [DdeCustomColumn("Минимальная цена", Order = 4)]
        public decimal LowPrice { get; set; }

        [DdeCustomColumn("Цена закрытия", Order = 5)]
        public decimal ClosePrice { get; set; }

        [DdeCustomColumn("Объем", Order = 6)]
        public int Volume { get; set; }
    }


    public class QuikCandleDateTime : Equatable
    {
        [DdeCustomColumn("Дата", Order = 0)]
        public string Date { get; set; }

        [DdeCustomColumn("Время", Order = 1)]
        public string Time { get; set; }

        public override QuikCandleDateTime Clone()
        {
            throw new NotImplementedException();
        }

        public override int GetHashCode()
        {
            return this.Date.GetHashCode() ^ this.Time.GetHashCode();
        }

        protected override bool OnEquals(QuikCandleDateTime other)
        {
            return this.Date == other.Date && this.Time == other.Time;
        }
    }
}
 
Атрибутом DdeCustomTableAttribute задается название таблицы, из которой будут читаться данные. Дополнительно, через StockSharp.Quik.DdeCustomColumnAttribute задаются название колонки в таблице и ее порядковый номер (нумерация идет с 0). 


Через специальный атрибут IdentityAttribute указывается идентификатор экспортируемой строки. Это позволит не создавать каждый раз объекты, а использовать уже ранее созданные. В случае с таблицей исторических свечек, идентификатор состоит их двух параметров: дата и время. Поэтому они были вынесены в отдельный класс QuikCandleDateTime.
Теперь рассмотрим основные события, которые нам понадобятся:
_trader.Connected += Trader_Connected;  //подписываемся на событие подключения 
_trader.Disconnected += Trader_Disconnected; //подписываемся на событие отключения
_trader.NewPortfolios += Trader_NewPortfolios;  //событие появления новых портфелей
_trader.NewSecurities += Trader_NewSecurities;  //событие появление новых инструментов
_trader.NewCustomTables += Trader_NewCustomTables; //событие появления новых произвольных таблиц
_trader.CustomTablesChanged += Trader_CustomTablesChanged;    //событие изменения данных в произвольных таблицах

Поскольку, это пример создания робота, ограничимся лишь этим набором событий.


Торговая система работает на основе пересечения цены некоего уровня Вуди, то нам необходимо иметь свечи, которые будут импортироваться из Quik. Для этого нам потребуется воспользоваться импортом произвольных свечей, создав объект:
_candlesTable = new DdeCustomTable(typeof(QuikCandle));
Остальные части кода нет смысла разбирать подробнее, т.к. код снабжен достаточным количеством комментариев.
Очень важным моментом в разработке робота является описание правил стратегии. В Stock# есть отдельный класс Strategy, который содержит основные торговые параметры такие как: портфель, инструмент, текущая позиция, прибыль-убыток и т.д.
Рекомендуется, чтобы код стратегии был реализован без привязки к какому-либо инструменту или портфелю. Такой подход позволяет использовать стратегию с разными инструментами на разных торговых счетах как одновременно, так и в разные периоды времени (Рис 3):
Торговая система на основе уровней Вуди. Часть 3. Создание торгового робота с использованием библиотеки Stock#
Класс Strategy использует подход, основанный на событиях. Такой код получается компактным и оперативно реагирует на рыночные события за счет мгновенного вызова. Помимо этого возможно использовать итерационную модель, в которой код вызывается только по окончанию интервала. Поскольку для нашей стратегии не требуется быстродействие, то будем использовать итерационный подход, с ежесекундным обновлением данных.
private PivotVudiStrategy _strategy;    //стратегия

_strategy = new PivotVudiStrategy(_candles, _timeFrame, 300)
{
        Volume = _shareCount,
        Security = _security,
        Portfolio = _portfolio,
        Trader = _trader,
        Interval = _timeRefreshStrategy
};<br /> 
В итоге приложении будет выглядеть следующим образом (Рис 4).
 Торговая система на основе уровней Вуди. Часть 3. Создание торгового робота с использованием библиотеки Stock#



Для запуска робота необходимо сначала нажать на кнопку «Подключить», при этом терминал Quik должен быть запущен. При успешном подключении в программу будут поступать свечи из терминала Quik (Рис 4).
При этом в программе реализованы изменение настроек, которые сохраняется в XML файл и переменные для тестирования, которые модно задать и протестировать на каком-либо демо счете (Рис 5).
 Торговая система на основе уровней Вуди. Часть 3. Создание торгового робота с использованием библиотеки Stock#




Хочется отметить, что данный робот не учитывает форс-мажорные обстоятельства как отключение электричества, перезагрузка компьютера и т.д., поэтому не рекомендуется запускать его на реальном счете без присмотра.
 
В заключение данной серии статей хотелось бы провести параллель между роботом на языке Qpile и с использованием библиотеки Stock#. Лично для меня, плюсами языка Qpile являются довольно простой синтаксис, хорошая поддержка со стороны разработчика, множество примеров. Минусы Qpile в ограниченности его синтаксиса, сложности отладки программы. Stock# же позволяет создавать стратегии любой сложности, начиная от примитивных простого пересечения со скользящей средней до HFT стратегий. В качестве недостатков стоит отметить то, что человеку, не знакомому с программированием, будет довольно сложно написать программу. Поддержка осуществляется на форуме Stock# как в рамках форума, так и в закрытом платном разделе.
 
Напомню, что для реальной торговли, данный робот может использоваться только после тестирования на демо счете и исправления выявленных ошибок. Автор данной статьи не несет ответственности за ваш торговый счет при использовании данного робота.

Сам код торгового робота и настройки для Quik для экспорта свечей вы можете скачать по ссылке внизу статьи.
 
 
19 Комментариев
  • vfreeman
    03 сентября 2012, 14:35
    +++
  • vfreeman
    03 сентября 2012, 14:46
    тебе спасибо!
    я прошел намного более сложный (и долгий путь) — при знакомстве с s# мне подобные статьи не попадались :)
  • А. Г.
    03 сентября 2012, 16:11
    О, логика моих систем и моего робота. Только там просто уровни, не «поддержка-сопротивление» (хотя эта разница чисто терминологическая) и в левой части стопы стоят на уровнях, а проверяются соответственно хай свечи при покупке и лоу свечи при продаже.
      • А. Г.
        03 сентября 2012, 16:36
        Максим Милованов,

        С моей точки — да. Но после встречи смарт-лаба я понял, что мои 35% годовых в последние 6 лет никому не интересны :) Теперь думаю, а в правильном ли направлении двигался я 14 лет :)
        • vfreeman
          03 сентября 2012, 16:47
          А. Г., где-то попадалось фраза — «на Wall Street за человеком, который из года в год показывает доходность 30-40%(не помню точно) _годовых_ инвесторы будут ходить по пятам...»
          • А. Г.
            03 сентября 2012, 17:34
            vfreeman,

            Так то в шататх с их ликвидностью, а это в России с нашей. Кому там интересен сайз в миллиард рублей? Да никому.
  • jtrade
    03 сентября 2012, 17:41
    Это бомба!)
      • jtrade
        03 сентября 2012, 20:30
        Максим Милованов, точно, так и есть.
        Максим, с помощью какой проги рисовал блок-схему?
        • jtrade
          03 сентября 2012, 21:29
          Jetta, не пробовал ли ту стратегию, та что на qpile (adx/cci)реализовать на S#?
  • zeppelin966
    03 сентября 2012, 21:27
    +++ Вот и готов робот осталось обкатать его Макс…
  • Мурен(а)
    02 октября 2012, 15:19
    а можно увидеть эквити этой стратегии? хотя бы в личку и на исторических данных

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн