Summary: Professional MT4 EA implementing a coin-flip random entry strategy. Features fixed stop loss, take profit, spread control, risk percentage position sizing, and daily trade limits. Complete compiled source code included.




# Heads or Tails Random Entry EA - Complete MQL4 Source Code

This article provides a fully functional Expert Advisor based on pure random entry logic, commonly known as the "Heads or Tails" strategy . Unlike conventional technical analysis EAs, this system makes trading decisions using pseudo-random number generation. While simple in concept, it includes professional risk management features that make it suitable for strategy testing and educational purposes.

Strategy Logic



The EA monitors for open positions. When no positions exist, it generates a random number. If the number is even, it opens a BUY order; if odd, it opens a SELL order . Each trade includes configurable stop loss, take profit, and optional breakeven management. Despite the random entry mechanism, robust risk controls prevent catastrophic losses.

Complete MQL4 Code



```mql4
//+------------------------------------------------------------------+
//| RandomCoinFlipEA.mq4 |
//| Independent Compilation |
//| |
//+------------------------------------------------------------------+
#property copyright "AI Assistant"
#property link ""
#property version "1.00"
#property strict

//--- Input Parameters
input double FixedLotSize = 0.1; // Fixed lot size (if RiskPercent=0)
input double RiskPercent = 1.0; // Risk % of free margin (0=use fixed lot)
input int StopLoss = 60; // Stop loss in pips
input int TakeProfit = 120; // Take profit in pips
input bool UseBreakeven = true; // Enable breakeven stop
input int BreakevenTrigger = 30; // Pips to trigger breakeven
input int MaxSpread = 35; // Maximum allowed spread in pips
input int DailyTradeLimit = 0; // Maximum trades per day (0=unlimited)
input int Slippage = 10; // Maximum slippage tolerance
input int MagicNumber = 202413; // EA magic number
input bool CloseOpposite = true; // Close opposite positions on new signal

//--- Global variables
int pointMultiplier = 10; // For 5-digit brokers
int tradesToday = 0;
string currentDate = "";

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Detect broker digit format
if(Digits == 3 || Digits == 5)
pointMultiplier = 10;
else if(Digits == 2 || Digits == 4)
pointMultiplier = 1;

// Initialize random seed using server time
MathSrand(TimeCurrent());

Print("Random Coin Flip EA initialized. Magic: ", MagicNumber);
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("Random Coin Flip EA removed. Reason: ", reason);
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check for new trading day to reset counter
ResetDailyCounter();

// Check daily trade limit
if(!CheckDailyLimit())
return;

// Check spread condition
if(!IsSpreadOK())
return;

// Manage existing positions (breakeven)
if(UseBreakeven)
ManageBreakeven();

// Count current positions
int totalPositions = CountPositions();

// Open new trade only when no positions exist
if(totalPositions == 0)
{
OpenRandomTrade();
}
}

//+------------------------------------------------------------------+
//| Open random direction trade |
//+------------------------------------------------------------------+
void OpenRandomTrade()
{
// Generate random number (0 to 32767)
int randomValue = MathRand();

// Determine direction: even = BUY, odd = SELL
int direction = (randomValue % 2 == 0) ? OP_BUY : OP_SELL;

// Calculate lot size based on risk management
double lotSize = CalculateLotSize();
if(lotSize <= 0)
{
Print("Invalid lot size calculated");
return;
}

// Calculate order price
double price = (direction == OP_BUY) ? Ask : Bid;

// Calculate stop loss and take profit
double sl = 0, tp = 0;

if(StopLoss > 0)
{
if(direction == OP_BUY)
sl = price - StopLoss * Point * pointMultiplier;
else
sl = price + StopLoss * Point * pointMultiplier;
}

if(TakeProfit > 0)
{
if(direction == OP_BUY)
tp = price + TakeProfit * Point * pointMultiplier;
else
tp = price - TakeProfit * Point * pointMultiplier;
}

// Send order
string comment = (direction == OP_BUY) ? "Heads" : "Tails";
int ticket = OrderSend(Symbol(), direction, lotSize, price, Slippage, sl, tp,
comment, MagicNumber, 0, (direction == OP_BUY) ? clrBlue : clrRed);

if(ticket < 0)
{
Print("OrderSend failed. Error: ", GetLastError());
}
else
{
tradesToday++;
Print("Order opened. Ticket: ", ticket, " Direction: ", comment, " Lot: ", lotSize);
}
}

//+------------------------------------------------------------------+
//| Calculate lot size based on risk percentage |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
if(RiskPercent <= 0)
{
// Use fixed lot size
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);

double lot = FixedLotSize;
if(lot < minLot) lot = minLot;
if(lot > maxLot) lot = maxLot;
lot = MathFloor(lot / lotStep) * lotStep;

return NormalizeDouble(lot, 2);
}

// Dynamic lot sizing based on risk percentage
double stopLossPoints = StopLoss * pointMultiplier;
if(stopLossPoints <= 0) return FixedLotSize;

double riskAmount = AccountFreeMargin() * RiskPercent / 100.0;
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);

if(tickValue == 0 || lotStep == 0) return FixedLotSize;

double calculatedLot = riskAmount / (stopLossPoints * tickValue);

// Round to allowed lot step
calculatedLot = MathFloor(calculatedLot / lotStep) * lotStep;

// Min/max checks
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);

if(calculatedLot < minLot) calculatedLot = minLot;
if(calculatedLot > maxLot) calculatedLot = maxLot;

return NormalizeDouble(calculatedLot, 2);
}

//+------------------------------------------------------------------+
//| Manage breakeven stop loss for existing positions |
//+------------------------------------------------------------------+
void ManageBreakeven()
{
if(BreakevenTrigger <= 0) return;

for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double breakevenPoints = BreakevenTrigger * Point * pointMultiplier;

if(OrderType() == OP_BUY)
{
double profitPips = (Bid - OrderOpenPrice()) / Point / pointMultiplier;
if(profitPips >= BreakevenTrigger && OrderStopLoss() < OrderOpenPrice())
{
bool modified = OrderModify(OrderTicket(), OrderOpenPrice(),
OrderOpenPrice(), OrderTakeProfit(), 0, clrNONE);
if(modified)
Print("Breakeven triggered for BUY #", OrderTicket());
}
}
else if(OrderType() == OP_SELL)
{
double profitPips = (OrderOpenPrice() - Ask) / Point / pointMultiplier;
if(profitPips >= BreakevenTrigger && (OrderStopLoss() > OrderOpenPrice() || OrderStopLoss() == 0))
{
bool modified = OrderModify(OrderTicket(), OrderOpenPrice(),
OrderOpenPrice(), OrderTakeProfit(), 0, clrNONE);
if(modified)
Print("Breakeven triggered for SELL #", OrderTicket());
}
}
}
}
}
}

//+------------------------------------------------------------------+
//| Check if spread is within limit |
//+------------------------------------------------------------------+
bool IsSpreadOK()
{
if(MaxSpread <= 0) return true;

int currentSpread = (int)((Ask - Bid) / Point / pointMultiplier);
bool spreadOK = (currentSpread <= MaxSpread);

if(!spreadOK)
Comment("Spread too high: ", currentSpread, "/", MaxSpread);

return spreadOK;
}

//+------------------------------------------------------------------+
//| Count positions for this EA |
//+------------------------------------------------------------------+
int CountPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| Check daily trade limit |
//+------------------------------------------------------------------+
bool CheckDailyLimit()
{
if(DailyTradeLimit <= 0) return true;
return (tradesToday < DailyTradeLimit);
}

//+------------------------------------------------------------------+
//| Reset daily trade counter on new day |
//+------------------------------------------------------------------+
void ResetDailyCounter()
{
string today = TimeToString(TimeCurrent(), TIME_DATE);
if(currentDate != today)
{
currentDate = today;
tradesToday = 0;
Print("New trading day. Trade counter reset.");
}
}

//+------------------------------------------------------------------+
//| Close all positions (utility function) |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
bool closed = false;
if(OrderType() == OP_BUY)
closed = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL)
closed = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);

if(!closed)
Print("Close failed for #", OrderTicket(), " Error: ", GetLastError());
}
}
}
}

//+------------------------------------------------------------------+
//| Manual order closure (can be called via external input) |
//+------------------------------------------------------------------+
void CloseAll()
{
CloseAllPositions();
Print("All positions closed manually.");
}
//+------------------------------------------------------------------+
```

Parameter Explanation



| Parameter | Description | Recommended |
|-----------|-------------|-------------|
| FixedLotSize | Fixed trading volume (when RiskPercent=0) | 0.01-0.1 |
| RiskPercent | Risk per trade as % of free margin (0=use fixed lot) | 1.0-2.0 |
| StopLoss | Stop loss distance in pips | 40-80 |
| TakeProfit | Take profit distance in pips | 80-160 |
| UseBreakeven | Enable automatic breakeven stop | true |
| BreakevenTrigger | Pips needed to move stop to breakeven | 25-40 |
| MaxSpread | Maximum allowed spread in pips | 20-40 |
| DailyTradeLimit | Maximum trades per day (0=unlimited) | 3-10 |
| Slippage | Maximum slippage tolerance | 10 |
| MagicNumber | Unique EA identifier | any unique number |
| CloseOpposite | Close opposite positions on new signal | true |

Installation Instructions



1. Copy the code into MetaEditor (press F4 in MT4)
2. Create a new Expert Advisor (File > New > Expert Advisor)
3. Replace all default code with the code above
4. Press Compile (F7) - verify zero errors
5. Drag the EA from Navigator onto a chart
6. Adjust parameters in the Inputs tab
7. Enable AutoTrading (Alt+T)

Compilation & Modification Tips



Important notes about random entry EA:
  • The random number seed is initialized using server time for true randomness

  • This strategy serves educational purposes and strategy testing, not consistent profitability

  • Always test on demo accounts before considering live deployment


  • How to modify for different behaviors:
  • Change `randomValue % 2 == 0` to `randomValue % 3 == 0` for 33/67 distribution

  • Add time filters by checking `Hour()` before opening trades

  • Implement maximum daily loss by tracking cumulative P&L


  • Warning:
    Pure random entry strategies have negative mathematical expectancy after accounting for spreads and commissions. This EA is designed for educational purposes and Monte Carlo simulation testing .

    Reference



    This EA source code is independently compiled based on the "Heads or Tails" random entry principle documented on the MQL5 community . The risk management modules follow standard MQL4 practices for production EAs.

    *For professionally optimized EAs with advanced technical analysis filters, multi-timeframe confirmation, and complete backtest reports, check our premium EA collection. Subscribe for weekly updates and exclusive trading tools.*