Price Action in MQL4: How Can You Code It?

Introduction to Price Action in MQL4

Understanding Price Action: A Brief Overview

Price action trading revolves around analyzing the ‘naked’ price movements of an asset to make trading decisions. It’s about understanding the story the market is telling through its price charts, without relying heavily on lagging indicators. Key elements include candlestick patterns, support and resistance levels, trendlines, and breakout analysis. The core idea is that past price behavior can offer clues about future price movements. Unlike indicator-based strategies, price action focuses on the immediacy and raw data provided by the price itself.

Why Use MQL4 for Price Action Analysis?

MQL4 provides the tools necessary to automate price action strategies. While manual chart analysis is valuable, MQL4 allows you to:

  • Backtest rigorously: Evaluate the historical performance of your price action rules.
  • Remove subjectivity: Code your rules precisely, eliminating emotional biases.
  • Automate execution: Develop Expert Advisors (EAs) that enter and exit trades based on defined criteria.
  • Create custom indicators: Develop tools specific to your unique style of price action.

Setting Up Your MQL4 Development Environment

To get started with MQL4 coding for price action, you’ll need the MetaTrader 4 platform. Open the MetaEditor (press F4 in MetaTrader 4). This is where you’ll write, compile, and debug your code. Familiarize yourself with the basic structure of an Expert Advisor (EA), custom indicator, or script. Remember that EAs automatically execute trading algorithms, indicators paint directly onto the chart, while scripts run a single task on demand. Understanding data types, variables, and control flow (if/else statements, loops) is crucial.

Coding Basic Price Action Patterns in MQL4

Identifying Candlestick Patterns: Bullish and Bearish Engulfing

Candlestick patterns are a cornerstone of price action. Let’s consider the Bullish Engulfing pattern. This pattern signals a potential reversal from a downtrend and involves two candlesticks:

  1. A bearish candlestick (usually black or red).
  2. A subsequent bullish candlestick (usually white or green) that completely engulfs the previous bearish candlestick’s body.

Here’s a simplified MQL4 code snippet to detect this:

bool IsBullishEngulfing()
{
   double Open1 = iOpen(NULL, 0, 1); // Open price of previous candle
   double Close1 = iClose(NULL, 0, 1); // Close price of previous candle
   double Open0 = iOpen(NULL, 0, 0); // Open price of current candle
   double Close0 = iClose(NULL, 0, 0); // Close price of current candle

   if(Close1 < Open1 && Close0 > Open0 && Close0 > Open1 && Open0 < Close1)
   {
      return(true);
   }
   else
   {
      return(false);
   }
}

This function checks if the current bullish candle engulfs the previous bearish candle, according to the price relationships of open and close prices. Similarly, you could identify a Bearish Engulfing pattern by flipping the comparison logic.

Implementing Functions to Detect Hammer and Shooting Star Patterns

Hammer and Shooting Star patterns are reversal signals that look similar but appear in different contexts. The Hammer appears after a downtrend, suggesting a potential bullish reversal, while the Shooting Star appears after an uptrend, suggesting a potential bearish reversal. Both have small bodies and long lower (Hammer) or upper (Shooting Star) shadows. Coding these involves defining rules based on the size of the body relative to the shadow.

bool IsHammer()
{
   double Open = iOpen(NULL, 0, 0);
   double Close = iClose(NULL, 0, 0);
   double High = iHigh(NULL, 0, 0);
   double Low = iLow(NULL, 0, 0);
   double Body = MathAbs(Close - Open);
   double LowerShadow = Open > Close ? Close - Low : Open - Low; //Consider which price is bigger

   if(LowerShadow > 2 * Body && High - MathMax(Open, Close) < 0.5 * Body)
   {
      return(true);
   }

   return(false);
}

bool IsShootingStar()
{
   double Open = iOpen(NULL, 0, 0);
   double Close = iClose(NULL, 0, 0);
   double High = iHigh(NULL, 0, 0);
   double Low = iLow(NULL, 0, 0);
   double Body = MathAbs(Close - Open);
   double UpperShadow = Open > Close ? High - Open : High - Close; //Consider which price is bigger

   if(UpperShadow > 2 * Body && MathMin(Open, Close) - Low < 0.5 * Body)
   {
      return(true);
   }

   return(false);
}

These functions quantify the relationships between the body and shadow to identify these patterns. The multiplier 2 and 0.5 can be considered parameters for optimisation.

Coding Doji and Spinning Top Identification

Doji and Spinning Top patterns indicate indecision in the market. A Doji has a very small body (open and close prices are nearly equal) and can have long upper and lower shadows. A Spinning Top also has a small body but with more pronounced upper and lower shadows than a Doji. The code will look for a minimal difference between open and close.

bool IsDoji()
{
   double Open = iOpen(NULL, 0, 0);
   double Close = iClose(NULL, 0, 0);
   double High = iHigh(NULL, 0, 0);
   double Low = iLow(NULL, 0, 0);

   double BodySize = MathAbs(Open - Close);
   double CandleRange = High - Low;

   // Define a threshold for what is considered a 'small' body.
   double DojiThreshold = 0.05; //As a percentage of the candle's range

   if (CandleRange > 0 && BodySize <= CandleRange * DojiThreshold) {
      return true;
   } else {
      return false;
   }
}

bool IsSpinningTop()
{
   double Open = iOpen(NULL, 0, 0);
   double Close = iClose(NULL, 0, 0);
   double High = iHigh(NULL, 0, 0);
   double Low = iLow(NULL, 0, 0);

   double BodySize = MathAbs(Open - Close);
   double UpperShadow = High - MathMax(Open, Close);
   double LowerShadow = MathMin(Open, Close) - Low;

    // Define thresholds for body size and shadow lengths.
   double BodyThreshold = 0.3; // As a percentage of the candle's range
   double ShadowThreshold = 0.2; // As a percentage of the candle's range
   double CandleRange = High - Low;

   if (CandleRange > 0 && BodySize <= CandleRange * BodyThreshold &&
       UpperShadow >= CandleRange * ShadowThreshold && LowerShadow >= CandleRange * ShadowThreshold) {
      return true;
   } else {
      return false;
   }
}

Storing Pattern Data and Accessing It

Once patterns are detected, it’s vital to store this information for further analysis or for use in trading logic. You can use global variables, custom indicator buffers, or arrays. Indicator buffers are the most efficient way to store data related to each bar.

#property indicator_buffers 1
#property indicator_plots   1
#property indicator_label1  "BullishEngulfing"
#property indicator_color1  clrGreen

double BullishEngulfingBuffer[];

int OnInit()
{
   SetIndexBuffer(0, BullishEngulfingBuffer, INDICATOR_DATA);
   SetIndexStyle(0, DRAW_ARROW, STYLE_SOLID, 2, clrGreen);
   SetIndexArrow(0, 233); // Example arrow code
   return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])
{
   for(int i = prev_calculated; i < rates_total; i++)
   {
      BullishEngulfingBuffer[i] = EMPTY_VALUE; // Initialize
      if(IsBullishEngulfing())
      {
         BullishEngulfingBuffer[i] = low[i] - Point * 10; // Display arrow below the candle
      }
   }
   return(rates_total);
}

This example stores a flag (arrow) in the BullishEngulfingBuffer if a bullish engulfing pattern is found on a particular bar.

Advanced Price Action Concepts and Their MQL4 Implementation

Coding Support and Resistance Level Detection

Support and resistance levels are key areas where price has previously reversed or stalled. Identifying them algorithmically is challenging but possible using techniques like pivot point analysis or detecting clusters of highs and lows within a specified period. Pivot point analysis can be implemented as:

double CalculatePivotPoint(int period)
{
   double High = iHighest(NULL, 0, MODE_HIGH, period, 0);
   double HighPrice = iHigh(NULL, 0, High);
   double Low = iLowest(NULL, 0, MODE_LOW, period, 0);
   double LowPrice = iLow(NULL, 0, Low);
   double Close = iClose(NULL, 0, 0);

   return((HighPrice + LowPrice + Close) / 3);
}

double CalculateResistance1(double pivotPoint, double low)
{
   return (2 * pivotPoint - low);
}

double CalculateSupport1(double pivotPoint, double high)
{
   return (2 * pivotPoint - high);
}

Here, the highest high and the lowest low prices over a period are used to compute the Pivot Point, Resistance 1, and Support 1 levels.

Implementing Trend Line Analysis Using MQL4

Trendlines are diagonal lines drawn connecting a series of highs (downtrend) or lows (uptrend). Coding trendline detection involves identifying at least two significant price points (highs or lows) and drawing a line that extends into the future. MQL4’s object functions are useful here. This usually involves detecting a sequence of higher lows (uptrend) or lower highs (downtrend) within a defined tolerance.

ObjectCreate("UptrendLine", OBJ_TREND, 0, Time[LowestIndex1], Low[LowestIndex1], Time[LowestIndex2], Low[LowestIndex2]);

This code creates an uptrend line based on two low points in the chart. The algorithm to define the two points themselves would be based on identifying local minima.

Detecting Breakouts and False Breakouts

Breakouts occur when price moves beyond a defined support or resistance level. A false breakout is when price briefly exceeds the level but then reverses back. Detecting breakouts involves monitoring price in relation to these levels. Filtering false breakouts can be achieved using techniques like requiring confirmation from a subsequent candle or using volume analysis.

if (High[0] > ResistanceLevel && Close[0] > ResistanceLevel) {
   // Breakout confirmed
}

This checks if the current candle’s high exceeds a calculated resistance level, and if the close is also above it, confirming the breakout.

Combining Price Action with Other Indicators in MQL4

Integrating Moving Averages with Price Action Signals

Moving averages (MAs) smooth price data and can help confirm trends identified through price action. For instance, a bullish engulfing pattern occurring above a rising moving average could provide a stronger buy signal.

double MA = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 0);
if(IsBullishEngulfing() && Close[0] > MA)
{
   // Bullish Engulfing confirmed by moving average.
}

Using RSI and Stochastic Oscillator to Confirm Price Action

RSI and Stochastic oscillators measure momentum and overbought/oversold conditions. These can be used to filter price action signals. For example, a bullish engulfing pattern in an oversold RSI condition may increase the probability of a successful trade.

double RSI = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
if(IsBullishEngulfing() && RSI < 30)
{
   // Bullish Engulfing confirmed by oversold RSI.
}

Coding a Complete Price Action Trading System

A complete price action trading system would involve:

  1. Identifying key levels: Support, resistance, trendlines.
  2. Detecting patterns: Candlestick patterns.
  3. Filtering signals: Using indicators like moving averages or RSI.
  4. Defining entry/exit rules: Based on pattern confirmation and risk management.
  5. Implementing position sizing: To control risk exposure.

This system would be structured as an Expert Advisor (EA) in MQL4, with functions for each of these steps. The EA would continuously monitor price action, identify potential trading opportunities, and execute trades automatically according to the defined rules.

Testing and Optimizing Your Price Action Code

Backtesting Price Action Strategies in MQL4

Backtesting is critical to evaluate the historical performance of your MQL4 code. Use the Strategy Tester in MetaTrader 4. Define the period you want to test, the trading instrument, and the EA. Analyze the reports generated to assess profitability, drawdown, and other key metrics.

Optimizing Parameters for Different Market Conditions

Price action strategies may perform differently under different market conditions (trending vs. ranging). Optimize parameters like moving average periods, RSI levels, or pattern sensitivity to improve performance. Use the Strategy Tester’s optimization feature to systematically test different parameter combinations.

Debugging and Troubleshooting Common MQL4 Errors

Debugging is an essential skill. Use Print() statements to output variable values and track the flow of your code. The MetaEditor’s debugger allows you to step through your code line by line and inspect variable values. Common errors include array out-of-bounds, incorrect data types, and logical errors in your trading rules. Review your code carefully, use debugging tools effectively, and consult the MQL4 documentation to resolve errors. Take into consideration that Alert() statements can freeze your EA in some cases. Use Comment() instead, or be very careful with using alerts.


Leave a Reply