← 戻る

Перфоманс тестинга на истории

На этих выходных пофиксил найденные баги в бэктестере. Заодно провел некоторое расследование о причинах медленного тестированию. Раньше самой тормозной частью была загрузка данных. Она была успешно залечена через параллельную подгрузку данных потоками, и теперь стал тормозить поток, который распараллелить невозможно - поток исполнения стратегий.

Я проверял производительность на примере SampleHistoryTesting. Тесты показали (мерил через dotTrace), что основной тормоз - это генерация свечек (48% уходит на CandleManager). Ускорить алго практически невозможно, так как он ускорялся и не раз. Но есть решение - использовать уже готовые свечки. В Гидре начиная с 3.2 версии появилась возможность сжатия свечек. Схема работы для бэктестера не очень удобная, так как за раз не получится загрузить и сжать все свечки (банально не хватит памяти). Поэтому я предлагаю всем заинтересованным пользователям откликнуться на это предложение и помочь в решении проблемы.

Исходники Гидры доступны каждому, они есть в дистрибутиве. Мое предложение такое. Необходимо сделать в Гидре (авто?) компрессор сделок по большому диапазону в отдельном окне. Тоесть, для такого компрессора не нужно будет выбирать и загружать сделки, а достаточно указать дни, с какого по какой нужно сжать сделки в свечки, и дальше он начнет их сжатие, загружая день за днем.

Если откликнутся желающие (а я надеюсь что такие найдутся), то со стороны S# мы сделаем авто загрузку свечек из истории через класс CandleManager. Как итог, ускорим бэктестинг стратегий, которые требуют свечки, причем существенное ускорение.

Других методов пока не придумал, если они вообще существуют. К сожалению, обратная сторона медали точного тестирования - это его производительность.

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

トピックを共有

コメント (65)

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

Garic
Garic

Что подразумевается под компрессией - схлопывание сделок прошедших по одной цене?

Мне кажется что можно было бы сделать такие варианты тестирования:

1.) Грубое тестирование - тест по заранее расчитанным и сохранённым свечам. Тут надо скармливать candleManager-у готовые свечи.

2.) Более детальное. По идее для свечных стратегий открытие позиции должно происходить по клоузу свечи. Тогда чтобы можно было прикинуть проскальзывание - будут интересны сделки только первых нескольких секунд новой свечи (сколько - это уже зависит от типа котирования используемого в стратегии). Т.е. надо сделать в Гидре компрессию сделок, например для 5-минуток: -реальные сделки первых нескольких секунд свечки (либо некоторое количество сделок, либо грузим сделки пока не проторгуется заданный объём - задаётся в параметрах - это зависит от типов свечей) -компрессия - цена закрытия 5минутки, весь оставшийся объём - одной сделкой.

3.) Детальное тестирование - как щас.

Mikhail Sukhov
Mikhail Sukhov 著者

Garic: Что подразумевается под компрессией - схлопывание сделок прошедших по одной цене?

Мне кажется что можно было бы сделать такие варианты тестирования:

1.) Грубое тестирование - тест по заранее расчитанным и сохранённым свечам. Тут надо скармливать candleManager-у готовые свечи.

а. В том то и дело, что эти свечки нужно получить откуда-то. Для этого есть Гидра. Но она пока не умеет их делать массово. Нужно ее обучить. б. На точность тестирование готовые свечки никак влиять не будут. Готовые свечки лишь оптимизируют работу CandleManager.

Garic
Garic

Mikhail Sukhov: а. В том то и дело, что эти свечки нужно получить откуда-то. Для этого есть Гидра. Но она пока не умеет их делать массово. Нужно ее обучить. б. На точность тестирование готовые свечки никак влиять не будут. Готовые свечки лишь оптимизируют работу CandleManager.

А, ну тогда всё проще.

Т.е. нужно сделать: 1.) Настройку в Гидре - где будет указываться какие свечи и для каких (или для всех) инструментов генерировать (сразу при загрузке данных). 2.) Кнопарь по которому можно указать тип свечей, период - и они сгенерятся 3.) Как лучше хранить свечи? Папка для каждого типа свечей - подпапка код тикера - отдельный файл на каждый день. Так?

Могу взяться, но скоро сваливаю в отпуск - может не хватить времени.

Mikhail Sukhov
Mikhail Sukhov 著者

Garic:

Mikhail Sukhov: а. В том то и дело, что эти свечки нужно получить откуда-то. Для этого есть Гидра. Но она пока не умеет их делать массово. Нужно ее обучить. б. На точность тестирование готовые свечки никак влиять не будут. Готовые свечки лишь оптимизируют работу CandleManager.

А, ну тогда всё проще.

Т.е. нужно сделать: 1.) Настройку в Гидре - где будет указываться какие свечи и для каких (или для всех) инструментов генерировать (сразу при загрузке данных). 2.) Кнопарь по которому можно указать тип свечей, период - и они сгенерятся 3.) Как лучше хранить свечи? Папка для каждого типа свечей - подпапка код тикера - отдельный файл на каждый день. Так?

Могу взяться, но скоро сваливаю в отпуск - может не хватить времени.

  1. Да, наверное так. Есть такой класс VisualSecurity, куда можно будет засунуть такой признак и информацию об авто генерировании (я думаю это должна быть отдельная таблица в БД). Но это если делать автоматику. Я думаю ее можно прикрутить потом.
  2. Да, фактически уже есть такое окно.
  3. Со стороны Storage API уже есть готовое. TradingStorage.GetCandleStorage().
Mikhail Sukhov
Mikhail Sukhov 著者

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

pyhta4og
pyhta4og

Mikhail Sukhov: Предлагаю решиться быстрее, потому что вопрос стоит в том, войдет такое решение в 3.2 или не войдет. Следующая версия пока не планируется. Желающий должен точно высказаться в этом топике, что берет это на себя, и когда ждать от него решение.

А чо, 3.3 не будет? Практически 33 -возраст Х.

хранение свечек я начинал делать, лежит где-то в ТФСе старом. Надо в директории с тиками и стаканами исчо candles.bin заделать. И все пропустить через общий алго сжатия. Короче, куча гемороя и в итоге ничего кроме подогнанного графека.

I will sell RTS VX on 50. Come with me!

Garic
Garic

Mikhail Sukhov:

  1. Да, наверное так. Есть такой класс VisualSecurity, куда можно будет засунуть такой признак и информацию об авто генерировании (я думаю это должна быть отдельная таблица в БД). Но это если делать автоматику. Я думаю ее можно прикрутить потом.
  2. Да, фактически уже есть такое окно.
  3. Со стороны Storage API уже есть готовое. TradingStorage.GetCandleStorage().
  1. Ок. Мне кажется правильней чтобы информация об автогенерировании можно было задавать не только для отдельного инструмента, но и по маске. Чтобы не пришлось к примеру для RI* загруженного с РТС для каждого нового фьюча настраивать.

  2. А оно реализовано?


var candleStorage = Storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(Security, ((DateTime)TimeFrame.DateTime).TimeOfDay);

Отсутствует реализация метода "#=qSgY$r90pFrF28LZPd8I1Iw==" в типе "#=qnoDh2NhJ_K7BrlaDnrVfD_$X6y8Kk1BuDAeot1QM$W9GwXexSSUV2IyqmZwEiQZl" из сборки "StockSharp.Algo, Version=3.2.9.0, Culture=neutral, PublicKeyToken=null".

   в StockSharp.Algo.Storages.TradingStorage.#=qjjCXVa_GkSf19tV164IPg7UEmibZUkgx4WuqhCpwOD0=.#=qy88HEUV8WIEWMypubtR3OoXNjHr1RNtBjcQh1UzlfU0=(Triple`3 #=qycS3I_WdKlNBnvNjehlFBQ==)

Я готов взяться, но мне нужно успеть до понедельника, думаю успею. Потом - сваливаю в отпуск, надо готовиться.

Mikhail Sukhov
Mikhail Sukhov 著者

Garic: 3. А оно реализовано?

Что-то не то с паблишингом... Можете пока ГУИ часть и код схематично написать?

Garic
Garic

Mikhail Sukhov: Что-то не то с паблишингом... Можете пока ГУИ часть и код схематично написать?

Ок, завтра-послезавтра постараюсь написать.

Garic
Garic

Mikhail Sukhov;99431.: Да, наверное так. Есть такой класс VisualSecurity, куда можно будет засунуть такой признак и информацию об авто генерировании (я думаю это должна быть отдельная таблица в БД). Но это если делать автоматику. Я думаю ее можно прикрутить потом.

Просто окно с генерацией свечей я сделал. А вот с автогенерацией моих познаний в C# не хватает - работа с БД вроде более-менее понятна. А что делать с CandleToken.Args не знаю - как его хранить (строкой?), он должен в PK входить.

Добавь меня на codeplex, ник Garic.

Mikhail Sukhov
Mikhail Sukhov 著者

Garic;10578:

Mikhail Sukhov;99431.: Да, наверное так. Есть такой класс VisualSecurity, куда можно будет засунуть такой признак и информацию об авто генерировании (я думаю это должна быть отдельная таблица в БД). Но это если делать автоматику. Я думаю ее можно прикрутить потом.

Просто окно с генерацией свечей я сделал. А вот с автогенерацией моих познаний в C# не хватает - работа с БД вроде более-менее понятна. А что делать с CandleToken.Args не знаю - как его хранить (строкой?), он должен в PK входить.

Добавь меня на codeplex, ник Garic.

Добавил, но Гидры пока нет на codeplex. Лучше пока куда нибудь залить в другое место.

Ни с какой БД работа в Гидре в плане тиков и свечек не идет. Все выполняется на уровне Storage API. Примерный код написан в файле CandlesWindow.xaml.cs. Его нужно лишь переделать, чтобы сделки за каждый день подгружались и сжимались в свечки.

Garic
Garic

Mikhail Sukhov: Добавил, но Гидры пока нет на codeplex. Лучше пока куда нибудь залить в другое место.

Ни с какой БД работа в Гидре в плане тиков и свечек не идет. Все выполняется на уровне Storage API. Примерный код написан в файле CandlesWindow.xaml.cs. Его нужно лишь переделать, чтобы сделки за каждый день подгружались и сжимались в свечки.

Я это понял и сделал - аттач.

Работа с БД - сохранение настроек - для каких инструментов делать автогенерацию свечей. Пример есть в Hydra.Core.MarketDataSourceSettings - с этим вроде всё понятно.

Будет новая таблица: SecurityId, CandleType, Args. Вот непонятно - как хранить CandleToke.Args. Он должен входить в PrimaryKey.

President
President

в качестве идеи - подгрузка свечек с финама - правда там периодичность жестка задана, зато уже все посчитано по всем инструментам.

Mikhail Sukhov
Mikhail Sukhov 著者

President: в качестве идеи - подгрузка свечек с финама - правда там периодичность жестка задана, зато уже все посчитано по всем инструментам.

Уже второе ответ не отвечает на вопрос. Тренд?

Подгрузку свечек делать не нужно. Все есть в тиках. Нужно лишь нарезать из. Брать финамоские свечки плохо по ряду причин:

  1. Они не отличаются качеством.
  2. Они только жесткий ТФ (и только ТФ).
  3. Нужно делать качалку свечек.
  4. Нужно делать их десериализатор.

Тоесть, к перечисленным делам в моем первом сообщении добавляются еще 2 задачи. Может все таки решить проблему наименьшими усилиями раз такой лес рук?

anothar2
anothar2

Мне кажется или свечки можно взять за гораздо больший период чем тики, а следовательно далекие годы можно тестировать только на свечах? Логичнее было бы строить( или качать) свечи только один раз и пихать их в бд, благо жесткий диск большой, а вот частота проца ограничена. Кроме того многие стратегии работают только на свечах и тики им совсем не нужны. По поводу грубого тестирования-у метатрейдера есть функция комбинированного тестирования: когда вы берете сначала все тики, когда тиков не осталось свечи меньшего диапазона, когда они закончились большего и так далее и таким методом можете тестировать за долгий период. Безусловно получается неравномерная точность тестирования, но хотя бы так.

Mikhail Sukhov
Mikhail Sukhov 著者

anothar: Мне кажется или свечки можно взять за гораздо больший период чем тики, а следовательно далекие годы можно тестировать только на свечах? Логичнее было бы строить( или качать) свечи только один раз и пихать их в бд, благо жесткий диск большой, а вот частота проца ограничена. Кроме того многие стратегии работают только на свечах и тики им совсем не нужны.

Так я про это и пишу, чтобы сделать нарезку из тиков. Зачем качать готовые, если уже все давно накачано и можно нарезать свои в любом формате?

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

Это отдельная тема, к ней когда нибудь вернемся. В данный момент есть место для хорошей оптимизации. Жаль рук нет.

Ок, ждем тогда до среды. Если до среды никто не объявится, значит всех скорость устраивает. Меня то она и так устраивала всегда, так как я тех анализом не пользуюсь. Не понятны тогда жалобы некоторых пользователей. Обманывали меня, получается, что медленно тестирование идет.😎

Yura
Yura

Добрый день. Такой вопрос. Мне нужно в режиме реал тайм сохранять сделки. Допустим нужно сохранить 100 сделок по некому инструменту и как только эти 100 сделок сохраняться, применять к ним анализ и сразу же выставлять заявки. Но сохранение данных не прекращать. Все это в режиме реалтайм.Как бы вы посоветовали мне такое осуществить. Может есть примеры которые помогут мне в этом.

Alexander
Alexander

Yura: Добрый день. Такой вопрос. Мне нужно в режиме реал тайм сохранять сделки. Допустим нужно сохранить 100 сделок по некому инструменту и как только эти 100 сделок сохраняться, применять к ним анализ и сразу же выставлять заявки. Но сохранение данных не прекращать. Все это в режиме реалтайм.Как бы вы посоветовали мне такое осуществить. Может есть примеры которые помогут мне в этом.

Создать событие, которое будет подниматься как 100 сделок сохранены и передавать именно эти 100 сделок.

Yura
Yura

Доброго времени суток. Такой вопрос, как мне сделать тестирование по нескольким инструментам сразу используя SampleSMA

Alexander
Alexander

Yura: Доброго времени суток. Такой вопрос, как мне сделать тестирование по нескольким инструментам сразу используя SampleSMA

Использовать BasketSecurity или создать несколько стратегий - по каждой на инструмент

bender
bender

Здравствуйте, напишу, как я решил проблему медленного тестирования по тикам. Изначально из тиковых данных гидры строятся минутные свечки(я использую только свечки по времени) и сохраняются в отдельный каталог. Это всё делается стандартными средствами S#. Затем начинается собственно тестирование, и вот как тестировать стратегии по коллекции свечек, а не тиков, в S# я не нашёл( может, чего пропустил?). Поэтому я сделал свою реализацию ITrader, в которую добавил событие NewCandle. Этот новый класс получает коллекцию минутных свечек за тестируемый период и нужный таймфрейм, по которым формирует новую коллекцию свечек нужного таймфрейма, затем идёт перебор этих свечек и с каждой новой свечёй вызывается событие NewCandle, на которое подписаны тестируемые стратегии. Кодом могу поделится, если кому надо.

Mikhail Sukhov
Mikhail Sukhov 著者

bender: Здравствуйте, напишу, как я решил проблему медленного тестирования по тикам. Изначально из тиковых данных гидры строятся минутные свечки(я использую только свечки по времени) и сохраняются в отдельный каталог. Это всё делается стандартными средствами S#. Затем начинается собственно тестирование, и вот как тестировать стратегии по коллекции свечек, а не тиков, в S# я не нашёл( может, чего пропустил?). Поэтому я сделал свою реализацию ITrader, в которую добавил событие NewCandle. Этот новый класс получает коллекцию минутных свечек за тестируемый период и нужный таймфрейм, по которым формирует новую коллекцию свечек нужного таймфрейма, затем идёт перебор этих свечек и с каждой новой свечёй вызывается событие NewCandle, на которое подписаны тестируемые стратегии. Кодом могу поделится, если кому надо.

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

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

bender
bender

Mikhail Sukhov: Я думаю, что подобное можно было бы решить через собственную реализацию ICandleManager, которая бы не строила свечки каждый раз из тиков, а просто из бы подгружала. Сама загрузка тиков и стаканов происходит несколькими потоками, которые отличны от потока эмуляции (теоретически, они не должны влиять на скорость обработки данных - тестирования). В потоке эмуляции как раз и происходит построение свечек, что сильно тормозит общий процесс тестирования.

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

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

Mikhail Sukhov
Mikhail Sukhov 著者

bender: А матчинг заявок это что? Если определение цены исполнения моей заявки по данным стакана, то никак не происходит, я оцениваю величину проскальзывания до тестирования и через него получаю ожидаемую цену.

Это исполнение заявок. Вы из своей стратегии выставляете заявку. Матчинг из или реализует или отменяет. Если реализует, получается сделка. А по сделке уже определяется общая профитность стратегии.

bender: И ещё, допустим, у меня система на пробое ценового канала. По свечкам я определю момент входа, а как потом используя тики и стакан произвести матчинг? Если прогонять все тики внутри свечи, то это снова может затормозить тестирование.

В том то и дело, что при тестировании на истории, что при проторговке в реале, код стратегии пишется одинаково. Просто пишите код так, будто торгуете на реале. Потом меняете на EmulationTrader и получаете тестирование.

AN
AN

Правильно я понял, что данную задачу сейчас никто не делает?

Я сделаю до конца недели следующее: У меня задача не тестирование, а оптимизация. Убежден, что всех нужных свечек в гидре не сожмешь, а то что сожмешь окажется ненужным. Поэтому при первом тестировании по инструменту / фрейму свечки сжимаю, а в дальнейшем использую. Т.е. нечего задавать в гидре будет не надо: просто тестируем как душе угодно, первый прогон медленный, но остальные быстрые.

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

Mikhail Sukhov
Mikhail Sukhov 著者

AN: Я сделаю до конца недели следующее: У меня задача не тестирование, а оптимизация. Убежден, что всех нужных свечек в гидре не сожмешь, а то что сожмешь окажется ненужным. Поэтому при первом тестировании по инструменту / фрейму свечки сжимаю, а в дальнейшем использую. Т.е. нечего задавать в гидре будет не надо: просто тестируем как душе угодно, первый прогон медленный, но остальные быстрые.

Я правильно понял идею, что свечки создаются не Гидрой, а самой программой (через CandleManager?), на которой идет прогонка? Вариант интересный. Можно попробовать это сделать парно, потому что я планирую вынести логику компрессии тиков из CandleManager в отдельный класс.

AN: Кроме того, мне не нравится, что для каждой стратегии создается свой CandleManager

Я сейчас сходу не вспомню, почему создается отдельно. А какие есть проблемы с тем, чтобы создавать один единый? Главное, чтобы тики в него лились упорядоченно (что невозможно при параллельном тестировании на разных временных диапазонах).

bender
bender

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

Mikhail Sukhov
Mikhail Sukhov 著者

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

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

Автоматику планируете сделать?

bender
bender

Mikhail Sukhov: Да, это было бы здорово. Но перед тем как делать советую ознакомится с этим и этим.

Я уже сделал, правда пока редко использовал, в прикреплённом архиве классы , которые надо добавить-заменить в Гидре, делал в 3.2.5, в следующих не пробовал. Посмотрел вторую ссылку, метод CandlesGenerate.Generate разве должен работать? Вот такой код у меня не работает:

	
var candleManager = new CandleManager(trades) { IsSyncRegister = true }; 
CandleToken token = candleManager.RegisterCandles(candleType, security, args); 
IMarketDataStorage<Candle> candleStorage = null;
candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(security, args.To<TimeSpan>()) as IMarketDataStorage<Candle>;
var candles = candleManager.GetCandles(token);
candleStorage.Save(candles);

Mikhail Sukhov: Автоматику планируете сделать? Это как? Чтобы при закачке сделок автоматически создавались и сохранялись свечки? Пока нет.

Mikhail Sukhov
Mikhail Sukhov 著者

bender: в прикреплённом архиве классы , которые надо добавить-заменить в Гидре, делал в 3.2.5, в следующих не пробовал.

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

bender: Посмотрел вторую ссылку, метод CandlesGenerate.Generate разве должен работать? Вот такой код у меня не работает:

var candleManager = new CandleManager(trades) ; CandleToken token = candleManager.RegisterCandles(candleType, security, args); IMarketDataStorage candleStorage = null; candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(security, args.To()) as IMarketDataStorage; var candles = candleManager.GetCandles(token); candleStorage.Save(candles);


Выкидывает исключение? Какое?
bender
bender

Mikhail Sukhov: Чтобы не быть помощником, для которого требуются еще другие помощники, предлагаю зарегистрироваться на КодеПлексе и залить туда свои изменения. Логин предварительно скажите, чтобы я смог присоединить вас к проекту.

Зарегился, YuraS

Выкидывает исключение? Какое?

	
candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(security, args.To<TimeSpan>()) as IMarketDataStorage<Candle>;

получается, candleStorage == null

Mikhail Sukhov
Mikhail Sukhov 著者

bender:

	
candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(security, args.To<TimeSpan>()) as IMarketDataStorage<Candle>;

получается, candleStorage == null

	
candleStorage = (IMarketDataStorage<TimeFrameCandle>)storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(security, args.To<TimeSpan>());

bender
bender

Mikhail Sukhov: ... У себя я так и сделал, просто я изначально про код по ссылке спрашивал,там кое-что сделано проще, чем у меня, но работать как-бэ не должно, во всяком случае в 3.2.5 не работает.

По КодеПлексу, я правильно понимаю, что мне надо скачать последний Change Set, внести свои изменения и залить обратно? Или можно залить своё рабочее решение (оно из версии 3.2.5 переделано)?

Mikhail Sukhov
Mikhail Sukhov 著者

bender: По КодеПлексу, я правильно понимаю, что мне надо скачать последний Change Set, внести свои изменения и залить обратно? Или можно залить своё рабочее решение (оно из версии 3.2.5 переделано)?

  1. Слить последнюю версию.
  2. Помержить с изменениями.
  3. Потестить, что не отвалилось все остальное.😂
  4. Залить.

Вот такой нехитрый алгоритм.

bender
bender
IMarketDataStorage<TimeFrameCandle> candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(input.Security, TimeSpan.FromMinutes(5));  

Вот такая строчка кода в последней версии выкидывает исключение

Отсутствует реализация метода "#=qZ54LkJX570V5vx1sz4z4Tg==" в типе "#=qZjnrk7nYv$HS6IuGzdGTyaz$pXGh_bkX5gnJpwhBozFKPUIkagMVdRegQjQZqC2r" из сборки "StockSharp.Algo, Version=4.0.2.0, Culture=neutral, PublicKeyToken=null". В 3.2.5 нормально работало

Mikhail Sukhov
Mikhail Sukhov 著者
IMarketDataStorage<TimeFrameCandle> candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(input.Security, TimeSpan.FromMinutes(5));  

Вот такая строчка кода в последней версии выкидывает исключение

Отсутствует реализация метода "#=qZ54LkJX570V5vx1sz4z4Tg==" в типе "#=qZjnrk7nYv$HS6IuGzdGTyaz$pXGh_bkX5gnJpwhBozFKPUIkagMVdRegQjQZqC2r" из сборки "StockSharp.Algo, Version=4.0.2.0, Culture=neutral, PublicKeyToken=null". В 3.2.5 нормально работало

Что-то обфускация сглючила. Поправил новой версией.

Alexander
Alexander
IMarketDataStorage<TimeFrameCandle> candleStorage = storage.GetCandleStorage<TimeFrameCandle, TimeSpan>(input.Security, TimeSpan.FromMinutes(5));  

Вот такая строчка кода в последней версии выкидывает исключение

Отсутствует реализация метода "#=qZ54LkJX570V5vx1sz4z4Tg==" в типе "#=qZjnrk7nYv$HS6IuGzdGTyaz$pXGh_bkX5gnJpwhBozFKPUIkagMVdRegQjQZqC2r" из сборки "StockSharp.Algo, Version=4.0.2.0, Culture=neutral, PublicKeyToken=null". В 3.2.5 нормально работало

Свежая версия с codeplex помогла (changeset 10471)?

bender
bender

Alexander Mukhanchikov: Свежая версия с codeplex помогла (changeset 10471)? Да, спасибо. Но теперь другая проблема вылезла, метод IMarketDataStorage(T).Delete (DateTime, DateTime) в 3.2.5 удалял только файлы свечек S# заданного типа, а сейчас (10484) удаляет каталоги за соответствующие числа целиком, со всем что в них есть. Нельзя-ли вернуть так, как было раньше?

Mikhail Sukhov
Mikhail Sukhov 著者

bender:

Alexander Mukhanchikov: Свежая версия с codeplex помогла (changeset 10471)? Да, спасибо. Но теперь другая проблема вылезла, метод IMarketDataStorage(T).Delete (DateTime, DateTime) в 3.2.5 удалял только файлы свечек S# заданного типа, а сейчас (10484) удаляет каталоги за соответствующие числа целиком, со всем что в них есть. Нельзя-ли вернуть так, как было раньше?

Вот это будет проблема. Из-за рефакторинга в 3.2 не был учтен это момент. Если сейчас попытаться вернуть все в зад, то может поехать другое - определение дат, для которых есть данные. Насколько критична ошибка? Может стоит сохранять данные в разных папках?

bender
bender

bender: Вот это будет проблема. Из-за рефакторинга в 3.2 не был учтен это момент. Если сейчас попытаться вернуть все в зад, то может поехать другое - определение дат, для которых есть данные. Насколько критична ошибка? Может стоит сохранять данные в разных папках?

Удаление в принципе нужно было для того, чтобы если пользователь формирует свечки по второму разу в тот-же каталог с налогающимся интервалом дат, то наложение надо удалить, иначе при записи дописываемые свечки дублируются, а не затирают старые( во всяком случае в 3.2 так было, как сейчас не могу пока посмотреть). В разные каталоги можно, но сейчас у меня сделано так, что отслеживание этого будет целиком лежать на пользователе. Хотя можно конечно каждый тип свечек сохранять в свой подкаталог, если в зад вернуть нельзя, попробую так сделать.

Mikhail Sukhov
Mikhail Sukhov 著者

bender: Удаление в принципе нужно было для того, чтобы если пользователь формирует свечки по второму разу в тот-же каталог с налогающимся интервалом дат, то наложение надо удалить, иначе при записи дописываемые свечки дублируются, а не затирают старые( во всяком случае в 3.2 так было, как сейчас не могу пока посмотреть).

http://stocksharp.com/doc/html/P_StockSharp_Algo_Storages_IMarketDataStorage_1_AppendOnlyNew.htm

Зачем удалять? Пользователь может генерировать свечки с разными параметрами. Может они все нужны ему?

bender
bender

Mikhail Sukhov: http://stocksharp.com/doc/html/P_StockSharp_Algo_Storages_IMarketDataStorage_1_AppendOnlyNew.htm О, спасибо, в 3.2.5 такого свойства ещё не было, поэтому удалял. Попробую его задействовать. Зачем удалять? Пользователь может генерировать свечки с разными параметрами. Может они все нужны ему? Я про свечки с одинаковыми параметрами писал, конечно. Свечки одинакового типа, но с отличными параметрами не удалялись.

bender
bender

Mikhail Sukhov:

bender: Удаление в принципе нужно было для того, чтобы если пользователь формирует свечки по второму разу в тот-же каталог с налогающимся интервалом дат, то наложение надо удалить, иначе при записи дописываемые свечки дублируются, а не затирают старые( во всяком случае в 3.2 так было, как сейчас не могу пока посмотреть).

http://stocksharp.com/doc/html/P_StockSharp_Algo_Storages_IMarketDataStorage_1_AppendOnlyNew.htm

C помощью IMarketDataStorage(T).AppendOnlyNew тоже не получается. Если сохраняется недоформированная свеча, то при последующем дописывании она не заменяется на полностью сформированную, а остаётся как есть.

bender
bender

Не знаю, баг или последствия рефакоринга, но в последней версии вот такое работать перестало:

var candleManager = new CandleManager(_trades) { IsSyncRegister = true };                  
var candles = candleManager.GetCandles(token).OrderBy((cnd) => cnd.Time);     

По докам вроде должно работать как и раньше

Mikhail Sukhov
Mikhail Sukhov 著者

bender: Не знаю, баг или последствия рефакоринга, но в последней версии вот такое работать перестало:

var candleManager = new CandleManager(_trades) ;
var candles = candleManager.GetCandles(token).OrderBy((cnd) => cnd.Time);

> По докам вроде должно работать как и раньше

Какая ошибка?
bender
bender

bender: Какая ошибка?

Нету у CandleManager конструктора с параметром IEnumerable<Trade>, а методов GetCandles нету вообще.

Mikhail Sukhov
Mikhail Sukhov 著者

Mikhail Sukhov:

bender: Какая ошибка?

Нету у CandleManager конструктора с параметром IEnumerable, а методов GetCandles нету вообще.

Видимо не последняя версия загружена с TFS.

bender
bender

Mikhail Sukhov: Видимо не последняя версия загружена с TFS. Вроде последняя, вот тут http://stocksharp.codeplex.com/SourceControl/changeset/changes/10521 и дифф есть в CandleWindow. Сделал также, а по старому не работает.

Mikhail Sukhov
Mikhail Sukhov 著者

bender:

Mikhail Sukhov: Видимо не последняя версия загружена с TFS. Вроде последняя, вот тут http://stocksharp.codeplex.com/SourceControl/changeset/changes/10521 и дифф есть в CandleWindow. Сделал также, а по старому не работает.

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

bender
bender

Mikhail Sukhov: Дифф показывает, что код, который вы привели выше, уже не существует. Поэтому я и говорю, что версия не последняя Гидры, нужно обновиться. Мы, кажется, друг друга не понимаем.))) У меня последняя версия, код, который я привёл, в ней действительно не существует. Но я про то, что этот код в последней версии не работает, хотя судя по докам http://stocksharp.com/doc/ должен работать, отсюда и возник этот вопрос. А где нибудь можно почитать про новый CandleManager?

Mikhail Sukhov
Mikhail Sukhov 著者

bender: Мы, кажется, друг друга не понимаем.))) У меня последняя версия, код, который я привёл, в ней действительно не существует. Но я про то, что этот код в последней версии не работает, хотя судя по докам http://stocksharp.com/doc/ должен работать, отсюда и возник этот вопрос. А где нибудь можно почитать про новый CandleManager?

Доки пока нет. Изменения вкратце. CandleManager теперь не строит свечки. Он лишь получает их от ICandleSource и передает дальше + сохраняет в контейер. Свечки строит CandleBuilder. Он принимает сделки от свои ITradeSource и через ICandleFactory превращается их в Candle.

bender
bender

Добавил окно с возможностью формирования свечек по интервалу дат, пока только таймфрейм, тики и объём, остальные пока не успел. Кнопка авто, автоматически выставляет интервал по всем загруженным сделкам, если свечки в указанный каталог уже сохранялись - то от последней свечи до последней сделки. Т.к. писал это для более ранней версии, сейчас там есть уже не нужные вещи вроде xml файла, постараюсь на неделе доработать. Залил на кодеплекс

Mikhail Sukhov
Mikhail Sukhov 著者

bender: Добавил окно с возможностью формирования свечек по интервалу дат, пока только таймфрейм, тики и объём, остальные пока не успел. Кнопка авто, автоматически выставляет интервал по всем загруженным сделкам, если свечки в указанный каталог уже сохранялись - то от последней свечи до последней сделки. Т.к. писал это для более ранней версии, сейчас там есть уже не нужные вещи вроде xml файла, постараюсь на неделе доработать. Залил на кодеплекс

Спасибо. Глянул мельком, замечаний море. Будем улучшать знания в C#. Скажите, когда будет финальный коммит, и можно будет пройтись по пунктам.

Сделайте, пожалуйста, табуляцию табами, а не пробелами. Сейчас иначе весь файл переформатируется студией, если его другие начнут править. Советую поставить R#, он покажет так же часть ошибок в коде.

bender
bender

Mikhail Sukhov: Спасибо. Глянул мельком, замечаний море. Будем улучшать знания в C#. Скажите, когда будет финальный коммит, и можно будет пройтись по пунктам.

Сделайте, пожалуйста, табуляцию табами, а не пробелами. Сейчас иначе весь файл переформатируется студией, если его другие начнут править. Советую поставить R#, он покажет так же часть ошибок в коде.

Поставил решарпер, в связи с этим несколько вопросов. Он в основном выдает три замечания - убрать this, использовать var и переименовать обработчики событий. Я думал, что var нужен только для анонимных типов, но если надо поменяю. А обработчики событий из, например, StartStop_Click предлагает переименовать в StartStopClick, хотя везде они поименованы через подчёркивание. Может он у меня настроен не так?

Mikhail Sukhov
Mikhail Sukhov 著者

bender: Поставил решарпер, в связи с этим несколько вопросов. Он в основном выдает три замечания - убрать this, использовать var и переименовать обработчики событий. Я думал, что var нужен только для анонимных типов, но если надо поменяю.

Предупреждений по var не увидел. Возможно у нас разные настройки. Обычно я var использую, когда тип переменной слишком большой. Анонимный тип тут не при чем.

bender: А обработчики событий из, например, StartStop_Click предлагает переименовать в StartStopClick, хотя везде они поименованы через подчёркивание. Может он у меня настроен не так?

Да скорее всего.

Мне больше сама структура кода смущает. Например, CandlesCompress уж слишком сложен в поминании. Там явно переизбыток лямбд.

Garic
Garic

Сломалась генерация свечек (4.0.9)

Я так понимаю в CandlesCompress вместо

candleManager.Sources.Add(new CandleBuilder(new RawConvertableCandleBuilderSource<Trade>(trades)));

надо

candleManager.Sources.Add(new CandleBuilder(new RawConvertableCandleBuilderSource<Trade>(trades)) { IsSyncRegister = true }); 
Alexander
Alexander

Garic: Сломалась генерация свечек (4.0.9)

Я так понимаю в CandlesCompress вместо

candleManager.Sources.Add(new CandleBuilder(new RawConvertableCandleBuilderSource<Trade>(trades)));

> надо
> ```csharp
candleManager.Sources.Add(new CandleBuilder(new RawConvertableCandleBuilderSource<Trade>(trades)) { IsSyncRegister = true }); 

Да, верно. Залил.

Garic
Garic

А как тестеру скормить предварительно расчитанные свечи? Ничего подходящего не нашёл, а без них он работает существенно медленней чем в старых версиях (сравниваю с 3.2.7)

Mikhail Sukhov
Mikhail Sukhov 著者

Garic: А как тестеру скормить предварительно расчитанные свечи? Ничего подходящего не нашёл, а без них он работает существенно медленней чем в старых версиях (сравниваю с 3.2.7)

ICandleSource

Garic
Garic

Mikhail Sukhov: ICandleSource

Т.е. нужно сделать по типу своего CandleBuilder? Он должен генерить события CandlesStarted, CandlesChanged, CandlesFinished

Что должно их провоцировать (какое внешнее событие), за какой период должны отдаваться свечки, по сколько штук за один раз? Не видя внутренности сложно понять. Я так понимаю, отдаваться должны свечи всех зарегистрированных типов?

Mikhail Sukhov
Mikhail Sukhov 著者

Garic:

Mikhail Sukhov: ICandleSource

Т.е. нужно сделать по типу своего CandleBuilder? Он должен генерить события CandlesStarted, CandlesChanged, CandlesFinished

Я бы сказал по аналогии с SmartCandleSource

/// <summary>
	/// SmartCOM источник свечек типа <see cref="TimeFrameCandle"/>.
	/// </summary>
	public class SmartCandleSource : ICandleSource
	{
		/// <summary>
		/// Создать <see cref="SmartCandleSource"/>.
		/// </summary>
		/// <param name="trader">Шлюз к SmartCOM, через событие <see cref="SmartTrader.NewHistoryCandles"/> будут получаться свечки.</param>
		public SmartCandleSource(SmartTrader trader)
		{
			if (trader == null)
				throw new ArgumentNullException("trader");

			Trader = trader;
			Trader.NewHistoryCandles += OnNewHistoryCandles;
			From = Trader.MarketTime.Date - TimeSpan.FromDays(5);
		}

		/// <summary>
		/// Начальная дата, с которой необходимо получать данные из SmartCOM. По-умолчанию равно -5 дней от начала текущей сессии.
		/// </summary>
		public DateTime From { get; set; }

		/// <summary>
		/// Шлюз к SmartCOM, через событие <see cref="SmartTrader.NewHistoryCandles"/> будут получаться свечки.
		/// </summary>
		public SmartTrader Trader { get; private set; }

		IEnumerable<CandleToken> ICandleSource.Tokens
		{
			get { return Trader.HistoryCandleTokens; }
		}

		private Action<CandleToken, IEnumerable<Candle>> _candlesStarted;

		event Action<CandleToken, IEnumerable<Candle>> ICandleSource.CandlesStarted
		{
			add { _candlesStarted += value; }
			remove { _candlesStarted -= value; }
		}

		event Action<CandleToken, IEnumerable<Candle>> ICandleSource.CandlesChanged
		{
			add { }
			remove { }
		}

		private Action<CandleToken, IEnumerable<Candle>> _candlesFinished;

		event Action<CandleToken, IEnumerable<Candle>> ICandleSource.CandlesFinished
		{
			add { _candlesFinished += value; }
			remove { _candlesFinished -= value; }
		}

		event Action<Exception> ICandleSource.ProcessDataError
		{
			add { }
			remove { }
		}

		CandleToken ICandleSource.GetToken(Type candleType, Security security, object arg)
		{
			CheckTypes(candleType, arg);
			return Trader.HistoryCandleTokens.FirstOrDefault(c => c.Security == security && c.Arg == arg);
		}

		bool ICandleSource.IsSupport(Type candleType, Security security, object arg)
		{
			return candleType == typeof(TimeFrameCandle) && security.Trader == Trader && arg is TimeSpan && SmartTimeFrames.CanConvert((TimeSpan)arg);
		}

		CandleToken ICandleSource.Register(Type candleType, Security security, object arg)
		{
			if (((ICandleSource)this).GetToken(candleType, security, arg) != null)
				throw new ArgumentException("Группировка свечек уже зарегистрирована ранее с переданными параметрами.");

			CheckTypes(candleType, arg);

			var token = Trader.RegisterHistoryRealTimeCandles(security, (TimeSpan)arg, From);
			token.Source = this;
			return token;
		}

		void ICandleSource.UnRegister(CandleToken token)
		{
			Trader.UnRegisterHistoryRealTimeCandles(token);
		}

		private static void CheckTypes(Type candleType, object arg)
		{
			if (candleType == null)
				throw new ArgumentNullException("candleType");

			if (candleType != typeof(TimeFrameCandle))
				throw new ArgumentException("SmartCOM поддерживает свечки только типа {0}.".Put(candleType), "candleType");

			if (!(arg is TimeSpan))
				throw new ArgumentException("Аргумент {0} должен быть типа {1}.".Put(arg, typeof(TimeSpan)), "arg");
		}

		private void OnNewHistoryCandles(CandleToken token, IEnumerable<TimeFrameCandle> candles)
		{
			_candlesStarted.SafeInvoke(token, candles);
			_candlesFinished.SafeInvoke(token, candles);
		}

		void IDisposable.Dispose()
		{
			Trader.NewHistoryCandles -= OnNewHistoryCandles;
		}
	}
Garic
Garic

Спасибо, заработало 🙄

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

Нужно синхронизировать поток свечей и поток NewTrade чтобы сделки проходили одинаково при обоих тестах (тест по расчитанным свечам и тест по сделкам). Т.е. нужно выдавать свечи по какому-то событию. Логично чтобы это был Trader.NewTrade. Но как определить по tradе нужно ли выплёвывать candleFinished для свечки? Для timeFrame свечей понятно, а для остальных - такой информации нет.

Похоже облом - нужно чтобы у сохранённой свечи в хранилище был код первой и последней сделки (или есть другой вариант? )

В моих кастомных range-барах это есть (для отладки сделал), но что делать со стандартными?

По скорости - тест недели RIZ1 стратегия на минутках - Покупка на 00 минуте, продажа на 30 минуте по candleFinished

  • по сделкам 02:07.10
  • по сохранённым свечам, синхронизация по Trader.MarketTimeChanged раз в минуту 00:21.96
  • по сохранённым свечам, синхронизация по Trader.MarketTimeChanged раз в секунду 00:22.77
  • по сохранённым свечам, синхронизация по Trader.NewTrade 00:24.15

примерно в 7 раз быстрее

Garic
Garic

Дошли наконец-то руки :)

Сделал пример для TimeFrameCandles Скорость примерно в 5.5 раза выше чем с CandleBuilder (в примере можно переключать)

Данные совпадают, за исключением свечей NonTradingDealType которые почему-то стандартный CandleBuilder выдаёт. Пример 06.10.2011 - свеча 14.00 - её быть не должно. Параметр CandleManager.NonTradingDealType не влияет.

Mikhail Sukhov
Mikhail Sukhov 著者

Garic: Дошли наконец-то руки :)

В ПО очень важно быть на онлайне постоянно. С тех пор и стратегия стала событийной, и S# 4.1 (что в dev ветке) поддерживает закачку свечек из хранилища.

Spiritschaser
Spiritschaser

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