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.
This EA implements a Stochastic Crossover Strategy. It enters a Buy trade when the Main line crosses above the Signal line, and a Sell trade when the Main line crosses below the Signal line.
//+------------------------------------------------------------------+
//| Stochastic_Crossover_EA.mq4 |
//| Copyright 2023, Quantitative Trading Assistant |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Trading Assistant"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input double Lots = 0.1; // Fixed Lot Size
input int StopLoss = 50; // Stop Loss in pips (0 = no SL)
input int TakeProfit = 100; // Take Profit in pips (0 = no TP)
input int MagicNumber = 12345; // Unique Identifier for this EA
input int Slippage = 3; // Max slippage in pips
//--- Stochastic Settings
input int K_Period = 5; // %K Period
input int D_Period = 3; // %D Period
input int Slowing = 3; // Slowing
input ENUM_MA_METHOD MA_Method = MODE_SMA; // MA Method
input ENUM_STO_PRICE Price_Field = 0; // Price Field (0=Low/High, 1=Close/Close)
//--- Global Variables
double pips;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust pips for 4 or 5 digit brokers
if(Digits == 3 || Digits == 5) pips = Point * 10;
else pips = Point;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if we have enough bars to calculate
if(Bars < 100) return;
// 1. Get Stochastic Values for the last closed bar (Shift 1) and the one before (Shift 2)
// We use closed bars to ensure the crossover is confirmed and won't repaint.
// Main Line
double main_1 = iStochastic(NULL, 0, K_Period, D_Period, Slowing, MA_Method, Price_Field, MODE_MAIN, 1);
double main_2 = iStochastic(NULL, 0, K_Period, D_Period, Slowing, MA_Method, Price_Field, MODE_MAIN, 2);
// Signal Line
double sig_1 = iStochastic(NULL, 0, K_Period, D_Period, Slowing, MA_Method, Price_Field, MODE_SIGNAL, 1);
double sig_2 = iStochastic(NULL, 0, K_Period, D_Period, Slowing, MA_Method, Price_Field, MODE_SIGNAL, 2);
// 2. Check for Crossover Signals
bool buySignal = (main_2 < sig_2) && (main_1 > sig_1); // Crossed Up
bool sellSignal = (main_2 > sig_2) && (main_1 < sig_1); // Crossed Down
// 3. Manage Trades
// Check if we already have an open position for this symbol and magic number
if(CountOpenTrades() == 0)
{
if(buySignal)
{
OpenBuy();
}
else if(sellSignal)
{
OpenSell();
}
}
}
//+------------------------------------------------------------------+
//| Helper: Count Open Trades for this EA |
//+------------------------------------------------------------------+
int CountOpenTrades()
{
int count = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| Helper: Open Buy Order |
//+------------------------------------------------------------------+
void OpenBuy()
{
double sl = (StopLoss > 0) ? Ask - StopLoss * pips : 0;
double tp = (TakeProfit > 0) ? Ask + TakeProfit * pips : 0;
// Normalize prices to prevent errors
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, sl, tp, "Stoch Buy", MagicNumber, 0, clrBlue);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Helper: Open Sell Order |
//+------------------------------------------------------------------+
void OpenSell()
{
double sl = (StopLoss > 0) ? Bid + StopLoss * pips : 0;
double tp = (TakeProfit > 0) ? Bid - TakeProfit * pips : 0;
// Normalize prices to prevent errors
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
int ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, sl, tp, "Stoch Sell", MagicNumber, 0, clrRed);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+
F4 to open the MetaEditor.F7 or click Compile. Ensure there are no errors.Shift 1 (the last closed candle) and Shift 2 (the candle before that) to detect the crossover. This ensures the signal is permanent and won't vanish if the price moves before the current candle closes.CountOpenTrades() function ensures the EA only opens one trade at a time per currency pair. It will not open a new trade until the previous one hits SL/TP or is manually closed.Q: Why do we use Shift 1 and Shift 2 instead of Shift 0?
A: Shift 0 represents the currently forming candle. The Stochastic values on Shift 0 fluctuate with every tick. A crossover might happen halfway through the candle duration but disappear by the time the candle closes. Using Shift 1 (the most recently closed candle) ensures the crossover is confirmed and final.
Q: How can I filter this strategy to only trade in the direction of the trend?
A: You can add a Moving Average filter. For example, add a condition in the OnTick function: double ma = iMA(NULL, 0, 200, ...);. Then, only execute a Buy signal if Close[1] > ma and only execute a Sell signal if Close[1] < ma.
Q: What is the Magic Number used for?
A: The Magic Number is a unique identifier assigned to orders opened by this specific EA. It allows the EA to distinguish its own trades from trades opened by you manually or by other EAs running on the same account.
Q: Can this EA handle ECN brokers?
A: The provided code uses standard OrderSend with SL and TP. Most modern MT4 bridges handle this fine. However, on some strict ECN brokers, you must send the order with 0 SL/TP first, get the ticket number, and then use OrderModify to add the SL/TP. The code provided works for 95% of standard retail brokers.