← 戻る

Получение свечных данных из сообщений

Добрый день. Храню свечные данные в СУБД MS SQL Server (open/close time, o, h, l, c, V).

До сего момента использовал данные из файлов (Hydra/<первая буква инструмента>/<инструмент>/candles_TimeFrameCandle_1.00-00-00.bin), примерно так:

var storageRegistry = new StorageRegistry { DefaultDrive = new LocalMarketDataDrive(config.history_folder_path) };

Хотел бы, чтобы HistoryEmulationConnector получал данные не из файлов а, например, из сообщений-свечек, полученных после выборки данных из СУБД.

Дайте, по-возможности, совет (лучше пример кода), как реализовать такую логику работы: -> Загрузили из БД свечные данные по инструменту -> Сформировали правильно сообщения-свечки из загруженных данных -> После старта исторического тестирования HistoryEmulationConnector начал получать сообщения-свечки -> Все работает, словно запустили тестирование из коробки

Спасибо!

このトピックは参考になりましたか?

トピックを共有

コメント (12)

ログイン または アカウントを作成, コメントを残すにはログインまたは新規登録してください

Support
Support

Посмотрите пример в атачменте. Там показано как подключить к эмулятору коллекцию свечей... По идее, то же самое можно сделать с коллекцией свечей...

gewinn
Support
Support

Support: Посмотрите пример в атачменте. Там показано как подключить к эмулятору коллекцию сделок... По идее, то же самое можно сделать с коллекцией свечей...

gewinn
gewinn 著者

Спасибо, попробую

Support
Support

..

gewinn
gewinn 著者

Все заработало. Спасибо!

Если кому будет интересно использовать свои свечные данные из своей (или удаленной СУБД), то, основываясь на примере от уважаемого суппорта SS, реализовал так:

  1. Получаем свечные данные из БД, формируем свечки, кладем в коллекцию:

    ....
    while (reader.Read())
            {
                candles_list.Add(new TimeFrameCandle()
                {
                    Security = security,
                    TimeFrame = TimeSpan.FromMinutes(period),
                    OpenTime = new DateTimeOffset((DateTime)reader["open_datetime"], ST.timezone_timespan_hours),
                    CloseTime = new DateTimeOffset((DateTime)reader["open_datetime"] + TimeSpan.FromMinutes(period), ST.timezone_timespan_hours),
                    OpenPrice = (decimal)(double)reader["o"],
                    HighPrice = (decimal)(double)reader["h"],
                    LowPrice = (decimal)(double)reader["l"],
                    ClosePrice = (decimal)(double)reader["c"],
                    TotalVolume = (decimal)(double)reader["v"]
                });
            }
            db.closeDbConnection();
  1. Пишем ф-цию, которая превращает свечки из коллекции в сообщения:

public IEnumerable<Message> getCandles(DateTimeOffset d)
{
    return candles_list.Where(с=> ((с.OpenTime.Date == d.Date) && (с.OpenTime.TimeOfDay == d.TimeOfDay))).Select(t => t.ToMessage());
} 

  1. Подписываемся на исторические данные из наших сообщений:
...
connector.RegisterHistorySource(security, MarketDataTypes.CandleTimeFrame, typeof(Candle), getCandles);
...
  1. Работаем дальше как из "коробки" - создаем экземпляр класса CandleManager, создаем серию свечек:
...
candle_manager = new CandleManager(connector);
...
candle_serie = new CandleSeries(typeof(TimeFrameCandle), security, TimeSpan.FromMinutes(period));
...
candle_manager.Start(candle_serie);
  1. Подписываемся на событие появления новых свечей и работаем с ними :)
candle_manager .Processing += (series, candle) => 
{
    //TODO
};

Еще раз спасибо!

Support
Support

..

gewinn
gewinn 著者

Добрый день! После обновления с версии 4.4.5.4 до версии 4.4.8 перестали приходить свечи. Проблема, судя по всему, в "3) Подписываемся на исторические данные из наших сообщений:".

Фрагмент лога:

0001/01/01 00:00:00.000| |AHistoryEmulationConnector|Connect 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connecting 'EmulationMessageAdapter'. 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connected to 'EmulationMessageAdapter'. 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connecting 'История (c 10.07.2013 3:00:00 +00:00 по 23.03.2018 3:00:00 +00:00)'. 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connected to 'История (c 10.07.2013 3:00:00 +00:00 по 23.03.2018 3:00:00 +00:00)'. 2013/07/10 03:00:00.000| |AHistoryEmulationConnector|Создан новый портфель TestPortfolio#0. 2013/07/10 03:00:00.000| |Strategy_SBER@TQBR|Стратегия Запущена. [0,-1]. Позиция 0. 2013/07/10 03:00:00.000| |Strategy_GAZP@TQBS|Стратегия Запущена. [0,-1]. Позиция 0. 2013/07/10 03:00:00.000| |Strategy_MICEX10INDEX@MICEX|Стратегия Запущена. [0,-1]. Позиция 0. 2013/07/10 03:00:00.000|Error |HistoryBasketMessageAdapter|System.InvalidOperationException: Не найден подходящий адаптер для MarketData,T(L)=2013/07/10 03:00:00.000,Sec=S#:SBER@TQBR, Native:,Type:,Sec=S#:SBER@TQBR, Native:,Type:,Type=CandleTimeFrame,IsSubscribe=True,Arg=1.00:00:00,TransId=8,OrigId=0. в StockSharp.Algo.BasketMessageAdapter.GetSubscriptionAdapters(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.ProcessMarketDataRequest(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.OnSendInMessage(Message message) в StockSharp.Messages.MessageAdapter.SendInMessage(Message message)

Не подскажите, как правильно теперь подписываться на свечи из внешнего источника? Спасибо.

Support
Support

Добрый день

Регистрация внешних источник была изменена в версии 4.4.7. Вы можете посмотреть пример SampleHistoryTesting как работать с внешними источниками. В примере используются сервисы Финам и Яху.

Изменения разработчиков https://github.com/StockSharp/StockSharp/commit/db0dfb39d05140db7565acdb05a771248e4b2202#diff-84a8277382d10d989376c69e0b8c30e5

gewinn
gewinn 著者

Добрый вечер. Пример SampleHistoryTesting и github я посмотрел прежде чем писать сообщение выше. После вашего ответа перепроверил еще раз - но каких-либо существенных изменений у вас в примере не нашел, кроме:

  1. Подписка происходит теперь по событию подключения
  2. Подписка происходит для всех инструментов сразу - в метод RegisterHistorySource() первым аргументом вы передаете null.

У меня в коннекторе HistoryEmulationConnector используется не один инструмент (у каждого своя стратегия). Плюс ко всему, каждый инструмент может содержать несколько таймфреймов. Поэтому ранее я метод RegisterHistorySource() вызывал для всех таймфреймов для каждого инструмента. Попробовал подписаться по событию подключения - тщетно. Поэтому непонятно даже, куда копать :( Танцевал с бубном долго.

Псевдокод получается такой:

  1. Для каждого таймфрейма каждого инструмента подгружаю из СУБД свечи в коллекцию таймфрейма
public List<Candle> candles_sourse;

В классе каждого таймфрейма реализован метод getCandles() :

public IEnumerable<Message> getCandles(DateTimeOffset d)
        {
            return candles_sourse.Where(
                c => c.OpenTime.Date == d.Date
            ).Select(t => t.ToMessage());
        }
  1. В HistoryEmulationConnector подписываюсь на события изменения состояния, успешного подключения и получения инструментов:
StateChanged += AHistoryEmulationConnector_StateChanged;
NewSecurity += AHistoryEmulationConnector_NewSecurity;
Connected += AHistoryEmulationConnector_Connected;
  1. Событие успешного подключения AHistoryEmulationConnector_Connected() :
private void AHistoryEmulationConnector_Connected()
        {
            для каждого инструмента security из всех инструментов
            {
                для каждого таймфрейма t из всех таймфремов инструмента
                {
                    RegisterHistorySource(security, MarketDataTypes.CandleTimeFrame, TimeSpan.FromMinutes(t.period), t.getCandles);
                }
            }
        }
  1. Событие получения инструмента AHistoryEmulationConnector_NewSecurity() :

4.1. Создаю стратегию для пришедшего инструмента
4.2. Если пришли все имеющиеся инструменты:
 -> Запускаю все стратегии методом strategy.Start()
 -> Вызываю метод Start() для HistoryEmulationConnector

Вопросы:

  1. Правильная ли логика и порядок действий?
  2. Прежде, чем собирать сжатый пример по данной ситуации (например, их двух инструментов в одном коннекторе), можете, пожалуйста, написать более подробно, что вы поменяли в плане подписок на внешние источники в версии 4.4.7. Попробую сам догадаться, т.к. в примере не совсем ясно, как реализованы методы getCandles() у источников Финам и Яху.

Спасибо!

Support
Support

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

gewinn
gewinn 著者

Добрый день. Подписка на данные в эмуляторе не помогла (ранее она была необходима только при биржевых подключениях).

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

Цель: получить на обработку свечку с методе processCandle() внутри стратегии.

Очень надеюсь на помощь.

Логи пока такие:

0001/01/01 00:00:00.000| |HistoryEmulationConnector|Connect 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connecting 'EmulationMessageAdapter'. 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connected to 'EmulationMessageAdapter'. 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connecting 'История (c 07.05.2018 10:00:00 +03:00 по 09.05.2018 10:00:00 +03:00)'. 0001/01/01 00:00:00.000| |HistoryBasketMessageAdapter|Connected to 'История (c 07.05.2018 10:00:00 +03:00 по 09.05.2018 10:00:00 +03:00)'. 2018/05/07 10:00:00.000| |HistoryEmulationConnector|Создан новый портфель TestPortfolio. 2018/05/07 13:13:50.521|Debug |SecurityMarketEmulator| --> Board,T(L)=0001.01.01 00:00:00.000,Code=TQBR,Ex=MOEX 2018/05/07 13:13:50.528|Debug |SecurityMarketEmulator| --> Security,T(L)=2018.05.07 10:00:00.000,Sec=S#:GASP@TQBR, Native:,Type: 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент GASP@TQBR подписается на Level1. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент GASP@TQBR подписается на Trades. 2018/05/07 13:13:50.669|Debug |SecurityMarketEmulator| --> Board,T(L)=2018.05.07 10:00:00.000,Code=TQBR,Ex=MOEX 2018/05/07 13:13:50.673|Debug |SecurityMarketEmulator| --> Board,T(L)=0001.01.01 00:00:00.000,Code=TQBR,Ex=MOEX 2018/05/07 13:13:50.673|Debug |SecurityMarketEmulator| --> Security,T(L)=2018.05.07 10:00:00.000,Sec=S#:LKOH@TQBR, Native:,Type: 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент LKOH@TQBR подписается на Level1. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент LKOH@TQBR подписается на Trades. 2018/05/07 10:00:00.000|Debug |strategy_GASP@TQBR|Переход из состояния Stopped в Started. 2018/05/07 10:00:00.000| |strategy_GASP@TQBR|Стратегия Запущена. [0,-1]. Позиция 0. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент GASP@TQBR подписается на CandleTimeFrame 1.00:00:00. 2018/05/07 10:00:00.000|Debug |strategy_LKOH@TQBR|Переход из состояния Stopped в Started. 2018/05/07 10:00:00.000| |strategy_LKOH@TQBR|Стратегия Запущена. [0,-1]. Позиция 0. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент LKOH@TQBR подписается на CandleTimeFrame 1.00:00:00. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент GASP@TQBR подписан на Level1. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент GASP@TQBR подписан на Trades. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент LKOH@TQBR подписан на Level1. 2018/05/07 10:00:00.000|Debug |HistoryEmulationConnector|Инструмент LKOH@TQBR подписан на Trades. 2018/05/07 10:00:00.000|Error |HistoryBasketMessageAdapter|System.InvalidOperationException: Не найден подходящий адаптер для MarketData,T(L)=2018/05/07 10:00:00.000,Sec=S#:GASP@TQBR, Native:,Type:,Sec=S#:GASP@TQBR, Native:,Type:,Type=CandleTimeFrame,IsSubscribe=True,Arg=1.00:00:00,TransId=11,OrigId=0. в StockSharp.Algo.BasketMessageAdapter.GetSubscriptionAdapters(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.ProcessMarketDataRequest(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.OnSendInMessage(Message message) в StockSharp.Messages.MessageAdapter.SendInMessage(Message message) 2018/05/07 10:00:00.000|Error |HistoryEmulationConnector|System.InvalidOperationException: Не найден подходящий адаптер для MarketData,T(L)=2018/05/07 10:00:00.000,Sec=S#:GASP@TQBR, Native:,Type:,Sec=S#:GASP@TQBR, Native:,Type:,Type=CandleTimeFrame,IsSubscribe=True,Arg=1.00:00:00,TransId=11,OrigId=0. в StockSharp.Algo.BasketMessageAdapter.GetSubscriptionAdapters(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.ProcessMarketDataRequest(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.OnSendInMessage(Message message) в StockSharp.Messages.MessageAdapter.SendInMessage(Message message) 2018/05/07 10:00:00.000|Error |HistoryBasketMessageAdapter|System.InvalidOperationException: Не найден подходящий адаптер для MarketData,T(L)=2018/05/07 10:00:00.000,Sec=S#:LKOH@TQBR, Native:,Type:,Sec=S#:LKOH@TQBR, Native:,Type:,Type=CandleTimeFrame,IsSubscribe=True,Arg=1.00:00:00,TransId=13,OrigId=0. в StockSharp.Algo.BasketMessageAdapter.GetSubscriptionAdapters(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.ProcessMarketDataRequest(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.OnSendInMessage(Message message) в StockSharp.Messages.MessageAdapter.SendInMessage(Message message) 2018/05/07 10:00:00.000|Error |HistoryEmulationConnector|System.InvalidOperationException: Не найден подходящий адаптер для MarketData,T(L)=2018/05/07 10:00:00.000,Sec=S#:LKOH@TQBR, Native:,Type:,Sec=S#:LKOH@TQBR, Native:,Type:,Type=CandleTimeFrame,IsSubscribe=True,Arg=1.00:00:00,TransId=13,OrigId=0. в StockSharp.Algo.BasketMessageAdapter.GetSubscriptionAdapters(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.ProcessMarketDataRequest(MarketDataMessage mdMsg) в StockSharp.Algo.BasketMessageAdapter.OnSendInMessage(Message message) в StockSharp.Messages.MessageAdapter.SendInMessage(Message message) 2018/05/07 10:00:00.000| |HistoryEmulationConnector|Изменение состояния эмуляции Stopped -> Starting 2018/05/07 10:00:00.000| |HistoryEmulationConnector|Изменение состояния эмуляции Starting -> Started 2018/05/09 07:00:00.000| |HistoryEmulationConnector|Изменение состояния эмуляции Started -> Stopping 2018/05/09 07:00:00.000| |HistoryEmulationConnector|Изменение состояния эмуляции Stopping -> Stopped 2018/05/09 07:00:00.000| |HistoryEmulationConnector|Disconnect 2018/05/09 07:00:00.000| |HistoryBasketMessageAdapter|Disconnecting 'EmulationMessageAdapter'. 2018/05/09 07:00:00.000| |HistoryBasketMessageAdapter|Disconnected from 'EmulationMessageAdapter'. 2018/05/09 07:00:00.000| |HistoryBasketMessageAdapter|Disconnecting 'История (c 07.05.2018 10:00:00 +03:00 по 09.05.2018 10:00:00 +03:00)'. 2018/05/09 07:00:00.000| |HistoryBasketMessageAdapter|Disconnected from 'История (c 07.05.2018 10:00:00 +03:00 по 09.05.2018 10:00:00 +03:00)'.
Support
Support

Проблема решена по почте.