← Zurück

Почему свеча отрисовывается многократно?

Пытаюсь работать со свечками. Рисовать на графике я их не хочу, просто хочу например выводить время закрытия законченной свечи тайм-фрейма 1 мин в ListBox, то есть например чтобы раз в минуту появлялась запись о сформировавшейся свече. Для этого я делаю _candleManager.Processing += PrintCandle;

И в процедуре PrintCandle у меня только это:

if (candle.State == CandleStates.Finished) { this.GuiAsync(() => MyList.Items.Add(candle.CloseTime + " " + candle.ClosePrice)); }

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

14.11.2013 18:31:00 143520 14.11.2013 18:32:00 143460 14.11.2013 18:31:00 143520 14.11.2013 18:32:00 143460 14.11.2013 18:31:00 143520 14.11.2013 18:32:00 143460 14.11.2013 18:31:00 143520 14.11.2013 18:32:00 143460

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

Спасибо.

War dieses Thema hilfreich?

Thema teilen

Kommentare (10)

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

alexan3010
alexan3010 Autor

Ok, спрошу по другому. PrintCandle как я понял вызывается несколько раз в секунду конструкцией _candleManager.Processing += PrintCandle;

Соответственно туда передаются все полученные свечки, как я понял и новые и исторические.

Мне нужно как то в MyList выводить только уникальную новую свечку после ее формирования, то есть один раз в TimeFrame.

Коннектор SmartCom если что.

Дюшес
Дюшес

alexan3010: нужно как то в MyList выводить только уникальную новую свечку после ее формирования, то есть один раз в TimeFrame. Правило WhenCandlesFinished не подходит?


            _series
                .WhenCandlesFinished()
                .Do(candle =>
                {
                })
                .Sync(syncToken)
                .Apply(this);


alexan3010
alexan3010 Autor

Как то сложно, а syncToken откуда берется?

А если вам не сложно, можете пояснить физику процесса, что происходит при вызове _candleManager.Processing += PrintCandle; ?

Из мануалов - это подписывание на событие появления нового элемента для обработки, который мы передаем в процедуру PrintCandle, где и обрабатываем. А что туда фактически передается и когда во времени? Правильно ли я понимаю, что любое изменение состояния свечи (по сути любая сделка) вызывает это событие? Если так, то как мне в процедуре обработку написать так, чтобы я видел скажем Close последних N полных завершенных свечей, а текущую - не видел, чтобы она появлялась только в момент своего завершения.

Дюшес
Дюшес

alexan3010: Как то сложно, а syncToken откуда берется? Это пример правила, для получения законченных свечек, если вы пользуетесь стратегиями. http://stocksharp.com/doc/html/2c3a0d3a-6e89-42a1-a158-9a258e0a62e1.htm synctoken - это new SyncObject(), примерно то же, что и new object(), т.е. объект синхронизации.

alexan3010: А если вам не сложно, можете пояснить физику процесса, что происходит при вызове _candleManager.Processing += PrintCandle; ?

Из мануалов - это подписывание на событие появления нового элемента для обработки, который мы передаем в процедуру PrintCandle, где и обрабатываем. А что туда фактически передается и когда во времени? Правильно ли я понимаю, что любое изменение состояния свечи (по сути любая сделка) вызывает это событие? Если так, то как мне в процедуре обработку написать так, чтобы я видел скажем Close последних N полных завершенных свечей, а текущую - не видел, чтобы она появлялась только в момент своего завершения. CandleManager формирует из тиков свечки заданного таймфрейма, с каждым тиком вызывается событие processing и передает вашему обработчику объект candle, т.е. текущую свечу. Если нужно ловить окончание свечи, то проверяете на candle.State == CandleStates.Finished. Получить n-последних свечек можно через метод _series.GetCandles, например так:


var candles = _series.GetCandles<TimeFrameCandle>(3).Where(c => c.State == CandleStates.Finished);

Mikhail Sukhov
Mikhail Sukhov

Дюшес:

alexan3010: Как то сложно, а syncToken откуда берется? Это пример правила, для получения законченных свечек, если вы пользуетесь стратегиями. http://stocksharp.com/doc/html/2c3a0d3a-6e89-42a1-a158-9a258e0a62e1.htm synctoken - это new SyncObject(), примерно то же, что и new object(), т.е. объект синхронизации.

На 100% не уверен, но с 4.2 скорее всего этот метод более не нужен. Причина - события ITrader вызываются из одного потока по умолчанию. Если это не менять, то и синхронизация не нужна.

alexan3010
alexan3010 Autor

Дюшес, спасибо за разъяснения!

Но тогда, как понимать то, что я описал в начале этой темы? Почему, когда с каждым тиком, когда вызывается processing и передает моему обработчику candle, т.е. текущую свечу, я по конструкции if (candle.State == CandleStates.Finished) { this.GuiAsync(() => MyList.Items.Add(candle.CloseTime + " " + candle.ClosePrice)); }

вижу чередование текущей и предыдущей?

Дюшес
Дюшес

alexan3010: Почему, когда с каждым тиком, когда вызывается processing и передает моему обработчику candle, т.е. текущую свечу, я по конструкции if (candle.State == CandleStates.Finished) { this.GuiAsync(() => MyList.Items.Add(candle.CloseTime + " " + candle.ClosePrice)); }

вижу чередование текущей и предыдущей? Ну тогда надо поглядеть весь код, угадать сложно.

alexan3010
alexan3010 Autor

Вот, код тестовый минимальный, коннект, подписка и вывод. Для версии API 4.1.19, в последней что то пока не разобрался в изменениях, свечки вообще не появляются. Код внутри обработки события OnClick кнопки. На форме только одна эта кнопка и лист-бокс MyList в который все выводится.


 var account = "BP****";

            _trader = new SmartTrader { Login = "BP****", Password = "*****"}; //Создаем шлюз
            this.GuiAsync(() => MyList.Items.Add("Производим подключение к SmartCom v3.0..."));
            _trader.ApplyWrapper(SmartComVersions.V3);   //тут указываем что именно третья версия.
            _trader.NewSecurities += securities =>
            {

                _ri = securities.FirstOrDefault(sec => sec.Code == "RIZ3");
                if (_ri != null)
                {
                    this.GuiAsync(() => MyList.Items.Add("RIZ3 появился."));
                    _trader.RegisterSecurity(_ri);
                      _trader.RegisterTrades(_ri);    
                    _candleManager = new CandleManager(_trader);  //Заводим менеджер свечей
                    _series = new CandleSeries(typeof(TimeFrameCandle), _ri, _timeFrame);
                    _candleManager.Start(_series);
                    _trader.RegisterTrades(_ri);
                    _candleManager.Processing += (s, candle) =>
                    {
                        if (candle.State == CandleStates.Finished) this.GuiAsync(() => MyList.Items.Add(candle.CloseTime + "  " + candle.ClosePrice));
                    };

                }

            };   //NewSecurities

          _trader.NewPortfolios += portfolios =>
            {
                portfolios.ForEach(_trader.RegisterPortfolio);
               if (_portfolio == null)
                {
                    // находим нужный портфель и присваиваем его переменной _portfolio
                    _portfolio = portfolios.FirstOrDefault(p => p.Name == account);
                   if (_portfolio != null)
                    {
                        this.GuiAsync(() => MyList.Items.Add("Портфель появился. "+_portfolio));
                   }
                } //конец if _portfolio
            };//конец NewPortFolios
            _trader.Connected += () =>
            {
                this.GuiAsync(() => MyList.Items.Add("Подключение было произведено успешно, запускаем экспорт."));
                 _trader.StartExport();   
             };
            _trader.Connect();


Дюшес
Дюшес

alexan3010: Вот, код тестовый минимальный Лучше полный проект, чтобы на своем терминале проверить. На каких-то версиях S# работает или не работает вообще?

alexan3010
alexan3010 Autor

Спасибо, я вроде более менее подразобрался. У меня не то чтобы не работало, более теоретический был вопрос, что валится после вызова обработчика _candleManager.Processing += PrintCandle. Просто если не указывать в _candleManager.Start(_series) временные рамки, то валится кроме текущих свечей еще ряд исторических свечей заданного таймфрема в обработчик. Вот это меня и смущало - валилось куча свечек разных. Но во-первых можно указать временные рамки, во вторых я научился их запихивать в List и уже там анализировать и выводить когда мне нужно.