🚀 AI One-Click Generation of mql4 Strategy Code

Automating the Commodity Channel Index (CCI) Strategy in Mql4

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

Problem Description

Please help me code a trading strategy that buys when an oscillator crosses below -100 and sells when it crosses above +100.

Solution

Here is a complete, fully functional Expert Advisor (EA) for MetaTrader 4 written in MQL4.

I have selected the Commodity Channel Index (CCI) for this strategy, as it is the standard oscillator that utilizes the +100 and -100 levels specifically.

Strategy Logic

  1. Buy Signal: The CCI line crosses below the -100 level (Momentum/Breakout entry).
  2. Sell Signal: The CCI line crosses above the +100 level.
  3. Execution: The strategy checks for crosses on closed bars (Bar 1 and Bar 2) to prevent "repainting" signals where the indicator changes while the candle is still forming.

MQL4 Code

//+------------------------------------------------------------------+
//|                                              CCI_Breakout_EA.mq4 |
//|                        Copyright 2023, Quantitative Trading AI   |
//|                                             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 points (0 = no SL)
input int    InpTakeProfit    = 100;      // Take Profit in points (0 = no TP)
input int    InpMagicNumber   = 12345;    // Magic Number to identify orders
input int    InpSlippage      = 3;        // Maximum slippage in points

//--- Oscillator Settings (CCI)
input int    InpCCIPeriod     = 14;       // CCI Period
input int    InpCCIPrice      = PRICE_TYPICAL; // CCI Applied Price
input double InpLevelHigh     = 100.0;    // Upper Trigger Level
input double InpLevelLow      = -100.0;   // Lower Trigger Level

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Basic validation
   if(InpCCIPeriod <= 0)
   {
      Print("Error: CCI Period must be greater than 0");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 1. Check if we are allowed to trade
   if(!IsTradeAllowed() || IsStopped()) return;

   // 2. Check if we already have an open position for this symbol and magic number
   if(CountOpenPositions() > 0) return; // Simple logic: only one trade at a time

   // 3. Calculate Indicator Values
   // We look at Bar 1 (just closed) and Bar 2 (previous) to detect a confirmed cross
   double cci_curr = iCCI(_Symbol, _Period, InpCCIPeriod, InpCCIPrice, 1);
   double cci_prev = iCCI(_Symbol, _Period, InpCCIPeriod, InpCCIPrice, 2);

   // 4. Check for Buy Signal (Cross Below -100)
   // Logic: Previous value was ABOVE or EQUAL to -100, Current value is BELOW -100
   if(cci_prev >= InpLevelLow && cci_curr < InpLevelLow)
   {
      OpenTrade(OP_BUY);
   }

   // 5. Check for Sell Signal (Cross Above +100)
   // Logic: Previous value was BELOW or EQUAL to 100, Current value is ABOVE 100
   if(cci_prev <= InpLevelHigh && cci_curr > InpLevelHigh)
   {
      OpenTrade(OP_SELL);
   }
}

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

   if(type == OP_BUY)
   {
      price = Ask;
      clr = clrBlue;
      
      // Calculate SL/TP for Buy
      double point = Point;
      if(Digits == 3 || Digits == 5) point *= 10; // Adjust for 5-digit brokers
      
      sl = (InpStopLoss > 0) ? price - InpStopLoss * point : 0;
      tp = (InpTakeProfit > 0) ? price + InpTakeProfit * point : 0;
   }
   else // OP_SELL
   {
      price = Bid;
      clr = clrRed;
      
      // Calculate SL/TP for Sell
      double point = Point;
      if(Digits == 3 || Digits == 5) point *= 10; // Adjust for 5-digit brokers
      
      sl = (InpStopLoss > 0) ? price + InpStopLoss * point : 0;
      tp = (InpTakeProfit > 0) ? price - InpTakeProfit * point : 0;
   }

   // Normalize prices to prevent Error 130 (Invalid Stops)
   price = NormalizeDouble(price, Digits);
   sl    = NormalizeDouble(sl, Digits);
   tp    = NormalizeDouble(tp, Digits);

   // Send Order
   int ticket = OrderSend(_Symbol, type, InpLots, price, InpSlippage, sl, tp, "CCI Cross Strategy", InpMagicNumber, 0, clr);

   if(ticket < 0)
   {
      Print("OrderSend failed with error #", GetLastError());
   }
   else
   {
      Print("Order opened successfully. Ticket: ", ticket);
   }
}

//+------------------------------------------------------------------+
//| Helper: Count Open Positions for this EA                         |
//+------------------------------------------------------------------+
int CountOpenPositions()
{
   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() == OP_BUY || OrderType() == OP_SELL)
            {
               count++;
            }
         }
      }
   }
   return count;
}
//+------------------------------------------------------------------+

How to Install and Use

  1. Open MetaTrader 4.
  2. Press F4 to open the MetaEditor.
  3. Click New -> Expert Advisor (template) -> Name it "CCI_Breakout".
  4. Delete everything in the new file and paste the code above.
  5. Press F7 or click Compile. Ensure there are no errors in the "Errors" tab at the bottom.
  6. Go back to the main MT4 window.
  7. Find "CCI_Breakout" in the Navigator panel under Expert Advisors.
  8. Drag it onto a chart.

Key Features of This Code

  • Cross Detection: It uses cci_prev (Bar 2) and cci_curr (Bar 1) to detect the exact moment the line crosses the level. This ensures the signal is confirmed (the candle is closed).
  • Risk Management: Includes inputs for Stop Loss and Take Profit.
  • 5-Digit Broker Support: Automatically adjusts points calculation for brokers using 5 decimal places (e.g., EURUSD at 1.12345).
  • Order Management: The CountOpenPositions function ensures the EA only opens one trade at a time per symbol to prevent over-trading.

Q&A: Strategy Details

Q: Why did you choose CCI?
A: The prompt specified levels of +100 and -100. The Commodity Channel Index (CCI) is the standard technical indicator designed specifically around these levels. RSI usually uses 30/70, and Stochastic uses 20/80.

Q: Can I use this for Mean Reversion (Buying when it crosses back UP above -100)?
A: The current code is a Momentum/Breakout logic (Buying as it plunges below -100). If you want a Mean Reversion strategy (Buying when it recovers from oversold), you simply need to swap the logic in the OnTick function:

  • Change: if(cci_prev < InpLevelLow && cci_curr >= InpLevelLow) for Buy.
  • Change: if(cci_prev > InpLevelHigh && cci_curr <= InpLevelHigh) for Sell.

Q: Why does the EA not trade immediately?
A: The EA waits for a specific "Cross" event. If the CCI is already below -100 when you attach the EA, it will wait until it goes back above -100 and crosses down again before trading. This prevents entering stale signals.