MAE and MFE in MT5: measure the path inside each trade

5 min readMetaKit

A trade closes with a five-pip gain. That result does not reveal whether it first suffered twenty pips of adverse movement, briefly offered fifteen pips of profit, or moved almost directly to the exit. MAE and MFE describe that path and can make a trading journal more useful than a list of final outcomes.

Maximum adverse excursion measures the greatest movement against the position during its lifetime. Maximum favorable excursion measures the greatest movement in its favor. MetaTrader's testing report documentation discusses both. The method below reports nonnegative price excursions in explicitly defined pips; it does not claim to reproduce every monetary convention in the Strategy Tester.

Pick the price that could close the position

For a long forex position, use bid observations when estimating liquidation value; for a short, use ask observations. Compare those prices with the actual entry fill. Using bid candles for a short trade omits the ask side and can understate adverse movement when the spread widens.

For a fixed entry and position size, define a favorable signed move as bid - entry for a long and entry - ask for a short. MFE is the largest positive move, floored at zero. MAE is the magnitude of the most negative move, also floored at zero. Divide by your explicitly supplied pip size if the output should be pips.

Pips are a reporting convention, not the same thing as every instrument's minimum price increment. A conventional EURUSD example may use 0.0001; another contract can need a different unit. The lot and pip-value guide explains that distinction. Do not apply a forex pip assumption to gold or an index because the chart looks familiar.

Two worked paths

Assume a synthetic long entry at 1.1002 and bid observations of 1.1000, 1.0994 and 1.1013 during the holding interval. With a pip size of 0.0001, its worst signed move is −8 pips and its best is +11 pips. Report MAE of 8 and MFE of 11. The initial two-pip disadvantage reflects the chosen entry-versus-bid observation, before commissions.

For a synthetic short entry at 1.1000, use ask observations of 1.1002, 1.1009 and 1.0989. The adverse extreme is 9 pips and the favorable extreme is 11 pips. Reusing the long-side formula on those prices would reverse their meaning.

The order of extrema matters for some questions. If favorable and adverse extremes both appear in one candle, OHLC alone does not establish which happened first. You cannot use that bar to prove a tighter stop would have survived before the profit opportunity arrived. Excursion summaries describe extrema; they are not a complete counterfactual execution simulator.

A calculator for a validated quote sample

This pure JavaScript function expects ticks already restricted to the position's actual holding interval. It does not infer entry or exit times, repair missing history, or validate timezone interpretation.

function priceExcursions({ side, entry, pipSize, ticks }) {
  if (!["buy", "sell"].includes(side) ||
      ![entry, pipSize].every(Number.isFinite) ||
      entry <= 0 || pipSize <= 0 || !Array.isArray(ticks) || !ticks.length) {
    throw new Error("A valid position and nonempty quote sample are required");
  }
  let adverse = 0;
  let favorable = 0;
  for (const tick of ticks) {
    if (!tick || ![tick.bid, tick.ask].every(Number.isFinite) ||
        tick.bid <= 0 || tick.ask < tick.bid) {
      throw new Error("Invalid bid/ask observation");
    }
    const move = side === "buy" ? tick.bid - entry : entry - tick.ask;
    favorable = Math.max(favorable, move);
    adverse = Math.max(adverse, -move);
  }
  const result = { maePips: adverse / pipSize, mfePips: favorable / pipSize };
  if (!Object.values(result).every(Number.isFinite)) throw new Error("Overflow");
  return result;
}

The long and short paths above were checked against this function with synthetic bid/ask fixtures. Empty history is an error, rather than a zero-excursion trade. A one-sided price path can legitimately produce zero MAE or zero MFE under this definition; that is different from having no observations.

Collect the path through MetaKit

MetaKit provides /v1/accounts/{id}/deals for entry/exit evidence and /v1/accounts/{id}/ticks for broker tick history. A tick range request uses symbol, from and to. Check truncated; the current API caps responses at 50,000 ticks. Split large intervals and establish coverage before calling the output a full-period statistic. The history-data walkthrough covers collection mechanics.

The current tick serializer exposes time, bid, ask, last and volume. It omits native millisecond time and tick flags. Native MqlTick has additional information, but a REST consumer cannot assume it is present. Multiple ticks can share a second; do not deduplicate by second timestamp alone and accidentally discard the extrema.

Boundary ambiguity matters for very short trades. If the fill and several quotes share the same exposed second, history may not establish which quote preceded the actual entry. Label the result approximate, or exclude the trade from precision-sensitive comparisons. Similarly, verify the broker/feed clock interpretation before joining quote times to deal times. A formatted timestamp does not certify that two independent datasets are aligned.

Keep price excursions separate from money and changing size

Multiplying a pip excursion by a fixed pip value only estimates a monetary excursion under the relevant contract and currency assumptions. Commission, swap, conversion rates and changing lot size require a richer P&L reconstruction. A trade scaled in twice does not have one unchanged entry basis and one fixed volume across its entire life.

For partial exits or reversals, define whether the journal unit is an individual fill segment, a position lifecycle or a strategy-defined trade. Record that choice alongside MAE/MFE. Do not compare a scaled position's reconstructed cash excursion with a fixed-entry price excursion as though they were the same measurement.

Use the metrics to formulate review questions: did a trade reach substantial favorable movement before a discretionary exit, or did many eventual winners tolerate large adverse movement? Answering those questions does not prove a new stop or target improves future results. Test a proposed rule on a separate sample with transaction costs and feasible order timing.

A practical trading journal can store the final outcome, sampled MAE/MFE, quote coverage, reporting unit and a data-quality flag. Link each row back to its deal evidence and raw quote interval. Verify the endpoint fields in the API documentation, and avoid presenting sampled extrema as guaranteed executable prices.

Sources and verification

Verified 19 October 2026. No live trades or performance tests were performed.