← Voltar

Возможная ошибка S#

Добрый день.

Пишу робота на S#. Подписан на событие формирования новой свечи. Timeframe 1 минута. В момент прихода новой свечи цена close последней свечи отличается от close той же свечи, полученной с Finam'a на 1-7 пунктов (контракт Si-9.13). Если отключаюсь и заново подключаюсь, то цены закрытия тех же самых свечей в точности совпадают с ценами закрытия по данным с Finam'а. Цены open, high, low также идут с ошибками: [Количество несовпадений (на примере одного дня)]: open: 0 high: 17 несовпадений low: 23 несовпадения close: 188 несовпадений Всего 532 бара. Во время вечерней сессии данные по свечам приходят корректные.

Общение с техподдержкой SmartCOM позволило выделить 2 возможные причины данной проблемы:

  1. Либо происходят потери при получении тиковых данных от сервера, на основе которых S# формирует свечи.
  2. Либо платформа S# неверно формирует свечи по тем данным, по которым получает данные от серверов.

Учитывая, что после перезапуска приложения, приходят корректные данные о свечах, можно предположить, что более вероятен второй вариант. Чтобы проверить, выполняю подписку на исторические свечи каждый раз после прихода события формирования новой свечи. В обработчике события NewHistoryCandles отслеживаю повторно полученную информацию о серии. Результат: данные не меняются.

Вопросы:

  1. Правильно ли я понимаю, что внутри метода, реализующего формирование новой свечи, вызов GetBars осуществляется всего один раз при самом первом запуске приложения, а затем, S# не запрашивает каждый раз сервер о параметрах сформировавшейся свечи, а сам каким-то образом формирует свечи?
  2. Как можно вызвать GetBars (или метод, который запросит информацию от сервера посредством GetBars)?
  3. В каком событии и как отлавливать пришедшую информацию?

Este tópico foi útil?

Compartilhar tópico

Comentários (20)

Entrar ou Criar conta, Faça login ou cadastre-se para deixar um comentário

andy_baka
andy_baka

Наверное событие NewHistoricalCandles? А как вы получаете исторические свечки в событии о приходе новой свечи? Нативными средствами SmartCom или же через CandleManager?

Mikhail Sukhov
Mikhail Sukhov

andy_baka: Наверное событие NewHistoricalCandles? А как вы получаете исторические свечки в событии о приходе новой свечи? Нативными средствами SmartCom или же через CandleManager?

Присоединяюсь к вопросу. Хотя бы схематический код нужен, что откуда и куда.

ttt
ttt Autor

Наверное событие NewHistoricalCandles? Да.

А как вы получаете исторические свечки в событии о приходе новой свечи? Нативными средствами SmartCom или же через CandleManager?

Через CandleManager. Напишите, pls, если возможно, как в моем случае можно использовать нативные средства SmartCOM (явно выполнить GetBars и затем обработать полученную серию).

Схема работы:

Запускаю получение свечей: ```csharp private void btnGetHistory_Click(object sender, EventArgs e) { DateTime date1 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 10, 0, 0); _lkSeries = new CandleSeries(typeof(TimeFrameCandle), _lkoh, TimeSpan.FromMinutes(1)); _candleManager.Start(_lkSeries, date1, DateTime.Now); }


Отлавливаю данные в обработчике события NewHistoricalCandles:
Схема:
ЕСЛИ пришла 1 свеча,
ТО вывожу на экран только ее
ИНАЧЕ вывожу все свечи, начиная с последней загруженной

               ```csharp
_trader.NewHistoricalCandles  += (seri, candy) =>
                {
                    int cou = seri.GetCandleCount();
                    if (seri.Security.Code == _lkoh.Code)
                    {
//                            http://stocksharp.com/forum/3656/Urok-4---Sviechi--ghrafiki--istoriia/
                             
                            TimeSpan ts = seri.GetCandle<Candle>(0).OpenTime - GlobalParameters.lkohTimeLoad;
                            if (ts.TotalMinutes == 1)  // получена одна свеча: все как положено, без сбоев   
                            {
                                GlobalParameters.lkohTimeLoad = seri.GetCandle<Candle>(0).OpenTime;
                                _lkCandle = seri.GetCandle<Candle>(0);

                                SafeAddToTxb(txtSmartInfo, DateTime.Now.ToString() + " | " + _lkCandle.OpenTime.ToString() + " | " + _lkCandle.CloseTime.ToString() + " | " + _lkCandle.OpenPrice.ToString() + " | " + _lkCandle.HighPrice.ToString() + " | " + _lkCandle.LowPrice.ToString() + " | " + _lkCandle.ClosePrice.ToString());

// далее выполняется повторный запрос последних 10 свечей (для выявления ошибки)
                                DateTime date1 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 10, 0, 0);
                                _trader.RegisterHistoryCandles(_lkoh, SmartTimeFrames.Minute1, DateTime.Now, 10, SmartHistoryDirections.Backward);
                            }
                            else if (ts.TotalMinutes > 1)  // был разрыв связи или еще какой-то сбой или самое начало работы
                            {
                                int i = 1;
                                try
                                {
                                    while (seri.GetCandle<Candle>(i).OpenTime > GlobalParameters.lkohTimeLoad)
                                    {
                                        i = i + 1;
                                    }
                                }
                                catch { }
                                GlobalParameters.lkohTimeLoad = seri.GetCandle<Candle>(0).OpenTime;

                                i = i - 1;
                                while (i >= 0)
                                {
                                    _lkCandle = seri.GetCandle<Candle>(i);

                                    SafeAddToTxb(txtSmartInfo, DateTime.Now.ToString() + " | " + _lkCandle.OpenTime.ToString() + " | " + _lkCandle.CloseTime.ToString() + " | " + _lkCandle.OpenPrice.ToString() + " | " + _lkCandle.HighPrice.ToString() + " | " + _lkCandle.LowPrice.ToString() + " | " + _lkCandle.ClosePrice.ToString());

                                    i = i - 1;
                                }
                            }
                            else  // вывод на экран данных, полученных в результате выполнения _trader.RegisterHistoryCandles выше
                            {
                                _lkCandle = seri.GetCandle<Candle>(0);

                                SafeAddToTxb(txtSmartInfo, "Пришел повтор: " + DateTime.Now.ToString() + " | " + _lkCandle.OpenTime.ToString() + " | " + _lkCandle.CloseTime.ToString() + " | " + _lkCandle.OpenPrice.ToString() + " | " + _lkCandle.HighPrice.ToString() + " | " + _lkCandle.LowPrice.ToString() + " | " + _lkCandle.ClosePrice.ToString());
                            }
                    }
andy_baka
andy_baka

Под нативными я имел ввиду вызов именно RegisterHistoryCandles. Совсем до вызовов SmartCom пока не дошло. Не много не по стартовому вопросу, но это именно та ситуация с которой я столкнулся - я пока не понял как сделать такую вещь:

  1. Получить сигнал об окончании свечи от CandleSeries, например по событию

_candleSeries.WhenCandlesFinished() .Do(OnCandlesFinished) .Apply(); 2. Далее, в обработчике OnCandlesFinished уже вызвать RegisterHistoryCandles, заказать сколько надо исторических свечек от SmartCom и спокойно их обработать в в обработчике на который подписываются например так: _trader.NewHistoricalCandles += OnNewHistoricalCandles;

Точнее, такая вещь реализуема, но пока не удалось разобрать кашу на выходе такой комбинации.

andy_baka
andy_baka

Проверил. Получается, что теперь (с какой версии не скажу, не знаю, но в 4.0.9 эти события еще работали отдельно) обработка вызова RegisterHistoryCandles проходит через обработчик событий формирования новой свечи CandleSeries, а потом, если была подписка, вызывается уже NewHistoricalCandles. Михаил, это как раз то что я с Иваном Бухариным несколько дней обсуждал. Реализовать не получилось и теперь не понятно как разделять потоки свечей в этом обработчике.

Mikhail Sukhov
Mikhail Sukhov

Переписка выдалась запутанной, судя по всему каждый пишет о своем.

Давайте поступим следующим образом - пойдем от простого к сложному. Запустите SampleCandles и проверьте, пожалуйста, работу.

ttt
ttt Autor

Михаил,

Сегодня с утра (24.06.2013) и SampleCandles, и моя программа показывают правильные(!!!) свечи. Свою программу программу поставил на весь день - собирать статистику: вечером сообщу о результатах.

Складывается впечатление, что S# строит "правильные" (совпадают с Finam'ом) свечи на "неинтенсивном" рынке (в понедельник с утра, на вечерней сессии,...)

Все же не понял:

  1. Могу ли я при приходе события появления новой свечи выполнить какой-нибудь метод, который внутри себя вызовет GetBars?
  2. Если это сделать можно, то в обработчике какого события надо отлавливать пришедшую в ответ на GetBars информацию?
Mikhail Sukhov
Mikhail Sukhov

ttt: Складывается впечатление, что S# строит "правильные" (совпадают с Finam'ом) свечи на "неинтенсивном" рынке (в понедельник с утра, на вечерней сессии,...)

В SampleCandles S# свечки не строит.

ttt
ttt Autor

За день 24.06.2013 по контракту Si-9.13: Всего свечей = 578. Ошибок (в сравнении с Finam'ом): open = 0 high = 0 low = 1 ошибка: отличие на 1 пункт (рубль), свеча сформировалась в 15:46:00 close = 2 ошибки: 1-я: отличие на 2 пункта (рубля), свеча сформировалась в 11:23:00 2-я: отличие на 1 пункт (рубль), свеча сформировалась в 18:26:00

ttt
ttt Autor

Михаил, сегодня (25.06.2013) SampleCandles в режиме Real-time строит на графике свечки с ошибками. В моей программе также идут сплошные ошибки (сравниваю с Finam'ом). После перезапуска программы свечки, которые в Real-time были с ошибками, становятся правильными (в точности совпадают с Finam'овскими данными). Вот отчет с утра: Всего 288 свечей. Ошибки: open = 0 high = 70 ошибок (от 1 до 21 пункта) low = 63 ошибки (от -1 до -15 пунктов) close = 234 ошибки (от -20 до 12 пунктов)

На прошлой неделе была такая же ситуация: один день свечи идут почти без ошибок, другой - почти в каждой свече ошибка.

Похоже, что когда где-то внутри S# делает запрос с помощью GetBars, то свечи получаются корректные. А вот когда свечи получаются как-то иначе, то свечи могут построиться как правильно, так и неправильно.

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

Mikhail Sukhov
Mikhail Sukhov

Мое сообщение проигнорировалось. Это ключевое сообщение.

ttt
ttt Autor

Так что делать-то? Как получить корректные свечи?

Mikhail Sukhov
Mikhail Sukhov

ttt: Так что делать-то? Как получить корректные свечи?

Вначале надо понять причину. То, что в SampleCandles свечки не страятся - факт. Другой вопрос, делаете ли вы проверку именно этим примером, или что-то свое испольуете... Вообщем поможет информация от вас. Вопрос номер 1 - вы тестируете SampleSmartCandles? Есть ли какие то модификации?

ttt
ttt Autor

Проверку делаю используя пример SampleSmartCandles. Модификаций, на мой взгляд, нет. Если быть совсем точным, то сначала, используя SampleSmartCandles, сделал свое приложение, которое получает исторические свечи. Вывод свечей выполняю в текстовой форме на экран. В real-time замечаю, что свечи идут с ошибками. Выключаю свое приложение. Запускаю SampleSmartCandles. Выбираю режим "Real-time". Сверяю свечи с Finam'овскими. Результат тот же: свечи отличаются на несколько пунктов.

Схема работы и код приложения в части работы со свечками приведены выше в этой теме в 4 посте от начала.

Mikhail Sukhov
Mikhail Sukhov

ttt: Проверку делаю используя пример SampleSmartCandles.

Я не совсем понял, а как идет сверка? В текстовый формат пример не выводит данные.

ttt
ttt Autor

На графике со свечками увеличиваю масштаб, рядом открываю текстовый файл с данными с Finam'а. И сравниваю. Можно сказать - в ручном режиме, отдельно каждую свечу.

В моем приложении процесс сравнения параметров свечей более автоматизирован: информацию о свечках вывожу на экран, затем копирую в текстовый файл. Поскольку механизм получения свечей реализован тот же, что и в SampleSmartCandles, то и результаты совпадают: если у меня в приложении свечки идут корректные, то и при тестах в SampleSmartCandles свечи тоже идут корректные. В случаях же, когда у меня в приложении данные отличаются, то и SampleSmartCandles тоже показывает свечи, отличающиеся от Finam'овских.

Mikhail Sukhov
Mikhail Sukhov

Может быть строить свечки из тиков?

ttt
ttt Autor

Зачем связываться с тиками, когда есть GetBars? Временная задержка на 1-2 секунды для получения информации о сформировавшейся свече не играет принципиального значения. Важно получить корректные параметры свечи. При использовании тиков придется отслеживать много технических моментов, и при этом никогда не будет 100%-ой уверенности, что конкретная свеча построилась правильно.

Mikhail Sukhov
Mikhail Sukhov

Постучитесь в скайп, попробую понять где проблема.

ttt
ttt Autor

Михаил, следующие варианты решения проблемы не сработали:

1)Использование new CandleManager(new TradeCandleBuilderSource(_trader)). Результат: события NewHistoricalCandles не приходят совсем.

  1. Реализовал следующий механизм: после прихода новой свечи, фиксирую параметры свечи (OHLC). Выставляю задержку 45(!) секунд. Затем выполняю: ```csharp _trader.RegisterHistoryCandles(_Si, SmartTimeFrames.Minute1, DateTime.Now, 10, SmartHistoryDirections.Backward);
Получаю данные через 45 секунд. Фиксирую параметры свечи(OHLC).

Имеем три разных свечи:
1-я: эталон, с Finam'а
2-я: свеча, зафиксированная сразу как только пришло событие формирования новой свечи
3-я: свеча, полученная после задержки

Результат:
во-первых, 2-я и 3-я свеча отличаются(!!!) между собой
во-вторых, ни 2-я, ни 3-я свеча не совпадают (!!!) с эталоном.
в-третьих, после перегрузки приложения, исторические свечи в точности совпадают с эталонными, то есть свечи, которые только что отличались от эталона, теперь полностью с ним совпадают.