![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Интересно стало почему же моя ф-я расчета комиссии по % в USD на лот добавляла аж 60%.
1) Я использовал GetSymbol() для передачи в функцию, а там работа с CharArrayToString - основная часть тормозов была тут, решил просто передавать _Symbol, но
2) оказывается если в функцию передается строка, то она вызывается намного медленнее, чем без неё. Если делать мультивалютник, то надо будет передавать SymbolID.
Новые замеры:
без моих ф-й, как ваш вариант, но со всеми ускорителями обнаруженными ранее:
shortest pass 0:00:00.152, longest pass 0:00:00.326, average pass 0:00:00.155 EURUSD USD
shortest pass 0:00:00.171, longest pass 0:00:00.372, average pass 0:00:00.173 по EURCHF EUR
Все мои функции
shortest pass 0:00:00.158, longest pass 0:00:00.323, average pass 0:00:00.160 по EURUSD USD без запроса цен - замедление 3%
Все с сложным расчетом по EURCHF CHF с запросом 2х цен
shortest pass 0:00:00.180, longest pass 0:00:00.381, average pass 0:00:00.183 - замедление 6%
Итого: от 3 до 6% замедления за получение комиссии, свопов, контроля времени и перевода прибыли в валюту депозита.
Symbol можно хранить в массиве структур символов и их параметров (для свопов, торг. сессии и т.д.), в осн. расчетах использовать только SymbolID.Наверное все таки буду пользоваться.
ПС. У вас там тоже есть обращения к GetSymbol() в Order_Base(), но они вроде нечасто вызываются, не смотрел детально. Отказаться бы от CharArrayToString.
А для комментариев может отдельный строковый массив сделать и использовать ID ордеров для чтения/записи.
Если делать мультивалютник, то надо будет передавать SymbolID.
На мультивалютке море проблем, это только одна из них, к сожалению.
ПС. У вас там тоже есть обращения к GetSymbol() в Order_Base(), но они вроде нечасто вызываются, не смотрел детально. Отказаться бы от CharArrayToString.
Для Тестера можете попробовать вместо _Symbol использовать NULL. Честно говоря, не понимаю, почему MQ выбрали дорогой string для SymbolInfo-функций.
На мультивалютке море проблем, это только одна из них, к сожалению.
Для Тестера можете попробовать вместо _Symbol использовать NULL.
Пока в отдельных переменных храню, но можно в массив структур для индексации инструментов все скинуть.
При пересчете их в валюту депозита нужна цена по первому тику в момент начисления каждый день. Расчет в конце теста, дает свою цену. Т.е. совпадения с тестером MQ не получилось.
Сделал проверку ролловера на каждом тике и расчет свопов на лету в NewTick( const MqlTick &Tick ):
Тормозов нет, т.к. на каждом тике всего 1 раз делается time / 86400, и 1 проверка Day > prewDay_. Все остальные расчеты 1 раз в день. Очень быстро. Всего на 1мс или 0,6% медленнее.
Для замера скорости, решил исключить влияние увеличения размера массива истории и задал ему сразу 200000 строк, в тесте около 150000 будет использовано. Это дало ускорение на 11%
массив 2000 без всех доп. функций
2023.12.07 18:13:21.984 Statistics shortest pass 0:00:00.184,
массив 200000 без всех доп. функций
2023.12.07 18:23:12.170 Statistics shortest pass 0:00:00.165, 11% быстрее от 184
свопы - массив 200000
2023.12.07 18:27:50.399 Statistics shortest pass 0:00:00.166, на 0,6% медленнее от 165
торг сессия - массив 200000
2023.12.07 18:38:46.890 Statistics shortest pass 0:00:00.165, то же время
пересчет в валюту депозита - массив 200000
2023.12.07 18:40:02.505 Statistics shortest pass 0:00:00.175, на 6% медленнее от 165
комиссия в % - массив 200000
2023.12.07 18:41:25.570 Statistics shortest pass 0:00:00.184, на 11% медленнее от 165
всё - массив 200000
2023.12.07 18:42:40.264 Statistics shortest pass 0:00:00.194, на 17% медленнее от 165
Итого свопы на лету и контроль торговой сессии можно добавить без потери скорости. Остальное можно включать по необходимости.
ПС.
Столкнулся с тем, что свопы были начислены случайным сделкам открытым сразу после ролловера. Видимо ячейка Swap не переписывается при перемещении строки на новое место в массиве сделок (когда она не задана). Задал в создании ордера Create(...){.... this.Swap = 0.0; ...} После этого лишние свопы не появляются.
Соответствие с тестром MQ точное, кроме инструментов, у которых свопы начисляются в конце теста, если их вычесть, то получится точно. Если исправят тестер MQ к одинаковому поведению, то будет точно совпадать со всеми инструментами.
Если делать мультивалютник, то надо будет передавать SymbolID.
Результат.
Остальное дописать - рутина, т.к. архитектурно все решилось. Реализация довольно простая. SymbolID не понадобился. Критика приветствуется.
Итого свопы на лету и контроль торговой сессии можно добавить без потери скорости. Остальное можно включать по необходимости.
Архитектурно создал мультивалютный Virtual. Можно запустить у себя на таком примере.
...
Остальное дописать - рутина, т.к. архитектурно все решилось. Реализация довольно простая. SymbolID не понадобился. Критика приветствуется.
Класс! Что можно тестировать? Что должно работать, а что нет?
Класс! Что можно тестировать? Что должно работать, а что нет?
Пока не сделан выбор по тикету, поэтому не работают функции, где это используется: OrderModify, OrderDelete, OrderClose, SELECT_BY_TICKET.
Как тикеты будут сделаны, станет полноценным. Сейчас можно (не проверял) выставить маркет/отложку с SL/TP и увидеть все этапы срабатывания.
Работает внутреннее время Обзора рынка.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Библиотеки: Virtual
fxsaber, 2023.12.08 00:42
Например, секунду назад был последний тик EURUSD, а сейчас пришел тик GBPUSD. На этом тике решили открыть позицию по EURUSD - время открытия будет равно тику GBPUSD.
Архитектурно создал мультивалютный Virtual. Можно запустить у себя на таком примере.
Результат.
Остальное дописать - рутина, т.к. архитектурно все решилось. Реализация довольно простая. SymbolID не понадобился. Критика приветствуется.
Все таки решили мультивалютник сделать. Возможно понадобится и мне, после тестов на одной валюте. Я только начинаю работу с виртуалкой и начну с 1 валюты (и боюсь это минимум на полгода-год), а вы, видимо, уже все возможности 1-валютных экспертов исследовали и хотите к мультикам перейти.
SymbolID полезен был бы для избавления от строковых полей в структурах (Symbol меняем на ID, коммент в отд. массиве хранить) и от медленного CharArrayToString и StringToCharArray при создании каждого ордера (не знаю насколько он медленный). Плюс по SymbolID хранение параметров символа в отд. массиве.
Из критики:По оптимизации скорости:
- зачем в MultiTick( void ) каждый раз создавать массив Ticks[], может где-то 1 раз его создать и потом использовать?
- в CalcOrders( void ) не очень понял что она делает... похоже что при изменении истории, коприрует все ордера по всем символам в один OrdersCounter[]. Но не вижу что с этим дальше делается. Может можно только 1 измененный добавлять? Возможно эти копирования будут медленнее, чем просто пересчитать все инструменты в валюту депозита (~17%)
Зачем все инструменты пересчитывать? Если собирать мульти тики с индикаторов на нужных инструментах, то можно как-то передать имя инструмента и только ему делать пересчет. По другим-то изменений нет. Если не с индикаторов, а по тикам основного символа, то да - всех пересчитывать.
- в int CorrectTicksTime( MqlTick &Ticks[] ){
const int Amount = ::MathMin(this.Size, ::ArraySize(Ticks));
размер Ticks вроде бы такой же как this.Size, ниже есть ArrayResize(Ticks, this.Size)
- CorrectTicksTime нужен, чтобы всем инструментам присвоить самое последнее время. Если передаем тики с индикаторов, то можно только его одного пересчитывать (см выше) или его время присвоить всем инстр. Если работаем по тикам основного, то можно без поиска старшего присвоить время тика всем инструментам.
По идее:
как я понял, для каждого символа делается свой new ORDERS и все расчеты идут в своих массивах. С одной стороны удобно смотреть баланс по конкретному инструменту.
Но обычно мультивалютник на одном балансе работает. Как потом сделать общий отчет, общий баланс? Видимо и итоговых отчетов через Report.mqh надо несколько делать?
Я думал, что можно сделать мультик в лоб - в одном ORDERS: прописывать символ (не использовать основные _Symbol, _Points... а из заранее заполненных переменных брать) и пересчитывать всё в валюту депозита. Пересчет добавит ~17%, но будет точный результат. Если не пересчитывать, а оставлять в пипсах, то будет конечно несоразмерный общий баланс, но он и с отдельными массивами несоразмерный, да еще и склеивать их как то придется (если по последней цене, то тоже несоразмерно, за полгода стоимость инструментов может и на 10% измениться). Как вариант аналогичный вашему, балансы разным инструментам в пипсах можно и в одном ORDERS считать по SymbolID, чтобы потом анализировать отдельные символы, если надо.
SymbolID полезен был бы для избавления от строковых полей в структурах (Symbol меняем на ID, коммент в отд. массиве хранить) и от медленного CharArrayToString и StringToCharArray при создании каждого ордера (не знаю насколько он медленный).
убрал вызовы CharArrayToString и StringToCharArray вместо них сохраняю NULL и возвращаю ""
shortest pass 0:00:00.114, - 4,4 % ускорения
Плюс ускорится, если функция не будет содержать входных параметров типа string .