Generate code in 3 minutes
Enter your idea and AI generates runnable code.
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.
//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+
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).CountOpenPositions function ensures the EA only opens one trade at a time per symbol to prevent over-trading.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:
if(cci_prev < InpLevelLow && cci_curr >= InpLevelLow) for Buy.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.