Я пишу приложение, целью которого является оптимизация торговой стратегии. Для простоты предположим только, что у нас есть торговая стратегия, которая гласит «вход здесь», затем другая, которая говорит «выход здесь, если в сделке», а затем позволяет иметь две модели: одна говорит, какой риск мы должны принять (как много мы теряем, если находимся не на той стороне рынка), а другой говорит, какую прибыль мы должны получить (то есть, какую прибыль мы получим, если рынок согласится).
Для простоты я буду называть исторически реализованные сделки тиками. Это означает, что, если я «войду в тик 28», это означает, что я вступил бы в сделку во время 28-й сделки в моем наборе данных по цене этой сделки. Тики хранятся в хронологическом порядке в моем наборе данных.
Теперь представьте, что стратегия ввода для всего набора данных насчитывает 500 записей. Для каждой записи я могу предварительно рассчитать точную отметку входа. Я также могу рассчитать точки выхода, определенные стратегией выхода для каждой точки входа (опять же, в виде номеров тиков). Для каждой записи я также могу предварительно рассчитать смоделированные убытки и прибыль, а также отметки, по которым эти потери или прибыль были бы достигнуты. Последнее, что остается сделать, — это рассчитать, что произошло бы в первую очередь, то есть выйти из стратегии, выйти из убытка или выйти из прибыли.
Поэтому я перебираю массив сделок и рассчитываю exitTick [i] = min (exitTickByStrat [i], exitTickByLoss [i], exitTickByProfit [i]). И весь процесс чертовски медленный (скажем, я делаю это 100 миллионов раз). Я подозреваю, что ошибки кэша являются основной причиной. И вопрос: можно ли это сделать как-нибудь быстрее? Я должен перебрать 4 массива некоторой нетривиальной длины. Одно из предложенных мною предложений — сгруппировать данные в кортежи по четыре, то есть иметь один массив структур, таких как (entryTick, exitOnStrat, exitOnLoss, exitOnProfit). Это может быть быстрее из-за лучшей предсказуемости кэша, но я не могу сказать точно. Почему я до сих пор не проверял это, так это то, что инструментальные профилировщики как-то не работают для двоичных файлов выпуска моего приложения, в то время как выборочные профилировщики кажутся мне ненадежными (я пробовал профилировщик Intel).
Итак, последний вопрос: можно ли решить эту проблему быстрее? Какой профилировщик лучше всего использовать для профилирования памяти с выпуском двоичных файлов? Я работаю на Win7, VS2010.
Редактировать:
Большое спасибо всем. Я попытался максимально упростить свой первоначальный вопрос, отсюда и путаница. Просто чтобы убедиться, что он читабелен — цель означает предполагаемую / реализованную прибыль, стоп — предполагаемую / реализованную прибыль.
Оптимизатор — грубой силы. Итак, у меня есть несколько настроек strat (например, периоды индикатора, что угодно), затем min / max breakEvenAfter / breakEvenBy и затем формулы, чтобы дать вам значения стоп / цель в тиках. Эти формулы также являются объектами оптимизации. Следовательно, у меня есть структура оптимизации, как
for each in params
{
calculateEntries()
for each in beSettings
{
precalculateBeData()
for each in targetFormulaSettings
{
precalculateTargetsAndRespectiveExitTicks
for each in stopFormulaSettings
{
precalulcateStopsAndRespectiveExitsTicks
evaluateExitsAndDetermineImprovement()
}
}
}
}
Поэтому я пересчитываю как можно больше и вычисляю только то, что мне нужно. И из 30 секунд вычисление тратит 25 секунд в функцииifyExitsAndDetermineImprovement (), которая выполняет то, что я описал в исходном вопросе, то есть выбирает min (exitOnPattern, exitOnStop, exitOnTarget). Причина, по которой мне нужно вызывать функцию 100 раз, заключается в том, что у меня есть 100 миллионов комбинаций всех параметров вместе. Но в течение последнего цикла for изменяется только массив exitOnStops. Я могу опубликовать код, если это поможет. Я благодарен за все комментарии!
Я не знаю много о торговых стратегиях, но я обычно делаю некоторую оптимизацию.
Ну, есть много способов оптимизации.
Например, тип контейнера, использующий другую функцию min (я думаю, что boost имеет несколько более быструю функцию, чем в библиотеке stl), попробуйте сократить те же вычисления и т.д.
Также вы можете оптимизировать, используя более быстрые функции, чтобы набрать скорость, или переосмыслив свой алгоритм.
Для профилирования я использую GlowCode под Win7 x64, и это нормально и для релизных сборок.
Может быть, я неправильно понимаю вашу систему, но:
что вы «предварительно рассчитываете» и когда и ЗАЧЕМ 100 миллионов раз ???
Я не знаю, поможет ли это вам, но это может значительно упростить вашу систему — есть две общие торговые стратегии: (описания мои и не официальный)
1) «Выход с фиксированной точкой» — когда происходит торговля, все точки выхода рассчитываются один раз и периодически проверяются на соответствие рыночным условиям / цене.
2) «Выход из переменной точки» — когда рынок движется, точки выхода пересчитываются (обычно для фиксации большей прибыли / уменьшения потерь).
В случае 1) фактический расчет происходит только один раз, поэтому он должен быть ОЧЕНЬ быстро
В случае 2) вычисления будут происходить каждый раз, но они могут быть оптимизированы многими различными способами — один из них заключается в том, что вы можете хранить свои сделки, проиндексированные по точкам выхода, и получать и пересчитывать только те, которые близки к реальной рыночной ситуации.
Я не уверен, к какому кешу вы не обращаетесь? Вы кеш данных? Кеш процессора?
Итак, после некоторой работы я понял совет Александра С. Когда я запустил профилирование пропуска кэша, я обнаружил, что из 15M вызовов функцииifyExits () у меня только 30K пропусков кэша, поэтому производительность этой функции не может быть затруднена. по кешу. Следовательно, мне пришлось «начать верить», что VTune действительно дает достоверные результаты, хотя и странные. Поскольку анализ выходных данных VTune не совпадает с именем текущего потока, я решил начать новый нить. Спасибо всем за мнения и рекомендации.