Возможная ошибка S#
Atom Ответить
21.06.2013


ttt

Фотография
Добрый день.

Пишу робота на 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) В каком событии и как отлавливать пришедшую информацию?

Теги:


Спасибо:




20 Ответов
andy_baka

Фотография
Курсы
Дата: 21.06.2013
Ответить


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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 21.06.2013
Ответить


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


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

ttt

Фотография
Дата: 21.06.2013
Ответить


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

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

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

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

Запускаю получение свечей:
Код
 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 свеча,
ТО вывожу на экран только ее
ИНАЧЕ вывожу все свечи, начиная с последней загруженной

Код
_trader.NewHistoricalCandles  += (seri, candy) =>
                {
                    int cou = seri.GetCandleCount();
                    if (seri.Security.Code == _lkoh.Code)
                    {
//                            ÷ñÒ1170378454êÖ0õæ÷https://stocksharp.ru/fo...chi--ghrafiki--istoriia/÷ñÒ1170378454êÖ1õæ÷
                             
                            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

Фотография
Курсы
Дата: 21.06.2013
Ответить


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

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

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

Спасибо:

andy_baka

Фотография
Курсы
Дата: 21.06.2013
Ответить


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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 21.06.2013
Ответить


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

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

ttt

Фотография
Дата: 24.06.2013
Ответить


Михаил,

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

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

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


Автор топика
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 24.06.2013
Ответить


ttt Перейти

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


В SampleCandles S# свечки не строит.
Спасибо:

ttt

Фотография
Дата: 24.06.2013
Ответить


За день 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

Фотография
Дата: 25.06.2013
Ответить


Михаил,
сегодня (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

Фотография
Автор статей Программист Трейдер
Дата: 25.06.2013
Ответить


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

ttt

Фотография
Дата: 25.06.2013
Ответить


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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.06.2013
Ответить


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


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

ttt

Фотография
Дата: 25.06.2013
Ответить


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

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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.06.2013
Ответить


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


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

ttt

Фотография
Дата: 25.06.2013
Ответить


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

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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.06.2013
Ответить


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

ttt

Фотография
Дата: 26.06.2013
Ответить


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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.06.2013
Ответить


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

ttt

Фотография
Дата: 28.06.2013
Ответить


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

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

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

Получаю данные через 45 секунд. Фиксирую параметры свечи(OHLC).

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

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


Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy