create-tradejs 3.1.22 → 3.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +19 -3
  2. package/dist/index.js +36 -5
  3. package/dist/skill-bundle/.codex/skills/ai-train-local-research/SKILL.md +596 -0
  4. package/dist/skill-bundle/.codex/skills/ai-train-local-research/references/gate-ablation.md +324 -0
  5. package/dist/skill-bundle/.codex/skills/ai-train-local-research/references/reporting.md +227 -0
  6. package/dist/skill-bundle/.codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs +5082 -0
  7. package/dist/skill-bundle/.codex/skills/ai-train-local-research/scripts/ai-gate-ablation.test.mjs +1170 -0
  8. package/dist/skill-bundle/.codex/skills/backtest-config-redis/SKILL.md +17 -0
  9. package/dist/skill-bundle/.codex/skills/backtest-config-redis/scripts/get_backtest_config.sh +21 -0
  10. package/dist/skill-bundle/.codex/skills/runtime-parity-mismatch-analysis/SKILL.md +146 -0
  11. package/dist/skill-bundle/.codex/skills/save-strategy-config-from-backtest/SKILL.md +58 -0
  12. package/dist/skill-bundle/.codex/skills/save-strategy-config-from-backtest/agents/openai.yaml +4 -0
  13. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/SKILL.md +334 -0
  14. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/references/research-notes.md +247 -0
  15. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/backtest-run-metrics.mjs +647 -0
  16. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/backtest-run-metrics.test.mjs +321 -0
  17. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/fast-ai-export-metrics.mjs +744 -0
  18. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/fast-ai-export-metrics.test.mjs +553 -0
  19. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/research-notes-check.mjs +125 -0
  20. package/dist/skill-bundle/.codex/skills/strategy-improvement-research/SKILL.md +18 -1
  21. package/dist/skill-bundle/.codex/skills/strategy-release/SKILL.md +22 -0
  22. package/dist/skill-bundle/.codex/skills/strategy-release/agents/openai.yaml +4 -0
  23. package/dist/skill-bundle/.codex/skills/strategy-release/references/diagnose-live.md +126 -0
  24. package/dist/skill-bundle/.codex/skills/strategy-release/references/direction-policy.md +141 -0
  25. package/dist/skill-bundle/.codex/skills/strategy-release/references/directional-parameter-split.md +93 -0
  26. package/dist/skill-bundle/.codex/skills/strategy-release/references/evidence-limitations.md +76 -0
  27. package/dist/skill-bundle/.codex/skills/strategy-release/references/evidence-retention.md +157 -0
  28. package/dist/skill-bundle/.codex/skills/strategy-release/references/historical-hypothesis-audit.md +163 -0
  29. package/dist/skill-bundle/.codex/skills/strategy-release/references/professional-research-loop.md +198 -0
  30. package/dist/skill-bundle/.codex/skills/strategy-release/references/release-workflow.md +755 -0
  31. package/dist/skill-bundle/.codex/skills/strategy-release/references/research-objective.md +255 -0
  32. package/dist/skill-bundle/.codex/skills/strategy-release/references/verdict-contract.md +200 -0
  33. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/direction-policy-checkpoint.mjs +137 -0
  34. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/direction-policy-checkpoint.test.mjs +85 -0
  35. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/directional-parameter-checkpoint.mjs +149 -0
  36. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/directional-parameter-checkpoint.test.mjs +120 -0
  37. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/release-progress-checkpoint.mjs +621 -0
  38. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/release-progress-checkpoint.test.mjs +349 -0
  39. package/dist/skill-bundle/.codex/tradejs-skill-bundle.json +44 -3
  40. package/package.json +1 -1
@@ -0,0 +1,324 @@
1
+ # AI Gate Ablation Tool
2
+
3
+ Use `scripts/ai-gate-ablation.mjs` for repeatable deterministic gate hypothesis
4
+ checks. It streams every shard in a merged export, reconstructs the current AI
5
+ payload and local gate, and evaluates causal feature expressions without using
6
+ trade outcome fields as inputs.
7
+
8
+ ## Prerequisite
9
+
10
+ Keep three roots explicit:
11
+
12
+ - `PROJECT_CWD` owns datasets and reports.
13
+ - `TRADEJS_SOURCE_REPOSITORY_ROOT` is the exact Git checkout that owns the
14
+ researched lineage: either the TradeJS framework or one standalone strategy.
15
+ - `TRADEJS_FRAMEWORK_REPOSITORY_ROOT` supplies the built `@tradejs/node` and
16
+ `@tradejs/cli` research runtime. It is optional only when the source root is
17
+ itself the framework checkout.
18
+
19
+ After adapter or gate changes, build the owning standalone strategy in its
20
+ source checkout. Build framework packages only in the framework checkout when
21
+ their sources changed:
22
+
23
+ ```bash
24
+ cd "$TRADEJS_SOURCE_REPOSITORY_ROOT" && yarn build
25
+ cd "$TRADEJS_FRAMEWORK_REPOSITORY_ROOT" && \
26
+ yarn workspace @tradejs/node build && \
27
+ yarn workspace @tradejs/cli build
28
+ ```
29
+
30
+ The ablation tool imports `strategyEntries` from the standalone strategy build
31
+ when the source root is a strategy. It never substitutes the Project's
32
+ published strategy package for that source lineage. `--list` is inventory-only
33
+ and does not require either source root.
34
+
35
+ `yarn ai-train --localOnly --json -n 0` remains the baseline authority. Before
36
+ interpreting a candidate, compare the tool's baseline qN+ support, PnL, PF,
37
+ max drawdown, strict loss, and loss streak with the matching `ai-train` run.
38
+
39
+ ## Dataset Discovery
40
+
41
+ List all merged groups or only one strategy:
42
+
43
+ ```bash
44
+ node .codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs --list
45
+ node .codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs --list --strategy LiquidityTails
46
+ ```
47
+
48
+ `--strategy` selects the latest matching merge. `--file` accepts any shard and
49
+ automatically resolves all sibling shards with the same strategy token and
50
+ merge id.
51
+
52
+ ## Variants
53
+
54
+ Pass each hypothesis as:
55
+
56
+ ```text
57
+ name::mode[@quality][LONG|SHORT]::expression
58
+ ```
59
+
60
+ Modes:
61
+
62
+ - `filter`: keep current qN+ approvals that match the expression.
63
+ - `exclude`: keep current qN+ approvals that do not match the expression.
64
+ - `add`: keep baseline approvals and add matching rejected rows at the optional
65
+ assigned quality.
66
+ - `replace`: ignore the current gate and approve only matching rows at the
67
+ optional assigned quality.
68
+
69
+ Append `[LONG]` or `[SHORT]` to scope a variant to one direction. Rows from the
70
+ other direction retain the current gate decision. Use this for release
71
+ side-rescue studies instead of encoding direction through an unrelated feature.
72
+ Use the literal expression `true` for an explicit direction-scoped pass-through.
73
+ For a single replacement policy with different rules per side, use the causal
74
+ metadata feature `derived.direction` in the expression.
75
+
76
+ When `@quality` is omitted, `add` and `replace` use `--minQuality`.
77
+
78
+ Example:
79
+
80
+ ```bash
81
+ node .codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs \
82
+ --file data/ai/export/ai-dataset-liquiditytails-merged-1784296244106-part1.jsonl \
83
+ --variant 'near-ma-and-zone::filter::additionalIndicators.baseContext.regime.trend.priceDistanceToMaSlowAtr <= 1.2 && additionalIndicators.baseContext.structure.liquidityZones.activeCount >= 1' \
84
+ --featurePattern 'priceDistanceToMaSlowAtr|liquidityZones.activeCount' \
85
+ --validationSplit 0.2 \
86
+ --testSplit 0.2 \
87
+ --output data/ai/output/liquiditytails-near-ma-and-zone.md
88
+ ```
89
+
90
+ Direction-aware repair example:
91
+
92
+ ```text
93
+ short-rescue::add@4[SHORT]::additionalIndicators.baseContext.structure.zones.resistance.ageBars <= 42
94
+ short-pass-through::add@4[SHORT]::true
95
+ direction-aware::replace@4::(derived.direction == LONG && derived.stopDistanceBps <= 465) || (derived.direction == SHORT && structure.pivots.barsSinceSwingHigh <= 47)
96
+ ```
97
+
98
+ Repeat `--variant` to compare several rules in one dataset pass. For a reusable
99
+ set, pass `--spec path/to/variants.json`:
100
+
101
+ ```json
102
+ {
103
+ "variants": [
104
+ {
105
+ "name": "body-065",
106
+ "mode": "filter",
107
+ "expression": "additionalIndicators.baseContext.regime.momentum.bodyStrength >= 0.65"
108
+ },
109
+ {
110
+ "name": "q3-recovery",
111
+ "mode": "add",
112
+ "quality": 4,
113
+ "expression": "additionalIndicators.liquidityTailsContext.oldP2CorrelationDirection == LONG"
114
+ }
115
+ ]
116
+ }
117
+ ```
118
+
119
+ ## Expression Grammar
120
+
121
+ Expressions support parentheses, `&&`, `||`, and comparisons:
122
+
123
+ ```text
124
+ <= >= < > == !=
125
+ ```
126
+
127
+ Values can be numbers, booleans, `null`, quoted strings, or unquoted enum-like
128
+ strings such as `LONG`, `high`, and `aligned`. Missing features never match a
129
+ predicate, including `!=`; test availability separately through the feature
130
+ inventory instead of treating missing data as approval evidence.
131
+
132
+ The shared pocket feature collector also exposes causal signal-risk distances
133
+ computed from the requested signal prices:
134
+
135
+ - `derived.stopDistanceBps`
136
+ - `derived.takeProfitDistanceBps`
137
+
138
+ Both are absolute distances from `signal.prices.currentPrice` in basis points.
139
+ They describe the signal-time order plan and do not use execution or outcome
140
+ fields.
141
+
142
+ Use `--featurePattern '<regex>'` to print matching causal paths, availability,
143
+ ranges, and categories. Do not use `--includeGateContext` for discovery; it is
144
+ only for auditing current gate output fields.
145
+
146
+ For direction-specific discovery, use `yarn ai-pocket-search --direction LONG`
147
+ or `--direction SHORT`. For release evidence reserve an untouched chronological
148
+ tail with `--testSplit ... --sealTest`; the search ranks pockets using only the
149
+ preceding train and validation rows and reports only the sealed test bounds.
150
+ Plain `--testSplit` exposes test metrics and cannot be called untouched after
151
+ the report is read. Open the sealed tail once with the frozen fixed-rule
152
+ ablation.
153
+
154
+ ## Cross-Strategy Feasibility
155
+
156
+ Use `--crossStrategy` to test whether the latest merged export for every
157
+ available strategy contains shared LONG or SHORT approval/block pockets:
158
+
159
+ ```bash
160
+ node .codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs \
161
+ --crossStrategy \
162
+ --validationSplit 0.2 \
163
+ --testSplit 0.2 \
164
+ --portfolioCapacity 5 \
165
+ --output data/ai/output/cross-strategy-shared-pockets.md
166
+ ```
167
+
168
+ This mode intentionally does not reconstruct current strategy gates. It reads
169
+ the causal payload snapshots saved in the exports and classifies every supported
170
+ `additionalIndicators.baseContext` primitive by provenance. It runs two
171
+ independent searches:
172
+
173
+ - `universal` — normalized target/setup state such as ATR/BPS distances,
174
+ ratios, ranks, target-relative state, structure events, and directional
175
+ derivatives;
176
+ - `benchmarkReference` — normalized BTC/ETH/reference/global state, including
177
+ causal `derivatives.referenceContexts` OI changes, funding z-scores,
178
+ liquidation imbalance/spike ratios, pressure/divergence, breadth, and CMC
179
+ regimes.
180
+
181
+ Top-level `baseContext.derivatives` is the primary BTC benchmark. Only
182
+ `targetContext` / `targetDerived` is target derivatives evidence. Never relabel
183
+ a configured `referenceContexts.<symbol>` branch as target evidence merely
184
+ because the symbol happens to match a traded target.
185
+
186
+ The mode:
187
+
188
+ - selects the latest merge independently for each strategy;
189
+ - restricts every strategy to their common chronological overlap;
190
+ - keeps each decision timestamp wholly in global train, tuning, or held-out
191
+ historical test;
192
+ - determines the eligible feature universe from train only, so tuning/test
193
+ availability cannot select a feature;
194
+ - requires a feature to cover at least `--minFeatureStrategies` strategies;
195
+ - uses `--minFeatureCoverage` for the universal profile (default `0.5`) and
196
+ `--minBenchmarkFeatureCoverage` for partial benchmark/reference history
197
+ (default `0.1`);
198
+ - balances discovery with `--maxRowsPerStrategy` and
199
+ `--maxRowsPerEvent` caps;
200
+ - builds each benchmark/reference snapshot by taking within-strategy consensus
201
+ first and then consensus across strategies, so symbol fan-out cannot outvote
202
+ other strategies;
203
+ - deduplicates benchmark/reference discovery to one timestamp-direction event,
204
+ scores macro-average normalized LU across strategies, and applies that same
205
+ event snapshot to every signal row during acceptance evaluation;
206
+ - searches LONG and SHORT separately for both profitable approval slices and
207
+ losing block slices;
208
+ - normalizes search PnL by each strategy's median absolute train loss, so one
209
+ strategy's currency scale cannot dominate;
210
+ - reports per-strategy historical-test behavior, strategy/symbol/event
211
+ concentration, temporal stability, benchmark snapshot consistency, and five
212
+ deterministic fixed-pocket circular-shift diagnostics that rotate whole
213
+ strategy/timestamp outcome blocks rather than individual signal rows;
214
+ - requires a shared pocket to have support in at least 60% of the configured
215
+ feature-strategy floor (minimum 5, capped by available strategies), with the
216
+ expected sign in at least 60% of those strategies in every partition;
217
+ - rejects approval pockets whose maximum simultaneous batch exceeds
218
+ `--portfolioCapacity` (default `5`) in train, tuning, or historical test, and
219
+ applies symbol concentration checks to all three partitions;
220
+ - accepts a block hypothesis only when the blocked slice is at most 80% of the
221
+ flow and its kept complement improves LU/event and PF in train, tuning, and
222
+ historical test.
223
+
224
+ The report does not silently drop the disputed fields. It emits separate audit
225
+ buckets:
226
+
227
+ - `dataQuality` — `stale`, availability, coverage, points, rows, and calculation
228
+ history. These fields can make a market feature ineligible, but never approve
229
+ a trade or act as bearish market evidence by themselves;
230
+ - `rawNonstationary` — absolute price/OI/liquidation/volume/market-cap/notional
231
+ levels and raw-unit slopes. They remain visible with the required causal
232
+ transform (return, BPS/ATR distance, pct-change, ratio, share, or z-score),
233
+ but absolute pooled thresholds are not searched;
234
+ - `derivedPolicy` — existing gate scores, risks, confirmations/conflicts, and
235
+ decision hints. They are causal but excluded from discovery to avoid merely
236
+ rediscovering the current hard-coded heuristic;
237
+ - `metadata` — source, provider, symbol, interval, and universe lineage.
238
+
239
+ Do not calculate rolling normalizations from the sparse export signal rows.
240
+ Such features must be produced at signal time from the full causal market
241
+ history and exported, or discovery/inference parity is broken.
242
+
243
+ ## Moving-average grid study
244
+
245
+ Use the dedicated mode when an export needs a causal SMA/EMA/WMA comparison:
246
+
247
+ ```bash
248
+ node .codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs \
249
+ --strategy LiquidityTails \
250
+ --movingAverageStudy \
251
+ --maPeriods 5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100 \
252
+ --validationSplit 0.2 \
253
+ --testSplit 0.2 \
254
+ --json \
255
+ --output data/ai/output/liquiditytails-ma-grid.json
256
+ ```
257
+
258
+ This mode never rolls over sparse signal rows. It loads closed candles from
259
+ Timescale for the export's provider and interval, bounded at each signal
260
+ timestamp, and calculates:
261
+
262
+ - SMA, finite-history EMA, and WMA for every requested period;
263
+ - direction-normalized price distance in ATR units;
264
+ - direction-normalized five-bar average slope in ATR units;
265
+ - current-gate filters for direction-side and direction-side-plus-slope;
266
+ - a standalone side-plus-slope negative/control comparison.
267
+
268
+ `--maLookbackBars` controls the finite EMA history (default `600`). The JSON
269
+ report includes the residual decay at the longest requested period and parity
270
+ against exported SMA14/49/50. Do not interpret the study when candle coverage
271
+ or parity is incomplete. Candidate ranking uses train and tuning only; the
272
+ timestamp-grouped test tail is reported after selection and remains exposed
273
+ historical evidence after the first run.
274
+
275
+ `--crossStrategy` requires positive `--validationSplit` and `--testSplit`.
276
+ Opening the historical test tail makes it exposed evidence. Re-running the tool
277
+ on the same cutoff does not make it untouched again. Every candidate remains
278
+ research-only until the exact frozen rule survives timestamps strictly after
279
+ the report cutoff and live-env lineage validation. The five shifts are
280
+ fixed-pocket diagnostics, not a family-wise permutation test. Cross-strategy LU
281
+ metrics are discovery units, not qN+ gate metrics or production PnL.
282
+
283
+ ## Report Contract
284
+
285
+ Every report contains:
286
+
287
+ - baseline and candidate tables for full history, `180d`, `90d`, `30d`, `7d`;
288
+ - q3+/q4+/q5+ summaries, configurable with `--qualityThresholds`;
289
+ - timestamp-grouped, time-ordered train/tuning/untouched-test splits;
290
+ - direction and monthly stability;
291
+ - matched, removed, and added slices;
292
+ - PnL, winrate, PF, Sharpe, Sortino, Calmar, max drawdown, DD ratios, strict
293
+ loss, max loss streak, losing months, cadence, and symbol concentration.
294
+ - decision-event cadence, active-day share, trades per event, p95/max batch,
295
+ top-event concentration, and capacity stress at caps `1,3,5`.
296
+
297
+ The JSON report also carries average trade, payoff ratio, recovery factor,
298
+ ulcer index, profit per day/month, cadence per week, and risk-adjusted ratios.
299
+ Use `--json` or an `.json` output path when downstream analysis needs those
300
+ fields.
301
+
302
+ Use `--maxLossValue` to turn batch capacity into maximum simultaneous stop-risk
303
+ only after resolving the historical effective `MAX_LOSS_VALUE` for the
304
+ backtest that produced the export. Prefer a config snapshot embedded in the
305
+ export or the archived checkpoint addressed by `backtestRunId` and
306
+ `backtestTestKey`. The current named Redis config, current strategy default,
307
+ and current production value are not valid substitutes without matching
308
+ lineage. Omit `--maxLossValue` and report stop-risk as `n/a` when the historical
309
+ value is unavailable. Set `--capacities` when the intended portfolio cap is
310
+ known; otherwise keep the default `1,3,5` stress grid. Timestamp groups are
311
+ never split between train/tuning/test.
312
+
313
+ ## Maintenance Rule
314
+
315
+ Do not create another `/tmp` parser, heredoc ESM replay, or strategy-specific
316
+ one-off script for capabilities that belong here. Extend this script and its
317
+ `node:test` coverage, then update this reference and `SKILL.md` when the
318
+ research contract changes.
319
+
320
+ Run the tool tests after every change:
321
+
322
+ ```bash
323
+ node --test .codex/skills/ai-train-local-research/scripts/ai-gate-ablation.test.mjs
324
+ ```
@@ -0,0 +1,227 @@
1
+ # AI-gate reporting contract
2
+
3
+ Use this contract for every user-facing AI-gate metrics report and every dated
4
+ AI-gate notes entry. The goal is that repeated runs remain directly comparable.
5
+
6
+ ## Contents
7
+
8
+ 1. Chat report contract
9
+ 2. Metric definitions
10
+ 3. Formatting rules
11
+ 4. Notes contract
12
+
13
+ ## Chat report contract
14
+
15
+ Use the exact section order and column names below. Do not replace required
16
+ tables with prose. Use `current` for a single gate, `before` / `after` for a
17
+ change, and `baseline` / `pocket-only` / `final` for an ablation.
18
+
19
+ An explicitly narrow question such as "what is 7d cadence?" may receive a
20
+ narrow answer. Otherwise, use the full contract.
21
+
22
+ Reserve metric tables for the final report. Intermediate progress updates
23
+ should describe status without ad hoc metric summaries unless the user
24
+ explicitly asks for preliminary numbers.
25
+
26
+ ### 1. Header and lineage
27
+
28
+ ```md
29
+ ## <Strategy> — AI gate report (`qN+`)
30
+
31
+ Decision: `<implement|observe|research-only|rollback|blocked>` — <one sentence>.
32
+
33
+ Dataset: `<merge_id>` (`<part_count>` parts), rows `<rows>`, `<min_ts>` .. `<max_ts>`, lag `<data_lag_days>d`.
34
+ Lineage: git `<sha>< dirty marker>`, gate `<gate_fingerprint>`, config `<config_ids_fingerprint>`, context `<context_fingerprint>`, `AI_MODE=<mode>`, `MIN_AI_QUALITY=<n>`, `DIRECTION_POLICY=<both|long_only|short_only|direction_aware>`.
35
+ Runtime comparison: `<comparable|different experiment|not checked>` — <one sentence>.
36
+ ```
37
+
38
+ ### 2. Outcome and tail risk
39
+
40
+ Always include `full`, `180d`, `90d`, `30d`, and `7d`, in that order. Keep a
41
+ row with zero approvals. In a comparison, put all gate rows for a window next
42
+ to each other before moving to the next window.
43
+
44
+ ```md
45
+ ### Outcome and tail risk
46
+
47
+ | Window | Gate | N | WR | PF | PnL | PnL/trade | MaxDD | Loss streak | Losing months |
48
+ | ------ | ---- | --: | --: | --: | --: | --------: | ----: | ----------: | ------------- |
49
+ ```
50
+
51
+ ### 3. Cadence and fan-out
52
+
53
+ Use the same windows and gate-row order as the outcome table.
54
+
55
+ ```md
56
+ ### Cadence and fan-out
57
+
58
+ | Window | Gate | Trades/day | Events/day | Active days | Events | Trades/event | p95 batch | Max batch | Top event count | Top event PnL |
59
+ | ------ | ---- | ---------: | ---------: | ----------: | -----: | -----------: | --------: | --------: | --------------: | ------------: |
60
+ ```
61
+
62
+ ### 4. Risk-adjusted metrics
63
+
64
+ Use the same windows and gate-row order. Do not omit unavailable ratios.
65
+
66
+ ```md
67
+ ### Risk-adjusted metrics
68
+
69
+ | Window | Gate | Sharpe | Sortino | Calmar | DD/gross | DD/PnL | Profit/day | Profit/month | Trades/week |
70
+ | ------ | ---- | -----: | ------: | -----: | -------: | -----: | ---------: | -----------: | ----------: |
71
+ ```
72
+
73
+ ### 5. Quality and direction
74
+
75
+ Use rows `qN+ total`, `q(N+1)+`, `LONG qN+`, and `SHORT qN+`, in that order.
76
+ When `N=5`, keep `q(N+1)+` as `n/a`.
77
+
78
+ For `long_only` or `short_only`, retain the suppressed direction as an explicit
79
+ zero-approval row. The raw-core direction metrics belong beside the approved
80
+ table in release research; never omit the losing or blocked counterfactual.
81
+
82
+ ```md
83
+ ### Quality and direction
84
+
85
+ | Slice | Gate | N | Events | WR | PF | PnL | MaxDD | Max batch |
86
+ | ----- | ---- | --: | -----: | --: | --: | --: | ----: | --------: |
87
+ ```
88
+
89
+ ### 6. Runtime execution bridge
90
+
91
+ Keep gate approvals, submitted orders, and filled trades distinct. When runtime
92
+ or exchange evidence is outside the task, keep one row of `n/a` values instead
93
+ of implying that every approval filled.
94
+
95
+ ```md
96
+ ### Runtime execution bridge
97
+
98
+ | Scope | Window | Approved | Attempts | Filled | Balance rejects | Other rejects | Requested notional | Max simultaneous stop-risk |
99
+ | ----- | ------ | -------: | -------: | -----: | --------------: | ------------: | -----------------: | -------------------------: |
100
+ ```
101
+
102
+ ### 7. Validation
103
+
104
+ Do not rename row-based candidate-selection output to an untouched test.
105
+
106
+ ```md
107
+ ### Validation
108
+
109
+ | Partition | Rows | Events | Approved N | WR | PF | PnL | MaxDD | Max batch |
110
+ | -------------- | ---: | -----: | ---------: | --: | --: | --: | ----: | --------: |
111
+ | train | | | | | | | | |
112
+ | tuning | | | | | | | | |
113
+ | untouched test | | | | | | | | |
114
+ ```
115
+
116
+ ### 8. Acceptance checks
117
+
118
+ Use only `PASS`, `FAIL`, or `UNKNOWN`.
119
+
120
+ ```md
121
+ ### Acceptance checks
122
+
123
+ | Check | Status | Evidence |
124
+ | ------------------------- | ------ | -------- |
125
+ | Freshness | | |
126
+ | Runtime lineage parity | | |
127
+ | Independent-event support | | |
128
+ | Event concentration | | |
129
+ | Portfolio capacity | | |
130
+ | Symbol concentration | | |
131
+ | Temporal stability | | |
132
+ | Untouched test | | |
133
+ ```
134
+
135
+ ### 9. Reject reasons and conclusion
136
+
137
+ Show exactly the top five terminal-30d reject reasons when threshold or pocket
138
+ tuning is in scope. Use `n/a` rows when the artifact does not contain them.
139
+
140
+ ```md
141
+ ### Top reject reasons (30d)
142
+
143
+ | Rank | Reason | N | Share |
144
+ | ---: | ------ | --: | ----: |
145
+
146
+ ### Conclusion
147
+
148
+ - Why: <short evidence-based explanation>.
149
+ - Residual risk: <tail, support, capacity, env, or validation gap>.
150
+ - Next check: <specific export, replay, or live observation>.
151
+ ```
152
+
153
+ Put optional strategy-specific findings only after this fixed block under
154
+ `### Strategy-specific findings`. Never reorder or rename the fixed sections.
155
+
156
+ ## Metric definitions
157
+
158
+ - `Events`: unique decision timestamps by default. Use a broader market episode
159
+ only when its deterministic grouping rule is documented.
160
+ - `Events/day`: events divided by the evaluated calendar span, using the same
161
+ minimum-one-day convention as `aiTrainMetrics.ts`.
162
+ - `Active days`: percentage of evaluated calendar days with at least one
163
+ approved event.
164
+ - `Trades/event`: approved trades divided by events.
165
+ - `p95 batch` / `Max batch`: p95 and maximum approved trades sharing one event.
166
+ - `Top event count`: largest event's percentage of approved trades.
167
+ - `Top event PnL`: largest event's percentage of approved PnL. If total PnL is
168
+ zero, report `n/a`.
169
+ - `Approved`: signals that passed the effective qN+ gate.
170
+ - `Attempts`: order submissions, including rejected submissions.
171
+ - `Filled`: successfully opened positions; do not call rejected attempts
172
+ cancelled or completed trades.
173
+ - `Balance rejects`: attempts rejected specifically for insufficient available
174
+ balance.
175
+ - `Max simultaneous stop-risk`: sum of configured per-order loss budgets in the
176
+ largest event, before fill/rejection effects.
177
+ - `DD/gross` and `DD/PnL`: max drawdown divided by gross profit and total profit.
178
+ - `PnL/trade`: total PnL divided by completed trades. The backtest CLI progress
179
+ `avg` is PnL per completed test/symbol and must not be used for this field.
180
+ Report `n/a` when `N=0`.
181
+ - `Losing months`: count; append month ids in parentheses when non-zero.
182
+ - `qN+`: all approvals with quality greater than or equal to `N`; never use
183
+ plain `qN` for this cumulative stream.
184
+
185
+ ## Formatting rules
186
+
187
+ - Counts: integer.
188
+ - WR, shares, active days, and drawdown percentages: one decimal plus `%`.
189
+ - PF, Sharpe, Sortino, Calmar, PnL, PnL/trade, MaxDD, and profit rates: two decimals.
190
+ - Trades/day, events/day, and trades/week: three decimals.
191
+ - Trades/event and batch percentiles: two decimals.
192
+ - Timestamps: ISO-8601 UTC.
193
+ - Unknown or unavailable: exactly `n/a`; never use an empty cell, `null`,
194
+ `undefined`, `Infinity`, a dash, or a guessed zero.
195
+ - Use `n/a` only after checking the source artifact; derive a metric from raw
196
+ evaluations when the data exists instead of treating a missing summary field
197
+ as missing evidence.
198
+ - Zero approvals: `N=0`, `PnL=0.00`, cadence `0.000`; ratio metrics remain
199
+ `n/a`.
200
+ - Use the artifact's PnL unit. Do not add `$` unless the artifact explicitly
201
+ establishes USD.
202
+ - Keep the metric names, section order, window order, and rounding unchanged
203
+ between runs.
204
+
205
+ ## Notes contract
206
+
207
+ Write each study to a new
208
+ `notes/<Strategy>/YYYY-MM-DD-<short-kebab-slug>.md` file. Never append dated
209
+ entries to a rolling strategy log. The file must first follow
210
+ `../../strategy-backtest-research/references/research-notes.md`, including the
211
+ resolved config and complete machine-readable metrics snapshot. Put the full
212
+ chat report contract above under `## Reported metrics`, then append these
213
+ sections in order when gate tuning is in scope:
214
+
215
+ 1. strategy intent and exact causal field paths
216
+ 2. existing gate audit with `keep`, `round`, `replace`, `disable`, or
217
+ `needs-more-data`
218
+ 3. live-env parity and feature provenance, including `target`, `benchmark`, or
219
+ `global` scope
220
+ 4. walk-forward evidence, symbol/event concentration, ablation, and negative
221
+ control
222
+ 5. raw and rounded thresholds, sensitivity, and boundary tests
223
+ 6. rollout, old-gate cleanup, and remaining production blockers
224
+
225
+ Use migrated `notes/<Strategy>/*.md` files only as historical content
226
+ references. The shared research-note contract and this reporting contract, not
227
+ their legacy body formatting, control new records.