Михал, вечер добрый.
В примере с экспортом инструментов волатильность и теор цена не обновляются в реальном времени. Думаю дело в том, что они биндятся к объекту Security, а не к полю. Если их забиндить через Path=ExtensionInfo и написать конвертер, то данные все равно не обновляются в реальном времени, хотя на ранних версиях S# это работало.... В чем может быть причина? ExtensionInfo больше не свойство зависимости? или не реализует INotifyPropertyChanged?
评论 (15)
登录 或 创建账户, 登录或注册以发表评论
Я думаю Вы правы. Это сложна структура и с ней такой простой ход как INotifyPropertyChanged не пройдет. Используйте подход как с SampleQuote (который читает данные из Quote.ExtensionInfo ).
Но ведь класс Security уже реализует INotifyPropertyChanged, и при изменении всех полей кроме ExtensionInfo соответствующие события посылаются. В версии 2.01 ExtensionInfo также генерировало RaisedPropertyChanged... Почему в 2.1 этого больше не происходит? Сейчас приходится опрашивать ExtensionInfo по таймеру, как в подходе с SampleQuote, что не есть гуд.
ExtensionInfo не могло генерировать RaisedPropertyChanged - это Dictionary из .NET, который ничего не знает о INotifyPropertyChanged.
Сильно неудобно? Посмотрю, что можно сделать. Но это будет не раньше новой версии. Как обходной путь сейчас, не использовать таймер, а использовать ITrader.SecuritiesChanged. Из него заполнять структуру VisualSecurity через нужное свойство. Которой в свою очередь бросает событие PropertyChanged. И форма преспокойно это отображает. Это более правильно чем через таймер.
Михаил, Вы правы, дикшенари ничего не знает о интерфейсе, и реализовать дифференцированный отклик на изменение каждой записи не так просто. Но ведь можно сделать "компромиссный" вариант - код, который заполняет или изменяет дикшенари, может отправлять RaisedPropertyChanged("ExtensionInfo"). То есть форма будет обновлять все поля при изменении какой-либо записи в ExtensionInfo. Не так чтобы очень сильно нужно, но это ведь просто реализовать. Поправте меня, если ошибаюсь. Идея с VisualSecurity тоже не очень удобно, сильно запутывает код.
Просто то просто, только все равно фичи раньше след. версии не смогу выпустить. А к следующей версии лучше сделать по правильному (как пока не знаю). Вам это только для обновления данных на форме?
Да, это только для формы, поэтому не к спеху, пока хватает и таймера.
Кажется я немного не понимаю как должны обновляться дополнительные поля у Security...
Для каждого из QuikTrader, входящих в MultiTrader я добавил нужные мне поля:
quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MarginBuy);
quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MarginSell);
quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MaxPrice);
quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MinPrice);
quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MinStepPrice); (Все эти поля есть в таблице квика.)
Пробую печатать из стратегии: AddLog(StrategyErrorStates.None, "ГО ({0}), minPrice ({1}), minStepPrice ({2})", new object[] { Security.MarginBuy, Security.MinPrice, Security.MinStepSize, });
Сегодня после клиринга изменилась печать лишь для ГО, для MinPrice и для MinStepPrice осталась прежней. Печать через try { AddLog(StrategyErrorStates.None, "ГО_2 ({0})", new object[]
{
(double)Security.ExtensionInfo[DdeSecurityColumns.MarginBuy] }); } catch (Exception) {
ГО_2", new object()); } выбрасывает exception.
Как сделать так, чтоб автоматически обновлялись и MinPrice, MinStepPrice, ...?
Security - что был получен через NewSecurities или ручками создан?
Через NewSecurities: const string workInstrument = "RTS-9.10"; var riFut = _securities.FirstOrDefault(s => s.Name == workInstrument);
где _securities как раз заполняется внутри обработчика NewSecurities. Первоначально все поля прописаны верно - как раз совпадает с таблицей в квике, после клиринга изменилось как ГО, так и MinPrice \ MaxPrice
MinStepPrice. Почему-то они вот и не обновились
Вот сейчас: MinPrice=137475.0 (должно быть 136130) MinStepPrice=3.05495 (должно быть 3.05254) MaxPrice=148815.0 (должно быть 147470) MarginBuy=7483.52 (всё верно, как раз изменилось после клиринга, до клиринга - было 7489.43)
Все, понял. Я поля QuikTrader заполняет один раз, при создании инструмента. Делал первоначально для мамбы, а там деривативов нет. Потом уже ФОРЦ прикрутил.
Отлично. Тогда пока MarginBuy\MarginSell буду использовать, а с MinPrice\MaxPrice подожду 2.3 :)
Забавно, но только перед отпуском я как раз думал, что надо всегда обновлять все поля у инструмента. Просто иногда бывают такие ситуации (редко, но бывают), когда сначала приходит по дде сделка, а затем уже инструмент. И тогда в системе начинает обитать пустой инструмент а минимум заполненных полей.
Встречался с таким во время тестов 1-2 раза, подумал что глюк у меня =)