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,17 @@
1
+ ---
2
+ name: backtest-config-redis
3
+ description: Fetch a TradeJS backtest or strategy configuration from the local RedisJSON users configuration namespace by config name, including named variants such as Grid:ai or TrendLine:research. Use for inspecting, reproducing, or recording Redis-backed strategy grids.
4
+ ---
5
+
6
+ # Backtest Config from Redis
7
+
8
+ ## Use
9
+
10
+ - Ask for the config name if not provided.
11
+ - Read the RedisJSON value from
12
+ `users:<user>:backtests:configs:<config>` and return the config object as-is
13
+ unless the user asks to edit or reformat it. The default user is `root`.
14
+ - Prefer using the script `scripts/get_backtest_config.sh` to access Redis via Docker.
15
+ - If the container name differs from `inv-redis`, ask for the correct name.
16
+ - For research lineage, embed the returned JSON and a canonical checksum in the
17
+ note. The mutable Redis key alone is not reproduction evidence.
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [[ $# -lt 1 ]]; then
5
+ echo "Usage: $0 <config> [user] [container]" >&2
6
+ exit 1
7
+ fi
8
+
9
+ config="$1"
10
+ user_name="${2:-root}"
11
+ container="${3:-inv-redis}"
12
+ key="users:${user_name}:backtests:configs:${config}"
13
+
14
+ # RedisJSON returns one root match in an array. Print the config object itself.
15
+ payload="$(docker exec "$container" redis-cli --raw JSON.GET "$key" '$')"
16
+ if [[ -z "$payload" ]]; then
17
+ echo "Backtest config not found: ${key}" >&2
18
+ exit 1
19
+ fi
20
+
21
+ printf '%s\n' "$payload" | jq 'if type == "array" and length == 1 then .[0] else . end'
@@ -0,0 +1,146 @@
1
+ ---
2
+ name: runtime-parity-mismatch-analysis
3
+ description: Analyze TradeJS runtime parity mismatch JSON files produced by runtime-parity notifications, identify root causes of runtime vs replay/backtest divergences, group them by cause, and point to the exact evidence fields and code paths to inspect next.
4
+ ---
5
+
6
+ # Runtime Parity Mismatch Analysis
7
+
8
+ Use this skill when the user asks to:
9
+
10
+ - analyze a `runtime-parity-mismatches-*.json` file
11
+ - explain why runtime and replay/backtest diverged
12
+ - investigate `runtimeOnly` / `backtestOnly` parity cases
13
+ - summarize mismatch causes from Telegram parity artifacts
14
+ - tell whether a divergence is caused by strategy core, gate/AI/ML, order failure, drift/tolerance, or missing evaluation
15
+
16
+ This skill is for reading the mismatch JSON artifact first. Do not rerun parity unless the user explicitly asks for a new replay.
17
+
18
+ ## Expected input
19
+
20
+ Prefer one of these:
21
+
22
+ - a local `runtime-parity-mismatches-*.json` file
23
+ - an attached JSON artifact from Telegram
24
+ - raw JSON pasted into the chat
25
+
26
+ Start with:
27
+
28
+ - `cases`
29
+
30
+ Fallback only if needed:
31
+
32
+ - `mismatches.runtimeOnly`
33
+ - `mismatches.backtestOnly`
34
+
35
+ ## Analysis priority
36
+
37
+ For each case, use this order:
38
+
39
+ 1. `why.classification`
40
+ 2. `why.reason`
41
+ 3. `decisionTrace`
42
+ 4. `timing`
43
+ 5. `artifacts`
44
+
45
+ Treat `why.classification` as the primary label, not as a hint.
46
+
47
+ ## Canonical cause mapping
48
+
49
+ Map each case to one of these buckets:
50
+
51
+ - `strategy_core`
52
+ - usually `core_skipped`
53
+ - replay/runtime core did not emit a signal
54
+ - `gate_ai_ml`
55
+ - usually `gated_out`
56
+ - signal existed but gate / AI / ML / skip logic blocked entry
57
+ - `order_placement`
58
+ - usually `order_failed`
59
+ - signal existed but order path failed
60
+ - `tolerance_or_drift`
61
+ - usually `backtest_drift`
62
+ - nearest trade exists but is outside allowed timing tolerance
63
+ - `missing_evaluation`
64
+ - usually `not_evaluated`
65
+ - no nearby runtime/replay evaluation was produced
66
+ - `true_mismatch`
67
+ - usually `true_mismatch`
68
+ - both paths evaluated the setup but still disagree
69
+
70
+ ## What to conclude from each classification
71
+
72
+ - `core_skipped`
73
+ - First suspect strategy core conditions, candle history, preload window, or config mismatch.
74
+ - `gated_out`
75
+ - First inspect `orderSkipReason`, AI/ML thresholds, and runtime-vs-replay gate inputs.
76
+ - `order_failed`
77
+ - First inspect order simulation / connector / placement path rather than strategy core.
78
+ - `backtest_drift`
79
+ - First inspect timestamp alignment, preload history, tolerance bars, and exchange candle differences.
80
+ - `not_evaluated`
81
+ - First inspect target coverage, filtering, persistence, or missing evaluation generation.
82
+ - `true_mismatch`
83
+ - First inspect direction, statuses, and signal/evaluation artifacts on both sides.
84
+
85
+ ## TradeJS-specific inspection paths
86
+
87
+ If the JSON alone is not enough, inspect these code areas:
88
+
89
+ - mismatch builder and classifications:
90
+ - `packages/cli/src/scripts/runtimeParity.ts`
91
+ - parity entry extraction and matching:
92
+ - `packages/cli/src/lib/runtimeParity.ts`
93
+ - runtime signal persistence/loading:
94
+ - `packages/cli/src/lib/runtimeSignalsLoader.ts`
95
+ - strategy runtime and signal/evaluation flow:
96
+ - `packages/node/src/testing.ts`
97
+ - `packages/node/src/strategyHelpers/runtime.ts`
98
+ - `packages/node/src/signals.ts`
99
+ - strategy implementation:
100
+ - `packages/strategies/**/core.ts`
101
+ - `packages/strategies/**/adapters/ai.ts`
102
+
103
+ When a case says `core_skipped`, inspect the strategy `core.ts` before blaming Telegram, Redis, or the connector.
104
+
105
+ ## Output format
106
+
107
+ For each case, provide:
108
+
109
+ 1. `Case`
110
+ - strategy / symbol / direction / signalId
111
+ 2. `Root cause`
112
+ - one short sentence
113
+ 3. `Evidence`
114
+ - cite the exact JSON fields that support the conclusion
115
+ 4. `Bucket`
116
+ - one of the canonical cause buckets above
117
+ 5. `Next checks`
118
+ - 1-3 concrete checks in code or config
119
+
120
+ If there are many cases, group them by:
121
+
122
+ - `why.classification`
123
+ - then by strategy
124
+
125
+ If all cases share one cause, say that explicitly before listing details.
126
+
127
+ ## What not to do
128
+
129
+ - Do not default to generic “timing issue” wording if `why.classification` already says `gated_out` or `core_skipped`.
130
+ - Do not treat `recommendedChecks` as proof; use them only as follow-up guidance.
131
+ - Do not ignore `decisionTrace` when `orderStatus` or `orderSkipReason` is present.
132
+ - Do not rerun backtests or parity automatically.
133
+
134
+ ## Example prompt
135
+
136
+ Use this prompt shape when the user gives you a mismatch artifact:
137
+
138
+ ```text
139
+ Analyze this runtime parity mismatch JSON.
140
+ For each case:
141
+ 1. Name the root cause.
142
+ 2. Cite the exact fields that prove it.
143
+ 3. Classify it as strategy_core, gate_ai_ml, order_placement, tolerance_or_drift, missing_evaluation, or true_mismatch.
144
+ 4. Give the next 1-3 checks in the TradeJS codebase.
145
+ If several cases share one cause, group them.
146
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: save-strategy-config-from-backtest
3
+ description: Promote a TradeJS backtest config grid from research Redis into the Git-owned runtime declaration in TradeJS-Project tradejs.config.ts. Use when the user asks to copy, promote, or save a backtest candidate for runtime or forward testing.
4
+ ---
5
+
6
+ # Promote Strategy Config From Backtest
7
+
8
+ ## Repository boundary
9
+
10
+ Run from `/Users/aleksnick/dev/tradejs/tradejs-project`. This repository owns
11
+ `tradejs.config.ts`, the exact package dependencies, and the runtime image.
12
+ Research Redis is only the source of the backtest candidate; production Redis
13
+ must never receive strategy config, deployment documents, or version pointers.
14
+
15
+ ## Workflow
16
+
17
+ 1. Resolve the exact user, strategy, source backtest config, target deployment,
18
+ and intended risk. Default the research user to `root`, but never guess a
19
+ production account or deployment.
20
+ 2. Read the source grid from
21
+ `users:<user>:backtests:configs:<Strategy>:<name>` with RedisJSON. A missing
22
+ source is a blocker; do not fall back to `users:*:strategies:*:config`.
23
+ 3. Convert the grid to one plain strategy config. Unwrap one-element arrays.
24
+ For multi-value arrays, resolve the exact winning result/config id or ask the
25
+ user; never choose a value arbitrarily. Preserve nested `LONG`, `SHORT`, AI,
26
+ detector, and risk objects.
27
+ 4. Remove operational/mode fields: `ENABLE`, `ACCOUNT_ID`, `DEPLOYMENT_ID`,
28
+ `ENV`, `MAKE_ORDERS`, `RECORD_RUNTIME_TRADES`, and `AI_REPLAY_ANALYSES`.
29
+ Keep `INTERVAL`, `UNIVERSE`, `POLICY_PROFILE_ID`, execution semantics, AI
30
+ mode, thresholds, and the complete strategy behavior config. For an
31
+ authorized micro-forward use `MAX_LOSS_VALUE=1`; otherwise preserve the
32
+ explicitly selected risk.
33
+ 5. Update the strategy entry under
34
+ `runtime.deployments.<deployment>.strategies.<Strategy>` in
35
+ `tradejs.config.ts`. Store exactly `{ generation?, enabled, selection?,
36
+ config }`. `generation` is optional human metadata. Never add or increment a
37
+ technical version: Project validation computes `strategyRevision` and
38
+ `deploymentCompositionId`. Keep account, connector, tickers, and asset
39
+ classes at deployment level.
40
+ 6. Ensure `package.json` and `yarn.lock` select the exact stable strategy
41
+ package containing the candidate. Normal development verifies a beta first;
42
+ committed Project and production use the protected stable promotion.
43
+ 7. Run Project validation, record the computed revisions, and run
44
+ `yarn runtime-control verify`. A production-like image smoke must prove that
45
+ the config loads with no controls key, pause creates only
46
+ `users:<user>:runtime:controls`, and resume removes it.
47
+
48
+ ## Safety
49
+
50
+ - Never write a runtime strategy config to Redis.
51
+ - Never copy credentials into `tradejs.config.ts` or research evidence.
52
+ - Do not overwrite another strategy or deployment while promoting one
53
+ candidate.
54
+ - A UI pause is an optional Redis override; desired activation remains the
55
+ committed `enabled` value.
56
+ - Commit and push only when the user requested the rollout through the active
57
+ `$strategy-forward-start` workflow, which owns the complete forward-test
58
+ handshake.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Save Strategy Config"
3
+ short_description: "Create runtime strategy configs from Redis backtest configs."
4
+ default_prompt: "Save a runtime strategy config from a backtest config."
@@ -0,0 +1,334 @@
1
+ ---
2
+ name: strategy-backtest-research
3
+ description: Execute a scoped TradeJS strategy implementation or preregistered core-backtest experiment, including StrategyAPI checks, figures, Redis configs, cache-only runs, metric reconciliation, and AI export preparation. Use strategy-improvement-research instead to choose hypothesis families or orchestrate a multi-round candidate lineage.
4
+ ---
5
+
6
+ # Strategy Backtest Research
7
+
8
+ Run operational research commands from `TradeJS-Project`, with `PROJECT_CWD`
9
+ as the artifact/config root and `TRADEJS_SOURCE_REPOSITORY_ROOT` as the Git and
10
+ build lineage root. Store `data/` and ignored `notes/` only under the project
11
+ root.
12
+
13
+ When research will apply and compare alternative strategy source edits, create
14
+ one dedicated worktree from the frozen baseline SHA for that immutable lineage.
15
+ Keep the canonical strategy checkout clean, point
16
+ `TRADEJS_SOURCE_REPOSITORY_ROOT` at the worktree, and run source checks there.
17
+ Pure config, artifact, reporting, or read-only backtest work does not require a
18
+ worktree. Before replacing a rejected source candidate, preserve its exact diff,
19
+ build hash, resolved config, and run outcome in Project-owned evidence; restore
20
+ only the disposable worktree. Commit only a selected candidate, and remove a
21
+ no-winner worktree only after evidence is frozen. A worktree does not isolate a
22
+ temporary package overlay in `TradeJS-Project/node_modules`, which must be
23
+ restored separately to the verified stable package.
24
+
25
+ Use this skill when working on strategy implementation, figures, backtest
26
+ configuration, or one already-preregistered core experiment in the owning
27
+ standalone strategy repository.
28
+
29
+ This is an execution skill, not the end-to-end improvement orchestrator. It
30
+ does not invent a multi-round research budget, choose competing hypothesis
31
+ families, rank the global candidate ledger, or freeze the final composition.
32
+ Use `$strategy-improvement-research` for those decisions. Do not use this skill
33
+ for general `ai-train --localOnly` gate research; use
34
+ `$ai-train-local-research` for a frozen core/export.
35
+
36
+ ## Strategy Shape
37
+
38
+ - `core.ts` must use `StrategyAPI`; do not call AI/ML providers or order placement directly.
39
+ - Geometry-based strategies should keep visual artifacts in the strategy package.
40
+ - `figures.ts` should include the lines/points needed to inspect why a trade happened.
41
+ - `adapters/ai.ts` should carry strategy-specific context into the AI payload when backtest exports need AI context, but local gate tuning belongs to `ai-train-local-research`.
42
+
43
+ ## DoubleTap Notes
44
+
45
+ When the strategy is `DoubleTap`, `engine.ts` ports the Bjorgum Double Tap pattern mechanics:
46
+
47
+ - maintain swing pivots from rolling highest/lowest windows
48
+ - detect double bottom on close above neckline
49
+ - detect double top on close below neckline
50
+ - derive target from `DOUBLETAP_TARGET_FIB_PCT`
51
+ - derive stop from invalidation pivot and `DOUBLETAP_STOP_FIB_PCT`
52
+ - `figures.ts` is required. Include pattern zig-zag, neckline, target, stop, pivot points, and entry marker.
53
+
54
+ ## Backtest Workflow
55
+
56
+ 1. Prepare or update Redis backtest config under `users:root:backtests:configs:<Strategy>:<name>`.
57
+ - When a research config includes `MAX_LOSS_VALUE`, set it to `10`.
58
+ - When updating a backtest `:ai` config, enable both `LONG` and `SHORT`; let the AI gate disable a side later if needed.
59
+ 2. Start with small cache-only runs: `yarn backtest -c <Strategy>:<name> -d 30 --cacheOnly --fast`.
60
+ 3. Tune strategy-specific grid fields first.
61
+
62
+ When a symmetric candidate loses in aggregate but its reconciled LONG/SHORT
63
+ attribution shows a material improvement on only one side, do not discard or
64
+ globally enable it automatically. Register a new direction-specific follow-up
65
+ with explicit `_LONG` and `_SHORT` fields, keep both directions enabled, and
66
+ screen the combined policy against the same control. The follow-up is a new
67
+ hypothesis lineage; preserve the rejected symmetric run and preregister the
68
+ directional rule before testing it.
69
+
70
+ For DoubleTap, prioritize:
71
+
72
+ - `DOUBLETAP_PIVOT_LENGTH`
73
+ - `DOUBLETAP_PIVOT_TOLERANCE_PCT`
74
+ - `DOUBLETAP_TARGET_FIB_PCT`
75
+ - `DOUBLETAP_STOP_FIB_PCT`
76
+ - `DOUBLETAP_MIN_PATTERN_HEIGHT_PCT`
77
+ - `DOUBLETAP_MAX_BREAKOUT_DISTANCE_PCT`
78
+ - side `minRiskRatio`
79
+
80
+ 4. Once a config is stable across 20+ tickers on `-d 30`, use it for year-scale `--ai` exports. Analyze exported local AI gate behavior with `ai-train-local-research`.
81
+
82
+ For detailed metrics from a non-`--fast` backtest run, use:
83
+
84
+ ```bash
85
+ yarn node -r dotenv/config .codex/skills/strategy-backtest-research/scripts/backtest-run-metrics.mjs --run <run-id> --json
86
+ ```
87
+
88
+ The report reconstructs completed trades from cached order artifacts and shows
89
+ full/365d/180d/90d/30d/7d metrics where applicable, including PF, drawdown, strict
90
+ loss, loss streak, losing months, cadence, and scale-in levels 2/3/4. Use a
91
+ matching no-scale-in run to separate sizing effects from scale-in effects.
92
+
93
+ For portfolio metrics from a `--fast --ai` core export, use the completed-trade
94
+ JSONL instead of treating the per-symbol Redis drawdown as portfolio MaxDD:
95
+
96
+ ```bash
97
+ yarn node -r dotenv/config .codex/skills/strategy-backtest-research/scripts/fast-ai-export-metrics.mjs \
98
+ --file <merged-export.jsonl> --run <run-id> --json
99
+ ```
100
+
101
+ `--file` may be repeated for disjoint export shards. If the Redis run manifest
102
+ is unavailable, pass its frozen end explicitly with `--end <epoch-ms|ISO>`.
103
+ The default core-screen terminal matrix is `1100d/365d/180d/90d/30d`, anchored strictly to
104
+ that manifest end rather than the newest export row. Windows are half-open
105
+ `[manifestEnd - days, manifestEnd)`, matching the backtest manifest. The report uses only
106
+ `tradeResult.netProfit`, `tradeResult.exitTimestamp`, direction, symbol, and
107
+ signal identity; it never consumes AI/LLM/gate decisions. It reports N/W/L,
108
+ WR, PF, PnL, PnL/trade, deterministic portfolio MaxDD, exact calendar-day
109
+ observed cadence, and LONG/SHORT breakdowns. With `--run`, it filters rows to
110
+ that run and separately reconciles export N/W/L/PnL against Redis
111
+ `result.stat`; Redis cannot supply export PF or portfolio MaxDD. Once N/W/L
112
+ and PnL reconcile within the documented per-symbol rounding tolerance, use the
113
+ row-level export as the authoritative trade-economic total instead of swapping
114
+ in the cent-rounded Redis aggregate.
115
+
116
+ For a `$strategy-improvement-research` final composition, extend the same permanent report
117
+ to `1095d/1460d/1825d-or-exact-maximum/365d/180d/90d/30d/7d`. When cached
118
+ coverage is shorter than 1825 days, report the exact covered duration (for
119
+ example 1800d) and do not label it a complete five-year window. Reuse this
120
+ tool's full ALL/LONG/SHORT statistics; do not replace them with a compact custom
121
+ parser. The release workflow must then run `ai-train --localOnly --chart -n 0`
122
+ on the exact full export so the UI chart and structured gate statistics share
123
+ the finalist lineage.
124
+
125
+ ## Required Core Metric Cohorts
126
+
127
+ For every reported config and full or terminal window, present one table with
128
+ these rows in fixed order:
129
+
130
+ 1. `ALL (aggregate portfolio)`
131
+ 2. `LONG`
132
+ 3. `SHORT`
133
+
134
+ Every row must contain `N`, `PnL`, `PnL/trade`, `PF`, `WR`, `realized MaxDD`,
135
+ and `cadence/day`. Use these definitions consistently:
136
+
137
+ - `N`: completed trades in the cohort.
138
+ - `PnL`: sum of completed-trade net realized PnL.
139
+ - `PnL/trade`: `PnL / N`, or `n/a` for `N = 0`.
140
+ - `PF`: gross winning PnL divided by absolute gross losing PnL.
141
+ - `WR`: winning completed trades divided by `N`.
142
+ - `realized MaxDD`: maximum peak-to-trough decline of the chronological
143
+ completed-trade net-PnL equity curve for that cohort and window. Label LONG
144
+ and SHORT values `side-only realized MaxDD` because each equity curve
145
+ contains only that direction's trades; label ALL as `aggregate portfolio
146
+ realized MaxDD`.
147
+ - `cadence/day`: cohort `N / exact calendar days` in the reported window.
148
+
149
+ Filter rows to LONG or SHORT before computing side metrics. Compute aggregate
150
+ `PnL/trade` as `(LONG PnL + SHORT PnL) / (LONG N + SHORT N)`; never average the
151
+ side `PnL/trade` values. Keep both directions enabled in raw-core configs even
152
+ when one is negative, and never omit the weak cohort from a table. AI-gate
153
+ research happens later and evaluates LONG and SHORT cohorts explicitly. Record
154
+ the baseline/candidate assessment status independently for ALL, LONG, and
155
+ SHORT; an aggregate label is not a directional label.
156
+
157
+ For a direction-targeted hypothesis, preregister the target direction, the
158
+ unaffected direction, matched control, metric thresholds, identity comparison,
159
+ rounding tolerance, possible shared-position occupancy path, non-target
160
+ non-regression rule, and aggregate portfolio guardrails. Judge the causal
161
+ hypothesis primarily on the target cohort. Require that cohort to satisfy the
162
+ preregistered improvements in PnL, PnL/trade, PF, WR, and side-only realized
163
+ MaxDD, with lower drawdown being better. Require exact signal/trade identities,
164
+ exact N, and PnL equality within only the documented reconciliation-rounding
165
+ tolerance on the non-target side only when the architecture makes it invariant.
166
+ If shared position occupancy, cooldown, order lifecycle, or another interaction
167
+ can affect it, report occupancy spillover explicitly: added and removed trade
168
+ identities, N/cadence delta, and PnL, PnL/trade, PF, WR, and side-only MaxDD
169
+ deltas. Apply the preregistered non-regression rule to that evidence. Report the
170
+ target-side causal verdict and the aggregate portfolio-promotion verdict
171
+ separately. Aggregate portfolio PnL and aggregate portfolio realized MaxDD are
172
+ guardrails, not substitutes for the target-side verdict.
173
+
174
+ For full-universe core robustness research:
175
+
176
+ 1. Freeze the ordered eligible ticker list and checksum, exact UTC start/end,
177
+ resolved config grids, git/dirty lineage, connector, interval, fees,
178
+ slippage, and entry delay before comparing strategies or variants.
179
+ Audit every non-candle membership input (wallet registry, top-symbol/perp
180
+ universe, benchmark basket, allowlist) too. Resolve an effective-dated
181
+ version at or before each decision timestamp. If only a later/current
182
+ snapshot exists, label the long-window study blocked for point-in-time
183
+ robustness and do not optimize from it.
184
+ 2. Use observed portfolio cadence = completed trades / exact calendar days.
185
+ Do not divide a full-universe cadence by symbol count or extrapolate it to an
186
+ approximate exchange count. If the experiment intentionally samples the
187
+ universe, show any linear projection separately with both universe sizes.
188
+ 3. For a wide parameter family, first use a clearly labelled all-universe
189
+ 180d screening grid, then rerun only shortlisted cells on one continuous
190
+ long window. A short screen is selection evidence, never robustness
191
+ evidence. Report terminal 365d/180d/90d/30d slices from the long run,
192
+ anchored to its immutable manifest end as half-open intervals, including
193
+ zero-activity slices. At
194
+ a 0.2/day floor, require at least 220/73/36/18/6 completed trades on
195
+ 1100/365/180/90/30d respectively.
196
+ 4. Keep each grid `configId` separate and require identical planned/completed
197
+ symbol counts. Never add metrics from several parameter buckets together.
198
+ Run shortlisted long-window cells as isolated single-config runs. Avoid a
199
+ multi-cell 1100d full-universe fan-out: it increases peak heap use and may
200
+ contaminate lifecycle/execution state when a strategy's shared-state key
201
+ does not cover the full resolved config. Use a multi-cell 180d screen only
202
+ after an explicit state-isolation test; otherwise split that screen too.
203
+ An OOM or partial manifest is a failed experiment, not a smaller sample.
204
+ Parallelism is a host-wide budget: count tester workers from every active
205
+ run and inspect memory pressure/swap before launching another batch. If two
206
+ batches already sustain pressure, wait or reduce `-p`; a per-worker heap cap
207
+ does not make a third batch safe.
208
+ 5. Confirm shortlisted variants without `--fast`. For stateful strategies,
209
+ also run standalone shorter horizons to measure reset/preload sensitivity;
210
+ a terminal slice and a cold-start horizon answer different questions.
211
+ 6. Save rejected as well as accepted hypotheses with the causal claim, full
212
+ resolved config, exact runs, structured metrics, and artifact checksums.
213
+ Do not repeat an old threshold sweep without a new causal rationale.
214
+ If a rejected symmetric lifecycle improves only LONG or only SHORT, record
215
+ that attribution and test at most one preregistered `_LONG`/`_SHORT`
216
+ follow-up with both directions still enabled before abandoning the family.
217
+
218
+ Use two explicit outcome labels. `Strictly robust` requires non-negative PnL,
219
+ PF >= 1, and the requested cadence floor in the full run and every required
220
+ terminal window. `Improved research candidate` is allowed for a still-negative
221
+ core only when full-window PnL and PnL/trade improve against the frozen control,
222
+ cadence survives every required window, and all terminal PnL/PF/MaxDD
223
+ regressions are disclosed. An aggregate win cannot hide a collapsed tail.
224
+
225
+ The `--ai` flag on a BACKTEST run may be used only as raw completed-core-trade
226
+ transport for the terminal metric tool: BACKTEST entry policy bypasses AI
227
+ quality. State this explicitly so the result is never mistaken for an AI-gated
228
+ backtest.
229
+
230
+ Treat row-level economics as acceptance-grade only when every config bucket
231
+ has a complete manifest, exact Redis N/W/L reconciliation, and only the allowed
232
+ per-symbol rounding delta in PnL. A missing row or conflicting duplicate makes
233
+ that bucket's PF, PnL/trade, terminal windows, and portfolio MaxDD invalid.
234
+ Never fill the gap from aggregate stats; repair the capture/export path and
235
+ rerun the affected cell.
236
+
237
+ Do not invoke `ai-export` while the selected run manifest is `running`, whether
238
+ the run id is explicit or found through latest-run discovery. Workers may still
239
+ own open append streams. The exporter must retain chunks by default and reject
240
+ active runs; cleanup is a separate post-run operation after reconciliation.
241
+
242
+ For all backtest summaries, calculate and report average trade PnL as
243
+ `total PnL / completed trades` and label it `PnL/trade`. The live CLI progress
244
+ `avg` is PnL per completed test/symbol, not PnL/trade; do not use it as a trade
245
+ quality metric. If it is useful operationally, label it `PnL/test` or
246
+ `PnL/symbol`. Report `PnL/trade` as `n/a` when `N = 0`.
247
+
248
+ For every AI export handed to gate research, record the merge id, shard count,
249
+ minimum and maximum timestamps, backtest config ids, git SHA, and the context env
250
+ used to construct derivatives/CMC inputs. A year-scale export without a fresh
251
+ terminal tail is suitable for historical research but not for a current live
252
+ cadence claim.
253
+
254
+ ## Core experiment execution
255
+
256
+ For every new core control-versus-candidate experiment, use the versioned
257
+ contour in `CORE_RESEARCH.md`:
258
+
259
+ 1. Create and edit a spec with `yarn research:core init ...`.
260
+ 2. Freeze the causal claim, family, target direction, ordered universe hash,
261
+ full resolved configs plus their canonical hashes, window, execution model,
262
+ variants, selection rules, and explicit
263
+ stage (`screen`, `isolated_long`, or `confirmation`) before runs. Never
264
+ infer the stage from period length or the presence of a run ID. Later stages
265
+ must name `parentResearchIds`; regenerate the family stage index.
266
+ 3. Run `prepare`, then `analyze` completed exports or `run` explicit isolated
267
+ commands. Never discover a mutable latest run implicitly.
268
+ 4. Require completed-manifest/full-checkpoint/one-config reconciliation.
269
+ Inspect setup matching, ALL/LONG/SHORT, terminal/fold/month/regime matrices,
270
+ cluster bootstrap, family-aware Holm, DSR/PBO diagnostics, and cost stress.
271
+ 5. Run `verify` before the immutable note. Link bundle hashes, while still
272
+ embedding the complete resolved config and structured metrics required by
273
+ the note schema.
274
+
275
+ When `$strategy-improvement-research` invokes this skill, execute only the
276
+ preregistered experiment and return its reconciled evidence. The orchestrator
277
+ owns parent/child selection, research-budget accounting, belief updates, and
278
+ the decision to run another candidate.
279
+
280
+ After changing the contour itself, use its public test seam:
281
+
282
+ ```bash
283
+ yarn research:core:test
284
+ yarn research:core:coverage
285
+ ```
286
+
287
+ The coverage command enforces the checked-in floor. Test observable immutable
288
+ specs/results/artifacts and selection decisions; mock only Redis, child-process,
289
+ time/randomness, or filesystem boundaries. Do not mock internal metric,
290
+ comparison, or statistics modules. Preserve single-pass streaming JSONL ingest,
291
+ stable non-empty trade identities, one semantic threshold evaluator across full/
292
+ terminal/cost-stress windows, unconditional terminal cadence floors, and bounded
293
+ SVG rendering. Visual downsampling must never alter full-resolution metrics,
294
+ matching, reconciliation, or `trades.jsonl`.
295
+
296
+ Reuse already chronological trades instead of sorting each cohort/window again,
297
+ group regimes in one pass, and stream normalized trade/match artifacts with
298
+ backpressure. Do not build one export-sized output string in memory.
299
+
300
+ Bootstrap the complete immutable calendar window, including zero-trade
301
+ clusters; do not sample only active clusters. Report CSCV/PBO as unavailable
302
+ when fold vectors are identical and there is no meaningful model ranking.
303
+
304
+ Use `--researchTrace` only when the question needs the setup/entry/skip funnel.
305
+ It writes compact events plus per-test skip summaries and adds deterministic
306
+ setup identity to AI rows; keep it off when completed trades answer the question.
307
+
308
+ Before writing research results, read `references/research-notes.md` and follow
309
+ it exactly.
310
+
311
+ - Store strategy research at
312
+ `notes/<Strategy>/YYYY-MM-DD-<short-kebab-slug>.md`.
313
+ - Keep `notes/` local-only. Never stage, commit, or force-add its contents; the
314
+ directory must remain ignored by Git.
315
+ - Create one file per research question and immutable run/export lineage. Never
316
+ append another dated study to an existing rolling notes file.
317
+ - Put repository-wide work in `notes/Shared/` and genuine multi-strategy
318
+ comparisons in `notes/CrossStrategy/`; never place files directly in
319
+ `notes/`.
320
+ - Embed the complete secret-free resolved config and the authoritative
321
+ structured metrics JSON. Paths to Redis, cached orders, exports, or output
322
+ reports are not enough because those artifacts may be deleted.
323
+ - Use `reproduction: complete` only when the note alone preserves every
324
+ reported aggregate metric and its lineage. Mark missing historical evidence
325
+ `partial` or `blocked`; never reconstruct it from current defaults.
326
+ - Run
327
+ `node .codex/skills/strategy-backtest-research/scripts/research-notes-check.mjs`
328
+ after creating or editing research records.
329
+
330
+ ## Validation
331
+
332
+ - Run the affected strategy tests after strategy edits, for example `yarn jest packages/strategies/src/<StrategyName> --runInBand`.
333
+ - Run `yarn prettify` before broader verification.
334
+ - Run `yarn checks` before final handoff when practical.