Объединение стратегий фундаментального и технического анализа на языке MQL5 для начинающих
Введение
Фундаментальный анализ и стратегии следования за трендом часто рассматривают как противоположные подходы. Многие трейдеры, предпочитающие фундаментальный анализ, считают технический анализ пустой тратой времени, поскольку в цене уже отражена вся необходимая информация. Напротив, последователи технического анализа считают, что в фундаментальном анализе имеется изъян, поскольку одинаковые паттерны, например «Голова и плечи», могут на одном и том же рынке приводить к разным результатам.
Любого начинающего трейдера это легко может сбить с толку: перед ним оказывается так много вариантов выбора, но какой из них лучший? Какая стратегия будет неизменно приносить прибыль на ваш торговый счет, не позволяя выйти на рынок в неблагоприятных условиях?
Как писатель, я считаю, что истина — где-то посередине. Цель данной статьи — разобраться, сможем ли мы создать стабильную торговую стратегию, сочетающую в себе лучшие качества фундаментального и технического анализа, а также выяснить, стоит ли такая стратегия вложенного в нее времени.
Создадим с нуля нашего экспертного советника с помощью возможностей языка MQL5, позволяющих гибко тестировать стратегию на любом рынке. К концу прочтения этой статьи вы поймете:
- Как создать собственные советники на языке MQL5.
- Как объединить технические индикаторы в единую систему.
- Общие принципы концептуализации фундаментальных и технических данных.
Обзор торговой стратегии
Наша торговая стратегия состоит из 2 компонентов:
- Фундаментальный анализ
- Технический анализ
Рассмотрим каждый подход по очереди, чтобы понять, каким образом они дополняют друг друга, а не пытаться выяснить, какой из них лучше. Начнем с понимания основополагающих принципов, лежащих в основе нашей стратегии.
На первый взгляд финансовые графики могут показаться совершенно случайными и непредсказуемыми. Наборы финансовых данных, как известно, сильно зашумлены, а иногда даже нестабильны. Однако анализ этих графиков с фундаментальной точки зрения может привести к совершенно иным выводам относительно поведения рынка.
Фундаментальный анализ
Фундаментальный анализ основан на понимании принципов функционирования рынков. В ходе обсуждения мы сосредоточимся на валютных парах и построим свой торговый алгоритм на основе понимания валютных рынков и их основных участников.

Рис. 1. Пример фундаментального анализа пары AUDJPY.
Сторонники фундаментального анализа в трейдинге часто обсуждают поддержку и сопротивление, хотя точных определений этих понятий не существует. Хотелось бы предложить одну возможную интерпретацию с фундаментальной точки зрения.
Глядя на обменных курс двух валют, легко забыть о возможных реальных воздействиях. Например, если график USDJPY растет, это означает, что японская иена дешевеет по отношению к доллару. Поскольку 90% мировых товаров оценивают в долларах, восходящий график указывает, что экспортные операции Японии приносят меньше денежных средств за рубежом.
Если обменный курс продолжит бесконтрольно расти, японское правительство столкнется с серьезными проблемами. Экспорт страны будет стоить очень мало, что приведет к экономическому напряжению и снижению уровня жизни. Рядовые граждане могут столкнуться с трудностями при обеспечении себя предметами первой необходимости, а страна в целом — оказаться лицом к лицу с гиперинфляцией и тяжелыми экономическими условиями.
Чтобы не допустить таких последствий, для благополучия Японии крайне важно, чтобы обменный курс иены к доллару США оставался в приемлемом диапазоне. При чрезмерном повышении обменного курса японское правительство вынуждено вмешаться в деятельность валютных рынков с целью защиты своей экономики. И наоборот, когда обменный курс слишком понижается, правительство США может оказать поддержку для обеспечения баланса. Вот как можно интерпретировать с фундаментальной точки зрения тему поддержки и сопротивления.
В большинстве случаев курсы обмена валют устанавливаются совокупными решениями, которые принимают крупные финансовые учреждения, такие как розничные банки, инвестиционные банки и хедж-фонды. Эти финансовые центры контролируют большие объемы денег, и именно их групповые решения движут рынками.
Таким образом, с точки зрения фундаментального анализа, мы не хотели бы торговать против крупных корпораций, а предпочли бы найти возможности торговать в одном направлении с доминирующими игроками рынка.
Анализируя изменения цены на старших таймфреймах, например недельных или месячных, можем получить представление о том, какой уровень цены для рассматриваемой ценной бумаги крупные институциональные игроки считают справедливым. Поэтому будем искать торговые возможности, соответствующие долгосрочному изменению цены.
Объединяя все вышеизложенное, наша фундаментальная стратегия включает в себя несколько этапов. Сначала проанализируем старшие таймфреймы, чтобы понять, куда институциональные игроки, вероятнее всего, поведут цену. После подтверждения определим уровни поддержки и сопротивления, проверив самые высокие и самые низкие цены за предшествующую неделю. Наша цель — торговать по высоковероятностным настройкам, поэтому при пробое ценой уровня сопротивления откроем позицию на покупку. И наоборот, если цена опустится ниже уровня поддержки, откроем позицию на продажу.
Технический анализ
Теперь дадим определение техническому анализу, применяемому в нашей торговой стратегии. Наш технический анализ направлен на выявление схем трейдинга, при которых наши индикаторы совпадают с фундаментальным анализом. Это означает, что если тренд бычий на более старших таймфреймах, то ищем только те настройки, при которых наши технические индикаторы сигнализируют о необходимости открывать длинные позиции. И наоборот, если на более старших таймфреймах тренд медвежий, ищем только те настройки, при которых наши индикаторы совпадают для короткой сделки.
Первым индикатором в нашей системе является индекс денежного потока (Money Flow Index, MFI). Индикатор MFI служит в качестве индикатора объема и играет в нашей стратегии решающую роль. Рассматриваем только сделки, подкрепленные значительным объемом. Сделки слабого или противоположного объема в рамках данной работы не рассматриваются. Мы в своей стратегии интерпретируем MFI иначе, чем традиционные методы. Центрируем MFI на 50: значения ниже 50 указывают на медвежий объем, а значения выше 50 — на бычий.
Далее используем индикатор схождения-расхождения скользящих средних (Moving Average Convergence Divergence, MACD). Так же, как в случае с MFI, мы не используем индикатор MACD в его традиционном смысле. Вместо этого мы центрируем MACD около 0. Сигнальная линия MACD ниже 0 указывает на медвежий тренд, а сигнальная линия выше 0 — на бычий тренд.
В дополнение к MFI и MACD наша стратегия включает в себя классический подход следования за трендом с помощью скользящей средней. В отличие от подхода к другим техническим индикаторам, интерпретируем скользящую среднюю традиционным образом: если цена ниже скользящей средней, это сигнализирует о возможности продажи; если цена выше скользящей средней, это сигнализирует о возможности покупки.
Кроме того, мы интегрируем в нашу стратегию стохастический осциллятор, придерживаясь его традиционной интерпретации. Когда осциллятор показывает значение выше 20, интерпретируем это как сигнал к покупке. И наоборот, показания осциллятора ниже 80 указывают на сигнал к продаже.
Таким образом, чтобы мы могли купить ценную бумагу:
- Цена должна закрываться выше скользящей средней
- Сигнал MACD должен быть выше 0
- Значение MFI должно быть больше 50
- Стохастический осциллятор должен быть выше 20
- Цена должна была вырасти за последние 3 месяца
- Уровни цен должны быть выше уровня поддержки.
И наоборот, чтобы мы могли продать ценную бумагу:
- Цена должна закрываться ниже скользящей средней
- Сигнал MACD должен быть ниже 0
- Значение MFI должно быть ниже 50
- Стохастический осциллятор должен быть ниже 80
- Цена должна была снизиться за последние 3 месяца
- Уровни цен должны быть ниже уровня сопротивления.
Приступим
Сначала импортируем нужные нам библиотеки. В данном случае импортируем торговую библиотеку для исполнения торговых ордеров.
//+------------------------------------------------------------------+ //| Price Action & Trend Following.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ /* This Expert Advisor will help us implement a combination of fundamental analysis and trend following principles to trade financial securities with precision thanks to the easy to learn MQL5 Language that gives us a blend of creative flexibility and technical control at the same time. Our Fundamental strategy follows the principles outlined below: 1)Respect price movements on higher order time frames 2)Enter at support levels and exit on resistance levels Our Trend following strategy follows principles that have been proven over time: 1)Only enter trades backed by volume 2)Do not trade against the dominant trend, rather wait for setups to go with the bigger trend. 3)Use an ensemble of good confirmation indicators Gamuchirai Zororo Ndawana Selebi Phikwe Botswana 11:06 Thursday 11 July 2024 */ //+------------------------------------------------------------------+ //| Include necessary libraries | //+------------------------------------------------------------------+ #include <Trade/Trade.mqh> CTrade Trade;
В продолжение работы теперь нужно определить входные данные для нашей программы. Эти входные данные будут контролировать периоды наших технических индикаторов, желаемый размер торгового лота и другие переменные подобного характера.
//+------------------------------------------------------------------+ //| Input parameters for technical indicators | //+------------------------------------------------------------------+ input int stoch_percent_k = 5; // Stochastic %K input int stoch_percent_d = 3; // Stochastic %D input int stoch_slowing = 3; // Stochastic Slowing input int macd_fast_ema = 12; // MACD Fast EMA input int macd_slow_ema = 26; // MACD Slow EMA input int macd_sma = 9; // MACD SMA input int ma_period = 60; // Moving Average Period input int mfi_period = 14; // MFI Period input int lot_multiple = 10; // Lot size multiplier
Теперь создадим глобальные переменные, которые используем по всему приложению. В этих переменных будут храниться наши уровни поддержки и сопротивления, буферы технических индикаторов, цены ask и bid и другая информация подобного характера.
//+------------------------------------------------------------------+ //| Global variables | //+------------------------------------------------------------------+ double ask, bid; // Ask and Bid prices double min_distance = 0.2; // Minimum distance for stoploss double min_lot_size = 0; // Minimum lot size double position_size; // Actual position size double last_week_high = 0; // High of the previous week double last_week_low = 0; // Low of the previous week string last_week_high_name = "last week high"; // Name for high level object string last_week_low_name = "last week low"; // Name for low level object double higher_time_frame_change = 0.0; // Change on higher time frame string zone_location = ""; // Current zone location int zone = 0; // Zone indicator string higher_time_frame_trend = ""; // Higher time frame trend int trend = 0; // Trend indicator int ma_handler, stoch_handler, macd_handler, mfi_handler; // Handlers for indicators double ma_reading[], stoch_signal_reading[], macd_signal_reading[], mfi_reading[]; // Buffers for indicator readings
Теперь наша цель — определить обработчик OnInit(). В этой функции инициализируем наши технические индикаторы и соответствующим образом скорректируем размер торгового лота.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Set up handlers for technical indicators ma_handler = iMA(_Symbol, PERIOD_CURRENT, ma_period, 0, MODE_EMA, PRICE_CLOSE); macd_handler = iMACD(_Symbol, PERIOD_CURRENT, macd_fast_ema, macd_slow_ema, macd_sma, PRICE_CLOSE); stoch_handler = iStochastic(_Symbol, PERIOD_CURRENT, stoch_percent_k, stoch_percent_d, stoch_slowing, MODE_EMA, STO_CLOSECLOSE); mfi_handler = iMFI(_Symbol, PERIOD_CURRENT, mfi_period, VOLUME_TICK); //--- Adjust lot size min_lot_size = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); position_size = min_lot_size * lot_multiple; //--- Initialization done return(INIT_SUCCEEDED); }
Теперь определим функцию, которая будет извлекать уровни поддержки и сопротивления, выявленные по истории торговли предшествующей недели.
//+------------------------------------------------------------------+ //| Function to get the previous week's high and low prices | //+------------------------------------------------------------------+ bool get_last_week_high_low(void) { //--- Reset values last_week_high = 0; last_week_low = 0; //--- Remove old levels if any ObjectDelete(0, last_week_high_name); ObjectDelete(0, last_week_low_name); //--- Update high and low values last_week_high = iHigh(_Symbol, PERIOD_W1, 1); last_week_low = iLow(_Symbol, PERIOD_W1, 1); //--- Mark current levels of support and resistance ObjectCreate(0, last_week_high_name, OBJ_HLINE, 0, 0, last_week_high); ObjectCreate(0, last_week_low_name, OBJ_HLINE, 0, 0, last_week_low); //--- Check for valid values return((last_week_high * last_week_low) != 0); }
Далее нам нужно понять действие цены, происходящее на более старшем таймфрейме. Не забывайте, что мы рассмотрим прошлый деловой цикл, примерно 3 месяца, чтобы выяснить, как действовали на рынке институциональные игроки.
//+------------------------------------------------------------------+ //| Function to determine higher time frame price movement | //+------------------------------------------------------------------+ bool get_higher_time_frame_move(void) { //--- Analyze weekly time frame higher_time_frame_change = iClose(_Symbol, PERIOD_CURRENT, 1) - iClose(_Symbol, PERIOD_W1, 12); //--- Check for valid values return((iClose(_Symbol, PERIOD_W1, 12) * iClose(_Symbol, PERIOD_W1, 1)) != 0); }
Следующей задачей станет интерпретация сигналов ценового поведения, которые мы собрали. В частности, нам нужно понять, находимся ли мы выше максимума предыдущей недели, что обозначим как зону 1; если мы ниже минимума прошлой недели, то мы в зоне 3; наконец, если мы в промежутке между ними, то мы находимся в зоне 2. Затем мы обозначим тренд, определенный нами на более старшем таймфрейме. Если на более высоком таймфрейме цена возрастала, мы обозначим тренд 1, в противном случае — отметим тренд как -1.
//+------------------------------------------------------------------+ //| Function to interpret price action data | //+------------------------------------------------------------------+ void interpet_price_action(void) { //--- Determine zone location based on last week's high and low if(iClose(_Symbol, PERIOD_CURRENT, 0) > last_week_high) { zone = 1; zone_location = "We are above last week's high"; } else if(iClose(_Symbol, PERIOD_CURRENT, 0) < last_week_low) { zone = 3; zone_location = "We are below last week's low"; } else { zone = 2; zone_location = "We are stuck inside last week's range"; } //--- Determine higher time frame trend if(higher_time_frame_change > 0) { higher_time_frame_trend = "Higher time frames are in an up trend"; trend = 1; } else if(higher_time_frame_change < 0) { higher_time_frame_trend = "Higher time frames are in a down trend"; trend = -1; } }
Теперь нам понадобится функция, которая будет обновлять значения нашего технического индикатора и извлекать текущие рыночные данные.
//+------------------------------------------------------------------+ //| Function to update technical indicators and fetch market data | //+------------------------------------------------------------------+ void update_technical_indicators(void) { //--- Update market prices ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); //--- Copy indicator buffers CopyBuffer(ma_handler, 0, 1, 1, ma_reading); CopyBuffer(stoch_handler, 1, 1, 1, stoch_signal_reading); CopyBuffer(macd_handler, 1, 1, 1, macd_signal_reading); CopyBuffer(mfi_handler, 0, 1, 1, mfi_reading); }
Эта функция выполнит наши торговые записи за нас; если наша функция медвежьих настроений даст на то разрешение, мы откроем сделку на продажу. И наоборот, мы можем открывать позиции на покупку, если у нас есть на это разрешение от функции бычьих настроений.
//+------------------------------------------------------------------+ //| Function to find entry points for trades | //+------------------------------------------------------------------+ void find_entry(void) { //--- Check for bullish sentiment if(bullish_sentiment()) { Trade.Buy(position_size, _Symbol, ask, (last_week_low - min_distance), (last_week_high + min_distance)); } //--- Check for bearish sentiment else if(bearish_sentiment()) { Trade.Sell(position_size, _Symbol, bid, (last_week_high + min_distance), (last_week_low - min_distance)); } }
Теперь тщательно определим, что означает соответствие двух наших торговых систем для настройки на покупку. Вспомните условия, которые мы определили ранее в обсуждении: нам нужно, чтобы цена закрывалась выше скользящей средней, индикатор MFI должен быть выше 50, показание MACD должно быть больше 0, стохастический осциллятор должен быть выше 20, тренд на более старшем таймфрейме должен быть бычьим, и мы должны находиться выше уровня поддержки.
//+------------------------------------------------------------------+ //| Function to analyze bullish signals | //+------------------------------------------------------------------+ bool bullish_sentiment(void) { //--- Analyze conditions for bullish sentiment return((mfi_reading[0] > 50) && (iClose(_Symbol, PERIOD_CURRENT, 1) > ma_reading[0]) && (macd_signal_reading[0] > 0) && (stoch_signal_reading[0] > 20) && (trend == 1) && (zone < 3)); }
Обратное же справедливо для наших установок на продажу.
//+------------------------------------------------------------------+ //| Function to analyze bearish signals | //+------------------------------------------------------------------+ bool bearish_sentiment(void) { //--- Analyze conditions for bearish sentiment return((mfi_reading[0] < 50) && (iClose(_Symbol, PERIOD_CURRENT, 1) < ma_reading[0]) && (macd_signal_reading[0] > 0) && (stoch_signal_reading[0] < 80) && (trend == -1) && (zone > 1)); }
Наконец, нам нужен обработчик событий OnTick(), который обеспечит исполнение потока событий в приложении в соответствии с нашим намерением. Обратите внимание, что начинаем мы с проверки временной метки. Это поможет нам гарантировать, что приложение будет проверять уровни поддержки и сопротивления только один раз в неделю. В противном случае, если у нас нет новых недельных свечей, нет смысла снова и снова проверять одну и ту же информацию на каждом тике! Если все работает корректно, то наш советник приступит к интерпретации ценового действия, обновит технические индикаторы, а затем начнет искать возможность входа в сделку.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Check for new candle on higher time frame static datetime time_stamp; datetime current_time = iTime(_Symbol, PERIOD_W1, 0); if(time_stamp != current_time) { time_stamp = current_time; if(!get_last_week_high_low()) { Print("Failed to get historical performance of ", _Symbol); Print("[ERROR]: ", GetLastError()); } else if(!get_higher_time_frame_move()) { Print("Failed to analyze historical performance of ", _Symbol); Print("[ERROR]: ", GetLastError()); } } else { interpet_price_action(); update_technical_indicators(); if(PositionsTotal() == 0) { find_entry(); } Comment("Last week high: ", last_week_high, "\nLast week low: ", last_week_low, "\nZone: ", zone_location, "\nTrend: ", higher_time_frame_trend); } }

Рис. 2. Наш советник торгует парой AUDJPY на таймфрейме H1.

Рис. 3. Результаты тестирования нашего торгового алгоритма на истории по данным H1 и символу AUDJPY за 1 месяц.
Заключение
В статье проиллюстрирована интеграция фундаментального и технического анализа в торговых стратегиях. С помощью MQL5 мы показали, как можно легко объединить выводы, сделанные с обеих точек зрения, в действенные торговые рекомендации. Представляя структуру, в которой данные фундаментального и технического анализа не конкурируют, а дополняют друг друга, мы даем читателям возможность эффективно использовать оба подхода.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/15293
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
От начального до среднего уровня: Массивы и строки (III)
Возможности Мастера MQL5, которые вам нужно знать (Часть 33): Ядра гауссовского процесса
Оптимизация хаотичной игрой — Chaos Game Optimization (CGO)
Разрабатываем мультивалютный советник (Часть 23): Приводим в порядок конвейер этапов автоматической оптимизации проектов (II)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Могу ли я получить файл программы?
Файла программы не существует.
Нажмите на ссылку в первом сообщении, чтобы прочитать статью.