Блог им. WinterMute

Торговая система своими руками. Часть 5. Работа с БД. Дата-сервис, структура таблиц.

    • 14 сентября 2017, 12:49
    • |
    • k100
  • Еще

     Приветствую. В предыдущем посте описывался интерфейс  для генерации тиковых данных – ITickGenerator. Его реализации могут быть разными: данные могут генерироваться на лету, или браться из БД. В случае с БД, возникает необходимость в организации ещё одного слоя приложения – слоя доступа к данным. TickGenerator, всё также будет оповещать подписчиков (стратегии, которые выставляют заявки), но по тем данным, которые он получит из БД.

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

     Я создал отдельный модуль, и там и развернул всю архитектуру, связанную с БД, основные компоненты которой: сущности, репозитории и дата-сервис.

     Хотя понятие сущности (Entity), само по себе, достаточно общее, здесь, буду применять его в узком смысле – это классы, представляющие таблицы БД, возможно, с какой-то дополнительной логикой. В простейшем случае, одна сущность – одна таблица. Между сущностями может быть связь (например, один ко многим), которая отражается и в связи между таблицами.  Сущность описывается полями класса, которые отражают колонки таблиц.

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

     И последнее, что необходимо – это класс дата-сервис. По сути, он аккумулирует все репозитории внутри себя. Впоследствии, на него может лечь управление транзакциями и правами доступа к данным. В остальных частях проекта используется именно дата-сервис.  Хотелось бы отметить также, что, дата-сервис отвечает и за маппинг. Это значит, что он конвертирует коллекции сущностей, полученные от репозиториев, в так называемые DTO (data transfer object). DTO – это классы-копии сущностей по части полей, но без логики и прочих аспектов. Т.е. DTO это облегченная версия сущности, и именно коллекции DTO должны циркулировать между различными слоями приложения, а не сущности. Для маппинга можно использовать готовые библиотеки, например – Automapper.

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

     Теперь, можно представить реализацию ITickGenerator работающую с дата-сервисом:

class TickGenerator : ITickGenerator
{
   public event EventHandler<StockTickEventArgs> OnTick;
   public event Action OnEnd;
   private IDataService dataService;

   public TickGenerator(IDataService dataService)
   {
     this.dataService = dataService;
   }

   public void Start(string symbol)
   {
     var ticks = dataService.Ticks(symbol);

     foreach (var t in ticks)
     OnTick?.Invoke(this, 
       new StockTickEventArgs()
       {
         Symbol = t.Symbol,
         Id = t.Id,
         DateTieme = t.DateTime,
         Price = t.Price,
         Vol = t.Vol
       });

     OnEnd?.Invoke();
   }
}

     TickGenerator, ничего не знает о способе хранения данных и организации доступа к ним. Задача TickGenerator’а – на каждый тик оповестить подписчиков (вызвать событие onTick) и в конце просигнализировать о завершении прогона (вызвать событие onEnd). Дата-сервис (IDataService), используется в качестве поставщика данных, и является связующим звеном между бизнес-логикой приложения и слоем доступа к данным.

     Для проведения бэк-тестов, я качаю данные (например, с Финама), заливаю их в таблицу TICKS и гоняю тесты. В качестве СУБД я использую ORACLE, есть бесплатные версии – XE. В ORACLE много интересных фишек – например, аналитические функции (о них расскажу позже). Также, можно использовать и PostgreSQL или даже встраиваемые NoSql СУБД, не требующие установки (это удобно для демонстрационных примеров). Что за СУБД не важно, если нет специфических требований по скорости (не важны миллисекунды), то сойдёт любая. БД – это просто способ хранения данных, ещё один аспект реализации. В следующем посте я расскажу про внутреннюю реализацию репозиториев и про способ связи с самой базой данных.

★12
14 комментариев
так работают тесты уже?
avatar
Denis, Да. Чуть позже я приведу примеры тестов.
avatar
k100, это вы хорошо, быстро двигается прогрес :)
avatar
Denis, Я вначале всё сделал, а потом захотел описать свой опыт на смартлабе, и, может быть, найти новых друзей )
avatar
k100, а какой в итоге опыт? Сколько сотен тысяч рублей в месяц? ;-)
avatar
Евгений, я лишь стараюсь беспристрастно описать свою систему. Сами стратегии и заработки — это отдельная тема, которой здесь посвящается достаточно топиков. Сама по себе система ничего не даст, я об этом подробнее напишу в скором времени.
avatar
k100, вот и давайте забежим вперед. Вы на что-то потратили время. Сколько теперь вам приносит доход эти затраты? Если ничего, то зачем об этом рассказывать? Другие потратят время в никуда, а могли бы на что-то полезное.
avatar
Евгений, когда я только начал тестировать систему, я мастерил самые простенькие стратегии — пробой предыдущего бара, простые импульсы и т.п. я удивился тогда, даже это могло бы дать прибыль… Но всё оказалось сложнее, на самом деле… Эта система — лишь —  шаг — на пути к результату, сделав этот шаг, я не стал миллионером, но это нисколько не умоляет его важность. По крайней мере для меня.
avatar
Евгений, Монетизировать сей труд не сложно даже вне биржи, если человек работает как разработчик, такого рода практика всегда полезна ибо повышает квалификацию, которая в последствии оплачивается выше :)

Но вы в целом с какой целью интерисуетесь? не тратьте время
avatar
Denis, стёб на айтишниками, которые думают, что их труды были полезны ;-) 
avatar
Евгений, я понимаю о чём вы. На самом деле я стараюсь в себе приглушить перфекционизм айтишника. Стейтмент важнее всего! Несомненно.
avatar
пока не прочел всю серию статей, но плюсую… интересно, продолжайте… мои роботы проще — главное чтобы работали, поддержка и модификация вторичны… но есть желание систематизировать торговую модель…
avatar
 тики финама — моветон на мой взгляд… сам использую orderLog цериха в qsh формате…
avatar
AntiKukl, Спасибо за отзыв!
avatar

теги блога k100

....все тэги



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