← 戻る

Создание CandleManager при неодновременном запуске двух стратегий в одном приложении

Имеется приложение, которое позволяет запускать несколько стратегий одновременно. Поясните, пожалуйста, каков подход Стокшарпа, экземпляр CandleManager должен создаваться свой отдельный на каждую стратегию, или один общий? При создании отдельного CandleManager на каждую стратегию, каким образом решается проблема, что второй созданный CandleManager не получает тиковые данные с начала текущей торговой сессии по тому же инструменту, по которому первый CandleManager их успешно получил и построил на их основании свечки? При создании одного общего CandleManager на все стратегии, каким образом должна решаться проблема, что вторая запускаемая стратегия не получит уже сформированные к моменту ее запуска свечки?

このトピックは参考になりましたか?

トピックを共有

コメント (24)

ログイン または アカウントを作成, コメントを残すにはログインまたは新規登録してください

Mikhail Sukhov
Mikhail Sukhov

Это все зависит от кода стратегий и самого приложения.

Подхода стокшарпа не существует, так как это АПИ, а не конкретное приложение. Есть подход по правильному написанию программ на .NET и WPF. Лучше их читать.

RomSunZ
RomSunZ

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

Evgeny
Evgeny 著者

RomSunZ, у меня главная предпосылка была, что стратегии и их соответствующие candlemanager`ы запускаются неодновременно. То есть сначала запускается первая стратегия с первым менеджером свечек, происходит подписка на тики по инструменту и этот первый менеджер свечек все нормально строит. Затем (например, через час) запускается вторая стратегия со вторым менеджером свечек. Этот второй менеджер свечек тоже подпишется на событие получения новых сделок (TradeCandleBuilderSource), но ведь от этого второй менеджер свечек уже все равно не получит тики за первый час, пока работал только первый менеджер свечек. Или не так и я что-то упустил?

gem81
gem81

Вопрос возник такой же) Попробую пояснить что не так. Есть соединение public QuikTrader client = new QuikTrader(); общее для всего приложения. Далее Мы создаём TradeCandleBuilderSource(client) и запускаем _candleManager.Start(_series); я опустил все инициации серий и т.п. затем через какое-то время мы нажимаем кнопку запустить второй алгоритм по тому же инструменту. Скрипт так сделан, что контролирует количество открытых им позиций по алгоритму, и ему не важно, сколько открывает позиций параллельный алгоритм. И вот теперь при попытке запустить второй экземпляр окна со своим набором TradeCandleBuilderSource(client) и _candleManager.Start(_series); ничего не происходит. из глобальных переменных тут только client, всё остальное формируется в классе нового окна с чартом. 🤬 пояснил, у самого моск подкоптился

Support
Support

gem81: Вопрос возник такой же) Попробую пояснить что не так. Есть соединение public QuikTrader client = new QuikTrader(); общее для всего приложения. Далее Мы создаём TradeCandleBuilderSource(client) и запускаем _candleManager.Start(_series); я опустил все инициации серий и т.п. затем через какое-то время мы нажимаем кнопку запустить второй алгоритм по тому же инструменту. Скрипт так сделан, что контролирует количество открытых им позиций по алгоритму, и ему не важно, сколько открывает позиций параллельный алгоритм. И вот теперь при попытке запустить второй экземпляр окна со своим набором TradeCandleBuilderSource(client) и _candleManager.Start(_series); ничего не происходит. из глобальных переменных тут только client, всё остальное формируется в классе нового окна с чартом. 🤬 пояснил, у самого моск подкоптился

Если у вас один candleManager, то второй раз вызывать _candleManager.Start(_series) не надо, можно просто во второй стратегии еще раз подписаться на событие CandleManager.Processing.. Вам нужно иметь ссылки на CandleSeries, и каждый раз при попытке вызова candleManager.Start(_series) проверять есть ли такая серия в CandleManager.Series... Если есть, то серия уже запущена... Уже построенные свечи получаем при помощи _candleManager.GetCandles(CandleSeries)...

RomSunZ
RomSunZ

Вопрос на засыпку, как в примерах с отдельными ChartWindow (суть с разными экземплярами "стратегий") все строится, а у Вас нет?

gem81
gem81

RomSunZ: Вопрос на засыпку, как в примерах с отдельными ChartWindow (суть с разными экземплярами "стратегий") все строится, а у Вас нет?

Написано всё как в примере. Результат на картинке. Первый раз всё вырисовывает, открываешь второй раз чарт по тому же инструменту, пусто

sh_double_sec.png

RomSunZ
RomSunZ

На сколько помню, при запуске candlemanager можно было задавать начальную/конечную дату. Попробуйте, может быть поможет.

Evgeny
Evgeny 著者

Я запустил у себя стандартный пример со свечками. И ожидаемо увидел тоже самое. При открытии того же окна с тем же инструментом график рисоваться не будет. С другим инструментом - будет, а с тем же - нет. И причина, насколько я понимаю, именно в том, что TradeCandleBuilderSource, который отвечает за построение онлайн свечек, вызывает перестроение свечи только при появлении нового тика. А когда открывается второе окно - старые тики, поступившие к этому моменту, второй раз не поступят, и соответственно свечи заново не сгенерятся. Возможно проблему можно решить добавив другой источник, который построит свечи либо по данным в хранилище, либо по данным коллекции тиков. Но в обоих случаях я вижу подводные камни. Я поэтому и хотел, чтобы на эту тему отписались разработчики. Каким-то образом, они же решали эту проблему, например, в дизайнере.

Support
Support
  1. Я бы рекомендовал использовать один CandleManager
  2. "По повод тиков с начала сессии". Для CandleManager существуют "источники данных", в частности, для работы с тиковыми реал-тайм данными используется RealTimeCandleBuilderSource. Вы можете попробовать использовать для каждого CandleManager один RealTimeCandleBuilderSource.
  3. Все сформированные свечи хранятся в контейнере CandleManager. Эту "историю" Вы можете использовать при запуске второй стратегии.
RomSunZ
RomSunZ

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

Support
Support

нельзя...

RomSunZ
RomSunZ

Что значит нельзя? Вариант 1: Вы вызываете candleManager.GetCandles<T>(CandleSeries). Получаете коллекцию. Обрабатываете ее - это занимает некоторое время, подписываетесь на событие Processing, начинаете получать сообщения. Но со времени получения и обработки коллекции уже могли произойти изменения в коллекции в candleManager (потоки-то разные), и какие-то из изменений могли пройти мимо нас.

Вариант 2: Подписываемся на Processing и начинаем получать сообщения. Вызываем candleManager.GetCandles<T>(CandleSeries). Получаем коллекцию. Обрабатываете ее, но во время ее обработки может придти сообщение от Processing - проблемы с синхронизацией обработки.

Есть еще какие-либо варианты?

Evgeny
Evgeny 著者

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

  1. CandleManager должен быть обязательно один и тот же.
  2. CandleSeries должны быть обязательно разные (даже если стратегии или чарты используют абсолютно идентичные свечи с тем же инструментом и таймфреймом).
  3. С момента запуска второй стратегии по этому инструменту должен придти хотя бы один тик. Если до конца сессии новых сделок так и не будет, то вторая стратегия так и не получит данные с начала сессии. Если же новые сделки будут получены, то вторая стратегия сначала получит все сформированные свечи с начала сессии, а потом начнёт получать реальные данные.

Третий пункт как раз меня и gem81 судя по всему и сбил с толку. Так как если запускать стандартный пример с графиками ChartWindow после окончания торговой сессии (то есть новых сделок уже точно не поступит), то второй чарт по одному инструменту не строится. Но если его запускать во время торговой сессии и по инструменту продолжают поступать сделки, то все строится нормально.

То есть по идее, если третье условие считать допустимым, то можно не прибегать к использованию метода GetCandles. В идеале, конечно, хотелось бы получить подтверждение от поддержки, что описанное действительно работает (и главное - должно работать) именно так, а я не набрёл на очередной частный случай.

RomSunZ
RomSunZ
  1. Не обязательно.
  2. Должны.
  3. Я же Вам написал ранее. Используйте candlemanager.Start(startTime, endTime) и получите Ваши свечи не зависимо от других запущенных стратегий.
Evgeny
Evgeny 著者

RomSunZ, вы сами пробовали на последней версии API запустить пример SampleQuikCandles с двумя чартами по одному инструменту предварительно сделав те доработки, про которые вы говорите?

  1. Если создавать два экземпляра CandleManager для одного коннектора, то при старте серии свечек по второму появляется ошибка System.InvalidOperationException: Subscribed. Появляется она из-за того, что в RealTimeCandleBuilderSource.Start производится подписка на получение тиков по инструменту. Попытка это вторая, т.к. при старте первого менеджера свечек подписка на тики уже ранее была произведена. Соответственно после появления этой ошибки ничего уже не строится.
  2. Это не работает. В том же примере заменяю строку запуске серии на candleManager.Start(series, System.DateTime.Today.AddDays(-1), System.DateTime.MaxValue); и от этого ничего не меняется. На втором чарте по тому же инструменту свечи появятся только если после запуска этого второго чарта придет хотя бы один тик. А он после окончания сессии никогда не придет.
RomSunZ
RomSunZ

В таком случае пишите свой обработчик загрузки истории, иначе никак.

RomSunZ
RomSunZ

А Вы смотрели поведение candlemanager например в S#.Disigner? Если там все работает, то значит решение есть, его просто надо увидеть :)

Support
Support

Для вашей задачи оптимальным будет следующее решение.. Во второй стратегии Вы просто подписываетесь на событие CandleManager.Processing..., кроме того создаете флаг для первой свечи в этой стратегии... При получении первой свечи запрашиваете все свечи CandleManager.GetCandles, выполняет нужные операции, сбрасываете флаг.... При создании дополнительных CandleManager или дополнительных CandleSeries накладные расходы программы будут больше....

RomSunZ
RomSunZ

Тут вопрос в другом. Событие появления обработки свечек сработает только после получения новой сделки по инструменту и Ваше решение бесполезно. А человеку надо получить свечки сразу после запуска второй стратегии, т.к. сделки придут неизвестно через какой промежуток времени (например после окончания торговой сессии это будет только на следующий рабочий день). Тогда уж наверное при запуске стратегии сначала делать запрос GetCandles и после их обработки подписываться на обработку. Правда как я уже писал придется проверять появились ли изменения в свечках с момента их получения до момента подписки на событие обработки.

Support
Support

Я не вижу в этом никакой проблемы...Получение свечей проходит очень быстро... Можно конечно проверять, но это принципиально ни на что не повлияет...

Evgeny
Evgeny 著者

Скажите, пожалуйста, если все-таки создавать дополнительный CandleSeries, то по свечам, которые уже были сформированы к моменту запуска второй стратегии, во второй стратегии должны срабатывать правила WhenCandlesStarted, WhenCandlesChanged и т.д.? Или только правило окончания свечи?

Support
Support

Да.

RomSunZ
RomSunZ

В общем суть проблемы в том, что класс RealTimeCandleBuilderSource, который является базовым для TradeCandleBuilderSource, вызывает метод AddNewValues только когда получает новый тик. А в этом методе идет проверка


					if (series.IsNew)
					{
						RaiseProcessing(series, Convert(GetSecurityValues(security)).OrderBy(v => v.Time));
						series.IsNew = false;
					}
					else
					{
						RaiseProcessing(series, securityValues);
					}

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