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 that implements the Awesome Oscillator (AO) Zero-Line Cross strategy.
//+------------------------------------------------------------------+
//| 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);
}
//+------------------------------------------------------------------+
F4 to open the MetaEditor.Awesome_ZeroCross.F7 to Compile. Ensure there are no errors.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."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.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.