MT5 magic numbers: attribute EA results without losing costs

6 min readMetaKit

Two Expert Advisors trade the same MT5 account. The account makes money, but you want to know which EA contributed, which generated costs, and whether a manual intervention changed the result. Filtering by symbol cannot answer those questions when both strategies trade EURUSD.

An MT5 magic number is useful evidence for this audit. It is an identifier supplied by trading software, not a verified strategy name or a complete allocation ledger. This guide builds a deal-level report and explains where a stronger position-ownership model is needed. The aim is an honest attribution report, rather than a persuasive-looking league table built from incomplete labels.

What the magic number identifies

MetaQuotes provides SetExpertMagicNumber to set the expert identifier used by a CTrade instance. The native deal properties include DEAL_MAGIC, alongside separate order, position and deal identifiers.

Treat those as different dimensions. A deal ticket identifies an execution record; positionId links related activity; a magic number is a software-supplied tag. Nothing in the number itself proves that strategy 101 is a particular commercial EA, that its parameters stayed unchanged, or that another program did not reuse the same tag.

Maintain a registry scoped to your account environment: strategy name, magic number, configuration version, deployment dates and expected symbols. Reserve zero as unassigned in your reporting unless you have stronger evidence. Software can use a default zero, so “zero means manual” is too strong a classification rule. Keep the raw tag even when you attach a friendly name.

Read history rather than guessing from open positions

MetaKit's GET /v1/accounts/{id}/deals returns each deal's magic, positionId, entry, type, profit, commission, swap, fee and other fields. The current open-position serializer does not expose a magic field. Do not build a collector that expects one there because the native terminal has additional properties.

The public order-creation schema also does not provide a configurable magic number. An internal terminal helper accepting that argument does not make it a public REST feature. Passing an invented magic property is not a supported tagging workflow. This article concerns reporting on tags already recorded by EAs and other execution sources; it does not instruct the REST API to assign new ones.

Use the API documentation for the current contract. Collect all history pages and deduplicate by account and deal identity before summarizing. The incremental history guide covers collection and checkpoint safety. Keep account boundaries: a magic number can be reused legitimately on a different account.

A deal-activity report that preserves costs

For a first audit, group buy/sell deal cash results by the tag recorded on each deal. Sum profit + commission + swap + fee, including opening executions. Excluding entries because they do not realize trading profit can discard commissions.

This JavaScript function accepts one account's complete, deduplicated deal set. It reports tagged deal activity, not completed-trade win rates or returns on allocated capital. It rejects missing cost fields rather than silently treating them as zero.

function taggedDealTotals(deals) {
  const totals = new Map();
  for (const deal of deals) {
    if (!["buy", "sell"].includes(deal.type)) continue;
    if (!Number.isSafeInteger(deal.magic) || deal.magic < 0) {
      throw new Error("Magic number needs a lossless representation");
    }
    const amounts = [deal.profit, deal.commission, deal.swap, deal.fee];
    if (!amounts.every(Number.isFinite)) {
      throw new Error("Incomplete deal cash fields");
    }
    const key = String(deal.magic);
    const row = totals.get(key) ?? { dealCount: 0, net: 0 };
    row.dealCount += 1;
    row.net += amounts.reduce((sum, value) => sum + value, 0);
    if (!Number.isFinite(row.net)) throw new Error("Cash total overflow");
    totals.set(key, row);
  }
  return Object.fromEntries(totals);
}

For a synthetic example, magic 101 has an opening commission of −$2 and a closing deal with $35 profit and −$2 commission. Its tagged net is $31. Magic 202 has a −$1 opening commission and a closing result of −$12 with another −$1 commission, giving −$14. An unassigned zero-tagged execution contributes $8. Total tagged buy/sell activity is $25.

The figures assume all other cost fields are explicitly zero. A closing-only filter would show $33 and −$13 for the first two groups, overstating each result by its missing opening cost. The MT5 trade-cost guide explains why costs need their own reconciliation.

If identifiers exceed JavaScript's safe integer range, use lossless parsing before aggregation and retain decimal strings. Stringifying an already-rounded number does not recover its original digits. Keep monetary rounding at the reporting boundary or use a suitable decimal representation for accounting work.

Execution tags are not always strategy ownership

An EA can open a position and another program can close it. Inspect the actual deal tags and reasons; do not assume the closing execution must carry the original opening tag. The deal-level report answers “which tag is on the cash-bearing execution?” That can differ from “which strategy initiated this exposure?”

A stronger ownership report links the complete position lifecycle and applies an explicit allocation rule. For a simple position opened by one strategy and closed manually, you might attribute lifecycle P&L to the opening strategy while separately marking the manual intervention. State that policy. It is an analytical choice, not information guaranteed by a numeric tag.

Netting accounts need extra care. Multiple entries can contribute to one symbol position, and opposing orders can reduce or reverse exposure. Allocating realized P&L between strategies then requires an inventory or virtual-book model. One position row cannot preserve separate EA ownership automatically. See netting versus hedging before interpreting a position-level join as an allocation algorithm.

Make the report auditable

Show unassigned, mixed-tag and unresolved rows instead of hiding them. Keep the measurement period and account currency next to every result. Count deals as deals; opening plus closing executions do not represent two completed trades. Do not calculate a strategy win rate from the number of positive deal cash flows.

Reconcile the sum of all tagged buy/sell activity against the same filtered trade ledger first. Then explain the bridge to account equity changes, including non-trading adjustments, funding and open P&L. Separate broker-posted charges that cannot be allocated confidently. A residual is a reason to investigate, not a number to distribute proportionally without disclosure.

The aggregation example was checked with synthetic opening costs, losses, zero tags, non-trading rows and invalid inputs. No EA or account was accessed live. For a production collector, start with read-only credentials and preserve the original records alongside any derived labels. That keeps a future change to the allocation policy reversible and makes the result useful for strategy review.

Sources and verification

Verified 19 October 2026 against MetaKit's deal serializer, position serializer and public order schema.