29 January, 2026 • Updated 24 October, 2026

Heads or Tails Trading Strategy in MQL5 — Full Source Code Breakdown

ForTrader.org
A complete MQL5 EA implementing the random-direction 'Heads or Tails' strategy—with code walkthrough, risks, and improvement ideas.

The ‘Heads or Tails’ trading strategy is a randomness-based methodology popular among traders on the Russian market. As the name suggests, trade direction is chosen entirely at random—like flipping a coin—selecting either Buy (Heads) or Sell (Tails) without analysis.

Contents

How the Strategy Works

The core logic is minimal and rule-driven:

  • Asset Selection: Choose a financial instrument (e.g., US stocks, forex pairs).
  • Coin Flip Decision: Randomly select Buy or Sell—no technical or fundamental input.
  • Position Entry: Open a trade at a fixed lot size once direction is determined.
  • Risk Management: Predefined stop-loss and take-profit levels lock in risk and reward parameters.

This eliminates discretionary decision-making—trading becomes fully mechanical and probabilistic.

Pros and Cons

Advantages:

  1. No need for technical or fundamental market analysis.
  2. Reduces emotional stress and screen time—no constant monitoring required.
  3. Highly suitable for automation via Expert Advisors (EAs) in MetaTrader 5.

Disadvantages:

  1. Win rate is statistically ~50%, far below most professional trading strategies.
  2. Ignores price action, volatility, economic events, and technical signals—increasing drawdown risk.
  3. Requires substantial capital to absorb consecutive losses under pure randomness.

For responsible implementation, follow these guidelines:

  • Limit position size to ≤1% of total account equity per trade.
  • Strictly enforce stop-loss and take-profit levels—no manual overrides.
  • Diversify across instruments to reduce portfolio-level exposure.

Beginners should test this strategy exclusively on a demo account first—to observe behavior, assess expectancy, and refine position management rules before risking real capital.

MQL5 Expert Advisor Code

1. File Structure Overview

The EA file begins with a descriptive header comment specifying:

  • File name (VR Heads or Tails.mq5);
  • Author and release year;
  • Developer website.

Followed by #property directives defining metadata: copyright, version, and external links.

2. Library Imports and Variable Declarations

Standard MQL5 trade libraries are included:

#include <Trade\Trade.mqh>
CTrade trade; // Instance for sending orders

#include <Trade\PositionInfo.mqh>
CPositionInfo posit; // Instance for reading open positions
  • CTrade handles order execution (Buy/Sell);
  • CPositionInfo retrieves data about current positions.

Next, user-configurable input parameters are declared:

input double iStartLots = 0.01; // Initial lot size
input int iTakeProfit = 450; // Take-profit (points)
input int iStopLoss = 390; // Stop-loss (points)
input int iMagicNumber = 227; // Unique trade identifier
input int iSlippage = 30; // Max allowed slippage (points)
  • iStartLots: Base volume for each new trade;
  • iTakeProfit / iStopLoss: Fixed profit and loss targets;
  • iMagicNumber: Ensures robot trades are distinguishable from manual ones;
  • iSlippage: Permitted price deviation during order fill.

3. OnInit() — Robot Initialization

This function runs once at EA startup to configure trading settings:

int OnInit() {
 trade.SetExpertMagicNumber(iMagicNumber);
 trade.SetDeviationInPoints(iSlippage);
 trade.SetTypeFillingBySymbol(_Symbol);
 trade.SetMarginMode();
 MathSrand(GetTickCount());
 return(INIT_SUCCEEDED);
}

Key actions:

  1. SetExpertMagicNumber(): Assigns unique ID to all robot-initiated trades.
  2. SetDeviationInPoints(): Sets maximum slippage tolerance.
  3. SetTypeFillingBySymbol(): Configures order execution type (e.g., ‘Market’).
  4. SetMarginMode(): Enables hedging mode (separate long/short positions per symbol).
  5. MathSrand(): Seeds the random number generator—used later to decide Buy/Sell.

4. OnTick() — Price Tick Handling

This function triggers on every new price tick. Let’s break it down.

4.1. Market and Position Data Retrieval

int total = ::PositionsTotal();
double Bid = ::SymbolInfoDouble(_Symbol, SYMBOL_BID);
double Ask = ::SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  • PositionsTotal(): Returns count of currently open positions;
  • SymbolInfoDouble(): Fetches live Bid (sell) and Ask (buy) prices.

If prices are invalid (≤ 0), the function exits early:

if(Bid <= 0 || Ask <= 0)
 return;

4.2. Open Position Analysis

A loop scans all positions to count active Buy and Sell trades tied to this EA:

for(int i = 0; i < total; i++) {
 if(posit.SelectByIndex(i)) {
 if(posit.Symbol() == _Symbol && posit.Magic() == iMagicNumber) {
 if(posit.PositionType() == POSITION_TYPE_BUY) b++;
 if(posit.PositionType() == POSITION_TYPE_SELL) s++;
 }
 }
}
  • SelectByIndex(): Loads position data by index;
  • Symbol() and Magic(): Verify instrument and EA ownership;
  • PositionType(): Identifies Buy vs. Sell.

4.3. New Trade Execution

If no positions exist (b + s == 0), the EA randomly selects direction:

if((b + s) == 0) {
 if(MathRand() % 2 == 0) { // 0 → Buy, 1 → Sell
 trade.Buy(iStartLots, _Symbol, Ask, Ask - iStopLoss * _Point, Ask + iTakeProfit * _Point, "");
 } else {
 trade.Sell(iStartLots, _Symbol, Bid, Bid + iStopLoss * _Point, Bid - iTakeProfit * _Point, "");
 }
}
  • MathRand() % 2: Generates 0 or 1 for binary choice;
  • trade.Buy(): Opens long position with TP/SL;
  • trade.Sell(): Opens short position with TP/SL.

Trade Function Parameters:

  • iStartLots: Trade volume;
  • _Symbol: Instrument symbol;
  • Ask/Bid: Entry price;
  • Ask - iStopLoss * _Point: Stop-loss level for Buy;
  • Ask + iTakeProfit * _Point: Take-profit level for Buy;
  • _Point: Point value for the symbol (e.g., 0.0001 for EURUSD).

After opening a trade, the function returns immediately to prevent duplicate orders.

5. OnDeinit() — Cleanup on Removal

This function executes when the EA is removed from the chart. In this basic version, it’s empty—but can be extended for:

  • Saving performance statistics;
  • Forcibly closing open positions;
  • Writing logs to file.
void OnDeinit(const int reason) {
 // Optional cleanup code goes here
}

6. How the Robot Operates Overall

  1. At launch (OnInit), trading parameters are initialized.
  2. On every tick (OnTick):
    • It checks for existing positions;
    • If none exist, it opens a random Buy or Sell with preset TP/SL;
    • If positions exist, it does nothing.
  3. On removal (OnDeinit), cleanup occurs (none in this version).

7. Key Notes for Beginners

  1. Testing: Always validate on a demo account or MT5 Strategy Tester before live use.
  2. Risk Awareness: Pure randomness is high-risk. In live markets, add filters (trend, RSI, volatility).
  3. Parameter Tuning: Adjust iStartLots, iTakeProfit, and iStopLoss to match your account size and risk tolerance.
  4. Magic Number: Ensure iMagicNumber doesn’t conflict with other EAs on the same account.
  5. Slippage: Set iSlippage according to instrument liquidity (tighter for majors, wider for exotics).

8. What Can Be Improved

This is a foundational example. For production use, consider adding:

  • Indicator-based filters (e.g., RSI > 50 for Buy bias, MACD crossover confirmation);
  • Dynamic position sizing (e.g., lot calculated as % of equity);
  • Trade logging to file or journal;
  • Anti-duplicate safeguards (e.g., time-based cooldown after entry);
  • Parameter optimization using MT5’s genetic algorithm or walk-forward analysis.

You’ve now reviewed the architecture of a minimal MQL5 trading robot—its core functions, initialization flow, and tick-driven logic. You’re ready to adapt this code for custom strategies or build more advanced EAs from scratch.

Learn more about forex algorithmic trading fundamentals.

FAQ

Is the Heads or Tails strategy profitable?

No—its theoretical win rate is ~50%, and real-world friction (spreads, slippage, commissions) makes it negatively expected without filters or edge enhancements.

Can I use this EA on a live account?

Only after thorough backtesting and forward testing on demo. Never deploy pure randomness without risk controls, position sizing, or market context filters.

What’s the role of MagicNumber in this EA?

It uniquely tags all trades opened by this robot, allowing safe coexistence with other EAs or manual trades—and enabling reliable position tracking in code.

Subscribe to us on Telegram

Fortrader contentUrl Suite 11, Second Floor, Sound & Vision House, Francis Rachel Str. Victoria Victoria, Mahe, Seychelles +7 10 248 2640568

More from this category

All articles

Recent educational articles

All articles

Editor recommends

All articles