Обсуждение статьи "Универсальный торговый эксперт: Интеграция со стандартными модулями сигналов MetaTrader (часть 7)" - страница 3
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Спасибо Василию за ваш вклад. Я узнал много нового. Скачал весь код, но в файле Panel.mqh ошибка компиляции:
'At' - object pointer expected Panel.mqh 210 39
'At' - object pointer expected Panel.mqh 228 37
Не могли бы вы проверить это?
Привет, Эми. Я только что закончил читать статьи Василия Соколова. Если вы все еще заинтересованы в поиске решения. Пожалуйста, опубликуйте здесь журнал ошибок. Я помню, как столкнулся с этой ошибкой и понял, что в декларациях в файле StrategiesList есть ".\Panel\Panel.mqh". Panel.mqh не существует. Вместо этого попробуйте зайти на сайт https://www.mql5.com/ru/articles/2411 и скачать оттуда файл Panel. Я полагаю, что там есть файл Panel.mqh.
Эта серия от Василия действительно хороша как основа. Я тоже многому научился, но когда возникают проблемы с библиотекой, если автор не предлагает поддержку, вы можете остаться в тупике, если вы не очень хороший программист. Именно об этом говорил Ален Верлейен в других ваших обсуждениях. Но те, кто тратит время на то, чтобы поделиться своими знаниями и умениями здесь, совершенно удивительны. Я бесконечно благодарен.
Движок совершенно замечательный, спасибо. Первый ООП MQL5 движок, на который я решился перейти.
Но Manager.OnTick(), к сожалению, очень медленный. Трассировка показывает почти 100% на ней. Тестирование проходит очень медленно на минутном таймфрейме и с OHLC M1. За 3 года - примерно 50 секунд. И при этом для проверки сам эксперт ничего не делает, всё, что нагружает, я закомментировал. То есть идёт просто перебор баров.
Очень хочется оптимизации кода в Manager.OnTick()
Движок совершенно замечательный, спасибо. Первый ООП MQL5 движок, на который я решился перейти.
Но Manager.OnTick(), к сожалению, очень медленный. Трассировка показывает почти 100% на ней. Тестирование проходит очень медленно на минутном таймфрейме и с OHLC M1. За 3 года - примерно 50 секунд. И при этом для проверки сам эксперт ничего не делает, всё, что нагружает, я закомментировал. То есть идёт просто перебор баров.
Очень хочется оптимизации кода в Manager.OnTick()
Так это функция, из которой все остальное запускается - разумеется она будет 100%. Вот внутри неё смотрите, на что время уходит и оптимизируйте. Можете скрин опубликовать.
Движок совершенно замечательный, спасибо. Первый ООП MQL5 движок, на который я решился перейти.
Но Manager.OnTick(), к сожалению, очень медленный. Трассировка показывает почти 100% на ней. Тестирование проходит очень медленно на минутном таймфрейме и с OHLC M1. За 3 года - примерно 50 секунд. И при этом для проверки сам эксперт ничего не делает, всё, что нагружает, я закомментировал. То есть идёт просто перебор баров.
Очень хочется оптимизации кода в Manager.OnTick()
Ничего удивительного здесь нет. Эта скорость сопоставима с холостым ходом тестера стратегий. OnTick определяет наступление нового тика и открытие нового бара. Эти операции не требуют много ресурсов.
Здравствуйте, Василий.
Спасибо за все ваши статьи.
Универсальный советник действительно впечатляет своей сложностью и программной архитектурой.
Для данной конкретной версии я хотел бы обратить внимание на один момент в этом куске кода:
На самом деле, параметры MacD (15, 32 и 6) здесь не имеют никакого значения, так как метод CreateSignal() инициализирует сигнал MacD до обновления параметров.
В этом случае я бы предложил разделить метод CSignalAdapter::CreateSignal() на две части, где в первой части сигнал фактически создается и возвращается как есть, а вторая часть будет инициализацией сигнала, после установки всех параметров "Signal Dependent" (в данном случае PeriodFast, PeriodSlow и PeriodSignal):
CExpertSignal* CSignalAdapter::CreateSignal(MqlSignalParams& params) { DeleteSignal(); switch(params.signal_type) { case SIGNAL_AO: m_signal = new CSignalAO(); break; case SIGNAL_AC: m_signal = new CSignalAC(); break; case SIGNAL_ADAPTIVE_MA: m_signal = new CSignalAMA(); break; case SIGNAL_CCI: m_signal = new CSignalCCI(); break; case SIGNAL_DeMARKER: m_signal = new CSignalDeM(); break; case SIGNAL_DOUBLE_EMA: m_signal = new CSignalDEMA(); break; case SIGNAL_ENVELOPES: m_signal = new CSignalEnvelopes(); break; case SIGNAL_FRAMA: m_signal = new CSignalFrAMA(); break; case SIGNAL_MA: m_signal = new CSignalMA(); break; case SIGNAL_MACD: m_signal = new CSignalMACD(); break; case SIGNAL_PARABOLIC_SAR: m_signal = new CSignalSAR(); break; case SIGNAL_RSI: m_signal = new CSignalRSI(); break; case SIGNAL_RVI: m_signal = new CSignalRVI(); break; case SIGNAL_STOCHASTIC: m_signal = new CSignalStoch(); break; case SIGNAL_TRIPLE_EA: m_signal = new CSignalTriX(); break; case SIGNAL_TRIPLE_EMA: m_signal = new CSignalTEMA(); break; case SIGNAL_WILLIAMS_PER_RANGE: m_signal = new CSignalWPR(); break; } if(CheckPointer(m_signal)!= POINTER_INVALID) m_params = params; return m_signal; } bool CSignalAdapter::Init() { if(m_params.symbol == "") /* CreateSignal method should be called first in order to update m_params */ return false; m_info.Name(m_params.symbol); if(!m_signal.Init(GetPointer(m_info), m_params.period, m_params.point)) return false; if(!m_signal.InitIndicators(GetPointer(m_indicators))) return false; m_signal.EveryTick(m_params.every_tick); m_signal.Magic(m_params.magic); m_open.Create(m_params.symbol, m_params.period); m_high.Create(m_params.symbol, m_params.period); m_low.Create(m_params.symbol, m_params.period); m_close.Create(m_params.symbol, m_params.period); m_times.Create(m_params.symbol, m_params.period); m_spread.Create(m_params.symbol, m_params.period); m_tik_vol.Create(m_params.symbol, m_params.period); m_real_vol.Create(m_params.symbol, m_params.period); m_signal.SetPriceSeries(GetPointer(m_open), GetPointer(m_high), GetPointer(m_low), GetPointer(m_close)); //m_signal.SetOtherSeries(GetPointer(m_spread), GetPointer(m_times), GetPointer(m_tik_vol), GetPointer(m_real_vol)); int mask = 1; mask = mask << m_params.usage_pattern; m_signal.PatternsUsage(mask); return true; }И, конечно же, необходимо вызвать только что созданный метод Init:
Спасибо за отличную работу, а еще больше за то, что поделились ею, Василий!
Будьте здоровы,
Родриго Халлер
Толковая и профессиональная работа, автору респект. в очередной раз столкнулся с тем что практически сделав что-то, нашёл практически такое уже сделанное ранее) как говорится всё придумано до нас)
Один момент хотелось отметить - в работе сигналов мне с самого начала было дико что берётся средневзвешенное значение от сигналов на покупку и продажу, это не вяжется с логикой принятия решений в каноническом виде (дерево решений которое здесь уже упоминали) и я сделал так - Прародитель сигналов содержит помимо собственно списка сигналов, из которых берётся direction (от -100 до 100) слоты для сигналов по AND, ANDNOT, XOR. в данном случае обычный является OR, не булевым только. Вся логика обработки этих слотов однозначна и зашита в классе прародителе. Т.е. для конструирования стратегии надо только добавлять в эксперт основной сигнал и сигналы в соответствующие логические слоты, по тому же принципу что и изначально, т.е. для каждого до 64 доп.фильтров. Мне видится это решение самым простым и легкореализуемым. Если вдруг интересна идея и что-то непонятно обращайтесь расскажу подробнее.
Как можно использовать класс CSignalMACD в скрипте?
Я пытался получить результат сигнала просто на месте, но всегда получал 0: