# Prime Academy: correctness and robustness audit (candidate 3)

Scope: the current approach as in the brief (paper, `modules/`, notebook sections 24-26, strategy, live runner).
Read-only everywhere except this folder. All Monte Carlo at most 5,000 paths, one process at a time; the notebook, `make_numbers.py` and every broker replay were not run (cached files were read). Scripts are in `scripts/` and each finding cites its script and log.

Labels: **[exec]** verified by running code, **[read]** verified by reading code or text, **[inf]** inferred, **[unv]** unverified.
"Gate" means expected wallet log growth over three years > 0 at 80% honoured, $1,000 wallet, $3,000 tier.
Monte Carlo noise: one 5,000-path gate run has SE 0.008, one 10,000-path run 0.006 (`e05.log`).

## Verdict in six lines

1. The chains are correct. `eval_chain`, `funded_chain`, `funded_line_search`, `plateau`, `wallet_mc`, `hedge.shared_wallet` and `day_split_mc` all reproduce, and `decision.json` reproduces to the last printed digit from the chains alone [exec].
2. The deployed code is not the deployed plan. `run_live.py` trades 4% with no account rules, and the strategy's clip nets commission only, so with a live spread or swap above what it nets, the clipped target lands just short of +9% and can stall there instead of passing [read + exec of my re-implementation].
3. The purchase gate "open at +0.013" is not a result. Across eight seeds it is +0.006 +- 0.0025, and two documented biases (mean-of-stops cost share, lot flooring) each move it by about -0.008 [exec]. The sign is set by choices the paper treats as free: the funded risk, the horizon and what a refusal does.
4. The expected-value view is robust where the log gate is not: at 80% honoured a purchase returns 1.29 x its fee, and every rule reading I tried keeps it above 1.0 [exec]. The step-asides close both views at the measured rate (1.33 a trade); the EV view reopens below 0.75 a trade, the log gate only below 0.02 [exec].
5. The 40-pip pick is within 3% of the deployed stop on the cash rate, which is inside every input I measured; it flips with the stop-rule knob (beta against floor) and with the pace used [exec].
6. Paper text disagrees with the code in six places (listed in section 4); one of them (days to first payout, 46) comes from a 14-trade clock, not the deployed 7.

---

## 1. Findings, ranked

### F1. HIGH, execution: `run_live.py` does not run the plan

- Claim: the live runner trades 4% risk, never calls `set_account`, so there is no target clip, no floor clip, no switch to the funded risk (1.575%), no payout clock and no stage tracking. The plan says 3% then 1.575% with clipped legs.
- Evidence [read]: `src/strategies/prime_academy_strategy/run_live.py:74` `FROZEN = dict(risk=0.04, ...)`, `:273-277` builds the strategy from it; `grep set_account run_live.py` returns nothing (the only caller in the repo is `modules/broker_map.py:63`; `test_prime_academy_strategy.py` never calls it either, so the account mode has no unit test). `acceptance.py:53` and the README also pin 4%. The unit is in the soak state: `/etc/prime-academy.env` has `PRIME_WINDOW=0-0`, `PRIME_SIDE=coin`, service active (read with `grep` of those keys only), so nothing trades today.
- Size [exec, `e08.log`]: at 4% the strict daily-loss reading (F6) fires on 3.3% of trades (6.5% of stop-outs) against 0.76% at 3%. At 4% the 35% rule (3.15%) is also broken if it applies in the assessment.
- Changes: the "deployed" trade, not a model number. Fix: read assessment risk, funded risk, stage and clip from config; call `set_account(STAGE_EVAL, 0.03, 0.01575 ...)` with a stage switch after a pass; gate the soak on an acceptance run at 3%.

### F2. HIGH, execution: the clip nets commission only, so with any spread or swap the clipped target stalls below +9%

- Claim: `PrimeAcademyStrategy` shortens the target to `((target - eq) * B + fee) / per_px` with `fee = cost_per_lot * lots` (`prime_academy_strategy.py:722-733`), and `broker_map.py:63` passes `cost_per_lot = 2 * commission_per_side = $5`. The model (`prime._legs`, cost C) nets commission plus spread (plus the swap mean). The replay broker charges no spread and no swap, so the parity checks cannot see the gap.
- Mechanism [read + exec]: if the true cost per trade exceeds the netted cost by d, a clipped win lands at T - d, and the next clipped win aims at (T - eq) + fee = d + fee and again nets exactly zero. Equity sits at T - d until a 3% stop-out. Only the tick round-up (at most one tick) can help.
- Evidence [exec, `e19.log`, my re-implementation of the clip rule on the tick lattice, 5,000 paths]: model (clip nets full cost) passes 45.3%; clip nets commission only with a 0.5-pip spread, 0.0% pass (6.7% of accounts still alive and stalled after 400 trades); clip nets the full cost but the true spread is 0.1 pip wider, 0.0% pass; true spread 0.1 pip narrower, 45.8%.
- Changes: the assessment pass rate in deployment, from 44.6% to near zero in the failure case. Not a change to the modelled numbers. The effect is a cliff, not a slope.
- Fix: put the quote's spread (read at entry) and a swap allowance into `cost_per_lot`, and aim T plus a margin of a few ticks. Settle by one demo-account assessment trade: compare the realised equity after a clipped win with T (the soak account already exists).
- Label: mechanism [read], size [exec on a re-implementation, not on the engine]. An engine run with a spread-charging broker is not available here [unv].

### F3. HIGH, decision: the purchase gate's "+0.013" is inside noise and below the size of known biases

The deployed row reads `g_80 = +0.0132` (`decision.json`, 10,000 paths, one seed). What it is made of [exec]:

| item | evidence | effect on gate |
|---|---|---|
| Monte Carlo noise | `e05.log` a: 8 seeds x 5,000: +0.0057, +0.0050, +0.0145, -0.0024, -0.0039, +0.0039, +0.0165, +0.0092; mean +0.0061, sd 0.0072 (SE of mean 0.0025, t = 2.4). `e11.log`: stop 34.8, six more seeds, mean +0.0102, sd 0.0071 | one run is +-0.006 to 0.008 |
| Cost share taken at the mean stop | `e07.log`: mean of per-trade (commission + spread)/stop is 2.964% against 2.874% at the mean stop (+3.1%, Jensen), swap per-trade 0.476%; total 3.440% against the gate's 3.353% | -0.009 (`e14.log`, 3 seeds: -0.0033 against +0.0058) |
| Lot flooring | `e14.log`: nominal 3% realises 2.968% on the walker's stops, nominal 1.575% realises 1.504% (-4.5%); chain cash/fee 1.612 to 1.595 | -0.008 (`e14.log`: -0.0024) |
| Both | `e14.log` | -0.0113 (negative in all three seeds) |
| Funded risk chosen by p_any, not by the wallet's growth | `e21.log`: g at 1.45% -0.010, 1.575% +0.006, 1.7% +0.016, 1.85% +0.025, 2.0% +0.030, 2.3% +0.034 (CRN, 3 seeds); p_any 0.536, 0.529, 0.517, 0.498, 0.480, 0.448 | +0.019 available at 1.85% (p_any still 49.8%) |
| Horizon | `e05.log` e: -0.037 at 0.83 y, -0.007 at 1.9 y, +0.004 at 2.5 y, +0.007 at 3 y, +0.019 at 3.9 y; zero near 2.2 y | the gate is a statement about a horizon |
| Terminal valuation | `e06.log`: mean final wallet $1,133 (gain $133) against 3 x G1 = $195; the account open at day 541 is worth $0 in the sim | conservative by about $60, about 0.05 in log |
| Strict daily rule (F6) | `e10.log` | -0.002 at q = 0.0056 per stop-out, -0.034 at q = 0.015 |

- Changes: the gate (open at +0.013) to "indeterminate, negative with the two corrections". The underlying expected-value margin does not move this much (section 3, F7).
- Fix: (a) report the gate as a mean with an SE from at least 40,000 paths; (b) compute the cost share as the mean of per-trade shares (`mean(1/stop)`), not 1/mean(stop); (c) set the nominal funded risk so the realised risk after the lot floor equals the chain's (nominal about 1.65% for 1.575% realised); (d) choose the funded risk to maximise the wallet's growth subject to p_any >= 50%, not the p_any plateau; (e) state the horizon and the terminal convention beside the number, or gate on the EV breakeven.

### F4. MEDIUM-HIGH, decision: what a refused payout does decides whether 80% honoured is a pass or a fail

- Claim: `wallet_mc` applies `p_paid` per request independently, and on a refusal still zeroes equity and restarts the clock (`prime.py:679-686`: `eq = np.where(can, 0.0, eq)`). The paper states this ("a refused request withdraws the equity and pays nothing", Prop. rate proof). No source supports it.
- Evidence [exec, `e06.log`, same seed, `refusal="reset"` reproduces `wallet_mc` exactly: +0.0070]: reset (as coded) g_80 = +0.007, flips at honour 0.787 (`e05.log` b: 0.80 +0.0070, 0.75 -0.0464); refusal leaves equity in place and the request repeats: g_80 = +0.188, no flip at any honour; refusal closes the account: g_80 = -0.176, flips at about 0.89 (0.9: +0.023, 0.8: -0.176). Firm-level honour (the firm pays always with probability 0.8, never otherwise): 0.8 x 0.195 + 0.2 x (-1.575) = -0.16, with no stop-buying rule.
- Changes: the gate. Fix: measure it (it is the firm's behaviour), or state the gate for each reading.

### F5. MEDIUM, decision: the 40-pip pick is smaller than the error in its inputs

Front, one account, swap charged (`front.json`): stop 34.8 has G = $65.2 a year and T = 148 days (fastest), stop 40 has G = $68.0 and T = 157 (richest), stop 45 has G = $65.2, T = 175, D = $304.

- G1 recomputed with the chains (`e12.log`):

| cell | cost share | pace | wait | G1 $/yr |
|---|---|---|---|---|
| 34.8, paper inputs | 3.353% | 2.025 | 7 | 65.16 |
| 40, paper inputs | 3.050% | 2.282 | 6 | 68.03 |
| 34.8, walker inputs (per-trade shares, my pace) | 3.440% | 2.108 | 7 | 60.02 |
| 40, beta knob (0.924 sigma, floor 30), walker inputs | 3.257% | 2.348 | 6 | 58.57 |
| 40, floor knob (0.75 sigma, floor 38.3), walker inputs | 3.124% | 2.440 | 6 | 61.70 |

  The 40-pip lead is +2.9 (+4.4%) on paper inputs, -1.4 on the beta knob and +1.7 on the floor knob like for like. It flips if the 40-pip cost share is more than 0.08 pp above 3.05% (36 $/yr per pp from `e12`), or its pace more than 4.5% slower than 2.28; the cost-share route is the one my measurements reach (beta knob +0.21 pp), the pace route is not.
- "The two knobs give the same cell" (paper, "From a mean stop to the rule") is false in my walker [exec, `e07.log`]: the beta knob has mean stop 39.4, Jensen +6.0%, pace 2.348, nights 0.995; the floor knob mean stop 40.2, Jensen +0.9%, pace 2.440, nights 1.085.
- Swap scales faster than the paper's "proportional to the stop": share ratio 1.21 for a stop ratio 1.13 (exponent about 1.5), so the swap cost at 40 pips is understated by about 0.06 pp [exec, `e07.log`].
- Pace mapping (Wald a x b, `l = sqrt(RR) l0`): holds within 3% on unclipped brackets (`e18.log`: pace(RR=2) 3.024 against pace(1, stops x sqrt 2) 3.119). The broker pace used is a mean over assessment cells at risks 1% to 4.5% with the target clipped, and it falls behind my unclipped walker as RR rises: broker 2.025 / 2.414 / 2.764 / 3.508 at RR 1 / 1.5 / 2 / 3 against walker 2.108 / 2.572 / 3.024 / 4.058. Removing the walker's own 4% offset at RR 1, the broker is faster by 2% / 5% / 11% at RR 1.5 / 2 / 3, so the pace at 40 pips (RR 1.32 equivalent) is understated by about 1% to 3% [exec for the walker; that the clip causes it is [inf]]. My walker's direct 40-pip paces are 2.35 (beta knob) and 2.44 (floor knob) against the paper's 2.28; the walker's own offset accounts for 4 points of that.
- The wait rounding contributes: `round(14/pace)` is 7 at 34.8 and 6 at 40; with wait 6 against 7 the gate gains +0.0035 (`e05.log` d) of the +0.029 lead in log growth; the rest is the cost-share scaling (`e11.log`: 40 pips +0.039, 34.8 +0.010).
- D is an atom, so its "SE" is zero and the dominance test is spurious: p90 of the year-one drawdown is a multiple of the $38 fee (342 = 9 fees, 304 = 8 fees). The share of paths at or above $342 is 14.1% at 34.8, 10.6% at 40, 8.0% at 45 [exec, `e11.log`]; the 40-pip cell sits 0.6 pp from dropping to $304. 45 pips is on the front only because of that atom.
- Changes: the pick between 34.8 and 40 (the front is a menu, both are on it). Fix: compute D as a mean of the drawdown or a smoothed quantile; carry pace and cost-share intervals into G and T; compare cells like for like.

### F6. MEDIUM, rule reading: the strict daily-loss rule fires on 0.76% of assessment trades at 3%

- Claim: `rules.json` says the daily limit is "5% of the previous day's equity" and "equity based, so unrealised counts". A trade up f stop-distances at the last 21:00 UTC rollover and then stopped out loses (1+f) r + c from that equity; at r = 3% that breaches 5% when f > 0.63. The paper treats this as a pending measurement (answer item 3) and later says "the daily loss limit never fires at one trade of 3% risk" (`prime_academy.tex:1551`).
- Evidence [exec, `e08.log`, my walker on 4,610 trades of real hourly EURUSD, deployed stop rule, 10 seeds]: 39% of trades cross a rollover; breaches per trade: 3% nominal 0.76% (1.50% of stop-outs), 2.97% lot-floored 0.28% (0.56%), 3.15% 1.26%, 4% 3.28%, 1.575% funded 0. Open profit at the last rollover: 90th percentile 0.62 of the stop, 95th 0.73.
- Effect [exec]: assessment pass 44.6% to 42.7% (q = 0.015) or 43.7% (q = 0.0056 at the floored risk) (`e09.log`); gate -0.002 to -0.034 (`e10.log`). Flips the gate at q about 0.004.
- Fix: measure on the demo account (equity snapshot at the rollover against the next day's low) or ask the firm; if strict, an assessment risk near 2.5% takes the breach threshold to f > 0.97 stop-distances and costs little pass rate (the vault entry of 2026-09-27 has the clipped pass rate flat in risk, 45.9% at 2% to 47.8% at 4%) [inf].
- Caveat: rollover fixed at 21:00 UTC (22:00 in winter) and the bar close at 20:00-21:00 stands for the day's equity [inf].

### F7. MEDIUM, interpretation: the expected-value margin is large and robust; the log gate is a thin proxy for it

- At the deployed cell cash per purchase is 1.612 x the fee, so at 80% honoured the purchase returns 1.29 fees; the breakeven honour is 62% (`e01.log`, `e15.log`).
- Under every rule reading tried, cash/fee stays at or above 1.43 (`e20.log`): floor not on the tick 1.84, target not clipped 1.43, 35% rule read on the net request 1.49, 35% rule absent in the funded stage 1.72, $100 minimum read before the split 1.52, payout clock from assessment opening 1.66, 14-trade clock 1.58, assessment 4% 1.64. The log gate needs about 1.606 (`e15.log`: flips at cost share 3.41% where cash/fee = 1.606), i.e. 0.4% below the deployed 1.612; four of the eight readings put cash/fee below it.
- So: "buy" is robust under the EV criterion down to honour 62% to 70%, and not under the log gate as defined. Fix: gate on breakeven honour with a stated margin, plus a ruin cap; keep the log growth as a report.

### F8. MEDIUM, paper vs code: three headline durations come from a 14-trade clock

- `decdaysfirstpay` = 46 days and `decdayslife` = 123 days are read from `broker_map.json` grids `DF` and `DL` at funded risk 1.5% (`make_numbers.py:980-983`). The broker replay passes `PAY_WAIT = 14` into `set_account` (`broker_map.py:34,63-64`), and the strategy counts that in trades (`since_pay >= pay_wait`, `prime_academy_strategy.py:338`), so the replay ran a 14-trade clock, about 28 days. The deployed clock is 7 trades (`decision.json`). The answer table sits beside p_any = 52.9% (the 7-trade chain).
- Chain at the deployed clock [exec, `e04.log`, `e01.log`]: median first payout 14 trades = 28 days at 2.03 d; mean life 46.6 trades = 95 days. The table says 46 and 123. The vault entry of 2026-10-01 records that the map still uses 14 trades; the answer table does not say so.
- Also: the broker "first payout" clock includes the idle days between accounts (account open time is the previous death), which the chain's trades do not.

### F9. LOW-MEDIUM, paper text that the code or the plan contradicts [read]

| paper | where | contradiction |
|---|---|---|
| "The target is not clipped ... It is not implemented. The strategy is deliberately blind to the firm's account rules" | tex:1548 | the plan table, abstract and `set_account` clip it |
| "It fixes the stop at one daily sigma, the risk at the daily-loss maximum" | abstract, tex:29 | stop is max(0.75 sigma, 30), risk 3% (35% cap) |
| "The daily loss limit never fires at one trade of risk" | tex:1551 | strict reading (F6) fires on 0.76% |
| "trade ... once a day", "one trade a day" | abstract, plan table | pace is 2.03 calendar days a trade (hold 1.0 d plus the next entry day) |
| "The horizon is 500 trading days" | tex:477 | the gate runs 541 trades; sections 6 and 25 use different horizons |
| "the fourteen-trade clock" in the funded cycle | tex:1146 | deployed clock is 7 trades |

### F10. LOW, accounts at once (N)

- `spread.family` passes the same `seed` to every account's `wallet_mc`; with `coins` supplied the rng draws only the honour uniform, so all accounts in a pool share each day's refusal draw (`spread.py:75-83`, `prime.py:679`). Effect [exec, `e16.log`, N = 2, commission-and-spread, 40 pips, two copula seeds]: ruin 3.50% / 3.48% against 3.42% / 3.40% with independent honour, log growth lower by 0.004 to 0.006. Conservative and small.
- The correlation used for every stop is the outcome correlation 0.26 measured at a 30-pip stop (paper: 0.57 at 60 pips); at 34.8 to 45 pips it is higher, so N >= 2 is optimistic [read]. Under the swap scenario every N = 2 cell fails already; N = 2 at 45 pips fails by -0.013 in log growth (SE 0.0097), which a funded risk of 1.85% (+0.02) could overturn [inf].

### F11. LOW

- `rules.json` has no entry for the $300,000 allocation cap, the news rule or the EA ban although the paper cites it for them (`spread.py:27` hard-codes 300,000) [read]. I did not check the firm's documents (no web).
- The funded pick sits at the edge of its plateau: p_any at 1.575% is 0.52885 against a threshold of 0.52860 (best 0.53860 minus 0.01) [exec, `e01.log`, `e04.log`]. The plateau rule trades a point of p_any for earlier first payout; cash/fee still rises with r through the kink (1.612 at 1.575%, 1.637 at 1.7%).
- The clip uses the strategy's `FLOOR_TOL = 5e-4` (0.05% of the bankroll, $1.5): equity within it of the floor is declared dead; the chain has no such margin. Negligible (tiny, conservative) [read].
- Swap nights are counted at a 21:00 UTC rollover all year (`broker_map.py:291`); the winter rollover is 22:00. My walker reproduces 0.729 nights a trade against the broker's 0.743 and 60.7% none against 60.4% [exec, `e07.log`] so any error is small [inf].
- The assessment strategy re-sizes lots from the 0.01 grid and clips with the lot-floored lots; consistent with the model at the effective risk (F3).

---

## 2. What checked out

| item | how | result |
|---|---|---|
| `decision.json` from the chains | `e01_reproduce_decision.py`: four scenarios, assessment, line search, pick, cash/fee | identical to 4-5 digits (pass 0.44605, any 0.52885, pick 1.575%, cash/fee 1.6121, plateau 1.15% to 1.575%) |
| `eval_chain` | `e02`: independent dict DP on the same lattice; independent float MC (5,000) | pass 0.44605379 = 0.44605379; E[trades] 9.65369 = 9.65369; MC 0.4468 +- 0.0070 |
| `funded_chain` | `e02`: independent DP (own clock, M, payout, renewal) | p_any 0.52884604, E[W] 0.065401, median 14: all equal |
| `wallet_mc` against the chains | `e03`: deep wallet, 1,000 paths x 3,000 trades | cash per purchase $60.35 against chain $61.26 (the gap is the account open at the horizon, about 1%); payouts per purchase 0.492 against 0.501; mean payout $122.7 against $122.4 |
| refusal handling | `e06`: copy of `wallet_mc` with a switch | `reset` reproduces `wallet_mc` exactly (+0.0070158) |
| clip landings in float | `e01`-adjacent `t01_float_edge.py`: 5,000 paths | 0 of 4,999 designed landings missed by rounding |
| 14 days to 7 trades | `e13`: for every walker trade, the index of the first exit at least 14 days later | mean 7.28, median 7, 55% at or below 7; mixture of chains over the empirical distribution p_any 0.5293 against 0.5288; wallet g 0.0040 against 0.0058 (noise) |
| `p_any` against the clock | `e04`: wait 5 to 14 | parity pairs (5=6, 7=8, 9=10); 0.5346 / 0.5288 / 0.5220 / 0.5067 at 5-6 / 7-8 / 9-10 / 14; cash/fee 1.619 / 1.612 / 1.603 / 1.578 |
| `day_split_mc` | `e17`: against an independent per-day DP and the exact chain | k=1 0.4292 +- 0.0070 against 0.4239; k=2,3 within 1 SE |
| mean stop 34.79 pips, nights, hold | `e07`: my walker (KF sigma, rule, bar walk) | mean stop 34.79 (exact), nights 0.729 against 0.743, none 60.7% against 60.4%, pace 2.108 against 2.025 |
| Wald pace mapping on unclipped trades | `e18` | within 3% (see F5 for the clipped broker pace) |
| 35% cap read gross, assessment 3% | arithmetic, `e20` | 0.35 x 9% = 3.15%; 3% against 3.15% moves pass 0.4461 to 0.4484 |
| floor on the tick is the pessimistic reading | `e20` | not enforced on the tick: pass 0.468, cash/fee 1.84 |
| `shared_wallet`, `flows`, `gate` | read | ruin, first-cash day, drawdown floored at the opening wallet are consistent (`T = (first_cash + 1) x pace` is right) |
| news aside rate | `news_battery.json` | 555 asides over 416 closed trades = 1.334; the cohort is all-currency and 4% at $50,000 |

---

## 3. Robustness table

Cells give the value of the input at which the decision flips, or the change it causes where there is no flip in a plausible range. Baseline = random side, swap charged, assessment 3%, funded 1.575%, wait 7, $1,000 wallet, 80% honoured. "Gate" = log growth > 0. "EV" = 0.8 x cash/fee > 1. "-" means no flip in the range tried. Sources in brackets.

| input (baseline) | Gate (log growth > 0) | EV (cash per fee x 0.8 > 1) | funded pick (1.575%) | 40-pip pick / N = 1 |
|---|---|---|---|---|
| live spread (0.5 pip) | flips at 0.52 pip (cost share 3.415%) [`e05` c] | flips at about 1.26 pip (cash/fee 1.25) [`e15`] | 1.55% at 0.5 to 1.70% at 1.0 pip [`e15`] | the commission+spread share is 1/l: a wider spread favours 40 over 34.8 [read] |
| swap debit, random side (-$2.24 a lot a night, 0.743 nights) | flips if the share rises 0.06 pp: -$2.53 a lot a night or 0.84 nights [`e05` c] | flips at about 6x [`e15`] | - | swap share scales about l^1.5, not l: 40 pips loses 0.06 pp [`e07`] |
| step-aside rate (0 in the swap row, 1.33 measured, all currency) | flips at 0.02 a trade [`e05` c, `e15`] | flips at 0.76 a trade [`e15`] | 1.6% at 0.1 to 1.7% at 0.7 | the gate is closed at every stop at 1.33 (`front.json`) |
| honour rate, refusal resets equity (0.80) | flips at 0.787 [`e05` b] | breakeven 0.62 [`e01`] | - | - |
| honour rate, refusal closes the account | flips at about 0.89 [`e06`] | - | - | - |
| honour rate, refusal leaves equity | never flips (g_80 +0.188) [`e06`] | - | - | - |
| honour as a firm-level trait (no exit rule) | -0.16 at 0.8 [`e05` b, derived] | - | - | - |
| strict daily-loss rule (not applied) | flips at q = 0.004 per stop-out; measured 0.006 to 0.015 [`e08`, `e10`] | pass -4%: cash/fee 1.55, still above 1.25 [`e09`] | none (funded breach impossible at 1.575%) | assessment 4% (`run_live`): breach 3.3% a trade |
| 35% rule read on the net request | cash/fee 1.485: closes [`e20`] | holds (1.485) | 1.2% | - |
| 35% rule absent in the funded stage | cash/fee 1.722: opens by margin [`e20`] | holds | 2.1% | - |
| 35% rule absent in the assessment | cash/fee 1.644 at 4%: opens [`e20`] | holds | - | assessment 4%: +1.0 pt pass |
| floor not enforced on the tick | cash/fee 1.837: opens by margin [`e20`] | holds | 1.65% | - |
| payout clock, trades (7) | flips at about 8.2 trades, i.e. pace below about 1.7 d [`e05` d]; 14 trades -0.032 | 14 trades 1.583: holds | clock from assessment opening (wait 1): 1.70%; wait 5 to 9 leaves it at 1.575% [`e04`] | wait rounding 7 to 6 at 40 pips: +0.0035 of the gate lead |
| $100 minimum read before the split | cash/fee 1.516: closes [`e20`] | holds | 1.15% | - |
| cost share, Jensen (3.353% to 3.440%) | closes (-0.009) [`e14`] | holds | - | 40-pip beta knob Jensen +6.0% against +3.1%: the lead flips (F5) |
| lot flooring (realised funded risk 1.504%) | closes (-0.008) [`e14`] | holds (cash/fee 1.595) | nominal about 1.65% realises 1.575% | - |
| funded risk (1.575% nominal) | flips below about 1.53%; +0.025 at 1.85%, +0.034 at 2.3% [`e21`] | cash/fee 1.566 at 1.4%, 1.637 at 1.7% [`e04`] | the pick is the p_any plateau edge, not the growth optimum | N = 2 at 45 pips (-0.013) could turn feasible [inf] |
| horizon (3 years, 541 trades) | flips at about 2.2 years [`e05` e] | - | - | - |
| Monte Carlo noise (10,000 paths) | SE 0.006 per run; 8-seed mean +0.0061 +- 0.0025 [`e05` a] | exact | exact | T SE 1.5 to 2.4 days; D atom-valued |
| pace (2.025 d a trade) | G and T scale 1/pace; `round(14/pace)` flips 7 to 6 at pace 2.15 and 6 to 5 at 2.55 | - | - | the lead of 40 over 34.8 (+4.4%) flips at pace +4.5% or cost share +0.08 pp [`e12`]; measured: pace +1% to +3%, cost share +0.07 pp (floor knob) to +0.21 pp (beta knob) [`e07`, `e12`] |
| stop-rule knob at 40 pips | - | - | - | beta knob: G 58.6 against 60.0 (34.8); floor knob: 61.7 [`e12`] |
| account correlation (0.26 outcome, 30-pip) | - | - | - | N = 2 more infeasible as it rises; honour artifact conservative (+0.004) [`e16`] |
| clip nets commission only (live spread > 0) | assessment pass 45.3% to 0.0% for any shortfall of 0.1 pip or more [`e19`] | EV negative if the account cannot pass | - | all |

---

## 4. Rules encoding, point by point

| rule (`rules.json`) | chain / wallet | strategy | note |
|---|---|---|---|
| floor on the tick, static 9%, full open cost | `_legs`: `b = min(R, st + D - C)`, C full at open [read] | stop clipped to `((eq + floor) * B - fee) / per_px`, fee = commission only | model conservative; strategy short by the spread (F2) |
| target 9%, clip lands on T net of cost | `a = min(RR r, T - st + C)` [read]; no float misses [exec] | `cap = ((target - eq) B + fee) / per_px`, rounded up a tick | stall below T under live costs (F2) |
| 5% daily, previous day's equity | not applied in chains (loss <= r + c < 5%); wallet applies `(prev - eq) > 5% (1 + prev)` to closed trades | `_score_account`, closed trades | strict reading not modelled (F6) |
| 35% rule gross | funded: `max(m1, RR r / 0.35)`; assessment: risk <= 3.15% | `big_win` is the net trade, so slightly more lenient than gross | assessment application unverified (paper says so) |
| 14-day payout clock | 7 trades, from funding or last payout, deterministic | `pay_wait` counts trades; broker map ran 14 | F8; conversion robust (e13) |
| $100 minimum after the split | `m1 = 100 / (0.7 B) = 4.76%` | `pay_min` the same | - |
| 3 trading days | counted in trades, never binds | trades | - |
| $300,000 allocation | `k_cap = min(12, 100)` | - | not in `rules.json` |
| 30 idle days | not modelled | - | slack at one trade per 2 days |

## 5. Scripts and logs

All in `scripts/` (`.py` with its `.log` beside): `pa_imp.py` (imports the repo's modules read-only), `walker.py` (my light re-implementation of the strategy's bracket on `eurusd_1h.parquet`), `wallet_variants.py` (a copy of `wallet_mc` with switches: refusal, strict-daily kill, random clock), `t01` float landing, `e01` reproduction, `e02` independent DP and MC, `e03` wallet against chain, `e04` clock and risk grid, `e05` gate noise and flips, `e06` refusal variants, `e07` walker inputs, `e08`/`e09`/`e10` strict daily rule, `e11` front noise, `e12` pick flip, `e13` clock, `e14` lots and combined, `e15` EV thresholds, `e16` honour correlation, `e17` day split, `e18` pace mapping, `e19` clip stall, `e20` rule readings, `e21` funded-risk sweep. `nb_24.txt` and `nb_25_26.txt` are my text extracts of notebook cells.

Unverified (could not be settled here): the firm's reading of the daily rule, the 35% rule in the assessment, the payout-clock origin, the live spread, whether the venue's equity treats a clipped win as I modelled (F2), the step-aside rate on a EUR+USD calendar, and any engine-level (not re-implemented) behaviour of the strategy with a spread-charging broker.
