На этих выходных пофиксил найденные баги в бэктестере. Заодно провел некоторое расследование о причинах медленного тестированию. Раньше самой тормозной частью была загрузка данных. Она была успешно залечена через параллельную подгрузку данных потоками, и теперь стал тормозить поток, который распараллелить невозможно - поток исполнения стратегий.
Я проверял производительность на примере SampleHistoryTesting. Тесты показали (мерил через dotTrace), что основной тормоз - это генерация свечек (48% уходит на CandleManager). Ускорить алго практически невозможно, так как он ускорялся и не раз. Но есть решение - использовать уже готовые свечки. В Гидре начиная с 3.2 версии появилась возможность сжатия свечек. Схема работы для бэктестера не очень удобная, так как за раз не получится загрузить и сжать все свечки (банально не хватит памяти). Поэтому я предлагаю всем заинтересованным пользователям откликнуться на это предложение и помочь в решении проблемы.
Исходники Гидры доступны каждому, они есть в дистрибутиве. Мое предложение такое. Необходимо сделать в Гидре (авто?) компрессор сделок по большому диапазону в отдельном окне. Тоесть, для такого компрессора не нужно будет выбирать и загружать сделки, а достаточно указать дни, с какого по какой нужно сжать сделки в свечки, и дальше он начнет их сжатие, загружая день за днем.
Если откликнутся желающие (а я надеюсь что такие найдутся), то со стороны S# мы сделаем авто загрузку свечек из истории через класс CandleManager. Как итог, ускорим бэктестинг стратегий, которые требуют свечки, причем существенное ускорение.
Других методов пока не придумал, если они вообще существуют. К сожалению, обратная сторона медали точного тестирования - это его производительность.
Комментарии (65)
Вход или Создать аккаунт, Войдите или зарегистрируйтесь, чтобы оставить комментарий
Что подразумевается под компрессией - схлопывание сделок прошедших по одной цене?
Мне кажется что можно было бы сделать такие варианты тестирования:
1.) Грубое тестирование - тест по заранее расчитанным и сохранённым свечам. Тут надо скармливать candleManager-у готовые свечи.
2.) Более детальное. По идее для свечных стратегий открытие позиции должно происходить по клоузу свечи. Тогда чтобы можно было прикинуть проскальзывание - будут интересны сделки только первых нескольких секунд новой свечи (сколько - это уже зависит от типа котирования используемого в стратегии). Т.е. надо сделать в Гидре компрессию сделок, например для 5-минуток: -реальные сделки первых нескольких секунд свечки (либо некоторое количество сделок, либо грузим сделки пока не проторгуется заданный объём - задаётся в параметрах - это зависит от типов свечей) -компрессия - цена закрытия 5минутки, весь оставшийся объём - одной сделкой.
3.) Детальное тестирование - как щас.
а. В том то и дело, что эти свечки нужно получить откуда-то. Для этого есть Гидра. Но она пока не умеет их делать массово. Нужно ее обучить. б. На точность тестирование готовые свечки никак влиять не будут. Готовые свечки лишь оптимизируют работу CandleManager.
А, ну тогда всё проще.
Т.е. нужно сделать: 1.) Настройку в Гидре - где будет указываться какие свечи и для каких (или для всех) инструментов генерировать (сразу при загрузке данных). 2.) Кнопарь по которому можно указать тип свечей, период - и они сгенерятся 3.) Как лучше хранить свечи? Папка для каждого типа свечей - подпапка код тикера - отдельный файл на каждый день. Так?
Могу взяться, но скоро сваливаю в отпуск - может не хватить времени.
Предлагаю решиться быстрее, потому что вопрос стоит в том, войдет такое решение в 3.2 или не войдет. Следующая версия пока не планируется. Желающий должен точно высказаться в этом топике, что берет это на себя, и когда ждать от него решение.
А чо, 3.3 не будет? Практически 33 -возраст Х.
хранение свечек я начинал делать, лежит где-то в ТФСе старом. Надо в директории с тиками и стаканами исчо candles.bin заделать. И все пропустить через общий алго сжатия. Короче, куча гемороя и в итоге ничего кроме подогнанного графека.
I will sell RTS VX on 50. Come with me!
Ок. Мне кажется правильней чтобы информация об автогенерировании можно было задавать не только для отдельного инструмента, но и по маске. Чтобы не пришлось к примеру для RI* загруженного с РТС для каждого нового фьюча настраивать.
А оно реализовано?
Я готов взяться, но мне нужно успеть до понедельника, думаю успею. Потом - сваливаю в отпуск, надо готовиться.
Что-то не то с паблишингом... Можете пока ГУИ часть и код схематично написать?
Ок, завтра-послезавтра постараюсь написать.
Просто окно с генерацией свечей я сделал. А вот с автогенерацией моих познаний в C# не хватает - работа с БД вроде более-менее понятна. А что делать с CandleToken.Args не знаю - как его хранить (строкой?), он должен в PK входить.
Добавь меня на codeplex, ник Garic.
Добавил, но Гидры пока нет на codeplex. Лучше пока куда нибудь залить в другое место.
Ни с какой БД работа в Гидре в плане тиков и свечек не идет. Все выполняется на уровне Storage API. Примерный код написан в файле CandlesWindow.xaml.cs. Его нужно лишь переделать, чтобы сделки за каждый день подгружались и сжимались в свечки.
Я это понял и сделал - аттач.
Работа с БД - сохранение настроек - для каких инструментов делать автогенерацию свечей. Пример есть в Hydra.Core.MarketDataSourceSettings - с этим вроде всё понятно.
Будет новая таблица: SecurityId, CandleType, Args. Вот непонятно - как хранить CandleToke.Args. Он должен входить в PrimaryKey.
в качестве идеи - подгрузка свечек с финама - правда там периодичность жестка задана, зато уже все посчитано по всем инструментам.
Уже второе ответ не отвечает на вопрос. Тренд?
Подгрузку свечек делать не нужно. Все есть в тиках. Нужно лишь нарезать из. Брать финамоские свечки плохо по ряду причин:
Тоесть, к перечисленным делам в моем первом сообщении добавляются еще 2 задачи. Может все таки решить проблему наименьшими усилиями раз такой лес рук?
Мне кажется или свечки можно взять за гораздо больший период чем тики, а следовательно далекие годы можно тестировать только на свечах? Логичнее было бы строить( или качать) свечи только один раз и пихать их в бд, благо жесткий диск большой, а вот частота проца ограничена. Кроме того многие стратегии работают только на свечах и тики им совсем не нужны. По поводу грубого тестирования-у метатрейдера есть функция комбинированного тестирования: когда вы берете сначала все тики, когда тиков не осталось свечи меньшего диапазона, когда они закончились большего и так далее и таким методом можете тестировать за долгий период. Безусловно получается неравномерная точность тестирования, но хотя бы так.
Так я про это и пишу, чтобы сделать нарезку из тиков. Зачем качать готовые, если уже все давно накачано и можно нарезать свои в любом формате?
Это отдельная тема, к ней когда нибудь вернемся. В данный момент есть место для хорошей оптимизации. Жаль рук нет.
Ок, ждем тогда до среды. Если до среды никто не объявится, значит всех скорость устраивает. Меня то она и так устраивала всегда, так как я тех анализом не пользуюсь. Не понятны тогда жалобы некоторых пользователей. Обманывали меня, получается, что медленно тестирование идет.😎
Добрый день. Такой вопрос. Мне нужно в режиме реал тайм сохранять сделки. Допустим нужно сохранить 100 сделок по некому инструменту и как только эти 100 сделок сохраняться, применять к ним анализ и сразу же выставлять заявки. Но сохранение данных не прекращать. Все это в режиме реалтайм.Как бы вы посоветовали мне такое осуществить. Может есть примеры которые помогут мне в этом.
Создать событие, которое будет подниматься как 100 сделок сохранены и передавать именно эти 100 сделок.
Доброго времени суток. Такой вопрос, как мне сделать тестирование по нескольким инструментам сразу используя SampleSMA
Использовать BasketSecurity или создать несколько стратегий - по каждой на инструмент
Здравствуйте, напишу, как я решил проблему медленного тестирования по тикам. Изначально из тиковых данных гидры строятся минутные свечки(я использую только свечки по времени) и сохраняются в отдельный каталог. Это всё делается стандартными средствами S#. Затем начинается собственно тестирование, и вот как тестировать стратегии по коллекции свечек, а не тиков, в S# я не нашёл( может, чего пропустил?). Поэтому я сделал свою реализацию ITrader, в которую добавил событие NewCandle. Этот новый класс получает коллекцию минутных свечек за тестируемый период и нужный таймфрейм, по которым формирует новую коллекцию свечек нужного таймфрейма, затем идёт перебор этих свечек и с каждой новой свечёй вызывается событие NewCandle, на которое подписаны тестируемые стратегии. Кодом могу поделится, если кому надо.
Я думаю, что подобное можно было бы решить через собственную реализацию ICandleManager, которая бы не строила свечки каждый раз из тиков, а просто из бы подгружала. Сама загрузка тиков и стаканов происходит несколькими потоками, которые отличны от потока эмуляции (теоретически, они не должны влиять на скорость обработки данных - тестирования). В потоке эмуляции как раз и происходит построение свечек, что сильно тормозит общий процесс тестирования.
Если убрать загрузки тиков, то тогда перестанут строится и стаканы. Как же у вас происходит матчинг заявок?
А матчинг заявок это что? Если определение цены исполнения моей заявки по данным стакана, то никак не происходит, я оцениваю величину проскальзывания до тестирования и через него получаю ожидаемую цену. А так вы наверное правы, просто сделал что первое пришло в голову. И ещё, допустим, у меня система на пробое ценового канала. По свечкам я определю момент входа, а как потом используя тики и стакан произвести матчинг? Если прогонять все тики внутри свечи, то это снова может затормозить тестирование.
Это исполнение заявок. Вы из своей стратегии выставляете заявку. Матчинг из или реализует или отменяет. Если реализует, получается сделка. А по сделке уже определяется общая профитность стратегии.
В том то и дело, что при тестировании на истории, что при проторговке в реале, код стратегии пишется одинаково. Просто пишите код так, будто торгуете на реале. Потом меняете на EmulationTrader и получаете тестирование.
Правильно я понял, что данную задачу сейчас никто не делает?
Я сделаю до конца недели следующее: У меня задача не тестирование, а оптимизация. Убежден, что всех нужных свечек в гидре не сожмешь, а то что сожмешь окажется ненужным. Поэтому при первом тестировании по инструменту / фрейму свечки сжимаю, а в дальнейшем использую. Т.е. нечего задавать в гидре будет не надо: просто тестируем как душе угодно, первый прогон медленный, но остальные быстрые.
Кроме того, мне не нравится, что для каждой стратегии создается свой CandleManager, при одновременной работе многих стратегий на одном фрейме это избыточно. Подумаю над тем, чтобы сделать глобальный менеджер, который бы статическим классом отдавал нужные свечки, или что-то типа этого.
Я правильно понял идею, что свечки создаются не Гидрой, а самой программой (через CandleManager?), на которой идет прогонка? Вариант интересный. Можно попробовать это сделать парно, потому что я планирую вынести логику компрессии тиков из CandleManager в отдельный класс.
Я сейчас сходу не вспомню, почему создается отдельно. А какие есть проблемы с тем, чтобы создавать один единый? Главное, чтобы тики в него лились упорядоченно (что невозможно при параллельном тестировании на разных временных диапазонах).
Если действительно никто не делает(вроде брался человек) и первый пост ещё актуален, я могу сделать, вернее уже сделал - отдельное окно в гидре, которое формирует свечки разных типов по заданному интервалу времени и сохраняет их по указанному пути, свечки не скачиваются,а формируются из закачанных сделок.
Да, это было бы здорово. Но перед тем как делать советую ознакомится с этим и этим. Возможно, что уже сделано многое, и тогда нужно лишь это привести в нормальный вид и скомбинировать.
Автоматику планируете сделать?
Я уже сделал, правда пока редко использовал, в прикреплённом архиве классы , которые надо добавить-заменить в Гидре, делал в 3.2.5, в следующих не пробовал. Посмотрел вторую ссылку, метод 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);
Зарегился, YuraS
получается, candleStorage == null
получается, candleStorage == null
По КодеПлексу, я правильно понимаю, что мне надо скачать последний Change Set, внести свои изменения и залить обратно? Или можно залить своё рабочее решение (оно из версии 3.2.5 переделано)?
Вот такой нехитрый алгоритм.
Вот такая строчка кода в последней версии выкидывает исключение
Вот такая строчка кода в последней версии выкидывает исключение
Что-то обфускация сглючила. Поправил новой версией.
Вот такая строчка кода в последней версии выкидывает исключение
Свежая версия с codeplex помогла (changeset 10471)?
Вот это будет проблема. Из-за рефакторинга в 3.2 не был учтен это момент. Если сейчас попытаться вернуть все в зад, то может поехать другое - определение дат, для которых есть данные. Насколько критична ошибка? Может стоит сохранять данные в разных папках?
Удаление в принципе нужно было для того, чтобы если пользователь формирует свечки по второму разу в тот-же каталог с налогающимся интервалом дат, то наложение надо удалить, иначе при записи дописываемые свечки дублируются, а не затирают старые( во всяком случае в 3.2 так было, как сейчас не могу пока посмотреть). В разные каталоги можно, но сейчас у меня сделано так, что отслеживание этого будет целиком лежать на пользователе. Хотя можно конечно каждый тип свечек сохранять в свой подкаталог, если в зад вернуть нельзя, попробую так сделать.
http://stocksharp.com/doc/html/P_StockSharp_Algo_Storages_IMarketDataStorage_1_AppendOnlyNew.htm
Зачем удалять? Пользователь может генерировать свечки с разными параметрами. Может они все нужны ему?
C помощью IMarketDataStorage(T).AppendOnlyNew тоже не получается. Если сохраняется недоформированная свеча, то при последующем дописывании она не заменяется на полностью сформированную, а остаётся как есть.
Не знаю, баг или последствия рефакоринга, но в последней версии вот такое работать перестало:
По докам вроде должно работать как и раньше
var candleManager = new CandleManager(_trades) ;
var candles = candleManager.GetCandles(token).OrderBy((cnd) => cnd.Time);
Нету у CandleManager конструктора с параметром IEnumerable<Trade>, а методов GetCandles нету вообще.
Видимо не последняя версия загружена с TFS.
Дифф показывает, что код, который вы привели выше, уже не существует. Поэтому я и говорю, что версия не последняя Гидры, нужно обновиться.
Доки пока нет. Изменения вкратце. CandleManager теперь не строит свечки. Он лишь получает их от ICandleSource и передает дальше + сохраняет в контейер. Свечки строит CandleBuilder. Он принимает сделки от свои ITradeSource и через ICandleFactory превращается их в Candle.
Добавил окно с возможностью формирования свечек по интервалу дат, пока только таймфрейм, тики и объём, остальные пока не успел. Кнопка авто, автоматически выставляет интервал по всем загруженным сделкам, если свечки в указанный каталог уже сохранялись - то от последней свечи до последней сделки. Т.к. писал это для более ранней версии, сейчас там есть уже не нужные вещи вроде xml файла, постараюсь на неделе доработать. Залил на кодеплекс
Спасибо. Глянул мельком, замечаний море. Будем улучшать знания в C#. Скажите, когда будет финальный коммит, и можно будет пройтись по пунктам.
Сделайте, пожалуйста, табуляцию табами, а не пробелами. Сейчас иначе весь файл переформатируется студией, если его другие начнут править. Советую поставить R#, он покажет так же часть ошибок в коде.
Поставил решарпер, в связи с этим несколько вопросов. Он в основном выдает три замечания - убрать this, использовать var и переименовать обработчики событий. Я думал, что var нужен только для анонимных типов, но если надо поменяю. А обработчики событий из, например, StartStop_Click предлагает переименовать в StartStopClick, хотя везде они поименованы через подчёркивание. Может он у меня настроен не так?
Предупреждений по var не увидел. Возможно у нас разные настройки. Обычно я var использую, когда тип переменной слишком большой. Анонимный тип тут не при чем.
Да скорее всего.
Мне больше сама структура кода смущает. Например, CandlesCompress уж слишком сложен в поминании. Там явно переизбыток лямбд.
Сломалась генерация свечек (4.0.9)
Я так понимаю в CandlesCompress вместо
надо
candleManager.Sources.Add(new CandleBuilder(new RawConvertableCandleBuilderSource<Trade>(trades)));
Да, верно. Залил.
А как тестеру скормить предварительно расчитанные свечи? Ничего подходящего не нашёл, а без них он работает существенно медленней чем в старых версиях (сравниваю с 3.2.7)
ICandleSource
Т.е. нужно сделать по типу своего CandleBuilder? Он должен генерить события CandlesStarted, CandlesChanged, CandlesFinished
Что должно их провоцировать (какое внешнее событие), за какой период должны отдаваться свечки, по сколько штук за один раз? Не видя внутренности сложно понять. Я так понимаю, отдаваться должны свечи всех зарегистрированных типов?
Я бы сказал по аналогии с SmartCandleSource
Спасибо, заработало 🙄
Правда пока криво и результаты немного расходятся с обычным тестом на истории - как доковыряю - выложу.
Нужно синхронизировать поток свечей и поток NewTrade чтобы сделки проходили одинаково при обоих тестах (тест по расчитанным свечам и тест по сделкам). Т.е. нужно выдавать свечи по какому-то событию. Логично чтобы это был Trader.NewTrade. Но как определить по tradе нужно ли выплёвывать candleFinished для свечки? Для timeFrame свечей понятно, а для остальных - такой информации нет.
Похоже облом - нужно чтобы у сохранённой свечи в хранилище был код первой и последней сделки (или есть другой вариант? )
В моих кастомных range-барах это есть (для отладки сделал), но что делать со стандартными?
По скорости - тест недели RIZ1 стратегия на минутках - Покупка на 00 минуте, продажа на 30 минуте по candleFinished
примерно в 7 раз быстрее
Дошли наконец-то руки :)
Сделал пример для TimeFrameCandles Скорость примерно в 5.5 раза выше чем с CandleBuilder (в примере можно переключать)
Данные совпадают, за исключением свечей NonTradingDealType которые почему-то стандартный CandleBuilder выдаёт. Пример 06.10.2011 - свеча 14.00 - её быть не должно. Параметр CandleManager.NonTradingDealType не влияет.
В ПО очень важно быть на онлайне постоянно. С тех пор и стратегия стала событийной, и S# 4.1 (что в dev ветке) поддерживает закачку свечек из хранилища.
Помогите. Программирую я плохо, как мифический индус. Пишу оптимизатор, хочу сделать тестирование на готовых свечках из текстовых таблиц. С чего нужно начать? Сделать свой источник или Builder?