Блог им. WinterMute

Торговая система своими руками. Часть 2. Базовые компоненты.

    • 01 сентября 2017, 11:36
    • |
    • k100
  • Еще

     Приветствую! В предыдущем посте была теория, теперь к делу. Кое-что буду упрощать, чтобы представить картинку в целом.

     Итак, чтобы проект не зависел от API внешней com библиотеки (SmartCom или д.р.), чтобы в коде стратегий  не использовались специфические типы, разработку я начала с обёрток над смарткомом. Я определил три базовых интерфейса: IConnectGate, IMarketDataGate и IPortfolioGate. Соответственно для подключения, для получения маркет-даты и для выставления заявок и работы с портфелем. Причём каждый из этих трёх интерфейсов мне надо было реализовать минимум дважды – для смарткома и для локального тестера.

     В случае со смарткомом, это некий адаптер-обёртка, благодаря которому, я оперирую собственными типами и не завишу от com библиотеки. Т.е. у меня есть свои типы (например, направление заявки, тайм-фрейм), которые используются в коде, а адаптер-обёртка конвертирует их в специфические, понятные внешней библиотеке. Также, желательно, чтобы у каждого объекта, в программе, была только одна обязанность, поэтому никакой дополнительной логики эти обёртки не несут.

     В случае с локальным тестером, реализации – это по большей части mock объекты, заглушки. Например, реализация IConnectGate для смарткома, это вызов метода подключения  и подписка на результат этого вызова, а в случае с локальным тестером мы никуда физически не подключаемся, а сразу генерируем событие “ Ok! Мы подключились!”.

     Далее, я определил интерфейс IStrategy, всего лишь с одним методом – Start. Вообще, изначально планировал сделать несколько классов  – класс генерирующий сигналы, класс, отвечающий за риск менеджмент, класс, который ведёт и закрывает позицию… Но, подумав, решил не усложнять  – особых плюсов это не дало бы, а только запутало. Все стратегии, которые я бы не делал, все реализуют интерфейс IStrategy. В конструктор стратеги передаются необходимые настройки (торгуемый тиккер, размер допустимой просадки, коэффициенты), инициализируются переменные и происходит подписка на события получения маркет-даты. А метод Start просто запускает процедуру получения маркет-даты и стратегия начинает работать. Конечно, можно было бы определить ещё несколько методов, благодаря которым, мы бы как-то влияли на стратегию во время её работы, или получали от неё какие-то данные, но пока опустим эти детали.

     Если стратегий несколько, и они используют специфические настройки, лучше использовать фабрику для их создания. Фабрика стратегий по некоему ID стратегии возвращает конкретную её реализацию, тем самым мы делегируем фабрике функцию создания стратегий:

interface IStrategyFactory
    {
        IStrategy CreateStrategy(int strategyID);
    }

     Согласно шаблону MVP, один презентер отвечает за одно представление (форму), каждое представление должно иметь презентера. Я создал два класса – некий MainPresenter и MainView для него. При старте программы, после необходимых настроек, вызывается конструктор MainPresenter’а и далее открывается MainView. В последующих постах, я буду детальнее описывать и развивать эту часть. Хочу подчеркнуть – внешний вид не важен, информацию можно получать и из консоли. Учитывая всё вышесказанное можно описать MainPresenter’а в первоначальном виде:

class MainPresenter
    {
        private IMainView mainView;
        private IStrategyFactory strategyFactory;
        private IConnectGate connectGate;

        public MainPresenter(IMainView mainView, IStrategyFactory strategyFactory, IConnectGate connectGate)
        {
            this.mainView = mainView;
            this.strategyFactory = strategyFactory;
            this.connectGate = connectGate;<br />
            this.connectGate.Connected += () =>
              this.strategyFactory.CreateStrategy(1).Start();

            this.connectGate.Connect();
        }

        public IMainView View => mainView;
    }

     В теле конструктора MainPresenter’а происходит инициализация переменных, подписка на событие подключения и собственно подключение. Почём подписка на событие могла бы выглядеть так:

private void ConnectHandler()
    {
        ...
    }

    connectGate.Connected += ConnectHandler; 

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

     Вот и всё. Мы скрыли все детали реализации, нам не важно, что за брокер, какова будет реализация интерфейсов, какая у нас стратегия торговли, мы не зависим от специфических библиотек – всё это решается в другом месте. Мы обобщили подход – инициализировали объекты, подписались на событие подключения, подключились, и запустились. Причём на данном этапе, все реализации могут быть заглушками.

 

     P.S.
     С днём знаний, друзья! ;-)

Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
182 | ★5

Читайте на SMART-LAB:
Фото
📊 Почему Группа «МГКЛ» уже превзошла цели предыдущего бизнес-плана
За последний год Группа «МГКЛ» значительно выросла по всем ключевым направлениям бизнеса. Компания увеличила объёмы операций и расширила клиентскую...
Фото
22 мая размещение облигаций Л-Старт (B.ru, 100 млн руб., YTM 32,53%)
❗️Информация для квалифицированных инвесторов ▶️ Разработчик и производитель оборудования для нефтегазовой отрасли Л-Старт объявляет о...
Фото
Лучше поздно чем никогда: краткие итоги мозгового штурма в понедельник
Доброе утро! Вчера болел зуб, поэтому я «зажал» конспект. Сегодня возвращаюсь с темами, к-е обсуждали. Напоминаю, каждый понедельник мы проводим...
Фото
Банк Санкт-Петербург: мультипликатор балансовой стоимости выглядит низким, пришло ли время покупать?
Банк Санкт-Петербург представил финансовые результаты по МСФО за 1-й квартал 2026 года. Чистая прибыль в 1К26 составила 10,9 млрд руб.,...

теги блога k100

....все тэги



UPDONW
Новый дизайн