Generate code in 3 minutes
Enter your idea and AI generates runnable code.
Here is a complete, fully functional MQL4 code for a Simple Hedging Expert Advisor (EA).
This is one of the most common and effective simple hedging strategies.
//+------------------------------------------------------------------+
//| SimpleHedgeEA.mq4 |
//| Copyright 2023, Quantitative Assistant |
//| https://mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Assistant"
#property link "https://mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input double LotSize = 0.1; // Fixed Lot Size
input int DistancePips = 20; // Distance from price to place pending orders
input int TakeProfitPips = 40; // Take Profit in Pips (0 = No TP)
input int StopLossPips = 0; // Stop Loss in Pips (0 = No SL, recommended for hedging)
input double ProfitTarget = 10.0; // Global Profit Target in Currency (USD/EUR) to close all
input int MagicNumber = 123456; // Unique Identifier for this EA
input int Slippage = 3; // Max Slippage allowed
//--- Global Variables
double pipMultiplier;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust pips for 3 or 5 digit brokers (Jpy pairs vs others)
if(Digits == 3 || Digits == 5) pipMultiplier = 10;
else pipMultiplier = 1;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Optional: Clean up comments or objects
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Check Global Profit
// If the total profit of our hedge basket exceeds the target, close everything.
if(GetTotalProfit() >= ProfitTarget)
{
CloseAllOrders();
DeleteAllPending();
return; // Wait for next tick
}
// 2. Count current orders
int totalOrders = 0;
int buyStops = 0;
int sellStops = 0;
int activeTrades = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
totalOrders++;
if(OrderType() == OP_BUYSTOP) buyStops++;
if(OrderType() == OP_SELLSTOP) sellStops++;
if(OrderType() == OP_BUY || OrderType() == OP_SELL) activeTrades++;
}
}
}
// 3. Logic: If no orders exist, place the Straddle (Hedge Trap)
if(totalOrders == 0)
{
double buyPrice = Ask + (DistancePips * Point * pipMultiplier);
double sellPrice = Bid - (DistancePips * Point * pipMultiplier);
// Calculate TP/SL prices
double buyTP = (TakeProfitPips > 0) ? buyPrice + (TakeProfitPips * Point * pipMultiplier) : 0;
double buySL = (StopLossPips > 0) ? buyPrice - (StopLossPips * Point * pipMultiplier) : 0;
double sellTP = (TakeProfitPips > 0) ? sellPrice - (TakeProfitPips * Point * pipMultiplier) : 0;
double sellSL = (StopLossPips > 0) ? sellPrice + (StopLossPips * Point * pipMultiplier) : 0;
// Send Orders
int ticket1 = OrderSend(Symbol(), OP_BUYSTOP, LotSize, buyPrice, Slippage, buySL, buyTP, "Hedge Buy", MagicNumber, 0, clrBlue);
int ticket2 = OrderSend(Symbol(), OP_SELLSTOP, LotSize, sellPrice, Slippage, sellSL, sellTP, "Hedge Sell", MagicNumber, 0, clrRed);
if(ticket1 < 0 || ticket2 < 0) Print("Error placing orders: ", GetLastError());
}
// 4. Maintenance: If one side hit TP and closed, but the other pending order is still there,
// we usually want to delete the pending order to restart the cycle.
if(activeTrades == 0 && totalOrders > 0)
{
// If we have pending orders but no active trades, it usually means one trade hit TP
// and the other pending order is left over. Let's clean up to restart.
// Note: This logic assumes we want a fresh start after a win.
DeleteAllPending();
}
// Display Info
Comment("Simple Hedge EA Running\n",
"Total Profit: ", DoubleToString(GetTotalProfit(), 2), "\n",
"Target: ", DoubleToString(ProfitTarget, 2));
}
//+------------------------------------------------------------------+
//| Helper: Calculate Total Profit for this Magic Number |
//+------------------------------------------------------------------+
double GetTotalProfit()
{
double profit = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
// Add Profit + Swap + Commission
profit += OrderProfit() + OrderSwap() + OrderCommission();
}
}
}
return profit;
}
//+------------------------------------------------------------------+
//| Helper: Close all Active Market Orders |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
bool res = false;
if(OrderType() == OP_BUY)
res = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL)
res = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
if(!res) Print("Failed to close order: ", OrderTicket(), " Error: ", GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
//| Helper: Delete all Pending Orders |
//+------------------------------------------------------------------+
void DeleteAllPending()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() > OP_SELL) // OP_BUYLIMIT, OP_BUYSTOP, etc. are > 1
{
bool res = OrderDelete(OrderTicket(), clrNONE);
if(!res) Print("Failed to delete order: ", OrderTicket(), " Error: ", GetLastError());
}
}
}
}
}
Pip Adjustment (pipMultiplier):
The code automatically detects if your broker uses 5-digit pricing (e.g., EURUSD 1.09123) or 3-digit JPY pricing and adjusts the DistancePips accordingly.
Global Profit Target (ProfitTarget):
This is crucial for hedging. Often, one trade will be positive and the hedge trade will be negative. The goal is for the volatility to push the winner far enough to cover the loser's drawdown plus a small profit. When GetTotalProfit() hits your target (e.g., $10), everything closes.
The "Straddle" Logic:
DistancePips above and a Sell Stop DistancePips below.Maintenance Logic:
DistancePips is too small (e.g., 5 pips) and the spread is high, both orders might trigger instantly, locking you in a loss immediately. Keep DistancePips at least 2x or 3x the spread.Q: How can I modify this to increase the lot size if the first trade fails (Martingale)?
A: You would need to modify the OnTick logic. Instead of placing both orders at the start, you would place one. If that trade goes into negative pips, you would open an opposite trade with LotSize * Multiplier. However, Martingale significantly increases the risk of blowing the account.
Q: Why do we use OrderSelect loop backwards when closing orders?
A: When you close or delete an order, the index of the remaining orders in the pool changes. If you loop forward (i++), you will skip orders. Looping backward (i--) ensures every order is checked and processed correctly.
Q: Can this EA work on Renko charts?
A: Yes, technically. However, Renko charts on MT4 are usually offline charts. You would need to enable "Allow DLL imports" and ensure the EA is attached to the offline chart generated by your Renko indicator. The logic remains the same.