# EXIT CODE for MetaTrader 5

Two Expert Advisors. They do different jobs and are distributed differently.

| File | Name | Distribution | Needs internet |
|---|---|---|---|
| `ExitCodeGates.mq5` | EXIT CODE Gates | From exitcode.trade only | Yes (syncs with your workstation) |
| `ExitCodeHeadroom.mq5` | EXIT CODE Headroom | MQL5 Market (planned) | No (fully self-contained) |

**Test on a demo account first.** Attach either EA to a demo account, watch it for a full trading day, and only then put it on an account you care about.

Neither EA carries the EXIT CODE gate rules; rule checks run on the server, never in these files. Neither EA ever decides to open a trade. The Gates EA can place exactly one kind of order: the one YOU created by pressing Execute on a gate-cleared ticket at exitcode.trade (the v1.10 Execute relay, below). The only other trade action either EA can take is closing your open positions when YOUR OWN daily loss limit is hit, and only if you turned that switch on. That guardian check is computed on your terminal from your own inputs, works with no internet connection, and is off by default. Nothing the server sends on the sync channel can open, close, or modify a position.

---

## Compiling

There is exactly one compiler for these files: MetaEditor.

1. Open MetaTrader 5, press F4 to open MetaEditor.
2. Open the `.mq5` file (copy it into `MQL5\Experts\` via File, Open Data Folder).
3. Press F7 to compile. Zero errors expected; warnings should be read, not ignored.
4. The compiled `.ex5` appears in the Navigator under Expert Advisors.

The EXIT CODE repo tooling does not parse `.mq5` files. Nothing in `run-tests.sh` validates them. A change to these files is unverified until it compiles in MetaEditor and runs on a demo account.

---

## EXIT CODE Gates (`ExitCodeGates.mq5`)

The connected EA. It does four things: telemetry (sends your account snapshot and closed trades to your EXIT CODE workstation), display (a status block on the chart with your day loss, the server day, notes, and lockout state), a local guardian (the optional close-at-limit described above), and, since v1.10, the Execute relay described below.

### New in v1.11: per-item readiness

Earlier versions told you only whether the EA could trade. v1.11 reports each precondition on its
own, so the setup page can name the one thing that is wrong instead of leaving you to guess: whether
trading is allowed on the account, whether algo trading is on in the terminal, whether it is on for
this EA, whether the EA is permitted, whether the terminal is connected, and whether the local
guardian is armed.

### New in v1.10: the Execute relay

The relay closes the gap between clearing a ticket on the site and placing it in your terminal. While the EA is linked, it asks the server every 5 seconds whether you pressed Execute on a gate-cleared ticket at exitcode.trade. If you did, the EA places that one market order in your terminal, with the stop and target from your ticket, sized from the risk you chose, and reports the broker's result back to the site.

The rules the relay lives by:

- **It only ever acts on your own Execute click.** No relayed order exists unless you created it yourself on a gate-cleared ticket. The EA never originates a trade, and the server never originates one either; it carries your click, nothing more. Orders travel on their own channel, separate from the sync response, which stays display-only.
- **One order at a time.** The server holds at most one order in flight for your account, and the EA will never place the same order twice, even across a terminal restart. If a relayed order cannot be placed (unknown symbol, sizing that would risk more than you intended, trading not allowed in the terminal), the EA reports exactly why, the ticket stays cleared on the site, and you can place it by hand. Nothing is lost.
- **Sizing rounds down, never up.** The lot size is computed from your risk amount and floored to the broker's volume step. If the smallest size the broker allows would risk more than 105 percent of what you intended, the EA refuses to place and tells the site the ticket needs manual sizing.
- **MT5 execution is off server-side until it is enabled.** Until then the chart block shows "Execute relay: off (server)" and the relay does nothing. When it is on and idle, the chart shows "Execute relay: ready".

v1.10 also streams recent chart candles (the symbol and timeframe of the chart the EA is attached to) inside the sync payload, so a future in-browser MT5 chart on the workstation has data from day one, and it defends against account switches: if the terminal logs into a different account than the one paired, the EA stops syncing, alerts once, and asks for a new pairing code from exitcode.trade/members/mt5/. The old link file is kept, so switching back to the paired account resumes on its own.

Matching your closed trades to cleared tickets for a verified journal is server-side work; the closed-trade data is stored from day one so it can be built on.

### Step 1: allow web requests to exitcode.trade

MetaTrader blocks all web requests by default. You must whitelist the EXIT CODE server by hand; there is no way for the EA to do it for you.

1. In MetaTrader 5: Tools, then Options (Ctrl+O), then the Expert Advisors tab.
2. Tick "Allow WebRequest for listed URL".
3. Add this exact entry to the list: `https://exitcode.trade`
4. Click OK.

If you skip this, the EA alerts once with these steps and the chart block shows "blocked". The same alert can appear if the EA is run in a context where web requests are not allowed at all.

### Step 2: pair the EA with your account

1. Log in at exitcode.trade and open the MT5 connection page. It gives you a pairing code (8 characters). Codes last 15 minutes and work exactly once. Codes never contain 0, O, 1 or I; if pairing fails, re-copy the code carefully.
2. Attach the EA to any chart. In the inputs, paste the code into `PairingCode`.
3. Watch the chart block. When it says "linked", open the EA inputs again and clear `PairingCode`. The EA cannot clear the input itself.

The EA stores its link key in `MQL5\Files\EXITCODE\link_key.txt` in the terminal data folder. It survives restarts and recompiles. To disconnect this terminal, remove the link from your exitcode.trade account page, or delete that file.

If the chart block says "link removed", the key was revoked on the server side. Get a new pairing code and pair again.

### Inputs

| Input | Default | Meaning |
|---|---|---|
| `PairingCode` | empty | One-time code from exitcode.trade. Clear it after linking. |
| `SyncSeconds` | 5 | Fastest allowed gap between syncs. Minimum 2. The EA also skips syncs when nothing changed. |
| `DailyLossLimitPercent` | 0 | Your daily loss limit as a percent of the account size. The guardian turns it into a fixed dollar amount: account size times this percent. 0 turns the whole guardian off. |
| `AccountSizeOverride` | 0 | Your firm account size in account currency. 0 records the balance on first run and keeps it. Set the real account size so the dollar limit matches your firm's. |
| `CloseAllAtLimit` | false | When the limit is hit: true closes all open positions, false alerts only. |
| `ShowChartComment` | true | Show the status block on the chart. |

### How the day and the day loss are measured

- The trading day used by the local guardian resets at midnight Prague time, which is FTMO's daily reset. The EA computes this locally from GMT with European daylight saving rules. This is not the same as midnight on your broker's server clock.
- At each Prague midnight the EA records your account balance as the day-start anchor. Day loss is that anchor minus your current equity, so floating losses on open positions count, matching how FTMO measures the daily loss.
- The limit itself is a fixed dollar amount: your account size times `DailyLossLimitPercent`. With `AccountSizeOverride` set to your firm's account size, this is a fixed dollar line, the same way FTMO states it. If you leave the override at 0 on an account that has already grown above its original size, the recorded base is bigger and the limit trips later than the firm's would. Set the override.
- The day identity and the day loss shown from the server are display only. They never move the guardian's own clock or anchor. The guardian is yours, computed on your machine, and it keeps working when the server is unreachable.
- If you trade with a firm that resets at a different time than FTMO, know that version 1 of this EA measures its local day on the Prague schedule.
- The anchor, the day, and the sync watermark survive a terminal restart. First install mid-day anchors at the current balance; the next Prague midnight puts it on the real schedule.

### What gets sent

Each sync posts: your equity, balance, day-start anchor, open positions (symbol, direction, lots, entry, stop, target, floating result), and trades closed since the last successful sync (with the trade's net result including commission, swap, and fees). For a closed trade, the direction sent is the direction of the position that was closed, not the closing deal: a buy position closes with a sell deal and is reported as a buy. Netting-account reversals are treated as closes. Deposits and withdrawals are never sent as trades. No password, no investor login, nothing that can place a trade leaves your terminal.

### Strategy Tester

Web requests cannot run in the Strategy Tester at all. In the tester this EA skips every network call; the local guardian and the display still work.

### MQL5 VPS

Only one terminal can be linked to your account at a time. Pairing any terminal revokes the previous link. When that happens, the old terminal's chart block shows "link removed"; that is expected, not a fault.

The link key file does not migrate to the MQL5 VPS, and there is no interactive chart there. Each pairing code works exactly once, so the local EA must not consume the code that is meant for the VPS.

If your local terminal is already linked:

1. Get a FRESH pairing code from exitcode.trade and put it in the EA's `PairingCode` input. The local EA ignores the code (it never re-pairs while it holds a key), so the code stays unused.
2. Migrate to the VPS right away, within the code's 15 minutes.
3. The EA on the VPS starts with no key file, sees the code in its migrated inputs, and pairs itself. The moment it does, your local terminal's link is revoked and its chart block shows "link removed". Expected.
4. Confirm via the VPS Journal: the EA prints its pairing state there. Request a VPS screenshot if you want to see the chart block.

If this is a fresh setup with no local link yet, an attached local EA will pair itself with the code within seconds and burn it before the VPS ever sees it. Either migrate to the VPS FIRST and only then enter the code, or keep the EA detached from any local chart until you are ready to migrate, so it cannot consume the single-use code.

Manage links from your exitcode.trade account page.

---

## EXIT CODE Headroom (`ExitCodeHeadroom.mq5`)

EXIT CODE · exitcode.trade · free forever · read-only unless you enable CloseAllAtDailyLimit.

The self-contained EA, built to be safe for the MQL5 Market: no web requests, no DLLs, nothing leaves your terminal. It watches your account against prop-firm loss limits and shows, on the chart: dollars left today, dollars left overall, how many losing trades at your risk percent you can still afford, and a state of OK, WARNING (75 percent of a limit used), or BREACHED. It alerts at WARN and at BREACH.

### Inputs

| Input | Meaning |
|---|---|
| `Preset` | FTMO_1STEP (3 percent daily, 10 percent trailing overall), FTMO_2STEP (5 percent daily, 10 percent static overall), or CUSTOM. |
| `CustomDailyLossPercent` | Daily limit when Preset is CUSTOM. |
| `CustomMaxDrawdownPercent` | Overall limit when Preset is CUSTOM. |
| `AccountSizeOverride` | 0 records the balance on first run as the account size. If you attach the EA after the account has already drawn down, set the real account size here or the limits will be measured from a shrunken base. |
| `RiskPerTradePercent` | Used for the losers-left number. |
| `DayResetServerHourOffset` | 0 means the day resets at midnight on your broker's server clock. Your firm may reset at a different time. FTMO resets at midnight Prague time, which usually lands about 1 hour after server midnight on typical FX servers. If you trade FTMO, set the offset to 1 and confirm the reset time in your FTMO dashboard. |
| `CloseAllAtDailyLimit` | Off by default. When on, closes all open positions at your daily limit. Same local-only rule as the Gates EA. |

Trailing versus static overall limits are implemented per the preset: a trailing floor moves up as your equity makes new highs; a static floor is fixed from the account size. Day-start and high-water marks are stored in terminal global variables so they survive a restart.

The trailing floor in this EA is measured intraday, on every equity high, on purpose. FTMO moves its trailing floor at the end of the day. That makes this EA deliberately stricter: it can show BREACHED before your firm's own count does. When that happens, the EA is early, not wrong; treat it as the earlier warning it is designed to be.

The Headroom EA has no connection to your EXIT CODE account and works without one.

---

## Support notes

- The Gates EA is version 1.11. Verified journal parity (matching closed trades to cleared tickets) is server-side work built on the synced deal data; it needs nothing further from these files.
- Some prop firms require approval before you run any EA, and some restrict which EAs are allowed. Check your firm's rules before attaching either EA to a funded account.
- Nothing in these EAs predicts markets, generates signals, or promises results. They check numbers you chose against numbers on your account.
