Forex correlation from MT5 data: align returns before comparing

6 min readMetaKit

A forex correlation table can suggest that several positions are behaving like the same trade. It can also give a precise-looking answer to the wrong question if it compares price levels, misaligned candles or different return intervals.

This guide builds the calculation behind a rolling correlation report using MT5 candle data. It focuses on data alignment and interpretation, rather than recommending pairs to trade. Correlation describes a sample of co-movement; it does not identify a permanent hedge ratio or guarantee diversification when markets change.

Measure returns over matching intervals

For a positive closing price, a simple return is close_now / close_previous - 1. Compute it consistently for both instruments over the same interval. Log returns are another possible convention, but do not mix the two definitions inside one report.

Consider an hourly dataset. EURUSD has observations at 09:00, 10:00 and 11:00, while GBPUSD is missing 10:00. Dividing GBPUSD's 11:00 value by its 09:00 value creates a two-hour return. Pairing that with EURUSD's 10:00-to-11:00 return does not compare like with like, even though both rows end at 11:00.

Require both endpoints for both instruments, and verify that the elapsed interval equals the chosen cadence. Do not silently forward-fill a missing quote and interpret the resulting zero as an observed market return. A gap can be an inactive session or a data problem; either way the policy needs to be explicit.

When using MT5 bars, remember that the returned timestamp labels the bar's opening time. Two close prices on adjacent H1 bars describe adjacent closing observations, but the currently forming bar is not a finalized close. Exclude it using validated bar boundaries and the report's observation time.

What Pearson correlation calculates

Pearson correlation divides the sum of products of centered observations by the product of their centered lengths. NIST's correlation reference documents the formula and its interpretation as a linear relationship.

For a tiny synthetic example, let one return series be [1, 2, 3] and the other [2, 4, 6], expressed in any consistent return unit. Their correlation is +1. Reversing the second series to [6, 4, 2] gives −1. Replacing it with [4, 4, 4] makes the denominator zero, so correlation is undefined. Reporting zero in that case would confuse missing variation with evidence of no linear association.

Three observations are enough to illustrate the arithmetic, not to assess a trading relationship. A production table should show its sample size and its chosen window. Missing aligned intervals mean a “last 100 hours” report may contain fewer than 100 usable return pairs.

A checked calculation core

This JavaScript function accepts already-aligned paired returns. Each row is [returnA, returnB]. It returns null for a constant series and rejects malformed data. Its ordinary floating-point arithmetic is intended for conventional financial return magnitudes, not extreme numerical inputs.

function pearsonReturns(pairs) {
  if (!Array.isArray(pairs) || pairs.length < 3 ||
      pairs.some(p => !Array.isArray(p) || p.length !== 2 ||
        !p.every(Number.isFinite))) {
    throw new Error("Need at least three valid paired returns");
  }
  const n = pairs.length;
  const mx = pairs.reduce((s, p) => s + p[0], 0) / n;
  const my = pairs.reduce((s, p) => s + p[1], 0) / n;
  let xx = 0, yy = 0, xy = 0;
  for (const [x, y] of pairs) {
    const dx = x - mx, dy = y - my;
    xx += dx * dx;
    yy += dy * dy;
    xy += dx * dy;
  }
  if (![xx, yy, xy].every(Number.isFinite)) throw new Error("Overflow");
  if (xx === 0 || yy === 0) return null;
  const denominator = Math.sqrt(xx) * Math.sqrt(yy);
  if (!Number.isFinite(denominator) || denominator === 0) {
    throw new Error("Unsupported numerical range");
  }
  return { correlation: Math.max(-1, Math.min(1, xy / denominator)), n };
}

The calculation was checked on positive, negative and zero-correlation fixtures, constant inputs and malformed rows. Clamping handles small rounding excursions outside the mathematical range; it is not a repair for bad input data. Store the unrounded result and round only the displayed cell.

For a rolling report, apply the function to each trailing block of valid observations. Decide whether the window is a fixed calendar interval or a fixed number of paired returns. Those policies behave differently around weekends and missing bars. Publish which one you use.

Collect comparable candles through MetaKit

MetaKit exposes GET /v1/accounts/{id}/candles with symbol, timeframe, from, to and count. The current response includes data and a truncated indicator; its cap is 5,000 candles. A truncated response is not a complete research window. Split the request or choose a suitable timeframe before calculating.

For the simplest comparison, use exact broker symbols from one account and a consistent timeframe. The historical-data guide explains retrieval. If you combine feeds from several brokers, validate actual time alignment, trading sessions and instrument definitions before joining them. Different suffixes and daily bar boundaries can represent different datasets.

The current adapter formats native time values as ISO timestamps without discovering a broker-specific offset. Do not apply an assumed offset because another account uses it. Verify a known boundary and keep the original timestamp plus any documented normalization. A one-hour shift can turn a contemporaneous correlation estimate into an accidental lead/lag experiment.

A matrix needs consistent samples

A diagonal cell is one only when a nonconstant series is compared with itself on a valid sample. For off-diagonal cells, show both the estimate and the number of paired observations. A color without that context makes a thin sample look as authoritative as a much larger one.

If each pair drops a different set of timestamps, every cell can describe a different sample. That may be acceptable for exploratory display, but the assembled matrix is not automatically suitable for portfolio optimization. For a matrix intended for joint numerical analysis, use a consistent common observation set and validate its numerical properties separately.

Also distinguish price-pair correlation from position P&L correlation. Taking the opposite side reverses the sign of a simple linear return exposure. Position size, account-currency conversion, financing and changing holdings add further differences. The currency-exposure guide provides a complementary view of shared currency legs; it does not replace statistical co-movement analysis.

Use correlation as one diagnostic alongside exposure, liquidity and drawdown. Inspect how estimates change across windows, especially around unusual market periods, before treating a historical relationship as stable. The trade-journal workflow can record the report available at entry time, avoiding a review that inadvertently uses future observations.

Confirm current request and response fields in the MetaKit documentation. This article's examples use synthetic data and do not establish a live correlation estimate for any currency pair.

Sources and verification

Verified 19 October 2026 against MetaKit's candle route and terminal serializer.