🚀 AI One-Click Generation of mql4 Strategy Code

Building a Trading Robot with the Accelerator Oscillator (AC) in Mql4

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

Problem Description

Write me a trading robot that uses the Accelerator/Decelerator Oscillator.

Solution

Here is a complete, fully functional Expert Advisor (trading robot) for MetaTrader 4 based on the Bill Williams Accelerator/Decelerator Oscillator (AC).

Strategy Logic

This robot implements a momentum-based strategy using the AC indicator:

  1. Buy Signal: The AC indicator rises for two consecutive closed bars (showing increasing upward momentum).
  2. Sell Signal: The AC indicator falls for two consecutive closed bars (showing increasing downward momentum).
  3. Risk Management: It uses fixed Stop Loss and Take Profit levels, plus a Trailing Stop to lock in profits as the price moves in your favor.

MQL4 Code

//+------------------------------------------------------------------+
//|                                            AC_Trader_Bot.mq4     |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative AI Assistant"
#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 = no SL)
input int    InpTakeProfit    = 100;   // Take Profit in pips (0 = no TP)
input int    InpTrailingStop  = 30;    // Trailing Stop in pips (0 = disabled)
input int    InpMagicNumber   = 12345; // Magic Number to identify orders
input int    InpSlippage      = 3;     // Maximum slippage in pips

//--- Global Variables
double m_pips;

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

   return(INIT_SUCCEEDED);
}

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   //--- 1. Check if we have enough bars to calculate
   if(Bars < 100) return;

   //--- 2. Define AC values (Shift 1 is the last closed bar, Shift 2 is the one before)
   // We use closed bars to avoid "repainting" signals during the current candle
   double ac1 = iAC(NULL, 0, 1); // AC of previous bar
   double ac2 = iAC(NULL, 0, 2); // AC of 2 bars ago
   double ac3 = iAC(NULL, 0, 3); // AC of 3 bars ago

   //--- 3. Check for Open Positions
   int openBuy = 0;
   int openSell = 0;
   
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
         {
            if(OrderType() == OP_BUY) openBuy++;
            if(OrderType() == OP_SELL) openSell++;
            
            // Manage Trailing Stop while looping through orders
            ManageTrailingStop(); 
         }
      }
   }

   //--- 4. Signal Logic
   // Buy: AC is rising for 2 consecutive bars (Green bars)
   bool buySignal = (ac1 > ac2) && (ac2 > ac3);
   
   // Sell: AC is falling for 2 consecutive bars (Red bars)
   bool sellSignal = (ac1 < ac2) && (ac2 < ac3);

   //--- 5. Execution Logic
   // Only open a trade if no trade is currently open in that direction
   // (Simple one-trade-at-a-time logic per direction)
   
   if(buySignal && openBuy == 0)
   {
      // Close opposite Sell positions if you want a reversal strategy (Optional)
      // CloseAllSell(); 
      
      double sl = (InpStopLoss > 0) ? Ask - InpStopLoss * m_pips : 0;
      double tp = (InpTakeProfit > 0) ? Ask + InpTakeProfit * m_pips : 0;
      
      // Normalize prices
      sl = NormalizeDouble(sl, Digits);
      tp = NormalizeDouble(tp, Digits);

      int ticket = OrderSend(Symbol(), OP_BUY, InpLots, Ask, InpSlippage, sl, tp, "AC Buy", InpMagicNumber, 0, clrGreen);
      if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
   }

   if(sellSignal && openSell == 0)
   {
      // Close opposite Buy positions if you want a reversal strategy (Optional)
      // CloseAllBuy();
      
      double sl = (InpStopLoss > 0) ? Bid + InpStopLoss * m_pips : 0;
      double tp = (InpTakeProfit > 0) ? Bid - InpTakeProfit * m_pips : 0;
      
      // Normalize prices
      sl = NormalizeDouble(sl, Digits);
      tp = NormalizeDouble(tp, Digits);

      int ticket = OrderSend(Symbol(), OP_SELL, InpLots, Bid, InpSlippage, sl, tp, "AC Sell", InpMagicNumber, 0, clrRed);
      if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
   }
}

//+------------------------------------------------------------------+
//| Function to manage Trailing Stop                                 |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
   if(InpTrailingStop == 0) return;

   // Order must be selected before calling this function logic inside the loop
   // However, for safety, we usually pass the ticket or assume OrderSelect is active.
   // Since this is called inside the OnTick loop where OrderSelect is active:
   
   if(OrderType() == OP_BUY)
   {
      if(Bid - OrderOpenPrice() > InpTrailingStop * m_pips)
      {
         if(OrderStopLoss() < Bid - InpTrailingStop * m_pips)
         {
            double newSL = NormalizeDouble(Bid - InpTrailingStop * m_pips, Digits);
            if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
               Print("Error modifying Buy Trailing Stop: ", GetLastError());
         }
      }
   }
   else if(OrderType() == OP_SELL)
   {
      if(OrderOpenPrice() - Ask > InpTrailingStop * m_pips)
      {
         if(OrderStopLoss() == 0 || OrderStopLoss() > Ask + InpTrailingStop * m_pips)
         {
            double newSL = NormalizeDouble(Ask + InpTrailingStop * m_pips, Digits);
            if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
               Print("Error modifying Sell Trailing Stop: ", GetLastError());
         }
      }
   }
}
//+------------------------------------------------------------------+

How to Install and Run

  1. Open MetaEditor: In MT4, press F4 or click the "MetaEditor" button.
  2. Create New File: Click New -> Expert Advisor (template) -> Next.
  3. Name It: Name it AC_Trader and click Next -> Finish.
  4. Paste Code: Delete everything in the new file and paste the code provided above.
  5. Compile: Press F7 or click the "Compile" button. Check the "Errors" tab at the bottom to ensure there are 0 errors.
  6. Run: Go back to the MT4 terminal. Find AC_Trader in the "Navigator" window under "Expert Advisors". Drag it onto a chart.

Key Features Explained

  • iAC Function: The code uses iAC(NULL, 0, shift) to get the Accelerator Oscillator value. NULL means the current symbol, 0 means the current timeframe.
  • Shift 1, 2, 3: We analyze bars 1, 2, and 3 (historical bars). We do not use bar 0 (the current forming candle) to generate signals. This prevents the robot from opening a trade and then having the signal disappear before the candle closes (repainting).
  • 4/5 Digit Broker Support: The OnInit function automatically detects if your broker uses 5 decimal places (e.g., EURUSD 1.12345) and adjusts the pip calculations accordingly so that 50 pips equals 500 points.
  • Trailing Stop: If the price moves in your favor by the amount specified in InpTrailingStop, the Stop Loss will follow the price to lock in profit.

Q&A

Q: Can I use this on any timeframe?
A: Yes, the code uses 0 in the iAC function, which automatically adapts to whatever timeframe (M15, H1, D1) the chart is currently set to.

Q: Why does it check Bars < 100?
A: The AC indicator requires historical data to calculate correctly. This check prevents the EA from crashing or calculating wrong values if you load it on a chart that hasn't downloaded history yet.

Q: How do I optimize the settings?
A: In MT4, go to View -> Strategy Tester. Select AC_Trader, choose a symbol and timeframe, and click "Expert properties". You can then test different values for Stop Loss and Take Profit to see what works best for your specific currency pair.