← Zurück

Тестирование 4.2.2.16. Вывод свечей на график.

Добрый вечер! Разъясните, пожалуйста, следующую ситуацию. Есть HistoryEmulationConnector. Есть свечи из бд (источник финам). Допустим такой набор

OPEN | HIGH | LOW | CLOSE | VOLUME | DATETIME_CANDLE 97.8000 | 98.2000 | 97.7500 | 98.0100 | 1505670 | 2013-10-01 10:00:00 98.0600 | 98.1100 | 97.8800 | 98.0000 | 1208190 | 2013-10-01 10:05:00 98.0000 | 98.1600 | 97.9500 | 98.0000 | 3890740 | 2013-10-01 10:10:00 98.0000 | 98.0500 | 98.0000 | 98.0400 | 99520 | 2013-10-01 10:15:00 ...

Свечи формируются следующим образом


var time = DateTime.ParseExact(candle.DatetimeCandle, "dd.MM.yyyy HH:mm:ss", null);
return new TimeFrameCandle()
{
    OpenPrice = candle.Open,
    HighPrice = candle.High,
    LowPrice = candle.Low,
    ClosePrice = candle.Close,
    TimeFrame = timeFrameCandle,
    OpenTime = time,
    CloseTime = time + timeFrameCandle,
    TotalVolume = candle.Volume,
    Security = security,
    State = CandleStates.Finished
};

Если смотреть через дебаггер - то значения соответствуют тем, что выше.

  1. Но вот при отрисовке свечей их OPEN и CLOSE значения изменяются. Изменяются они не намного, но все же мне пока не понятно по какому принципу это происходит.
  2. И еще - все первые свечи (10:00:00) каждого дня при отрисовке имеют OPEN = HIGH = LOW = CLOSE, что, например, не соответствует данным, указанным выше. (Для первого набора, например, эти значения равны 97,8)

Буду благодарен, если кто-то объяснит почему так происходит.

War dieses Thema hilfreich?

Thema teilen

Kommentare (13)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Bond
Bond

Добрый день! К сведению, некоторые особенности формирования свечей из тиков:

  • Свечи закрываются первой сделкой из следующей свечи. Так может возникнуть запаздывание события закрытия свечи.
  • В первой свече может возникнуть неопределенность и, в принципе, по алгоритму может формироваться новая свеча только когда закроется первая. Но это нужно смотреть алгоритм.

Изменяются они не намного Уточните конкретнее о чем речь.

Вам лучше по шагам просмотреть как парсится текстовый файл. Тогда сразу будет все понятно.

romany4
romany4 Autor

Добрый день.

Уточните конкретнее о чем речь. Есть уже готовые свечи в бд. Хранятся они в таком виде:

OPEN | HIGH | LOW | CLOSE | DATETIME_CANDLE 97.8000 | 98.2000 | 97.7500 | 98.0100 | 2013-10-01 10:00:00 98.0600 | 98.1100 | 97.8800 | 98.0000 | 2013-10-01 10:05:00 98.0000 | 98.1600 | 97.9500 | 98.0000 | 2013-10-01 10:10:00 98.0000 | 98.0500 | 98.0000 | 98.0400 | 2013-10-01 10:15:00

Данные из бд получаю и сохраняю в IEnumerable<Candle> candles Если смотреть candles через дебаггер - то все нормально - данные те же самые.
Далее я их сохраняю в StorageRegistry, который в свою очередь используется в HistoryEmulationConnector И вот если через дебаг смотреть уже метод DrawCandle то там будут такие значения

OPEN | HIGH | LOW | CLOSE | DATETIME_CANDLE 97.8000 | 98.8000 | 97.8000 | 98.8000 | 2013-10-01 10:00:00 97.7500 | 98.2000 | 97.7500 | 98.0600 | 2013-10-01 10:05:00 98.1100 | 98.1100 | 97.8800 | 98.0000| 2013-10-01 10:10:00 98.1600 | 98.1600 | 97.9500 | 98.0000 | 2013-10-01 10:15:00 98.0000 | 98.0500 | 98.0000 | 98.0400 | 2013-10-01 10:20:00

Т.е. получается так. Первая свеча формируется из OPEN. При этом OPEN = HIGH = LOW = CLOSE. Для остальных свечей HIGH и LOW соответствуют первоначальным значениям (что и в бд). А вот OPEN и CLOSE не намного изменяются, и изменяются они не везде, но в большинстве случаев.

Bond
Bond

Приведите полный код преобразований. Здесь явно какая-то ошибка.

romany4
romany4 Autor

Так получаю свечи


IEnumerable<Candle> candles = instanceCandle.GetHistoryCandle(_security, _fromDate.ToMysqlTimestampFormat(), _toDate.ToMysqlTimestampFormat(), timeFrameCandle);

если смотреть через дебаг - candles содержит тот же набор что и в бд.

теперь сохраняю в StorageRegistry, затем создаю HistoryEmulationConnector, и вывожу свечи


var registry = new StorageRegistry();
registry.GetCandleStorage(typeof(TimeFrameCandle), _security, timeFrameCandle).Save(candles);
// тестовый портфель
var portfolio = new Portfolio
{
    Name = "test account",
    BeginValue = 10000,
};

//шлюз для эмуляции
var trader = new HistoryEmulationConnector(
    new[] { _security },
    new[] { portfolio })
{
    StorageRegistry = registry,
    MarketEmulator =
    {
        Settings =
        {
            // использовать свечки
            UseCandlesTimeFrame = timeFrameCandle,
            MatchOnTouch = false,
        }
    }
};
trader.MarketDataAdapter.SessionHolder.MarketTimeChangedInterval = TimeSpan.FromSeconds(10);

trader.NewSecurities += securities =>
{
    if (securities.All(s => s != _security))
        return;

    trader.RegisterMarketDepth(new TrendMarketDepthGenerator(trader.GetSecurityId(_security))
    {
        // стакан для инструмента в истории обновляется раз в секунду
        Interval = TimeSpan.FromSeconds(1),
        MaxAsksDepth = 1,
        MaxBidsDepth = 1,
        UseTradeVolume = true,
        MaxVolume = 1,
        MinSpreadStepCount = 2,
        MaxSpreadStepCount = 5,
        MaxPriceStepCount = 3
    });
};
trader.Connect();
trader.StartExport();

_candleManager = new CandleManager(trader);

_series = new CandleSeries(typeof(TimeFrameCandle), _security, timeFrameCandle);
                                
_area = new ChartArea();
Chart.Areas.Add(_area);

//создание элемента графика представляющего свечки
_candlesElem = new ChartCandleElement();
_area.Elements.Add(_candlesElem);

_series.ProcessCandle += DrawCandle;

Вот собственно весь код.

И вот еще сам метод DrawCandle

private void DrawCandle(Candle candle)
{
    this.GuiAsync(() => Chart.ProcessCandle((ChartCandleElement)Chart.Areas[0].Elements[0], candle));
}

Bond
Bond

Вы берете текстовый файл с данными свечи. Потом его парсите и сохраняете в хранилище. Потом берете из хранилища сохраненные свечи(!). При этом используете генератор стакана! Затем создаете свечи из приходящих сделок (скорее всего случайные из стакана. Здесь появляются отличия.) 😂 Я даже не знаю как эту схему еще больше можно усложнить) Берете свечи - используйте свечи. Торгуете тики и стаканы - используйте тики и стаканы. От себя советую не использовать никакие генераторы - это бред. Торгуйте свечи или тики. Нужны стаканы - берите ордер лог. Данные качайте Гидрой и не забиыайте себе голову всякими ненужными преобразованиями.

devruss
devruss

Bond: От себя советую не использовать никакие генераторы - это бред.

Не использовать ни при каких обстоятельствах. Я где-то создавал тему, где сравнивал подходы и генератором и без, там вывод был, что с включенным генератором результат получается сильно искаженным

romany4
romany4 Autor

Спасибо за советы) Намудрил) Тогда подскажите, правильно ли я понимаю, что могу исключить этот блок кода


trader.NewSecurities += securities =>
                                {
                                    if (securities.All(s => s != _security))
                                        return;
                                    trader.RegisterMarketDepth(new TrendMarketDepthGenerator(trader.GetSecurityId(_security))
                                    {
                                        // стакан для инструмента в истории обновляется раз в секунду
                                        Interval = TimeSpan.FromSeconds(1),
                                        MaxAsksDepth = 1,
                                        MaxBidsDepth = 1,
                                        UseTradeVolume = true,
                                        MaxVolume = 1,
                                        MinSpreadStepCount = 2,
                                        MaxSpreadStepCount = 5,
                                        MaxPriceStepCount = 3
                                    });
                                };

скорее всего случайные из стакана. Здесь появляются отличия Почему тогда эта случайность одна и та же? или тут речь о псевдослучайности?

PS Закомментил пока этот код у себя. Но результат тот же.

romany4
romany4 Autor

Собственно в продолжение темы решил данные выкачать гидрой и проверить.

  1. Для сравнения выкачиваем данные с финама вручную (тыц) (Сбербанк, с 01.10.2013 по 01.12.2013, 5мин. свечи) - это будет эталон, на который будем ориентироваться.
  2. С помощью гидры также выкачиваем Сбер за аналогичный период. (только пятиминутные свечи, без сделок)
  3. Протестируем данные гидры на SampleHistoryTesting (4.2.2.16)
  4. Проверим данные, записанные в лог и сравним их с тем, что прислал финам Вот что я вижу - финам
<TICKER>;<PER>;<DATE>;<TIME>;<OPEN>;<HIGH>;<LOW>;<CLOSE>;<VOL> SBER;5;20131001;100000;97.8000000;98.2000000;97.7500000;98.0100000;1505670 SBER;5;20131001;100500;98.0600000;98.1100000;97.8800000;98.0000000;1208190 SBER;5;20131001;101000;98.0000000;98.1600000;97.9500000;98.0000000;3890740 SBER;5;20131001;101500;98.0000000;98.0500000;98.0000000;98.0400000;99520 SBER;5;20131001;102000;98.0400000;98.3500000;98.0400000;98.2000000;1323520 SBER;5;20131001;102500;98.1900000;98.6400000;98.1600000;98.4100000;2353380 SBER;5;20131001;103000;98.4300000;98.6200000;98.3000000;98.3500000;1511960 SBER;5;20131001;103500;98.3900000;98.4000000;98.2500000;98.3000000;558720 SBER;5;20131001;104000;98.3500000;98.4400000;98.2600000;98.3000000;715980 SBER;5;20131001;104500;98.3100000;98.3900000;98.2000000;98.2100000;316160 SBER;5;20131001;105000;98.2200000;98.2800000;98.0700000;98.1100000;890210 SBER;5;20131001;105500;98.1200000;98.2800000;98.0300000;98.1700000;892270

лог с SampleHistoryTesting

2013/10/01 00:00:00.000| |SS_SBER@EQBR_test account|Стратегия запущена. [0,-1]. Позиция при старте 0. 2013/10/01 00:00:00.000| |HistoryEmulationConnector|Инструмент SBER@EQBR зарегистрирован на получение рыночных данных для Candles. 2014/03/15 12:44:13.945| |HistoryMessageAdapter|Loading 01.10.2013 0:00:00 Events: 0 2014/03/15 12:44:14.096| |HistoryMessageAdapter|Loading 02.10.2013 0:00:00 Events: 212 2014/03/15 12:44:14.102| |HistoryMessageAdapter|Loading 03.10.2013 0:00:00 Events: 424 2014/03/15 12:44:14.107| |HistoryMessageAdapter|Loading 04.10.2013 0:00:00 Events: 636 2013/10/01 10:05:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:00:00: 97.8000000;97.8000000;97.8000000;97.8000000; объем 376417 2014/03/15 12:44:14.421| |HistoryMessageAdapter|Loading 05.10.2013 0:00:00 Events: 848 2014/03/15 12:44:14.425| |HistoryMessageAdapter|Loading 06.10.2013 0:00:00 Events: 848 2014/03/15 12:44:14.427| |HistoryMessageAdapter|Loading 07.10.2013 0:00:00 Events: 848 2013/10/01 10:10:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:05:00: 97.7500000;98.2000000;97.7500000;98.0600000; объем 1431300 2013/10/01 10:15:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:10:00: 98.1100000;98.1100000;97.8800000;98.0000000; объем 1878828 2013/10/01 10:20:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:15:00: 98.1600000;98.1600000;97.9500000;98.0000000; объем 2942935 2013/10/01 10:25:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:20:00: 98.0000000;98.0500000;98.0000000;98.0400000; объем 405520 2013/10/01 10:30:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:25:00: 98.0400000;98.3500000;98.0400000;98.1900000; объем 1580985 2013/10/01 10:35:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:30:00: 98.1600000;98.6400000;98.1600000;98.4300000; объем 2143025 2013/10/01 10:40:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:35:00: 98.6200000;98.6200000;98.3000000;98.3900000; объем 1273650 2013/10/01 10:45:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:40:00: 98.4000000;98.4000000;98.2500000;98.3500000; объем 598035 2013/10/01 10:50:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:45:00: 98.4400000;98.4400000;98.2600000;98.3100000; объем 616025 2013/10/01 10:55:00.000| |SS_SBER@EQBR_test account|Новая свеча 10/01/2013 10:50:00: 98.3900000;98.3900000;98.2000000;98.2200000; объем 459672

Наблюдаются те же самые расхождения. Совпадают только HIGH и LOW цены.

devruss
devruss

romany4: Наблюдаются те же самые расхождения. Совпадают только HIGH и LOW цены.

У финама дырявые данные. НО бесплатные=))) Доверять можно только данным записанным вживую с рынка, и то, с определенным скептицизмом (latency, рассинхронизация на очень маленьких таймфреймах и т.д.)

Bond
Bond

Сбросьте ВСЕ файлы, включая ваш пример и исторические данные в одном архиве на почту bond_algotrade@mail.ru Найдем, где собака зарыта.

romany4
romany4 Autor

У финама дырявые данные Тут суть то в том, что через гидру я тоже качаю финамовские данные (источник Финам). И получается, что данные полученные от финама напрямую, отличаются от данных финама, скачанные гидрой. Собственно со всего этого и началось. Я хочу понять почему так происходит.

Сбросьте ВСЕ файлы, включая ваш пример и исторические данные в одном архиве Сегодня-завтра скину

Bond
Bond

Добрый день! Раньше, к сожалению, не было возможности посмотреть ваши файлы. Поэтому отвечаю только сейчас. Значит, что я обнаружил. Ошибку вашу подтверждаю. Свечки строятся не правильно. В высланном вами примере творится хаос. На мой взгляд все слишком мудрено написано. Странная схема построения свечек и работа с series. Это все таки тестирование, а не реальная торговля, зачем с этим заморачиваться не понятно. Предлагаю такую схему работы со свечами:


//Загружаем из хранилища свечи, + добавляем один день(косяк - не выводит последний день)
var candles = storageRegistry.GetCandleStorage(typeof(TimeFrameCandle), security, timeFrame).Load(startTime, stopTime.AddDays(1));

//Перебираем полученные свечи
foreach (var candle in candles)
{
   DrawCandle(candle, ChartCandleElement);
}

//Выводим их на график или обрабатываем как нравится
private void DrawCandle(Candle candle, ChartCandleElement chartCandleElement)
{
   this.GuiAsync(() => _candleWindow.Chart.ProcessCandle(chartCandleElement, candle));
}

Отправил вам на почту рабочий пример работы со свечами.

romany4
romany4
romany4 Autor

Спасибо за помощь)

Ошибку вашу подтверждаю. Свечки строятся не правильно. ... Это все таки тестирование, а не реальная торговля, зачем с этим заморачиваться не понятно. Просто если вести статистику - то можно запутаться, получается что на деле значения свечи одни а в эмуляторе уже другие. И тем более при переходе на реальную торговлю это не вызовет неожиданных результатов? Было бы классно, если ребята из S# прокомметировали эту ситуацию...