🚀 AI One-Click Generation of mql4 Strategy Code

How to Build an Expert Advisor for the Awesome Oscillator in Mql4

mql4 | Published on: 2025/12/5
The following content is generated by EasyQuant .

Problem Description

Can you show me how to code an automated trading strategy using the Awesome Oscillator signals, like the zero-line cross?

Solution

Here is a complete, fully functional Expert Advisor (EA) for MetaTrader 4 that implements the Awesome Oscillator (AO) Zero-Line Cross strategy.

Strategy Logic

  1. Indicator: Awesome Oscillator (Standard Bill Williams settings: 34 SMA - 5 SMA).
  2. Buy Signal: The AO histogram crosses from below the zero line to above the zero line.
  3. Sell Signal: The AO histogram crosses from above the zero line to below the zero line.
  4. Execution: The strategy checks values on closed bars (Bar 1 and Bar 2) to ensure the signal is confirmed and does not "repaint" during the current candle.

MQL4 Code

//+------------------------------------------------------------------+
//|                                       Awesome_ZeroCross_EA.mq4   |
//|                                     Copyright 2023, MetaQuotes   |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Trading AI"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- Input Parameters
input double InpLots          = 0.1;      // Lot Size
input int    InpStopLoss      = 50;       // Stop Loss in pips (0 = none)
input int    InpTakeProfit    = 100;      // Take Profit in pips (0 = none)
input int    InpMagicNumber   = 889977;   // Magic Number to identify orders
input int    InpSlippage      = 3;        // Maximum Slippage in pips

//--- Global Variables
double m_adjusted_point;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Adjust points for 3/5 digit brokers
   if(Digits == 3 || Digits == 5)
      m_adjusted_point = Point * 10;
   else
      m_adjusted_point = Point;

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Clean up if necessary
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // We only trade on a new bar open to ensure the signal is confirmed
   static datetime last_bar_time = 0;
   if(Time[0] == last_bar_time) return; // Same bar, exit
   last_bar_time = Time[0];

   //--- 1. Get Awesome Oscillator Data
   // We check Bar 1 (previous closed candle) and Bar 2 (candle before that)
   double ao_curr = iAO(NULL, 0, 1); // Value of closed bar
   double ao_prev = iAO(NULL, 0, 2); // Value of bar before closed bar

   //--- 2. Check for Buy Signal (Cross from Negative to Positive)
   if(ao_prev < 0 && ao_curr > 0)
   {
      // Close existing Sell positions first (Reversal logic)
      ClosePositions(OP_SELL);
      
      // Check if we already have a Buy open
      if(CountOrders(OP_BUY) == 0)
      {
         OpenTrade(OP_BUY);
      }
   }

   //--- 3. Check for Sell Signal (Cross from Positive to Negative)
   if(ao_prev > 0 && ao_curr < 0)
   {
      // Close existing Buy positions first (Reversal logic)
      ClosePositions(OP_BUY);
      
      // Check if we already have a Sell open
      if(CountOrders(OP_SELL) == 0)
      {
         OpenTrade(OP_SELL);
      }
   }
}

//+------------------------------------------------------------------+
//| Helper: Open a Trade                                             |
//+------------------------------------------------------------------+
void OpenTrade(int type)
{
   double price, sl, tp;
   color cmd_color;

   if(type == OP_BUY)
   {
      price = Ask;
      sl = (InpStopLoss > 0) ? price - InpStopLoss * m_adjusted_point : 0;
      tp = (InpTakeProfit > 0) ? price + InpTakeProfit * m_adjusted_point : 0;
      cmd_color = clrBlue;
   }
   else // OP_SELL
   {
      price = Bid;
      sl = (InpStopLoss > 0) ? price + InpStopLoss * m_adjusted_point : 0;
      tp = (InpTakeProfit > 0) ? price - InpTakeProfit * m_adjusted_point : 0;
      cmd_color = clrRed;
   }

   // Normalize prices
   price = NormalizeDouble(price, Digits);
   sl    = NormalizeDouble(sl, Digits);
   tp    = NormalizeDouble(tp, Digits);

   int ticket = OrderSend(Symbol(), type, InpLots, price, InpSlippage, sl, tp, "AO Zero Cross", InpMagicNumber, 0, cmd_color);

   if(ticket < 0)
   {
      Print("OrderSend failed with error #", GetLastError());
   }
}

//+------------------------------------------------------------------+
//| Helper: Close positions of specific type                         |
//+------------------------------------------------------------------+
void ClosePositions(int type)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
         {
            if(OrderType() == type)
            {
               bool result = false;
               if(type == OP_BUY)
                  result = OrderClose(OrderTicket(), OrderLots(), Bid, InpSlippage, clrRed);
               else if(type == OP_SELL)
                  result = OrderClose(OrderTicket(), OrderLots(), Ask, InpSlippage, clrBlue);
               
               if(!result) Print("OrderClose failed: ", GetLastError());
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Helper: Count open orders of specific type                       |
//+------------------------------------------------------------------+
int CountOrders(int type)
{
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
         {
            if(OrderType() == type) count++;
         }
      }
   }
   return(count);
}
//+------------------------------------------------------------------+

How to Install and Run

  1. Open MetaTrader 4.
  2. Press F4 to open the MetaEditor.
  3. Click New -> Expert Advisor (template) -> Name it Awesome_ZeroCross.
  4. Delete everything in the new file and paste the code above.
  5. Press F7 to Compile. Ensure there are no errors.
  6. Go back to the MT4 Terminal, find the EA in the Navigator window, and drag it onto a chart.

Key Features of This Code

  • New Bar Logic: The code uses static datetime last_bar_time to ensure it only calculates and trades once per candle. This prevents the EA from opening multiple trades on the same signal tick and ensures the AO signal is "locked in."
  • 5-Digit Broker Support: The m_adjusted_point logic automatically detects if your broker uses 5 decimal places (points) or 4 (pips) and adjusts the Stop Loss and Take Profit calculations accordingly.
  • Reversal Logic: If a Buy signal appears while a Sell trade is open, the EA will close the Sell trade immediately before opening the Buy trade. This keeps you in sync with the market momentum.
  • Risk Management: Inputs for Stop Loss and Take Profit allow you to define your risk per trade.

Q&A: Awesome Oscillator Strategy

Q: Why do we use iAO(NULL, 0, 1) and iAO(NULL, 0, 2)?
A: In MQL4, index 0 is the current forming candle. Index 1 is the last completed candle. To confirm a "cross," we need to see that the bar before the last one (index 2) was on one side of the zero line, and the last completed bar (index 1) is on the other side.

Q: Can I use this on any timeframe?
A: Yes. The iAO function uses 0 as the timeframe parameter, which means "Current Timeframe." If you attach this EA to an H1 chart, it calculates based on H1 data. If you attach it to M15, it uses M15 data.

Q: What happens if I set StopLoss to 0?
A: The code checks if(InpStopLoss > 0). If you set it to 0, the order will be sent without a hard Stop Loss attached to the broker order. The trade will only close when a reversal signal occurs (the opposite cross).

Q: Does this strategy work in ranging markets?
A: The AO Zero-Line cross is a momentum strategy. Like most trend-following indicators, it performs well in trending markets but may generate false signals (whipsaws) in sideways/ranging markets. You might consider adding a filter (like a Moving Average) to only take Buy crosses when price is above the MA.