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 last-price or volume changes.
MqlTick includes a millisecond timestamp and change flags. Buy/sell flags describe feed-provided trade information when available; quote ticks alone do not establish buying or selling 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 selects returned tick types. MetaQuotes notes that selecting INFO or TRADE requires additional filtering and provides no significant speed advantage over ALL; measure your own workload.
| Query Flag Constant | Selection | Data Stream Included |
|---|---|---|
| COPY_TICKS_ALL | Full tick history | All price quote changes, execution deals, and volume updates |
| COPY_TICKS_INFO | Info ticks only | Only bid and ask price alterations (quote updates) |
| COPY_TICKS_TRADE | Trade ticks only | Ticks with last-price or volume changes |
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 Field | Data Type | Description and Significance |
|---|---|---|
| time | datetime | Standard timestamp rounded to seconds |
| bid | double | Current bid price recorded on tick |
| ask | double | Current ask price recorded on tick |
| last | double | Last trade execution price |
| volume | ulong | Volume associated with the current last price; not a bar tick count |
| time_msc | long | Millisecond precision timestamp |
| flags | uint | Bitmask identifying tick cause (TICK_FLAG_BUY, TICK_FLAG_BID, etc.) |
| volume_real | double | Floating-point trade volume for exchange instruments |
Interpreting Tick Direction: TICK_FLAG Constants
Use bitwise AND to inspect which fields changed and any reported buy/sell trade flags. Availability depends on the instrument and data feed; do not infer aggressor-side volume from bid/ask quote updates or assume every record has a trade direction.
- (tick.flags & TICK_FLAG_BUY): Reports a buy-deal flag supplied in this tick.
- (tick.flags & TICK_FLAG_SELL): Reports a sell-deal flag supplied in this tick.
- (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
A nonzero CopyTicks from value starts the request at that millisecond timestamp; from=0 requests the latest count ticks. Results are oldest-first. CopyTicksRange uses an inclusive [from_msc, to_msc] interval.
Indicators return available ticks immediately while synchronization starts. EAs and scripts can wait up to 45 seconds for synchronization, then return available data and continue downloading. Inspect both returned count and errors; a short result is not proof of a particular cause.
Implementation details & mechanics
Core implementation pattern
OnTick requests the latest InpTickCount records, default 20, then logs their buy/sell flags and average quoted spread. It does not place orders. Counts describe the supplied tick flags, not traded volume or verified market-wide order flow. Consecutive rolling windows overlap; this is not an exactly-once tick consumer.
Error handling & safety rules
This example has no positions, trailing stops or CTrade exits. It frees the array in OnDeinit and rejects zero or excessively large input counts. Missing, partial or errored data requires inspection of the return count and GetLastError. OnTick notifications can coalesce multiple market updates.
MQL5 Code Implementation
//+------------------------------------------------------------------+
//| 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()
{
if(InpTickCount==0 || InpTickCount>100000) return INIT_PARAMETERS_INCORRECT;
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()
{
// from=0 selects the latest N ticks; returned array is oldest-first.
ResetLastError();
int copied = CopyTicks(_Symbol, g_ticks, COPY_TICKS_ALL, 0, InpTickCount);
// Check if data is synchronized
if(copied <= 0 || copied < (int)InpTickCount)
{
PrintFormat("Tick data incomplete: %d of %u requested; error %d.",
copied, InpTickCount, GetLastError());
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("Reported tick flags -> Buys: %d | Sells: %d", buyCount, sellCount);
// Illustrative count filter, not a validated trading signal.
if((double)buyCount / copied >= 0.70 && avgSpread <= 25.0)
{
Print("Illustrative flag-count threshold reached; no order sent.");
}
}
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 generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.
Frequently Asked Questions
Related MQL5 pages
Technical references
Risk and testing note
These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.