Forex time-weighted return: separate trading from cash flows

6 min readMetaKit

An account starts with $10,000, receives a $5,000 deposit, and finishes at $15,300. The balance increased by 53%, but calling that a 53% trading return would count new funding as performance. Subtracting the deposit leaves $300; the next question is how much capital was exposed, and for how long.

Forex time-weighted return answers that question by separating investment performance from external deposits and withdrawals. This guide uses synthetic account values to show exact subperiod linking, a Modified Dietz approximation, and the MT5 data needed to implement either. It is an analytics method, not a forecast of trading results.

Start with a cash reconciliation

For a period measured in one account currency, define net external cash flow as deposits minus withdrawals. With consistent equity valuations and complete cash-flow classification:

investment P&L = ending equity - beginning equity - net external cash flow

For the opening example, $15,300 minus $10,000 minus $5,000 equals $300. This is a currency amount, not yet a rate of return. Dividing it by the beginning $10,000 gives 3%, but ignores that some of the result may have been earned with the extra $5,000 in the account.

Use equity if the report includes open positions. Mixing beginning equity with ending balance drops floating P&L from one side of the comparison. Keep charges and credits consistent as well: a broker fee is not an investor withdrawal simply because both reduce the account value.

MT5 distinguishes trading deals from balance, credit and other deal types in its deal properties. Those labels help identify records, but a generic balance entry still needs reconciliation with the broker statement. Broker corrections, promotions and transfers can need separate treatment. Do not blindly count every positive non-trading value as fresh investor capital.

Exact time-weighted return needs valuations at flows

Divide the measurement period at each external cash flow. Calculate each no-flow subperiod's return using equity immediately after the previous flow and immediately before the next one. Link the growth factors by multiplication.

This principle is discussed in the GIPS Standards Handbook for Firms. Applying this arithmetic does not establish GIPS compliance; formal compliance has broader requirements.

Consider a separate synthetic account path:

EventEquityExternal flow
Start$10,000None within the measured period
Just before deposit$10,200None
Just after deposit$15,200+$5,000
Period end$15,048None

The first subperiod returned $200 divided by $10,000, or 2%. The second returned negative $152 divided by $15,200, or negative 1%. The linked result is 1.02 × 0.99 − 1 = 0.0098, or 0.98%. Simply adding 2% and negative 1% gives 1%, which misses compounding.

The account's investment P&L is only $48: $15,048 minus $10,000 minus the $5,000 deposit. There is no contradiction between $48 and 0.98%. The two subperiod returns were earned on different amounts of capital.

Implement the linking step explicitly

This JavaScript function accepts already-validated, no-flow subperiods. It does not reconstruct equity at deposit times from a deal list.

function linkedReturn(periods) {
  if (!Array.isArray(periods) || periods.length === 0) {
    throw new Error("At least one valued subperiod is required");
  }
  let growth = 1;
  for (const { start, end } of periods) {
    if (![start, end].every(Number.isFinite) || start <= 0 || end < 0) {
      throw new Error("Unsupported equity values");
    }
    growth *= end / start;
    if (!Number.isFinite(growth)) throw new Error("Return overflow");
  }
  return growth - 1;
}
 
const result = linkedReturn([
  { start: 10000, end: 10200 },
  { start: 15200, end: 15048 },
]);
console.log((result * 100).toFixed(2)); // 0.98

Record the timestamps, valuation source and cash-flow convention outside this function. A deposit at the reporting boundary belongs either outside the period or inside under a stated policy; counting it twice changes the answer. If equity reaches zero, subsequent funding starts a new economically meaningful segment. Do not link through a zero starting value. Negative equity also requires a separately defined methodology; this helper rejects it.

The pure calculation was checked with synthetic fixtures, including a loss and invalid denominators. A production reporting system should use an appropriate decimal representation and a documented rounding policy for stored monetary values. Round the displayed percentage after linking, rather than rounding every subperiod to two decimals first.

When only beginning and ending equity are available

You cannot recover an exact return path from two equity values and a cash ledger. Modified Dietz is one useful approximation when flow timing is known but intermediate valuations are missing:

R = (ending equity - beginning equity - sum(flows))
    / (beginning equity + sum(weight × flow))
 
weight = fraction of the measurement period remaining after the flow

For the opening $10,000-to-$15,300 example, assume the $5,000 deposit arrives halfway through a thirty-day period. Investment P&L is $300. Weighted capital is $10,000 + 0.5 × $5,000 = $12,500, giving an estimated 2.4% return.

If the same deposit arrives with three days remaining, its weight is 3/30 = 0.1. The denominator is $10,500, and the estimated return is approximately 2.8571%. The cash-flow amount and total P&L are identical; timing changes the estimated capital employed.

The GIPS handbook describes Modified Dietz as an approximation whose accuracy can deteriorate with large flows and volatile return paths. State whether weights use actual elapsed time or a beginning/end-of-day convention. If weighted capital is zero or negative, flag the period for review rather than publishing an arbitrary percentage. More decimal places do not repair missing valuations.

Build the MT5 data pipeline honestly

MetaKit's /v1/accounts/{id}/deals returns raw deal fields including type, profit, commission, swap and fee. The current serializer maps buy, sell, balance and credit explicitly; other native types can appear as other. Preserve them for investigation rather than silently discarding them from the reconciliation.

The current /analyses implementation calculates growth from trade profit relative to deposits; it is not an exact cash-flow-linked TWR series. /performance provides its own reconstructed performance metrics. Neither endpoint should be relabeled as the exact calculation above without checking the method and available valuation data.

Maintain your own timestamped equity observations and classified cash ledger if you need this report. Ordinary periodic polling may miss the exact pre-flow valuation; label results approximate when that happens. The equity dashboard guide is a starting point for collecting observations, while trade-cost reconciliation explains why net P&L needs more than the headline profit field.

Publish a methodology note next to the result: account currency, period, equity or balance basis, included costs, flow classification, valuation frequency and whether the return is exact or estimated. Compare it with currency P&L and risk measures rather than using one percentage as a complete assessment. Verify current field definitions in the MetaKit documentation.

Sources and verification

Verified 18 October 2026. All numerical paths are synthetic; no account performance is claimed.