
Автоматизация торговли с помощью трендовой стратегии Parabolic SAR на MQL5: Создаем эффективный советник
Введение
Алгоритмические торговые стратегии произвели революцию в финансовой торговле, позволив трейдерам быстро принимать обоснованные решения. Это помогло исключить человеческие ошибки и эмоции, поскольку автоматизированные системы следуют заранее заданным параметрам в быстро меняющейся рыночной среде. Автоматизированная торговля обеспечивает последовательность, поскольку система каждый раз использует одну и ту же логику для совершения сделок.
Создание и внедрение автоматизированных методов с использованием MetaTrader 5 является обычной практикой. В статье подробно рассматривается создание советника, использующего индикатор Parabolic SAR для автоматического проведения сделок.
Обзор стратегии Parabolic SAR
Индикатор Parabolic SAR. Индикатор был разработан в 1978 году Уэллсом Уайлдером. Индикатор выделяет потенциальные точки разворота рыночного тренда с помощью серии точек на графике, которые следуют за движением цены вверх и вниз. Когда точки находятся ниже цены, рынок находится в восходящем тренде; когда они выше, рынок находится в нисходящем тренде. Это делает его особенно полезным для определения потенциальных точек разворота, когда тренд может подойти к концу.
Шаг SAR: помогает определить, насколько близко точки SAR отслеживают цену. Небольшой шаг отстает от цены на несколько точек, снижая чувствительность. Более высокий шаг перемещает точки ближе к цене, увеличивая чувствительность.
Точки SAR: действует как фактор ускорения в качестве верхнего предела. На трендовом рынке Parabolic SAR увеличивает шаги, чтобы догнать цены. Таким образом, трейдеры могут определять точки входа и выхода на потенциальных разворотах тренда.
Стратегию можно объединить с другими индикаторами или использовать в качестве самостоятельной стратегии на трендовых рынках, включая форекс и товары.
Реализация средствами MQL5
В заголовок мы включаем основные метаданные, такие как авторские права и номер версии. Библиотека Trade.mqh включена для обработки торговых операций, то есть открытия и закрытия позиций.
#property copyright "Copyright 2024, MetaQuotes Ltd." "Duke" #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh>
Теперь определим входные параметры, которые позволят нам настроить советник.
LotSize - размер лота. Позволяет советнику определять размер сделок. Это означает, что небольшой размер лота снизит риски и прибыль за счет уменьшения размера сделки. Кроме того, большой LotSize означает повышенные риски и прибыль.
SAR_Step и SAR_Maximum - чувствительность Parabolic SAR при обнаружении движения цены и расчете индикатора Parabolic SAR.
Slippage - проскальзывание. Позволяет советнику установить максимально допустимое проскальзывание при размещении ордеров.
//--- Input parameters input double LotSize = 0.2 ; // Lot size for trading input double SAR_Step = 0.02; // Parabolic SAR step input double SAR_Maximum = 0.2; // Parabolic SAR maximum input int Slippage = 3; // Slippage for orders
Мы можем создать экземпляр класса CTrade для управления торговыми операциями.
//--- Trade object
CTrade trade;
Наш следующий шаг — функция OnInit, которая выполняется при загрузке советника. Функция просто выводит сообщение с подтверждением успешной инициализации журнала советника (EA). Поэтому мы проверим, что советник был загружен и инициализирован без каких-либо проблем. Эта функция также полезна при отладке, гарантируя готовность советника к началу обработки данных. Функция также может вернуть INIT_FAILED, если инициализация по какой-либо причине не удалась, что привело к остановке работы советника.
int OnInit() { //--- Initialization code here Print("Parabolic SAR EA Initialized"); return(INIT_SUCCEEDED); }
Переходим к функции OnDeint. При перекомпиляции советник удаляется из графика. Действие активирует функцию OnDeint для выполнения задач очистки и обеспечения надлежащего высвобождения ресурсов. Эти записи в журнале позволяют явно определить, был ли советник удален, перекомпилирован или работа терминала была завершена. Это предоставляет полезную информацию на этапе разработки и тестирования. Эту функцию можно расширить до любых необходимых процедур очистки. Например, вам может потребоваться закрыть все открытые ресурсы, освободить хэндлы файлов или сохранить текущее состояние.
Это поможет повысить надежность и стабильность, поскольку гарантирует, что проблемы с производительностью, возникавшие при предыдущих запусках, не повлияют на способность советника перезапускаться.
void OnDeinit(const int reason) { //--- Cleanup code here Print("Parabolic SAR EA Deinitialized"); }
После OnDeint рассмотрим функцию OnTick. Эта функция является ядром советника и выполняется с каждым рыночным тиком. Он рассчитывает значение Parabolic SAR и сравнивает его с последней ценой закрытия. На основе этого сравнения советник определяет, открывать ли ордер на покупку или продажу.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the Parabolic SAR value double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle //--- Check if there is an existing position if(!IsPositionOpen(_Symbol)) { //--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } }
Теперь мы можем разобрать функцию OnTick для лучшего понимания.
- Расчет Parabolic SAR: Первая строка кода вычисляет значение Parabolic SAR:
double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value
- iSAR() - встроенная функция в платформах MetaTrader, которая рассчитывает значение индикатора Parabolic SAR для заданного актива за указанный период.
- _Symbol - анализируемый финансовый инструмент, например EURUSD или золото.
- _Period - таймфрейм графика (M1, H1, D1 и так далее). Это помогает функции определить, какие свечи использовать для расчета SAR.
- _SAR_Step и SAR Maximum - параметры, специфичные для индикатора Parabolic SAR, которые контролируют его чувствительность. SAR_Step — это значение шага приращения, которое ускоряет индикатор по мере развития тренда, в то время как SAR Maximum ограничивает ускорение, чтобы не допустить слишком быстрой реакции индикатора на изменение цены.
- Получение цены закрытия предыдущей свечи: Следующая строка извлекает цену закрытия последней завершенной свечи:
double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle
- iClose() - функция возвращает цену закрытия конкретной свечи на графике.
- _Symbol и _Period - как и iSAR(), функция относится к конкретному анализируемому финансовому инструменту и таймфрейму.
- 1 - параметр указывает, какую цену закрытия свечи мы хотим получить. В этом случае 1 обозначает последнюю завершенную свечу (предыдущую), поскольку текущая свеча все еще формируется.
Значение, хранящееся в LastPrice, представляет собой окончательный уровень цены, по которому торговался актив на момент закрытия последней свечи.
Мы используем код Parabolic SAR для автоматизации решений по установке стоп-лоссов и определению выходов из сделок или разворотов. Например, если цена закрытия падает ниже значения SAR в длинной позиции, это может указывать на разворот тренда, побуждая трейдера закрыть позицию или рассмотреть возможность открытия короткой позиции. Советник использует это сравнение, чтобы определить, продолжает ли рынок свой тренд или разворачивается. Это помогает устранить эмоции и полагаться на четкие торговые сигналы.
При построении торгового алгоритма обычно реализуется проверка того, открыта ли уже позиция по определенному активу (символу).
//--- Check if there is an existing position if(!IsPositionOpen(_Symbol))
IsPositinOpen(_Symbol) - функция проверяет, имеется ли в данный момент открытая позиция по символу _Symbol. Символ обычно представляет собой тикер или код актива.
!IsPositionOpen(_Symbol) - условие истинно, только если открытых позиций по символу нет.
Оператор if - если открытой позиции по символу нет, будет выполнен код внутри блока if. Это может быть открытие новой позиции, совершение сделки или запуск другой торговой логики.
Таким образом, эта функция гарантирует отсутствие излишней торговли, которая может быть вызвана открытием нескольких позиций по одному и тому же символу. Это поможет системе лучше контролировать торговую активность.
Parabolic SAR отслеживает тренды, указывая точки входа и выхода с помощью скользящего стоп-лосса, который корректируется в зависимости от движения цен. Пересечение сигнализирует о возможном развороте тренда.
//--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } }
LastPrice - текущая рыночная цена торгуемого актива.
sar - текущее значение Parabolic SAR.
Сравнивая эти два показателя, алгоритм определяет, является ли тренд восходящим или нисходящим, и действует соответствующим образом.
Логика покупки и продажи
Ордера на покупку устанавливаются, когда последняя цена превышает значение sar, что указывает на восходящий тренд. Затем алгоритм запускает функцию OpenBuyOrder() для исполнения сделки, исходя из предположения, что рынок продолжит расти, а цена превысит SAR.
Ордера на продажу устанавливаются, если lastPrice ниже SAR. Это интерпретируется как сигнал о том, что рынок находится в нисходящем тренде. Алгоритм реагирует вызовом функции OpenSellOrder(), инициируя сделку на продажу. В данном случае стратегия предполагает, что поскольку цена опустилась ниже SAR, рынок может продолжить падение.
Код отдает приоритет оценке ордера на покупку. Если условие ордера на покупку (lastprice > sar) выполняется, система немедленно исполняет сделку на покупку. Если это условие не выполняется, код проверяет условие продажи (lastPrice<sar). Если условие истинно, совершается сделка на продажу.
Следующий шаг — вспомогательные функции
Здесь мы начинаем с проверки функции OpenPositions. Функция IsPositionOpen проверяет, существует ли уже открытая позиция по текущему торговому символу. Это не позволяет советнику открывать несколько позиций в одном направлении одновременно.
//+------------------------------------------------------------------+ //|Check if there is an open position for the given symbol | //+------------------------------------------------------------------+ bool IsPositionOpen(string symbol) { uint total=PositionsTotal(); //Get the total number of open positions for(uint i=0; i<total; i++) { string POSITION_SYMBOL=PositionGetSymbol(i); //Get the symbol of the position if(POSITION_SYMBOL == _Symbol) //Check if the symbol matches the current symbol { return true; } } return false; }
Теперь рассмотрим код подробнее, разбив код функции следующим образом:
- Входные параметры: функция принимает аргумент строкового символа, представляющий желаемый символ, например валютную пару или биржевой тикер.
- Получаем общее количество позиций: функция извлекает общее количество открытых в данный момент позиций с помощью PositionsTotal(). Функция возвращает количество позиций, открытых в терминале на момент выполнения.
- Итерации по позициям: используя цикл for, код выполняет итерации по всем открытым позициям. Переменная total хранит количество открытых позиций, цикл выполняется от 0 до total - 1.
- Сравнение символов: извлеченный символ POSITION_SYMBOL затем сравнивается с текущим символом с использованием условия if (POSITION_SYMBOL==_SYMBOL). Переменная _Symbol — это предопределенный идентификатор, представляющий символ графика, из которой вызывается функция. Если символы совпадают, это означает, что по данному символу уже есть открытая позиция.
- Возвращаемое значение: если функция находит совпадение (то есть позиция для данного символа уже открыта), она возвращает true. Если после проверки всех открытых позиций циклом не найдено ни одной соответствующей позиции, функция возвращает значение false, что указывает на отсутствие открытых позиций для указанного символа.
Эта функция особенно полезна для предотвращения открытия алгоритмом новой позиции, когда одна из позиций уже активна. Например, если вы торгуете на EURUSD и функция возвращает значение true, стратегия может избежать открытия новой позиции и вместо этого сосредоточиться на управлении существующей.
Наша следующая вспомогательная функция — OpenBuyOrder(). Она отвечает за выполнение сделки на покупку. Она пытается открыть ордер на покупку с указанным размером лота, а также включает обработку ошибок, чтобы гарантировать правильность завершения процесса или уведомить трейдера, если что-то пойдет не так.
//+------------------------------------------------------------------+ //| Open a Buy order | //+------------------------------------------------------------------+ void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, 0, 0, 0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } }
Функция объявлена как void OpenBuyOrder(). Это означает, что она не возвращает никакого значения, а выполняет определенную задачу, в данном случае размещает ордер на покупку.
Функция использует метод trade.Buy() для выполнения ордера на покупку. Для метода необходимы следующие параметры:
- LotSize - размер ордера, в нашем случае - 0.2.
- Null - текущий символ графика, из которого вызывается функция. В этом случае NULL по умолчанию соответствует символу на текущем графике.
- 0 - цена ордера. Использование нуля означает, что ордер будет исполнен по текущей рыночной цене.
- 0 - уровень стоп-лосса. 0 означает, что при открытии ордера стоп-лосс не открывается.
- 0 - уровень тейк-профита. Ноль означает, что изначально тейк-профит не установлен.
- Buy Order - комментарий для идентификации ордера.
При успешном размещении ордера (if(trade.Buy(....) равен true) функция вызывает Print() для отображения сообщения: "Buy order placed successfully" (ордер на покупку размещен успешно).
Если ордер не исполнен (else), функция выводит "Error placing buy order" (ошибка размещения ордера на покупку) с кодом ошибки, возвращаемым GetLastError(). Функция GetLastError() извлекает последнюю ошибку, произошедшую в системе, предоставляя трейдеру ценную информацию для устранения неполадки.
Наша последняя вспомогательная функция — Opening a Sell Order. Функция предназначена для автоматизации процесса открытия ордера на продажу в алгоритмической торговой системе. Функция повторяет логику функции OpenBuyOrder(), но предназначена для сделок или ордеров на продажу.
//+------------------------------------------------------------------+ //| Open a Sell order | //+------------------------------------------------------------------+ void OpenSellOrder() { if(trade.Sell(LotSize, NULL, 0, 0, 0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
Функция void OpenSellOrder() не возвращает никакого значения, а фокусируется на выполнении конкретной задачи: размещении ордера на продажу.
Метод trade.Sell() используется для инициирования ордера на продажу. Параметры, передаваемые этому методу, следующие:
- Lotsize - количество лотов для ордера на продажу, в нашем случае - 0.2.
- NULL - символ текущего графика, из которой вызывается функция. При NULL функция начинает торговать по символу на текущем графике.
- 0 - цена ордера. При 0 ордер будет исполнен по текущей рыночной цене.
- 0 - уровень стоп-лосса. При 0 стоп-лосс не используется.
- 0 - уровень тейк-профита. При 0 не используется.
- Sell order - комментарий для идентификации ордера.
Если ордер на продажу размещен успешно, выводится соответствующее сообщение с помощью функции Print().
Если ордер не исполнен, функция выводит "Error placing sell order:" (ошибка размещения ордера на продажу) с кодом ошибки, возвращаемым GetLastError().
Ниже представлен полный код:
//+------------------------------------------------------------------+ //| ParabolicSAR_EA.mq5 | //| Copyright 2024, MetaQuotes Ltd."Duke" | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." "Duke" #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> //--- Input parameters input double LotSize = 0.2 ; // Lot size for trading input double SAR_Step = 0.02; // Parabolic SAR step input double SAR_Maximum = 0.2; // Parabolic SAR maximum input int Slippage = 3; // Slippage for orders //--- Trade object CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Initialization code here Print("Parabolic SAR EA Initialized"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Cleanup code here Print("Parabolic SAR EA Deinitialized"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the Parabolic SAR value double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle //--- Check if there is an existing position if(!IsPositionOpen(_Symbol)) { //--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } } //+------------------------------------------------------------------+ //|Check if there is an open position for the given symbol | //+------------------------------------------------------------------+ bool IsPositionOpen(string symbol) { uint total=PositionsTotal(); //Get the total number of open positions for(uint i=0; i<total; i++) { string POSITION_SYMBOL=PositionGetSymbol(i); //Get the symbol of the position if(POSITION_SYMBOL == _Symbol) //Check if the symbol matches the current symbol { return true; } } return false; } //+------------------------------------------------------------------+ //| Open a Buy order | //+------------------------------------------------------------------+ void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, 0, 0, 0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } } //+------------------------------------------------------------------+ //| Open a Sell order | //+------------------------------------------------------------------+ void OpenSellOrder() { if(trade.Sell(LotSize, NULL, 0, 0, 0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
Ниже приведены результаты тестирования на истории:
Тестирование проводилось на графике USDJPY М1. Период тестирования - с 2024.01.01 по 2024.08.05. Модель - все тики.
Ниже приведены входные параметры, использовавшиеся в процессе тестирования:
После нескольких тестов на графике М1 я смог понять, что:
- Эта стратегия подходит для USDJPY и EURUSD.
- Эта стратегия не очень хорошо работает с парой GBPUSD.
Заключение
Из результатов можно сделать вывод, что этот простой советник может гарантировать трейдеру хорошие результаты, если внести в него дальнейшие усовершенствования и адаптации для улучшения управления, а также снизить подверженность активов высоким рискам. Это подразумевает управления рисками, в частности добавление трейлинг-стопа, который поможет повысить производительность советника за счет обеспечения прибыли при благоприятных рыночных условиях. Кроме того, необходимы оптимизация параметров, ряд тестов и тонкая настройка таких параметров, как SAR Step и Maximum, для оптимальной производительности в различных рыночных условиях.
Приведенный здесь код предназначен только для того, чтобы помочь трейдерам освоить основы реализации стратегии Parabolic SAR. Полученные при тестировании на истории результаты не гарантируют будущей эффективности советника в торговле.
Перед использованием критически важно провести тщательное тестирование на истории и форвард-тестирование. Для предотвращения непредвиденных потерь и быстрого внесения корректировок необходим постоянный мониторинг. Автоматизация торговли с использованием этой стратегии может помочь свести к минимуму человеческий фактор, позволяя создать сложную и прибыльную торговую систему посредством настройки, оптимизации и тестирования. Внедрение такого типа автоматизации может привести к более эффективному использованию возможностей и повышению эффективности торговли. В статье рассмотрены необходимые знания и навыки, требуемые для реализации стратегии Parabolic SAR. Любые другие ресурсы, необходимые для реализации, содержатся в языке MQL5.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/15589





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
PSAR с моделями глубокого обучения дает отличные результаты.
не могли бы вы указать, как вы используете dl и psar?
https://www.mql5.com/en/articles/15589
Хорошая шутка
Хорошая шутка
неплохая..
без неё не обратил-бы внимания что :
на сайте статья датирована 10 марта 2025, первый коммент 26 авг 2024 за 7 месяцев ДО публикации :-)
"темна вода в небесях"
на сайте статья датирована 10 марта 2025, первый коммент 26 авг 2024 за 7 месяцев ДО публикации :-)
Это дата перевода. Оригинал статьи был опубликован 23 августа 2024