Complete MQL5 guide & code

MQL5 CopyTicks & CopyTicksRange: Real-Time & Historical Tick Data

Master the MQL5 CopyTicks function. Learn how to fetch real-time and historical tick data into MqlTick structures, use COPY_TICKS flags, and handle async caching.

What this MQL5 guide covers

CopyTicks retrieves tick data from terminal memory or broker trade servers into dynamic arrays of MqlTick structures.

Three query flags control data filtering: COPY_TICKS_ALL for complete streams, COPY_TICKS_INFO for bid/ask price shifts, and COPY_TICKS_TRADE for execution deals.

Each MqlTick record provides millisecond precision timestamps (time_msc) along with flags indicating whether a tick represents buyer or seller pressure.

If historical ticks are not yet cached locally, CopyTicks initiates a background download; verify that returned tick count matches expectations before processing.

CopyTicks Function Signatures and Query Flags

The CopyTicks function extracts ticks for a designated symbol into an array of MqlTick structures. Its signature is int CopyTicks(string symbol_name, MqlTick &ticks_array[], uint flags = COPY_TICKS_ALL, ulong from = 0, uint count = 0).

Filtering flags allow algorithms to restrict data transmission to relevant events, saving memory and processing overhead in high-frequency trading systems.

Query Flag ConstantBit MaskData Stream Included
COPY_TICKS_ALLFull tick historyAll price quote changes, execution deals, and volume updates
COPY_TICKS_INFOInfo ticks onlyOnly bid and ask price alterations (quote updates)
COPY_TICKS_TRADETrade ticks onlyOnly last price changes and real trade deal executions

The MqlTick Structure and Millisecond Precision

Each element filled by CopyTicks is an MqlTick struct. Unlike standard datetime variables that resolve to whole seconds, MqlTick includes time_msc, a 64-bit integer tracking the exact millisecond elapsed since 1970.01.01.

MqlTick FieldData TypeDescription and Significance
timedatetimeStandard timestamp rounded to seconds
biddoubleCurrent bid price recorded on tick
askdoubleCurrent ask price recorded on tick
lastdoubleLast trade execution price
volumeulongTick volume or contract volume for the deal
time_msclongMillisecond precision timestamp
flagsuintBitmask identifying tick cause (TICK_FLAG_BUY, TICK_FLAG_BID, etc.)
volume_realdoubleFloating-point trade volume for exchange instruments

Interpreting Tick Direction: TICK_FLAG Constants

The flags member reveals the market action that triggered the tick. Using bitwise AND checks, your Expert Advisor can isolate buyer-initiated aggressive orders from seller-initiated orders.

  • (tick.flags & TICK_FLAG_BUY): Indicates a market buy deal that lifted the offer.
  • (tick.flags & TICK_FLAG_SELL): Indicates a market sell deal that hit the bid.
  • (tick.flags & TICK_FLAG_BID): Indicates the bid price changed.
  • (tick.flags & TICK_FLAG_ASK): Indicates the ask price changed.

CopyTicks vs CopyTicksRange and Server Synchronization

CopyTicks fetches count ticks starting backward or forward from a specified millisecond timestamp. CopyTicksRange requests all ticks that occurred within an explicit interval [from_msc, to_msc].

When requesting historical ticks that are stored on the broker server but not yet synced locally, the terminal starts an asynchronous background download. The initial call may return 0 or fewer ticks than requested. Always check the return value, and retry on subsequent ticks if data is loading.

Implementation details & mechanics

Core implementation pattern

In OnTick(), copy the most recent 30 ticks using CopyTicks(_Symbol, g_ticks, COPY_TICKS_ALL, 0, 30). Confirm that returned count equals 30. Calculate order flow imbalance by summing buy flags vs sell flags across the buffer. If buyer-initiated ticks exceed 70% and the spread is below maximum threshold, trigger a market buy entry.

Error handling & safety rules

Continuously track tick latency and spread widening in OnTick(). If bid drops past trailing stop tick levels or seller volume spikes beyond risk parameters, exit immediately via CTrade. Clean up the dynamic tick array in OnDeinit(const int reason) with ArrayFree(g_ticks).

MQL5 Code Implementation Code

//+------------------------------------------------------------------+
//|                                              CopyTicksGuideEA.mq5|
//|                             Copyright 2026, Pineify Guides Series |
//|                                              https://pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify Guides Series"
#property link      "https://pineify.app/mql5/copyticks-guide"
#property version   "1.00"
#property strict

//--- Input parameters
input uint InpTickCount = 20;  // Number of recent ticks to monitor

//--- Dynamic buffer for tick data
MqlTick g_ticks[];

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   PrintFormat("CopyTicks EA initialized for %s. Requesting %u ticks per tick.",
               _Symbol, InpTickCount);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ArrayFree(g_ticks);
   PrintFormat("Tick buffer released. Deinit reason: %d", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Copy the last N ticks from current time (0 = current moment backward)
   int copied = CopyTicks(_Symbol, g_ticks, COPY_TICKS_ALL, 0, InpTickCount);

   // Check if data is synchronized
   if(copied < (int)InpTickCount)
     {
      PrintFormat("Tick history synchronizing... Copied %d of %u requested ticks.",
                  copied, InpTickCount);
      return;
     }

   int buyCount  = 0;
   int sellCount = 0;
   double totalSpread = 0.0;

   // Process copied ticks
   for(int i = 0; i < copied; i++)
     {
      // Inspect tick flags
      if((g_ticks[i].flags & TICK_FLAG_BUY) != 0)
         buyCount++;
      if((g_ticks[i].flags & TICK_FLAG_SELL) != 0)
         sellCount++;

      double tickSpread = (g_ticks[i].ask - g_ticks[i].bid) / _Point;
      totalSpread += tickSpread;
     }

   double avgSpread = totalSpread / copied;
   MqlTick latestTick = g_ticks[copied - 1]; // Newest tick in array

   PrintFormat("Latest Tick -> Bid: %.5f | Ask: %.5f | Spread: %.1f pts | Time: %I64d ms",
               latestTick.bid, latestTick.ask, avgSpread, latestTick.time_msc);
   PrintFormat("Order flow window -> Buys: %d | Sells: %d", buyCount, sellCount);

   // Simple momentum check: aggressive buyer flow dominance
   if(buyCount >= (int)(InpTickCount * 0.70) && avgSpread <= 25.0)
     {
      // Order flow confirms bullish aggressive buying
     }
  }

Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.

Generate custom MQL5 code with Pineify AI

Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify produces clean, typed MQL5 source code ready to compile in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.