Why Average Forex Spreads Differ: Weight the Same Quotes by Time, Updates or Trades
The same one-minute forex quote stream can average 1.6667 pips by time, 4.6364 pips by quote count and 1.8 pips by matched trade volume. Rebuild the denominator before comparing providers or treating a quoted average as your trading cost.
An average forex spread is incomplete without its weighting rule. A brief burst of frequent quotes can dominate an update-count average while occupying little of the clock. An average attached to actual trading can differ again because trades need not arrive uniformly through time.
The following hypothetical EUR/USD stream produces three correct averages with different meanings. It can even rank below a constant two-pip comparison stream under one definition and above it under another. The task is to identify the observation unit and denominator, not choose whichever number looks most attractive.

Define a valid quote interval before calculating an average
Use a 60-second observation window starting at time 0 and ending just before time 60. Prices are USD per EUR and one pip is defined as 0.0001. A spread is the ask minus the bid, divided by that pip size. The two sides must belong to the same quote state; combining an old bid with a later ask can manufacture a spread that was never actually displayed.
Assume the feed is complete and each two-sided quote remains valid until the next qualifying update or the end of the window. At time 0, stream A quotes a one-pip spread. It updates again at second 25 with a changed price level but the same one-pip spread. At second 50 the spread becomes five pips, followed by updates every half-second through 59.5. These are distinct qualifying quote updates, not retransmitted copies of one message.
Thus there are two observations at one pip and twenty at five pips. The one-pip state occupies 50 seconds in total; the five-pip state occupies 10 seconds. Updating a price level does not necessarily change its spread. Neither a quote update nor a change in spread proves that a trade occurred.
| Spread state | Valid duration, seconds | Qualifying quote records | Share of time |
|---|---|---|---|
| 1 pip | 50 | 2 | 83.3333% |
| 5 pips | 10 | 20 | 16.6667% |
| Total | 60 | 22 | 100% |
Time weighting measures how long the spread was present
For spread sᵢ and its valid duration Δtᵢ, the time-weighted mean is Σ(sᵢ×Δtᵢ)/ΣΔtᵢ. In this complete window, the denominator is 60 seconds. Stream A gives (1×50+5×10)/60 = 100/60 = 1.6666667 pips. The narrow state has 50/60, or 83.3333%, of the time weight.
Use intervals that include their starting instant and exclude their ending instant: the update at second 50 governs [50,50.5), not the preceding interval. The final update covers [59.5,60). Such a convention prevents overlapping durations. Events at the exact endpoint belong to the next window and have no duration in this one.
The last valid state before the start may be needed when a window begins between updates. Its eligibility must be established from the feed specification and status, rather than assumed indefinitely. A quote expiry, withdrawal or missing side can end an interval before the next price message arrives.
Stream B has a two-pip spread throughout the same valid 60 seconds. Its time-weighted average is two pips, regardless of how frequently its unchanged spread accompanies price updates. On this definition alone, A is narrower than B. That says what was displayed through time, not what any particular order would pay.
Counting updates answers a different question—and reverses the ranking
An equal-update mean gives one observation weight to each qualifying quote record. For A, it is (2×1+20×5)/22 = 102/22 = 4.6363636 pips. The five-pip state receives 20/22, or 90.9091%, of the count weight despite lasting only one-sixth of the minute. Equal observation weights are not equal time weights.
For constant-spread B, the count mean remains two pips. A now ranks wider than B, although no quote or timestamp in either stream has changed. The reversal is caused by the weighting definition. It does not by itself show that a provider altered prices, that a data vendor made an error or that one method is dishonest.
A feed that sends more qualifying price updates in the wide-spread interval contributes more wide-spread observations to the count mean. A feed that batches changes may contribute fewer. Record the capture rule, filtering and source when comparing counts. Remove demonstrable transport duplicates, but do not silently discard distinct price updates merely because they share a spread.
A regular-time snapshot average is another sampling design. With genuinely equal spacing, valid observations and a stated endpoint convention it can approximate a time mean; sparse snapshots can miss brief states or overrepresent their particular sampling instants. Relabelling every irregular update as one second cannot create a time-weighted statistic.
Trade-volume weighting needs actual trades matched to quotes
Now add a separate, hypothetical execution record to the same complete quote stream. A total of EUR 80,000 trades during the one-pip state and EUR 20,000 during the five-pip state. Each amount is matched to the valid prevailing quote immediately before the relevant trade, with sequence information resolving any identical timestamps. These volumes cannot be inferred from the 22 quote records.
The trade-volume-weighted quoted spread is (80,000×1+20,000×5)/100,000 = 1.8 pips. It describes the quoted spreads associated with that particular execution sample, weighted by euro amount. It is not the arithmetic mean of execution prices, the quoted depth, or the number of trades. A different trading schedule can change this statistic without changing the quote history. For the B comparison, independently assume the same two volume totals are executed in the corresponding periods of its constant two-pip stream; its weighted quoted spread is therefore two pips. This is a comparison assumption, not evidence that identical trades could be executed on both streams.
| Weighting rule | A, pips | B, pips | What receives weight |
|---|---|---|---|
| Valid time | 1.666667 | 2.000000 | Duration of each quote state |
| Equal quote records | 4.636364 | 2.000000 | Each qualifying update |
| Matched executed EUR volume | 1.800000 | 2.000000 | EUR 80,000 narrow; EUR 20,000 wide |
Quoted spread at trade time is also different from effective spread computed from a fill and a contemporaneous midpoint. Without the actual fills, direction, sizes and applicable charges, the 1.8-pip statistic is not a dollar-cost invoice. It does not establish a one-way cost of 1.8 pips, an achieved round-trip cost, or a saving available to a trader who can simply wait. A zero-trade sample has no trade-volume-weighted mean; it is not zero pips.
Missing coverage changes the denominator, not just the numerator
Treat the following as an independent data-quality scenario. Suppose only seconds [0,55) are verifiably covered: one pip for 50 seconds and five pips for five seconds. The final five seconds have unknown quote status. The valid-time numerator is 1×50+5×5 = 75 pip-seconds, and the observed-time mean is 75/55 = 1.3636364 pips.
Coverage is 55/60 = 91.6667%. Dividing 75 by the full 60 seconds instead gives 1.25 pips and implicitly assigns a zero spread to the unobserved interval. Carrying the five-pip quote to the end recreates 1.6666667 pips only under an additional validity assumption that this incomplete record does not establish. Report the missing coverage rather than selecting the more favourable result.
Equal-weighting subgroup averages causes a related problem. In the complete example, the first 50-second block averages one pip and the last 10-second block averages five. Their simple average is three pips, not the full-window time mean. Weighting them by 50 and 10 returns 1.6666667. When valid coverage differs across minutes, days or providers, preserve those denominators when pooling.
Keep currency pair, pip definition, quote access, account conditions, time window and tradable quantity comparable. Do not average EUR/USD and USD/JPY pip figures into a universal cost without an explicit normalization. Even a correctly matched spread statistic leaves order size and depth unresolved; see calculating the price for a full forex order from available depth. Commissions, execution differences and rejected orders also require their own records.
An audit that makes each reported average reproducible
First specify the question: time spent at each quoted spread, the distribution of qualifying updates, or quoted conditions associated with executed volume. Retain the pair and unit, bid and ask, quote identifier or sequence, timestamp precision, validity and withdrawal rules, window boundaries and filters. Record source time and receipt time separately when both exist.
Then sort and validate events, reconstruct the eligible two-sided states, clip intervals to the chosen window and measure valid coverage. Reject or investigate malformed or crossed states under a documented rule; do not turn a negative spread created by asynchronous data into a trading opportunity. Count each qualifying update once. For trade weighting, join actual euro volumes to the applicable prior quote without borrowing a later quote.
Finally reconcile both numerator and denominator. In the complete example they are 100 pip-seconds over 60 seconds, 102 pip-observations over 22 observations, and 180,000 pip-euros over EUR 100,000. Preserve full precision before rounding. Report the weighting and coverage beside 1.6667, 4.6364 and 1.8 pips. Those labels explain the difference; the word average alone does not.


