У хорошего мастера должны быть хорошие инструменты – у кузнеца – молот, у столяра – рубанок, у алготрейдера… — оптимизатор.
Выкатил новую версию.
Настоящий мужской оптимизатор конечно же должен быть консольным. Этот красавчик быстр – 10 лет 5-минуток на простой стратегии вместе с вычислением всяких там PF, RF 0,3 секунды. И это на одном потоке! (с многопоточностью, к слову, пока не смог подружить, но заложил такую возможность).
Бэктестер берет задания из csv файла и пашет. Т.е. на данный момент задания на оптимизацию задаются в момент создания файла с заданиями, решил поменять план оптимизации – меняю файл – меняется дальнейшая оптимизация. Т.е. по факту сейчас план на оптимизацию предустановленный, но легко прикрутить в дальнейшем оптимизацию с обратной связью на результаты предыдущих бэктестов. Меня всегда смущали стандартные оптимизаторы в этой части – где перебирается один параметр, или несколько строго итерационно, но я не мог задать явно другие алгоритмы перебора или в общем случае даже не перебора, а «изменения» значений. А здесь могу: т.е., могу за раз закинуть задания сразу на нужное количество гипотез, хочу посмотреть, как стратегия себя ведет между тикерам – не трогаю ничего, меняю только тикер, хочу проверить как ведет себя между тайм-фреймами – меняю только тайм-фреймы и т.д., т.е. минут за 5-10 во всемогущем экселе можно создать файл с заданиями для нужного набора гипотез. Потом когда бэктестер отработает – берешь эксельку и дата-майнишь данные.
Все-таки когда ты точно знаешь, чего хочешь, свой бэктестер это кайф! Нужна скорость, но не нужна какая-то функциональность – супер, не делаешь тормозящую функциональность, получая преимущество в скорости, интересует какая-то конкретная парадигма в оптимизации – отлично, пилишь архитектуру именно под парадигму, без оглядки на стандартные «лучшие практики», «модные мнения» и прочие «а вот я так делаю, а ты какую-то херню».
Более менее ООПшная прога получилась, так что есть надежда, что можно мяса при необходимости накрутить с контролируемым уровнем сложности и поддерживаемости.
Если вдруг кто-то собирался завидовать – не надо, вам бы не понравился мой оптимизатор. Думаю, он будет нравиться только мне! :)
ezomm, збазиба)
Ну ок, волновая. Но неужели не хочется автоматизировать, улучшить, одновременно находить входы на 200 инструментах и т.д.?)
ezomm, Ну просто если это алгоритмизировано и так круто работает эта теория, тогда б все туда и ринулись в алгоритмизацию этой темы, но почему-то я про такое не слышал — в чем несостыковка?
Волновая теория — норм тема, только не та где римские цифры и вот это все (может и она хорошая, но не уверен), но алгоритмизация этого всего — не тривиальная задача, вернее она не сложная, но слегка трудоемкая. Сложнее, чем входить по пересечению скользящих))).
ezomm, ну это же всё равно юмор. Не?
И да, я тоже уже оплатил входной билет.
D = f(C,M,E)
Если торговый алгоритм не учитывает аргументы этой функции, то любой бэкстест такого алгоритма — интересная математическая игрушка с прикольными результаты. Не более того.
Имхо, единственный рациональный метод тестирования алгоритма выглядит так
Конечно система не только правило входа, но и анализ объема (как сути торговли) и ММ — расчета риска.
а потом раскидывать по темам чужим
где вы тут софистику увидели? помогите рассмотреть))
Носорог, Спасибо).
Если умеешь отличить случайность от закономерности, то в принципе можно и не знать, какие за этим протекают процессы на физическом уровне.
угадай систему
возникает лотерея:
угадай систему вариант пОртфеля
tranquility, Да, я не профи в кодинге, тоже по ходу написания проги время от время рисечу, экспериментирую в подобных направления. Вот буквально недавно запустил очередную свежую порцию кода и заподозрил, что не нормально, что 300К строк в csv файл пишутся несколько секунд, порисечил этот вопрос, оказалось, что собрать массив строк и записать через WriteAllLines() на порядки быстрее отрабатывает, чем через накапливание в одной текстовой переменной и потом записывание через WriteAllText().
А так да, загружаю полностью, потом разбираю. Более того, сохраняю некоторые данные в оперативке и при последующем обращении забираю из оперативки, а не из файла! Ну типа если на одном дата-сете гоняю прогоны — беру их один из файла, остальные — из оперативки.
У меня такой вот код долго работает (конкретно этот — пару секунд, т.к. лучшие цены меняются в несколько раз чаще чем сделки происходят и данных очень много получается, сотни тысяч записей):
Сам понимаю, что можно сначала в память весь этот текст записать, а потом уже в файл целиком сбрасывать, но все лень как-то заморачиваться. Но надо уж как-нибудь собраться с этим...
Я как-то для сравнения преобразовывал данные из QSH-файлов и текстового вида (полученного из QSH) в свой собственный, так вот текст обрабатывался сущееественно дольше… Правда, тому могло быть объяснением мои кривые руки или тормоза Delphi при работе со строками, или и то и другое одновременно, но — правды не спрятать: родной формат все равно должен быть побыстрее
Qsh конечно же быстрее, но реализовать его на с++ под свои задачи у меня достаточно времени заняло. А текстовый вариант все равно полезен, в первую очередь для поиска ошибок (в бинарнике делать это куда сложнее), а во вторую — для построения графиков. Можно сохранять в базу да на С++, а потом читать ее на питоне, но у меня не возникло потребности так заморачиваться.
2. вычислять размер массива в цикле не правильно, он будет этим заниматься каждым проходом, присвойте один раз перед циклом, например так:
int bookSize = _bids.size();
for(int i = 0; i < bookSize; i++) {}
p.s.: для работы с большими данными уже лет 30 используют базы данных.
P.S. цикл и так в отдельном методе, там что-то вроде storeData() — после того как стратегия отторговала день, данные в нем сбрасываются в файлы логов. Это вообще можно отключить чтобы не тратить время, но и при бектестинге тоже иногда надо смотреть логи. Поэтому проще их оставлять включенными. В общем, это не проблема, будет напрягать — что-нибудь придумаем)
он же не знает для чего вы каждый раз функцию вызываете, может у вас размерность меняется или счётчик какой обновляете.
я лишь указал на две нехороших вещи которые увидел. привычка, кодревью все дела, соррян если что:) вообще на плюсах уже лет 10 не писал.
про первый пункт, я имел веду что у вас одинаковые циклы меняется только источник и по хорошему их нужно в отдельный метод вытащить, примерно так:
printBook(«asks», _asks);
printBook(«bids», _bids);
void printBook(std::string name, std::vector<int> book)
{
int size = book.size();
cout<<name<<":"<<size<<endl;
for(int i = 0; i < size; i ++)
{
cout<<i<<endl;
}
}
на производительность это не влияет, но читать код приятней
А так, из спортивного интереса откликнулся на вакансию прогера в хфт контору, там как раз С++14 им подавай, метапрограммирование — вот это все. Провалил собеседование то, ну да ладно, все равно бы не пошел туда работать, даже при успешном исходе. Что-то подход увиденный мне не нравится, надо показать что ты г-н Чегоизволите, а если скажешь на собеседовании, делая тестовое задание типа: «ну, если вам надо, запилю тут логарифмический поиск, плавали, знаем, но если позволите мне здесь сэкономить свое время — буду очень признателен» — то просто перестанут на сообщения отвечать. Рабов ищут, не иначе как…
tranquility, вот вам набросочек. С «анонимной» функцией.
Range-based циклы выучить не легко, а очень легко. По сравнению со всем остальным, конечно.
А как бы вы работали с C++14 кодом, если вы его не понимаете?
Даже если бы сами не писали именно C++14-й код...
Кстати, если в getBookTop вы заранее знаете, сколько элементов придётся поместить в вектор, следует обязательно вызвать метод reserve, как у меня в наброске сделано, чтобы не устраивать «тест памяти», когда данные в большом количестве многократно гоняются по памяти.
Программирование нынче очень сложно, очень объёмно (обогнало медицину) и, главное, оно продолжает расти и усложняться, причём, скорость, похоже, растёт.
С++ — самый hardcore. Каждые 3 года новый стандарт. Я не знаю, что делать. На любительском уровне — точно не угнаться.
ЗЫ. Вот и редактор сообщений у Тимофея тут такой, что приходится цитаты в HTML'е оформлять, а то он упорно весь текст пытается зацитировать...
ЗЗЫ. И после отправки потом в том же HTML'е расставлять элементы br, чтобы промежутки между текстом и цитатами смотрелись нормально...
Насчет 'не понимаете' — сложно согласиться, практика показывает, мне все равно на каком процедурном языке писать, хоть на ассемблере опять, ей б-гу, это же не хаскель какой-нибудь с нуля учить. А вектор перебирать можно и через итератор, если не ошибаюсь, будет та же эффективность, что и с использованием ключевого слова auto. Хотя, последнее как видно, дает новые возможности для написания шаблонов, может быть полезным не тоьько для чтения кода, но и при его непосредственной разработке...
Извиняюсь если дислайкнул коммент, мобильная версия, все дела…
tranquility, чем больше времени проходит, тем меньше вероятность такого исхода. На сайте mingw указано, что туда входит gcc версии 8.2.0. Он не только практически полностью поддерживает 17-й стандарт, но и частично 20-й. Под Linux'ами обычно и то древнее версии, чем в mingw.
Надо просто попробовать, и тогда согласиться станет намного легче.
Range-based циклы как раз и работают через итераторы, но скрывают всю работу с ними, оставляя лишь то, что нужно, ничего лишнего.
Ключевое слово auto не имеет к этому никакого отношения. Оно здесь лишь для того, чтобы не выписывать лишний раз тип, а также, чтобы его не пришлось править во многих местах, в том числе и в этом, если потом, в результате рефакторинга, этот тип станет другим.
Вот у меня знакомый некоторые методы и функции иногда на ассемблере писал — говорил это не по приколу, а ему так проще, - вот это я понимаю…
Алексей, а уж ranged-based циклы из C++11 насколько приятней читать...
int vector::size() const
{
return m_size;
}
а свойство если получить, его же поменять можно случайно, а это уже небезопасно получается.
tranquility, если впоследствии решите сменить контейнер на std::list, — мало не покажется, искать потом, откуда тормоза взялись…
А ranged-based цикл даже не заметит, что что-то изменилось…
Replikant_mih, некоторые компиляторы поддерживают.
Правда, надо добавить опцию -fdeclspec в командную строку.
Алексей, сюда ranged-based циклы из C++11 идеально ложатся:
tranquility, std::endl в нагруженном цикле?
А пробовали на '\n' заменить?
Почитайте, чем std::endl занимается после того, как выведет '\n'.
а оптимизатор ну… вреда от него нету конечно, но и помощи особой...
Интереса ради — что у вас там за оптимизация? GA, SA, ILS, SS, Path Relinking, брутфорс ?
Бабёр-Енот, Я ж говорю, у меня оптимизация без обратной связи, единоразово определяю наборы значений для прогонов, дальше идут прогоны по этим заданиям.
+ Оптимизация — это просто устоявшееся понятия, использую, чтоб люди понимали примерно о чем речь, но по факту применительно к моему подходу это никакая не оптимизация. Я формирую по каждой стратегии набор гипотез, определяю какие данные помогут мне каждую гипотезу верифицировать, далее задания для получения каждой гипотезы объединяю в один набор заданий и скармливаю оптимизатору. Дальше дата-майнинг как процесс верификации гипотез на основе полученных данных. При необходимости допроверка или новые гипотезы (с новыми заданиями на прогоны), по итогам имею работающие гипотезы, на их основе строю систему.
А входной csv содержит тики или OHLC?
Тиковые csv значительно весят ведь. Да еще и по нескольким символам, да за 10 лет..
qadexys, Ну да, если с начала — можно некоторую эволюцию проследить), ну или динамику просто.
Сейчас mt5+mql5 для автоматизации, Quik+TradingView для ручной торговли, ну и Python для скриптов и рисёча где они нужны — для ручной или для алго.