@battlegrid/mcp-server 31.2.93 → 31.2.95
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.
- package/README.md +47 -0
- package/SKILL.md +3 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/skills/EXPORT.json +15 -15
- package/skills/battlegrid-agent-management/SKILL.md +1 -1
- package/skills/battlegrid-arena-play/SKILL.md +22 -2
- package/skills/battlegrid-market-analysis/SKILL.md +1 -0
- package/skills/battlegrid-radar-deployment/SKILL.md +21 -13
- package/skills/battlegrid-radar-deployment/references/arena-stage-examples.md +1 -4
- package/skills/battlegrid-strategy-authoring/SKILL.md +63 -70
- package/skills/battlegrid-strategy-authoring/references/strategy-stage-examples.md +11 -5
- package/skills/battlegrid-strategy-doctor/SKILL.md +10 -6
- package/skills/battlegrid-strategy-examples/SKILL.md +42 -58
- package/skills/battlegrid-strategy-examples/references/playbooks.md +10 -24
- package/skills/battlegrid-strategy-examples/references/recipes.md +1 -1
- package/skills/battlegrid-strategy-examples/references/tradingview-ports.md +5 -9
- package/skills/battlegrid-trade-analysis/SKILL.md +2 -2
- package/skills/battlegrid-trade-proposal/SKILL.md +4 -4
package/README.md
CHANGED
|
@@ -24,6 +24,53 @@ Seeing package `31.x` alongside handshake `battlegrid@33.x` — the package **be
|
|
|
24
24
|
|
|
25
25
|
**What this changes for you:** nothing about how you call anything. Upgrading the package no longer waits on a server deploy, and a server deploy no longer strands you on a package that names the wrong contract — reconnect and the announcement follows. **Contract breaking-change notes are no longer keyed to package versions**, since a contract move is no longer a release here; the v11-and-earlier notes below are kept as history, and the live vocabulary is always discovery.
|
|
26
26
|
|
|
27
|
+
## Contract history — v108 (conditions are the only entry gate; signal rules are removed)
|
|
28
|
+
|
|
29
|
+
**Breaking at v108: signal rules, the aggregate-score gate and the required-count gate are removed.**
|
|
30
|
+
v108 is the contract on top of v107. A strategy's deterministic entry gate is its conditions: a
|
|
31
|
+
required condition, or a condition that carries a verdict. A strategy that declares neither never
|
|
32
|
+
trades, and its draft says so with the warning `NO_ENTRY_CONDITION`.
|
|
33
|
+
|
|
34
|
+
### Removed tools
|
|
35
|
+
|
|
36
|
+
- **`simulate_aggregate_score`, `list_strategy_signals`, `get_strategy_signal_definition`,
|
|
37
|
+
`derive_strategy_rule_view` and `get_coin_signal_preview`** leave discovery with no alias. A call
|
|
38
|
+
gets the standard unknown-tool refusal.
|
|
39
|
+
|
|
40
|
+
### Rejected input — something you send is no longer accepted
|
|
41
|
+
|
|
42
|
+
- **`stage_strategy_draft` refuses the `SIGNAL_RULES` and `SETUP_GATES` axes** as unrecognized keys.
|
|
43
|
+
The ATR floor `minAtrPct` is staged in the `TRADE_LEVEL_POLICY` axis, beside the stop-loss multiples
|
|
44
|
+
and the risk-reward minimum; a `TRADE_LEVEL_POLICY` stage without it is refused.
|
|
45
|
+
- **`decide_trade` cites `entry.conditionChecklist`**: 1–8 items `{ conditionKey, verdict,
|
|
46
|
+
interpretation }` over the decision's evaluated entry conditions, each key at most once, `CONFIRM`
|
|
47
|
+
only on a condition that read TRUE. `signalChecklist` and `signalModulesUsed` are refused.
|
|
48
|
+
- **The signal-log and agent-profile filters refuse `dominantBias`.**
|
|
49
|
+
|
|
50
|
+
### Reshaped output — something you read has moved or been removed
|
|
51
|
+
|
|
52
|
+
- **Strategies, agents and drafts** lose `signalRules`, `signalRuleTally`, `minAggregateScore` and
|
|
53
|
+
`minRequiredCount`; the trading-config catalog loses the gate dial steps.
|
|
54
|
+
- **Qualification and scans** (`get_agent_coin_qualification`, `scan_agent_coins`, `scan_coin_agents`)
|
|
55
|
+
lose the score and required-count gates, the score shortfall and the signal readings. Scan rows rank
|
|
56
|
+
qualifying first, then by ticker or agent name.
|
|
57
|
+
- **Radar reads** lose every score field: the activity events, the close decision, the curve samples
|
|
58
|
+
(`{ at, atrPct, qualified }`) and the curve digest.
|
|
59
|
+
- **Entry decisions** carry `conditionChecklist` in place of `signalChecklist` and `signalModulesUsed`.
|
|
60
|
+
The public signal-log detail serves it as `{ name, outcome }` only.
|
|
61
|
+
- **Signal logs and signal performance** lose the aggregate score, bias, conflict and count fields; a
|
|
62
|
+
signal-log detail loses its scorecard and serves `candidateLevels`. The agent explorer loses its
|
|
63
|
+
average score.
|
|
64
|
+
|
|
65
|
+
### Narrowed enums
|
|
66
|
+
|
|
67
|
+
- **The qualification and screen reasons lose `AGGREGATE_BELOW_MIN` and `REQUIRED_COUNT_BELOW_MIN`
|
|
68
|
+
and gain `NO_ENTRY_CONDITION`**, which is the first reason a strategy fails. The attempt reasons lose
|
|
69
|
+
`NO_ALLOCATED_SIGNALS`, and the error codes lose `REPAIR_REQUIRED`.
|
|
70
|
+
|
|
71
|
+
A client that stages a signal rule or a gate, cites a signal in `decide_trade`, or reads a score field
|
|
72
|
+
breaks at v108, which is why this is a MAJOR.
|
|
73
|
+
|
|
27
74
|
## Contract history — v107.1 (an arena entry is recorded before its fee moves)
|
|
28
75
|
|
|
29
76
|
**Additive at v107.1: a paid entry can be recorded while its fee confirms.** v107.1 is the contract on top
|
package/SKILL.md
CHANGED
|
@@ -17,7 +17,7 @@ from BattleGrid's own server so they name exactly the tools you reach here:
|
|
|
17
17
|
|---|---|
|
|
18
18
|
| Playing Market Grid sessions | `battlegrid-arena-play` |
|
|
19
19
|
| Building or changing a strategy | `battlegrid-strategy-authoring` |
|
|
20
|
-
| Composing beyond a bare template —
|
|
20
|
+
| Composing beyond a bare template — report sections, conditions, trade levels, playbooks | `battlegrid-strategy-examples` |
|
|
21
21
|
| Creating and governing intelligence agents | `battlegrid-agent-management` |
|
|
22
22
|
| Putting an agent on standing duty (Radar, Arena presets) | `battlegrid-radar-deployment` |
|
|
23
23
|
| Reading the market — regime, funding, leaders, a coin deep-dive | `battlegrid-market-analysis` |
|
|
@@ -43,7 +43,7 @@ Never put `account` inside `request`, and never flatten request fields beside it
|
|
|
43
43
|
|
|
44
44
|
## Scopes
|
|
45
45
|
|
|
46
|
-
- `mcp:read` — strategy discovery **and** non-financial configuration writes (stage and commit strategy and agent drafts
|
|
46
|
+
- `mcp:read` — strategy discovery **and** non-financial configuration writes (stage and commit strategy and agent drafts). Treat it as configuration authority, not view-only.
|
|
47
47
|
- `mcp:wager` — financial actions (submit paid entries, accept/cancel entry decisions, deployment policies). Enable **Server-Signed Wagers** in Profile → MCP to grant it. Pending entry decisions come from the conversational surface, which waits for approval; an agent deployed to a radar coin or a trading-enabled arena slot executes without one.
|
|
48
48
|
|
|
49
49
|
## Author a strategy or an agent, and bind them
|
|
@@ -93,7 +93,7 @@ The `play-market-grid` prompt (discover via `prompts/list`) provides a guided en
|
|
|
93
93
|
|
|
94
94
|
## Retired operations
|
|
95
95
|
|
|
96
|
-
`create_strategy`, the plan tools (`compile_strategy_plan`, `stage_strategy_plan`, `apply_strategy_plan`), `update_strategy_signal_rule`, and the direct agent writers (`create_intelligence_agent`, `update_intelligence_agent`, `rebind_intelligence_agent`) are **retired** — they are absent from discovery and cannot be invoked. Stage into the entity's draft, read it back, and commit the version you read; a
|
|
96
|
+
`create_strategy`, the plan tools (`compile_strategy_plan`, `stage_strategy_plan`, `apply_strategy_plan`), `update_strategy_signal_rule`, the signal-rule tools (`simulate_aggregate_score`, `list_strategy_signals`, `get_strategy_signal_definition`, `derive_strategy_rule_view`, `get_coin_signal_preview`), and the direct agent writers (`create_intelligence_agent`, `update_intelligence_agent`, `rebind_intelligence_agent`) are **retired** — they are absent from discovery and cannot be invoked. Stage into the entity's draft, read it back, and commit the version you read; a strategy's entry gate is its conditions (a required or verdict-carrying condition — a strategy with none never trades, and its draft warns `NO_ENTRY_CONDITION`), its ATR floor `minAtrPct` is part of the `TRADE_LEVEL_POLICY` axis, and a strategy binding is the agent draft's `STRATEGY_BINDING` axis. A deployment preview's `previewToken`, and the `confirm` on a deployment commit, resume, delete or draft discard, are retired the same way: a strict input refuses either key. Do not attempt flat legacy payloads; the server enforces a closed-world request root and the proxy never reconstructs them.
|
|
97
97
|
|
|
98
98
|
## Common errors
|
|
99
99
|
|
|
@@ -106,6 +106,5 @@ The `play-market-grid` prompt (discover via `prompts/list`) provides a guided en
|
|
|
106
106
|
| `DRAFT_VERSION_MOVED` | The draft changed after you read it, or no draft is held (`details.draftVersion` null) | Call `get_<kind>_draft` again, show the player what it now holds, and commit only on their word |
|
|
107
107
|
| `DRAFT_AXIS_CONTESTED` | The player changed `details.contestedAxes` in their open form after the version you staged against | Read the draft again and propose against what they now have |
|
|
108
108
|
| `CONFLICT` on a commit | The live revision moved after the draft read | Read the draft again, show the player the new diff and impact, and commit at the new `committedRevision` only on their word |
|
|
109
|
-
| Required at allocation Off | A rule flags `required` on a signal weighted `0` (contract 34) | Read `details.inertRequiredSignalIds`; per signal either raise `allocation` or set `required: false` |
|
|
110
109
|
| Method not found | Calling a retired/unknown tool | Re-run `tools/list`; stage, read and commit through the entity's draft |
|
|
111
110
|
| `Wager scope required` | `mcp:wager` not enabled | Enable Server-Signed Wagers in Profile → MCP |
|
package/dist/index.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ import { type Implementation, type Prompt, type Resource } from '@modelcontextpr
|
|
|
49
49
|
* being asked. Move it for a change to THIS package — a proxy fix, a dependency bump, a docs
|
|
50
50
|
* correction. Never move it to track the server.
|
|
51
51
|
*/
|
|
52
|
-
export declare const PACKAGE_VERSION = "31.2.
|
|
52
|
+
export declare const PACKAGE_VERSION = "31.2.95";
|
|
53
53
|
export declare const DEFAULT_URL = "https://mcp.battlegrid.trade/mcp";
|
|
54
54
|
export interface EnvConfig {
|
|
55
55
|
apiKeys: string[];
|
package/dist/index.js
CHANGED
|
@@ -52,7 +52,7 @@ import { ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema
|
|
|
52
52
|
* being asked. Move it for a change to THIS package — a proxy fix, a dependency bump, a docs
|
|
53
53
|
* correction. Never move it to track the server.
|
|
54
54
|
*/
|
|
55
|
-
export const PACKAGE_VERSION = '31.2.
|
|
55
|
+
export const PACKAGE_VERSION = '31.2.95';
|
|
56
56
|
export const DEFAULT_URL = 'https://mcp.battlegrid.trade/mcp';
|
|
57
57
|
const MAX_RETRIES = 3;
|
|
58
58
|
const RETRY_DELAYS_MS = [2000, 4000, 8000];
|
package/package.json
CHANGED
package/skills/EXPORT.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generator": "battlegrid-app/server/scripts/export-mcp-skills.mjs",
|
|
3
|
-
"contractVersion": "
|
|
3
|
+
"contractVersion": "108.2.0",
|
|
4
4
|
"files": {
|
|
5
|
-
"battlegrid-agent-management/SKILL.md": "
|
|
5
|
+
"battlegrid-agent-management/SKILL.md": "34a868f8068df189ce13af47c23011aabcf6a1f07128da4d4706066628cfaa5f",
|
|
6
6
|
"battlegrid-agent-management/references/agent-stage-examples.md": "d47555906ce8dedf4c17422f8f5d60187f2d6b3c0af5d9545617a10a5bdb59a1",
|
|
7
|
-
"battlegrid-arena-play/SKILL.md": "
|
|
8
|
-
"battlegrid-market-analysis/SKILL.md": "
|
|
9
|
-
"battlegrid-radar-deployment/SKILL.md": "
|
|
10
|
-
"battlegrid-radar-deployment/references/arena-stage-examples.md": "
|
|
7
|
+
"battlegrid-arena-play/SKILL.md": "719dfd57a9ad5b70801f366f11d0e0a57c87c7aae7751b9acca7a5a1584aa36e",
|
|
8
|
+
"battlegrid-market-analysis/SKILL.md": "b647dbe9db4ecc67b744b7f7a82ec4e56f2e7f4d2cb1c20546649085b1ae1529",
|
|
9
|
+
"battlegrid-radar-deployment/SKILL.md": "12ae488bcc81e17fdd749448ecd98f42846c98960895c1d579db833836739eb2",
|
|
10
|
+
"battlegrid-radar-deployment/references/arena-stage-examples.md": "f605aaa266a291ef1b6d02a0e8885ad5df2fea88c800be2b6625cd629cd741f2",
|
|
11
11
|
"battlegrid-radar-deployment/references/radar-stage-examples.md": "1ddad4a11f021dd65234ee65cc12d7d1561fe9acfd61cb021f4352080d4cecd5",
|
|
12
|
-
"battlegrid-strategy-authoring/SKILL.md": "
|
|
13
|
-
"battlegrid-strategy-authoring/references/strategy-stage-examples.md": "
|
|
14
|
-
"battlegrid-strategy-doctor/SKILL.md": "
|
|
15
|
-
"battlegrid-strategy-examples/SKILL.md": "
|
|
16
|
-
"battlegrid-strategy-examples/references/playbooks.md": "
|
|
17
|
-
"battlegrid-strategy-examples/references/recipes.md": "
|
|
18
|
-
"battlegrid-strategy-examples/references/tradingview-ports.md": "
|
|
19
|
-
"battlegrid-trade-analysis/SKILL.md": "
|
|
20
|
-
"battlegrid-trade-proposal/SKILL.md": "
|
|
12
|
+
"battlegrid-strategy-authoring/SKILL.md": "2b6bb9a9f419bae5dd85457f6f89131fd6f09ab218f67a0d9e27cad4072945fe",
|
|
13
|
+
"battlegrid-strategy-authoring/references/strategy-stage-examples.md": "9822cc2bcc8975a3e436c2a960b10e03c95e6e6b4b04bc2206e0ac90688cab66",
|
|
14
|
+
"battlegrid-strategy-doctor/SKILL.md": "e34e055b0cc9b355bc1adeb5d49d464eaa0756ca3f48dc89ca2ccdda94e1311f",
|
|
15
|
+
"battlegrid-strategy-examples/SKILL.md": "baf8f976d1b33c9009f21bb292943798a233464ebe4149f2f887cc40e2bfa5d4",
|
|
16
|
+
"battlegrid-strategy-examples/references/playbooks.md": "2309eb7e8324f563c5b1b51e05da931b37c542484135a2be749eff6ef78aa40f",
|
|
17
|
+
"battlegrid-strategy-examples/references/recipes.md": "3fc3280a854fca924b77f2fe154231e91a0dc779023413597d966cbb1ac88baf",
|
|
18
|
+
"battlegrid-strategy-examples/references/tradingview-ports.md": "fe70a84c700f0cd72b9adf91cafccae2af0db007951afc9be37bc3134142c5a1",
|
|
19
|
+
"battlegrid-trade-analysis/SKILL.md": "3f927b4f9796178526fa1673a2043c5f14358c39aa955de33192ea58641f18fb",
|
|
20
|
+
"battlegrid-trade-proposal/SKILL.md": "e761fc6bddc0d1db79fcb90046d03a18439562c8658de726ec286830edd6369b"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -171,7 +171,7 @@ State the blast radius **from server fields, as numbers**, before the confirm fo
|
|
|
171
171
|
- **Rebind** — a strategy change is the draft's STRATEGY_BINDING axis: stage `{ strategyId }`, read
|
|
172
172
|
`get_agent_draft`, and take both strategies from its `impact.rebind` — the strategy it replaces
|
|
173
173
|
(`fromStrategyName`) and the one it binds (`toStrategyName`, at `toStrategyRevision`). Say that
|
|
174
|
-
the target strategy's
|
|
174
|
+
the target strategy's report, conditions, trade levels, prose and timeframe **replace** the ones
|
|
175
175
|
materialized on the agent (this is not a merge), naming both strategies. Agent-owned settings are
|
|
176
176
|
untouched. The commit checks the new strategy against the coins the radar acts on for this agent;
|
|
177
177
|
a refusal names the coin and the condition — surface it, never retry it unchanged.
|
|
@@ -47,7 +47,10 @@ the enablement path there.
|
|
|
47
47
|
1. `list_market_grid_sessions` with status `PENDING` — the sessions still enterable. **The
|
|
48
48
|
`sessionId` you use comes from here; never fabricate one.**
|
|
49
49
|
2. `get_market_grid_session` — the coin pool (note each coin's `id`), the entry fee, the pool and
|
|
50
|
-
the
|
|
50
|
+
the session's three instants: `startsAt` (the **Opening Bell** — the open of the one candle it
|
|
51
|
+
scores), `lockAt` (entries close) and `settleAt` (the candle closes). Entries stay open through
|
|
52
|
+
the Opening Bell window, from `startsAt` until `lockAt`, so an entry made inside the window can
|
|
53
|
+
read the candle that closed at the bell; the full candle from `startsAt` is scored either way.
|
|
51
54
|
3. `get_market_context` for that session — the indicators, rankings and trends the picks will
|
|
52
55
|
actually be reasoned from.
|
|
53
56
|
4. `check_market_grid_submission` — **before composing anything.** If a submission already exists,
|
|
@@ -102,7 +105,8 @@ reasoning as the player's, and the attribution is part of what was scored.
|
|
|
102
105
|
|
|
103
106
|
### 5. After settlement
|
|
104
107
|
|
|
105
|
-
- A session moves PENDING → LIVE → RESOLVING → SETTLED.
|
|
108
|
+
- A session moves PENDING → LIVE → RESOLVING → SETTLED. It stays PENDING through the Opening Bell
|
|
109
|
+
window and goes LIVE at `lockAt`. Two states sit off that path: CANCELLED
|
|
106
110
|
(entry fees refunded) and SETTLEMENT_QUARANTINED (settlement exhausted its retries and awaits an
|
|
107
111
|
operator). Either one is the answer — report it as the status.
|
|
108
112
|
- `get_market_grid_results` — available only once the session is SETTLED. Before that it returns a
|
|
@@ -115,6 +119,22 @@ reasoning as the player's, and the attribution is part of what was scored.
|
|
|
115
119
|
the picks, so say that rather than reconstructing one. `list_my_market_grid_entries` is the history
|
|
116
120
|
across sessions. An agent's decisions are a different record, `get_agent_journal`.
|
|
117
121
|
|
|
122
|
+
## On the arena's session page
|
|
123
|
+
|
|
124
|
+
When the conversation is embedded in the player's Market Grid session page, the round on screen
|
|
125
|
+
arrives as the attached scope, and the session it names is the one in scope.
|
|
126
|
+
|
|
127
|
+
- **Propose, do not submit.** When the player asks for a grid, call `generate_agent_grid` for the
|
|
128
|
+
session in scope (the billed-inference warning in step 3 still applies). The result reaches them
|
|
129
|
+
as a card with **LOAD INTO GRID**, which puts the picks into their own builder as a starting point.
|
|
130
|
+
- **A loaded grid they have not changed is the agent's.** Their builder will not place it as theirs.
|
|
131
|
+
If they want the agent's grid entered as it stands, run step 4: one confirmation, then
|
|
132
|
+
`submit_agent_grid` on their explicit pick, never on free text.
|
|
133
|
+
- **Once they change a pick, the grid is theirs.** They place it themselves from their ticket. Do not
|
|
134
|
+
submit it for them, and do not describe it as the agent's.
|
|
135
|
+
- **A newer generation for the same agent replaces the older card.** The older one reads SUPERSEDED;
|
|
136
|
+
only the newest is what `submit_agent_grid` would enter.
|
|
137
|
+
|
|
118
138
|
## Refusals, and what each one means
|
|
119
139
|
|
|
120
140
|
Each is typed and distinguishable. Read the code, do not paraphrase:
|
|
@@ -40,6 +40,7 @@ Run these in order. Skip a step only when the player's question makes it irrelev
|
|
|
40
40
|
`source: { "kind": "FIELDS", "timeframe": …, "sections": [ … ] }` — no authoring vocabulary is
|
|
41
41
|
needed. Use `{ "mode": "ranked", "limit": N }` as the coin selection when you have no explicit
|
|
42
42
|
list. Looping a per-coin tool over N coins costs several times this and returns the same values.
|
|
43
|
+
A refused preview names its recovery in `nextAct`.
|
|
43
44
|
4. **Coin deep-dive**, when the player named a coin or when one dominates the read: the SAME
|
|
44
45
|
`preview_strategy_report` call as step 3, with `{ "mode": "explicit", "tickers": ["SOL"] }` as the
|
|
45
46
|
coin selection and the funding / open-interest / positioning sections chosen — one coin is a
|
|
@@ -36,9 +36,8 @@ approves needs no deployment. An Arena deployment enters an agent into a preset'
|
|
|
36
36
|
5. **Answering "why isn't it firing?" by paging the journal.** *Cue: any question about why a
|
|
37
37
|
deployed agent has been quiet — "is it working?", "it hasn't traded all day", "what's blocking
|
|
38
38
|
it?".* `get_radar_activity_summary` now answers the whole question in one small call — which
|
|
39
|
-
cause recurs, how
|
|
40
|
-
|
|
41
|
-
already serves. The journal read is for ONE occurrence, or for more rows than the summary's ten.
|
|
39
|
+
cause recurs, how often the pair qualified, and what just happened — so paging the journal for it
|
|
40
|
+
tallies an aggregate the server already computed and re-derives a reading it already serves. The journal read is for ONE occurrence, or for more rows than the summary's ten.
|
|
42
41
|
→ step 5.
|
|
43
42
|
|
|
44
43
|
## Sequence
|
|
@@ -198,18 +197,26 @@ resolver:
|
|
|
198
197
|
- `reading.live` is the reading its qualification verdict was built from: the gates with their margins
|
|
199
198
|
(`qualification`); every entry-lane condition — required, direction-setting, and the ones they
|
|
200
199
|
reference — with its outcome and its clause values against their thresholds
|
|
201
|
-
(`conditions.entries[]`);
|
|
200
|
+
(`conditions.entries[]`); and the data it lacked
|
|
202
201
|
(`missingData`). An `UNEVALUATED` entry is a condition this tick could not read, with its
|
|
203
202
|
`reachReason`. A pair the scan can never read was refused above, so every such cause is one the next
|
|
204
203
|
sweep can change — report it as the current reading, never as a reason the deployment will not
|
|
205
204
|
work. `anchorBarStatus` says which bar the conditions read (`live` while it is still forming), and
|
|
206
|
-
`scoredBarStart` names the bar the
|
|
205
|
+
`scoredBarStart` names the bar the gates were read on. **A live reading decides
|
|
207
206
|
nothing**: the radar decides at the close, on the closed bar, so say what it reads right now, never
|
|
208
207
|
that it will fire.
|
|
209
208
|
- `reading.lastClose` is the one decision the agent's on-duty row names as its last close: `RECORDED`
|
|
210
209
|
with that bar's close-decision record — the reading it was decided on, or why it was missed —
|
|
211
210
|
`PENDING` while that record is still being written, or `NONE` when the pair remembers no decision.
|
|
212
|
-
For the decisions before it, call `get_radar_close_decisions` (step 5).
|
|
211
|
+
For the decisions before it, call `get_radar_close_decisions` (step 5). Name a close by the served
|
|
212
|
+
`barCloseAt` — on a record's `bar`, on a `PENDING` close and on the on-duty row's
|
|
213
|
+
`closeDecision.last` — and a `DEFERRED` row's bar being decided by `closeDecision.decidingBarStart`;
|
|
214
|
+
never add a timeframe to `barStart`.
|
|
215
|
+
- `reading.sinceClose` is how the live reading moved since the deciding reading, computed by the
|
|
216
|
+
server: the ATR reading's move (`UP`, `DOWN`, `UNCHANGED`), whether the required conditions, the
|
|
217
|
+
trade levels, the condition verdict and the first failing gate changed, and each live condition
|
|
218
|
+
against the deciding entry for its key (`ABSENT`, `NOT_READ`, `UNCHANGED`, `CHANGED`). It is `null` unless `lastClose` is `RECORDED`
|
|
219
|
+
on a reading. Quote it; never compare the two readings yourself.
|
|
213
220
|
|
|
214
221
|
An `UNSCORABLE` entry is an on-duty agent the preview could not read on the coin, with
|
|
215
222
|
`coinDataStopped` when the coin's data explains why; it never fails the preview. `readings` is null
|
|
@@ -304,7 +311,7 @@ Four reads, cheapest first. Stop as soon as the player's question is answered.
|
|
|
304
311
|
the agent the pause refused, not to a trade. That is the whole answer while the pause lasts; never
|
|
305
312
|
send the player to change an agent or a policy for it. Most "is it working?" questions end here.
|
|
306
313
|
When the question is what ONE on-duty agent of a scanning coin needs to fire — which condition
|
|
307
|
-
reads false, how far
|
|
314
|
+
reads false, how far the ATR reading sits from its floor — drill into its row
|
|
308
315
|
with `get_agent_coin_qualification({ agentId, coinTickers: [<the coin's ticker>], reading: true })`
|
|
309
316
|
and read the verdict's `reading` as step 2 of the deploy flow describes it: `live` is what the
|
|
310
317
|
agent reads now, and `lastClose` is the decision its row names as its last close, with the reading
|
|
@@ -313,11 +320,12 @@ Four reads, cheapest first. Stop as soon as the player's question is answered.
|
|
|
313
320
|
carries three parts and they answer three different questions, each on its own scope:
|
|
314
321
|
- `groups` — which cause recurs and how often, over the window the response names. Quote the
|
|
315
322
|
counts with that window; never sum them across calls.
|
|
316
|
-
- `curveDigest` — how
|
|
317
|
-
lowest-numbered slot on duty now, named in `curveAgentName`)
|
|
318
|
-
|
|
319
|
-
coin
|
|
320
|
-
`ringEndAt` describe the ring, NOT the cause window
|
|
323
|
+
- `curveDigest` — how often the pair qualified, over the FIRST on-duty agent's ring (the
|
|
324
|
+
lowest-numbered slot on duty now, named in `curveAgentName`): `qualifiedCount` of
|
|
325
|
+
`sampleCount`, and the latest ATR% with how many samples read one. A pair that qualified on no
|
|
326
|
+
sample is one whose strategy does not fit this coin as it trades now; the `groups` above name the
|
|
327
|
+
gate that blocked it. Its `ringStartAt` / `ringEndAt` describe the ring, NOT the cause window
|
|
328
|
+
above.
|
|
321
329
|
- `recentEvents` — the last ten key events, lean. Deliberately NOT bounded by the cause window, so
|
|
322
330
|
a pair quiet for longer returns no groups beside populated older rows. That is correct, not a
|
|
323
331
|
contradiction; each row carries its own `occurredAt`.
|
|
@@ -334,7 +342,7 @@ Four reads, cheapest first. Stop as soon as the player's question is answered.
|
|
|
334
342
|
`outcome` (`FIRED`, `NOT_QUALIFIED`, `CLAIMED` or `MISSED`), the fire's `fireDisposition` as
|
|
335
343
|
arbitration settled it, and the `evidence` the bar was decided on — the closed-bar reading's gates
|
|
336
344
|
with their margins, every condition's outcome with its clause evidence, each condition the scan
|
|
337
|
-
could not evaluate with its reach reason,
|
|
345
|
+
could not evaluate with its reach reason, and `missingData` — or, for a
|
|
338
346
|
`MISSED` bar, the close step's own answer: the bar never settled, an input was not on its due bar,
|
|
339
347
|
or the window passed. An `outcome` of `FIRED` says the bar qualified and its agent was offered the
|
|
340
348
|
coin's fire; `fireDisposition` says what the fire came to — `FIRED` when a decision was enqueued,
|
|
@@ -22,7 +22,7 @@ axis you omit keeps the value the draft already has.
|
|
|
22
22
|
"draftVersion": 0,
|
|
23
23
|
"axes": {
|
|
24
24
|
"DEFAULT_SLOT": {
|
|
25
|
-
"defaultSlot": { "agentId": "<AGENT_ID>", "minConfidence": null
|
|
25
|
+
"defaultSlot": { "agentId": "<AGENT_ID>", "minConfidence": null }
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -42,7 +42,6 @@ axis you omit keeps the value the draft already has.
|
|
|
42
42
|
{
|
|
43
43
|
"agentId": "<AGENT_ID>",
|
|
44
44
|
"minConfidence": null,
|
|
45
|
-
"entryStrategy": "STANDARD",
|
|
46
45
|
"conditions": [{ "kind": "regime", "regimes": ["bull_expansion", "bull_ranging"] }]
|
|
47
46
|
}
|
|
48
47
|
]
|
|
@@ -68,7 +67,6 @@ session occurrence, never both.
|
|
|
68
67
|
{
|
|
69
68
|
"agentId": "<AGENT_ID>",
|
|
70
69
|
"minConfidence": 0.6,
|
|
71
|
-
"entryStrategy": "TWO_LOOK",
|
|
72
70
|
"conditions": [
|
|
73
71
|
{ "kind": "session_start", "startTimes": ["14:00:00", "15:00:00"], "days": [1, 2, 3, 4, 5] }
|
|
74
72
|
]
|
|
@@ -93,7 +91,6 @@ session occurrence, never both.
|
|
|
93
91
|
{
|
|
94
92
|
"agentId": "<AGENT_ID>",
|
|
95
93
|
"minConfidence": null,
|
|
96
|
-
"entryStrategy": "STANDARD",
|
|
97
94
|
"conditions": [
|
|
98
95
|
{ "kind": "regime", "regimes": ["volatile"] },
|
|
99
96
|
{ "kind": "session_start", "startTimes": ["14:00:00"], "days": [1, 2, 3, 4, 5] }
|
|
@@ -15,12 +15,13 @@ All three come from real authoring sessions, and all three were discovered only
|
|
|
15
15
|
was already built. None of them is allowed to happen here.
|
|
16
16
|
|
|
17
17
|
1. **Built ≠ picked.** The player selected a "≥ +10%" trigger and a +5% trigger was implemented.
|
|
18
|
-
Nobody noticed until the results looked wrong. You prevent this by showing the *drafted*
|
|
18
|
+
Nobody noticed until the results looked wrong. You prevent this by showing the *drafted* conditions,
|
|
19
19
|
as the server's own draft read serves them, next to their *locked* picks, before committing, and
|
|
20
20
|
naming any contradiction yourself.
|
|
21
21
|
2. **Silent zero-trigger.** A strategy was built that could never fire, and produced nothing for
|
|
22
22
|
days before anyone diagnosed it. You prevent this by reading the draft's own report preview and
|
|
23
|
-
|
|
23
|
+
its diagnostics before committing, and flagging a draft that shows no passing conditions or
|
|
24
|
+
warns `NO_ENTRY_CONDITION`.
|
|
24
25
|
|
|
25
26
|
3. **Silent substitution.** A player asked for a strategy that triggers on the daily chart and
|
|
26
27
|
executes on the 4-hour. The grammar carries no such semantics. Instead of saying so, the flow
|
|
@@ -100,13 +101,19 @@ anywhere; if the two ever disagree, you have created the exact ambiguity this st
|
|
|
100
101
|
### 3. Discover the grammar — never guess it
|
|
101
102
|
|
|
102
103
|
`list_strategy_categories` → `list_strategy_vocabulary` → `get_strategy_column_contract` and
|
|
103
|
-
`get_strategy_section_template
|
|
104
|
-
`get_strategy_signal_definition` for each signal you intend to use.
|
|
104
|
+
`get_strategy_section_template`.
|
|
105
105
|
|
|
106
|
-
Compose sections, columns
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
Compose sections, columns and conditions **only** from vocabulary returned in this conversation. A
|
|
107
|
+
field you remember from another strategy is not discovery.
|
|
108
|
+
|
|
109
|
+
**Conditions are the only deterministic entry gate.** A condition gates an entry when it is
|
|
110
|
+
`required` or carries a verdict (UP, DOWN or NEITHER); a building block — neither required nor a
|
|
111
|
+
verdict carrier — gates nothing, and an exit rule never counts. A strategy whose entry conditions
|
|
112
|
+
include no required and no verdict-carrying condition never routes a trade: every coin fails first
|
|
113
|
+
with `NO_ENTRY_CONDITION`, and its draft carries the warning of the same name. It stays a valid
|
|
114
|
+
strategy — Market Grid reads it as context — so a strategy the player means to trade needs at least
|
|
115
|
+
one. Before any condition is read, a coin must clear the ATR floor, `minAtrPct`, the
|
|
116
|
+
TRADE_LEVEL_POLICY dial beside the stop-loss band.
|
|
110
117
|
|
|
111
118
|
**Read the answer, not just the call.** Each of these returns one field that decides a composition
|
|
112
119
|
question you would otherwise guess — and a refusal you would otherwise earn:
|
|
@@ -150,25 +157,17 @@ question you would otherwise guess — and a refusal you would otherwise earn:
|
|
|
150
157
|
transform (and a chained transform) reads its series: the read shape, the window's unit, the price
|
|
151
158
|
basis and what an absent bar does. `seriesHome` says where the metric's series is kept — `candle`,
|
|
152
159
|
`history`, or `null` when the metric has no series, which is why a series transform does not
|
|
153
|
-
compose on it. Window and offset carry a declared `minimum` and
|
|
154
|
-
|
|
160
|
+
compose on it. Window and offset carry a declared `minimum` and a served `maximum` on each metric's
|
|
161
|
+
transform entry — the largest value whose read size fits the lookback cap, or `null` when none
|
|
162
|
+
does. Stage at most that maximum.
|
|
155
163
|
- `get_metric_construction_hints` → `rankOrderings`. Present only when rank is composable on that
|
|
156
164
|
metric, already range-gated server-side — read the offered set rather than deriving one from
|
|
157
165
|
the metric's native output.
|
|
158
166
|
|
|
159
167
|
For full-surface composition patterns — custom and benchmark sections, condition trees with
|
|
160
|
-
verdicts and enforcement
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
`derive_strategy_rule_view` belongs here, at composition time, and only here: it reports report
|
|
165
|
-
membership and registry-default allocations for sections and rows you are about to stage. It reads
|
|
166
|
-
no draft and no strategy, so it can never stand in for the review in step 5. Its suggestions and
|
|
167
|
-
reset-to-default choices change only what you stage next — no tool applies one on its own.
|
|
168
|
-
|
|
169
|
-
`simulate_aggregate_score` does **not** belong here. It is a review tool (step 5), and running it
|
|
170
|
-
now answers a question about rows you have not staged, not about the draft the player will be
|
|
171
|
-
asked to approve.
|
|
168
|
+
verdicts and `required` enforcement, the trade-level policy with its ATR floor, position-management
|
|
169
|
+
presets, worked desk-grade playbooks — activate `strategy-examples`. It teaches what to compose; this
|
|
170
|
+
skill stays the authority on the flow.
|
|
172
171
|
|
|
173
172
|
### 4. Stage, and iterate on the diagnostics
|
|
174
173
|
|
|
@@ -184,24 +183,24 @@ two stages in parallel against one draft. Complete stage payloads showing the en
|
|
|
184
183
|
stage; the response carries the id minted for it, which every later call names. A create needs
|
|
185
184
|
IDENTITY (`{ name, description, tagline }`) and TIMEFRAME_PROFILE (`{ timeframe }`). A create with
|
|
186
185
|
no REPORT starts from the platform's starting report (Price Action, RSI, MACD and Moving Averages),
|
|
187
|
-
one with no ENTRY takes the seed entry
|
|
188
|
-
|
|
186
|
+
and one with no ENTRY takes the seed entry. A create with no CONDITIONS declares no entry gate and
|
|
187
|
+
will not trade until one is staged.
|
|
189
188
|
|
|
190
189
|
**An UPDATE carries only the axes that change.** Axes you omit keep the values the draft has, and
|
|
191
190
|
an axis the draft does not hold is the committed strategy's. Each axis you send is written WHOLE —
|
|
192
|
-
a REPORT is the complete section list, CONDITIONS the complete set
|
|
193
|
-
rows replace the drafted rows for the same `signalId` and keep every other one. Restating an axis
|
|
191
|
+
a REPORT is the complete section list, CONDITIONS the complete set. Restating an axis
|
|
194
192
|
you are not changing is never required, changes nothing about the result, and the player pays for
|
|
195
193
|
every byte of it on this call and on every later step of the conversation. Send the axes you are
|
|
196
194
|
changing; send no other axis.
|
|
197
195
|
|
|
198
|
-
**A
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
`get_strategy`.
|
|
203
|
-
|
|
204
|
-
|
|
196
|
+
**A whole axis restates what it keeps.** "Raise the ATR floor to 0.8%" is one TRADE_LEVEL_POLICY
|
|
197
|
+
stage carrying all four of its dials — `minStopLossAtrMultiple`, `maxStopLossAtrMultiple`,
|
|
198
|
+
`minRiskRewardRatio` and `minAtrPct` — the three you are not changing exactly as they stand now:
|
|
199
|
+
read them from the draft's TRADE_LEVEL_POLICY when the draft holds it, otherwise from
|
|
200
|
+
`get_strategy`. The same holds for a condition: CONDITIONS carries every condition, each with its
|
|
201
|
+
`required` flag and verdict as they stand. Never set `required` or a verdict from memory, and never
|
|
202
|
+
change either unless the player asked: a wrong value there is how a building block silently becomes
|
|
203
|
+
a mandatory trade gate, or a gate silently disappears.
|
|
205
204
|
|
|
206
205
|
**Read the diagnostics every stage returns.** Past its checks of shape — an undeclared key, a
|
|
207
206
|
parameter beside `ON_CANDLE_CLOSE`, a coin that names nothing — a stage refuses nothing for being
|
|
@@ -210,9 +209,9 @@ are where you learn what the commit would do:
|
|
|
210
209
|
|
|
211
210
|
- `errors` — the refusals the commit would raise, each with its `field` and `details` naming the
|
|
212
211
|
`path`, the value it received and the `allowedDomain` it accepts. Fix the axis and stage again.
|
|
213
|
-
- `warnings`
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
- `warnings` — observations that never refuse. `NO_ENTRY_CONDITION` means the strategy declares no
|
|
213
|
+
required and no verdict-carrying entry condition, so it will never route a trade. Fix it, or carry
|
|
214
|
+
it into the review as something to explain.
|
|
216
215
|
|
|
217
216
|
An empty `errors` is not a promise: the strategy quota, the name and capital feasibility are
|
|
218
217
|
decided only by the commit itself.
|
|
@@ -237,7 +236,7 @@ Once the stage's diagnostics carry nothing you cannot explain, read the draft wi
|
|
|
237
236
|
`get_strategy_draft`. Everything here comes from that read:
|
|
238
237
|
|
|
239
238
|
- **What will actually run.** Its `diff` — every drafted axis with its `live` and drafted value
|
|
240
|
-
and the field-level `changes` between them, the drafted
|
|
239
|
+
and the field-level `changes` between them, the drafted conditions among them — beside the
|
|
241
240
|
picks they locked in step 2. **If any drafted row or diff entry contradicts a locked pick, say so
|
|
242
241
|
in words before you ask for anything.** Do not make them spot it.
|
|
243
242
|
- **All of what the commit publishes.** The diff names every axis the draft holds, including
|
|
@@ -250,23 +249,16 @@ Once the stage's diagnostics carry nothing you cannot explain, read the draft wi
|
|
|
250
249
|
register with every coin's verdict, and the verdict tally; ask for `"detailed"` only when you need
|
|
251
250
|
each coin's full evaluation or the addressable headers (`authoring`). A preview is bounded by a
|
|
252
251
|
deadline and a result-character cap, both served by discovery as `previewExecutionLimits`
|
|
253
|
-
(`deadlineMs`, `maxResultChars`); one over either is refused whole, never truncated
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
`
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
per-signal scores from the preview you just read — and show those inputs beside its output so a
|
|
264
|
-
copy slip is visible on the card itself.
|
|
265
|
-
|
|
266
|
-
**Flag before confirming** if the preview shows no passing conditions, the coin preview shows
|
|
267
|
-
zero triggered signals, the simulation reports `wouldRoute: false`, or the diagnostics warn
|
|
268
|
-
`NO_SIGNAL_ACTIVE`. Any one of those means the strategy probably never fires — ask whether to
|
|
269
|
-
revise rather than presenting it as healthy.
|
|
252
|
+
(`deadlineMs`, `maxResultChars`); one over either is refused whole, never truncated, and the
|
|
253
|
+
refusal carries `nextAct: narrow` — preview again asking for less, in the order the tool's
|
|
254
|
+
description gives. The preview's `coinSelection` is its cohort, never strategy state: no strategy
|
|
255
|
+
has one and `get_strategy` will not return one, so choose it — a short explicit list of the
|
|
256
|
+
tickers the change is about for a single-condition edit, a `ranked` cohort for a broad one. Any
|
|
257
|
+
reasonable cohort is correct.
|
|
258
|
+
|
|
259
|
+
**Flag before confirming** if the preview shows no passing conditions or the diagnostics warn
|
|
260
|
+
`NO_ENTRY_CONDITION`. Either one means the strategy probably never fires — ask whether to revise
|
|
261
|
+
rather than presenting it as healthy.
|
|
270
262
|
|
|
271
263
|
**State the impact as numbers, not buried in prose.** The read's `impact` carries:
|
|
272
264
|
|
|
@@ -314,13 +306,13 @@ Prose never triggers a commit. The same holds for an answer typed into the form'
|
|
|
314
306
|
answer-in-your-own-words box: it is the player's words in an answer slot, not a confirming pick,
|
|
315
307
|
so treat it exactly as you would free text in the chat.
|
|
316
308
|
|
|
317
|
-
Do not pre-check ownership,
|
|
309
|
+
Do not pre-check ownership, validity, quota or the name before calling. The server is the only
|
|
318
310
|
authority on all of them; your job is to react to what it returns.
|
|
319
311
|
|
|
320
|
-
**Report the change from the receipt.** The commit returns the committed `strategy
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
312
|
+
**Report the change from the read and the receipt.** The commit returns the committed `strategy`.
|
|
313
|
+
State each change as its live value in the read the player confirmed against its value in the
|
|
314
|
+
receipt's strategy. Never describe a value from memory or from any other read — those two are the
|
|
315
|
+
only records that cannot be stale.
|
|
324
316
|
|
|
325
317
|
**Offer to discard a draft only on the player's explicit word**, never on your own judgement that
|
|
326
318
|
it looks stale, and never batched into another act. `get_strategy_draft` is the read of what a
|
|
@@ -334,11 +326,12 @@ removed. The unsaved values are gone afterwards and there is no other copy.
|
|
|
334
326
|
|
|
335
327
|
`fork_strategy`, `restore_strategy`, `archive_strategy`, `discard_strategy_draft` and
|
|
336
328
|
`preview_strategy_report` are part of this flow. Every change to a strategy's content — a single
|
|
337
|
-
tuned
|
|
338
|
-
verbs writes content.
|
|
329
|
+
tuned condition or dial included — is a staged draft committed with `commit_strategy_draft`; none of
|
|
330
|
+
the other verbs writes content.
|
|
339
331
|
|
|
340
|
-
- **Tuning a single
|
|
341
|
-
State how many agents are bound, and that the change reaches every one of them
|
|
332
|
+
- **Tuning a single condition or dial** is its axis staged whole (step 4), read, confirmed and
|
|
333
|
+
committed. State how many agents are bound, and that the change reaches every one of them
|
|
334
|
+
immediately.
|
|
342
335
|
- **Forking** — `fork_strategy` takes the `strategyId`, the exact `sourceRevision` to copy and an
|
|
343
336
|
optional `name`, and returns a NEW create draft's `strategyId` and `draftVersion`. **No strategy
|
|
344
337
|
exists yet.** Read the draft with `get_strategy_draft` — every authored axis equals the source
|
|
@@ -352,10 +345,9 @@ verbs writes content.
|
|
|
352
345
|
- **Restoring** — find the archived strategy with `list_strategies` and `get_strategy` with
|
|
353
346
|
`includeInactive: true`, which add the player's own strategies in any state; another player's
|
|
354
347
|
PRIVATE strategy stays hidden either way. `restore_strategy` with the `strategyId` and
|
|
355
|
-
`expectedRevision` brings back unchanged
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
commit it — that commit restores it, and its read says `operation: RESTORE`.
|
|
348
|
+
`expectedRevision` brings back the unchanged content and keeps the player's draft, re-based onto
|
|
349
|
+
the restored revision. To change the content as it comes back, stage the change into the
|
|
350
|
+
strategy's draft and commit it — that commit restores it, and its read says `operation: RESTORE`.
|
|
359
351
|
|
|
360
352
|
**Your `ask_user` is the approval, and the server does not repeat it.** No strategy verb takes a
|
|
361
353
|
confirmation flag. So never call `commit_strategy_draft`, `archive_strategy`, `restore_strategy` or
|
|
@@ -369,7 +361,8 @@ offered, and nothing else is.
|
|
|
369
361
|
|
|
370
362
|
Each refusal is a specific typed code, and a refusal of a draft's stage or commit names its next
|
|
371
363
|
act in `details.nextAct` — `get_draft` or `stage`; a moved or contested draft names `get_draft`
|
|
372
|
-
from any tool
|
|
364
|
+
from any tool, and a refused preview names `narrow`. Read it and take the cheapest correct step —
|
|
365
|
+
never retry the same call blindly.
|
|
373
366
|
|
|
374
367
|
- **`DRAFT_VERSION_MOVED`** (`nextAct: get_draft`) — the draft changed after your read: the
|
|
375
368
|
player's form saved an edit, another surface staged, or a human-paced review outlived it. Read
|
|
@@ -385,8 +378,8 @@ from any tool. Read it and take the cheapest correct step — never retry the sa
|
|
|
385
378
|
- **A validation error** (`nextAct: stage`) — the error the diagnostics named, with its own
|
|
386
379
|
`field` and `details`. Nothing was written. Return to step 4: fix the axis, stage, read, and
|
|
387
380
|
confirm again.
|
|
388
|
-
- **A refusal with no `nextAct`** — the strategy quota (`FORBIDDEN`), a name already in use,
|
|
389
|
-
`
|
|
381
|
+
- **A refusal with no `nextAct`** — the strategy quota (`FORBIDDEN`), a name already in use, or a
|
|
382
|
+
`CONFLICT` whose `details.reason` is `RADAR_DEPLOYMENT_MOVED`. The draft is
|
|
390
383
|
untouched. Clear the cause with the player — a rename is an IDENTITY stage, which makes a new
|
|
391
384
|
version to read and confirm — then commit the draft they confirmed. A moved radar deployment is
|
|
392
385
|
a race, not a decision: read and commit again.
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
checked in CI against the live `stage_strategy_draft` schema; a create example is also checked for the axes a new
|
|
5
5
|
strategy needs. Its shape is current.
|
|
6
6
|
|
|
7
|
-
These examples show the envelope and the small axes. A full composition (report sections, conditions,
|
|
8
|
-
|
|
7
|
+
These examples show the envelope and the small axes. A full composition (report sections, conditions, trade
|
|
8
|
+
levels) is in `strategy-examples`' playbooks, which have their own compile gate.
|
|
9
9
|
|
|
10
10
|
Every `<UPPER_SNAKE>` value is a placeholder: `<STRATEGY_ID>` is the id a read returned. Never send a placeholder as
|
|
11
11
|
written, and never invent an id. `draftVersion` is the version `get_strategy_draft` returned: 0 when there was no
|
|
@@ -33,9 +33,10 @@ and TIMEFRAME_PROFILE before it can be created.
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
## Change an existing strategy's
|
|
36
|
+
## Change an existing strategy's trade levels
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
TRADE_LEVEL_POLICY is sent whole: all four dials, even when only one changes. `minAtrPct` is the ATR% volatility floor
|
|
39
|
+
a coin must clear before any condition is read; the other three are the stop-loss band and the reward-to-risk floor.
|
|
39
40
|
|
|
40
41
|
```json stage_strategy_draft
|
|
41
42
|
{
|
|
@@ -43,7 +44,12 @@ SETUP_GATES is sent whole: all three gates, even when only one changes.
|
|
|
43
44
|
"strategyId": "<STRATEGY_ID>",
|
|
44
45
|
"draftVersion": 2,
|
|
45
46
|
"axes": {
|
|
46
|
-
"
|
|
47
|
+
"TRADE_LEVEL_POLICY": {
|
|
48
|
+
"minStopLossAtrMultiple": 1,
|
|
49
|
+
"maxStopLossAtrMultiple": 2,
|
|
50
|
+
"minRiskRewardRatio": 1.5,
|
|
51
|
+
"minAtrPct": 0.8
|
|
52
|
+
}
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
}
|
|
@@ -50,22 +50,26 @@ Three reads, and they are not interchangeable:
|
|
|
50
50
|
|
|
51
51
|
### 2. Diagnose from typed sources
|
|
52
52
|
|
|
53
|
-
- **The one vocabulary is `TradeEvaluationAttemptReasonCode
|
|
53
|
+
- **The one vocabulary is `TradeEvaluationAttemptReasonCode`**, two of its members
|
|
54
54
|
`@deprecated` and historical-only (`TRADING_MODE_OFF`, `TRADING_MODE_INELIGIBLE`): if either
|
|
55
55
|
turns up, it is an old row, not a live cause, and you say so. Do not translate a code into a
|
|
56
56
|
different enum's wording, and do not try to unify the platform's overlapping reason vocabularies
|
|
57
57
|
— they describe different stages and merging them invents a cause.
|
|
58
|
-
- Render every code through its display meta. A raw `
|
|
58
|
+
- Render every code through its display meta. A raw `NO_ENTRY_CONDITION` or `OPEN_POSITION_CONFLICT` on
|
|
59
59
|
screen is a system identifier leaking into an explanation.
|
|
60
60
|
- **`get_agent_decision_context` is keyed by COIN**, not by agent. Use it for "why did nothing
|
|
61
61
|
happen on SOL", once you know which coin the blocks are about.
|
|
62
62
|
- **`get_agent_coin_qualification` answers the forward-looking half.** The reason codes above say
|
|
63
63
|
why an agent did NOT trade in the past; this says whether a coin would route for it RIGHT NOW,
|
|
64
|
-
and which gate stops it —
|
|
65
|
-
|
|
66
|
-
four-member verdict as written: `NOT_ENFORCED` means the
|
|
67
|
-
|
|
64
|
+
and which gate stops it — the strategy's entry condition, candidate levels, the ATR% volatility
|
|
65
|
+
floor and the strategy's required conditions and verdict, without spending an LLM call. Read the
|
|
66
|
+
four-member verdict as written: `NOT_ENFORCED` means the strategy declares nothing for that gate to
|
|
67
|
+
enforce, `UNMEASURABLE` means the input was missing and the gate fail-opened. Neither is a pass, and
|
|
68
68
|
reporting either as "cleared" is the conflation the verdict vocabulary exists to prevent.
|
|
69
|
+
- **`NO_ENTRY_CONDITION` is a property of the strategy, not of the market.** It fails every coin
|
|
70
|
+
first, in both directions: the bound strategy declares no required and no verdict-carrying entry
|
|
71
|
+
condition, so it never routes a trade. Say so once, for every coin at once, and route the fix — a
|
|
72
|
+
required or verdict condition — to the strategy-authoring flow; no coin or radar change clears it.
|
|
69
73
|
- **A failing condition comes back as a KEY — resolve it.** `requiredConditions.failedKeys` names
|
|
70
74
|
gates like `LOCATION_OK`: an identifier, not an explanation. Read the agent's bound strategy with
|
|
71
75
|
`get_strategy` (the `strategyId` is on `get_intelligence_agent`), find the matching
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: battlegrid-strategy-examples
|
|
3
|
-
description: Full-surface composition patterns for the strategy studio — validated desk-grade examples of custom report sections, benchmark sections, condition trees with verdicts and enforcement
|
|
3
|
+
description: Full-surface composition patterns for the strategy studio — validated desk-grade examples of custom report sections, benchmark sections, condition trees with verdicts and required enforcement, the entry-condition rule, ATR trade levels with the ATR floor, and position management. Activate beside strategy-authoring whenever a strategy is being composed or upgraded beyond a basic template.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Strategy Studio — full-power composition patterns
|
|
7
7
|
|
|
8
8
|
`strategy-authoring` owns the flow (evidence → locked spec → discover → stage → review →
|
|
9
9
|
commit). This skill owns **what to compose**: a default build — a few platform sections, no
|
|
10
|
-
conditions, untouched
|
|
10
|
+
conditions, untouched trade levels — wastes the studio, and one with no entry condition never trades. The playbooks below are compiled in CI, so their
|
|
11
11
|
shapes are binding in the sense that matters — they are checked, not merely asserted. Loose tokens
|
|
12
12
|
elsewhere in this file are not covered by that gate, and vocabulary moves with deploys, so discovery
|
|
13
|
-
in the conversation stays the authority — prefer what `list_strategy_vocabulary
|
|
14
|
-
`get_strategy_column_contract
|
|
15
|
-
printed here, and read exact headers from a `detail: "detailed"` preview's
|
|
13
|
+
in the conversation stays the authority — prefer what `list_strategy_vocabulary` and
|
|
14
|
+
`get_strategy_column_contract` return over anything printed here, and read exact headers from a `detail: "detailed"` preview's
|
|
16
15
|
`authoring.conditionColumns` before conditioning on them.
|
|
17
16
|
|
|
18
17
|
## The full-power checklist
|
|
@@ -22,14 +21,12 @@ Before committing a CREATE, every "no" here is a decision to state, not an omiss
|
|
|
22
21
|
1. At least one **custom section** whose columns encode the thesis — not only platform modules.
|
|
23
22
|
2. **Conditions** encode the entry logic: building blocks (`verdict: null`) + verdict carriers,
|
|
24
23
|
and at least one `required: true` condition vetoing obvious disqualifiers **before any
|
|
25
|
-
billing or LLM call**.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
4. **
|
|
30
|
-
|
|
31
|
-
5. **Trade levels + position management** match the setup's geometry and holding period.
|
|
32
|
-
6. `marketReadText` states standing orders with `{...}` markers so live values render inline.
|
|
24
|
+
billing or LLM call**. They are the only deterministic entry gate: with no required and no
|
|
25
|
+
verdict-carrying entry condition the strategy never routes a trade (`NO_ENTRY_CONDITION`).
|
|
26
|
+
3. **The ATR floor** (`minAtrPct`) is set for the coins and timeframe the thesis trades, not left
|
|
27
|
+
at the default by accident — a coin below it is refused before any condition is read.
|
|
28
|
+
4. **Trade levels + position management** match the setup's geometry and holding period.
|
|
29
|
+
5. `marketReadText` states standing orders with `{...}` markers so live values render inline.
|
|
33
30
|
|
|
34
31
|
## Header grammar (system-generated — never named by the author)
|
|
35
32
|
|
|
@@ -45,6 +42,12 @@ Before committing a CREATE, every "no" here is a decision to state, not an omiss
|
|
|
45
42
|
| `maxShare` wN | `<code>_maxShare` | `volBase_ltf_maxShare` |
|
|
46
43
|
| `classifyZone` / `classifyState` | `<code>_zone` / `<code>_state` | `RSI14_zone`, `ADX_state` |
|
|
47
44
|
| `levelInteraction` | `<code>_lvl`, `<code>_lvl_b<N>` at a buffer of N bps | `bbUpper_lvl`, `bbUpper_lvl_b25` |
|
|
45
|
+
| any, stored `"bars": "all"` | `<code>_dev`, then the transform's suffix | `RSI14_dev_t1` |
|
|
46
|
+
| `value` at `offset` N > 0 | `<code>_o<N>` | `RSI14_1d_o1` |
|
|
47
|
+
|
|
48
|
+
The code carries its tokens in this order: `<code>[_<tf>][_dev][_o<N>]`, then the transform's suffix.
|
|
49
|
+
`_dev` follows the STORED selector — the author chose Developing — whatever bar set the column then
|
|
50
|
+
reads; `_o<N>` appears on a `value` at offset N > 0.
|
|
48
51
|
|
|
49
52
|
Non-anchor rungs affix `_ltf` (lower) / `_htf` (regime): `MAalign_htf`,
|
|
50
53
|
`zones_htf_support_dist`. Chains are bounded at two: inner `distance`/`spread` → outer
|
|
@@ -56,11 +59,12 @@ when the strategy timeframe changes — `regime` is the anchor's ladder successo
|
|
|
56
59
|
anchor). *Pinned* (`{abs: "<tf>"}`) is fixed, ignores anchor retunes, suffixes the literal
|
|
57
60
|
(`RSI14_1d`, `dist_SMA200_1d`, `MAalign_1d` — validated), and binds to discovery's
|
|
58
61
|
`rankedTimeframes`, a **superset** of the authorable anchor set — `{abs: "1d"}` is valid while
|
|
59
|
-
`1d` is not an anchor. `offset
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
`1d` is not an anchor. `offset` steps back inside the bar set the Read selector admits, counted
|
|
63
|
+
from the newest bar that set admits, and suffixes the header `_o<N>` (`RSI14_1d_o1`). A pinned
|
|
64
|
+
column above the strategy timeframe reads Confirmed, so its offset 0 is already the newest
|
|
65
|
+
**completed** bar of that timeframe — the deterministic daily-close read — and offset 1 is the
|
|
66
|
+
day before it. **Daily-strategy pattern:** anchor 4h, pinned-1d thesis columns with
|
|
67
|
+
`"bars": "closed"` at offset 0, `required: true` daily conditions gating every carrier, anchor-rung
|
|
64
68
|
columns only for entry timing and risk — daily inputs then move once per daily close while
|
|
65
69
|
stops and time decay keep managing intraday. **Benchmark sections** (`benchmarkTicker: "BTC"`,
|
|
66
70
|
required-nullable on every custom section) read the benchmark's values on every row — the
|
|
@@ -156,7 +160,16 @@ Recipes — each one clause:
|
|
|
156
160
|
before billing. And the RESOLVED verdict binds entry DIRECTION: `UP` admits long setups only,
|
|
157
161
|
`DOWN` short only, and `NEITHER`/`UNRESOLVED` admit none — the refused side is absent from the
|
|
158
162
|
setups block and from the `decide_trade` contract, not merely discouraged in them. A strategy that
|
|
159
|
-
declares no verdict-carrying condition resolves `null` and constrains
|
|
163
|
+
declares no verdict-carrying condition resolves `null` and constrains no side.
|
|
164
|
+
|
|
165
|
+
**A strategy without an entry condition never routes.** An entry condition gates when it is
|
|
166
|
+
`required: true` or carries a verdict (`UP`, `DOWN` or `NEITHER`); a building block gates nothing,
|
|
167
|
+
and an exit rule never counts. A strategy whose conditions include neither never trades: every coin
|
|
168
|
+
fails first with `NO_ENTRY_CONDITION`, before the trade levels, the ATR floor or any condition is
|
|
169
|
+
read, and its draft carries the `NO_ENTRY_CONDITION` warning. It stays a valid strategy — Market Grid
|
|
170
|
+
reads it as context — so this is a choice to state, never an accident. When the agent decides a
|
|
171
|
+
routed trade, its `decide_trade` call cites 1–8 of the evaluated entry conditions in
|
|
172
|
+
`conditionChecklist`, and only a condition that read TRUE may be cited as `CONFIRM`.
|
|
160
173
|
|
|
161
174
|
A verdict carrier must read no DEVELOPING bar. A verdict is refused over any closure that reads a
|
|
162
175
|
column selecting Developing above the strategy timeframe (`CONDITION_VERDICT_READ_ILLEGAL`). The
|
|
@@ -461,7 +474,7 @@ bar whose close decides an entry is the strategy's OWN timeframe.
|
|
|
461
474
|
|
|
462
475
|
**Every trigger is decided at the close of the strategy's own bar — there are three, and the close
|
|
463
476
|
is the only entry clock.** The newest completed bar is read on the closed basis — every one-close
|
|
464
|
-
condition resolves on that bar and the
|
|
477
|
+
condition resolves on that bar and the gates read its close — and a reading that still qualifies
|
|
465
478
|
fires at that close. A bar that does not qualify decides nothing and is not revisited. The fill lands
|
|
466
479
|
at the next tick, and the platform refuses it if the market has already run past its own drift budget
|
|
467
480
|
from that close. A fourth value, `AT_SIGNAL`, is readable on strategies authored before this contract
|
|
@@ -505,45 +518,16 @@ column reaches any other timeframe by pinning it (`timeframe: { abs: '4h' }`). `
|
|
|
505
518
|
than omitting them, because the section is rebuilt whole on save and an omitted key clears the
|
|
506
519
|
author's value silently. On a CREATE, omit `sectionKey` — it is derived from the section itself.
|
|
507
520
|
|
|
508
|
-
## Signal rules
|
|
509
|
-
|
|
510
|
-
`{ signalId, allocation, required, params }` — one entry per signal you want scoring.
|
|
511
|
-
`allocation` is the tier (0–3) and `params` replaces canonical defaults only when present. Staged
|
|
512
|
-
into the draft's SIGNAL_RULES axis, every row is complete — `allocation` and `required` on each —
|
|
513
|
-
and replaces the drafted row for its signal while every other row is kept.
|
|
514
|
-
|
|
515
|
-
## Signal weights and gate math
|
|
516
|
-
|
|
517
|
-
Tiers: 0 Off · 1 Normal · 2 Important · 3 Critical.
|
|
518
|
-
|
|
519
|
-
```
|
|
520
|
-
aggregateScore = Σ(score × allocation) / Σ(allocation) over triggered signals
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
Weights are relative — build a pyramid: 1–2 Critical (thesis, usually `required`), 2–4
|
|
524
|
-
Important (independent confirmation, different modules), 1–3 Normal (context), rest Off so
|
|
525
|
-
noise cannot dilute the average. Gate check: with 3/2/2/1 weights, Critical + one Important at
|
|
526
|
-
score 1.0 → (3+2)/8 = 0.625, so a 0.6 gate means "thesis plus one confirmation".
|
|
527
|
-
`simulate_aggregate_score` does this arithmetic from the draft's values at review time.
|
|
528
|
-
`required: true` counts the signal toward `minRequiredCount` when triggered; at
|
|
529
|
-
`allocation: 0` it is rejected (contract 34). `params` replace canonical defaults only when
|
|
530
|
-
present — read `get_strategy_signal_definition({ signalId, timeframe })` before tuning (e.g.
|
|
531
|
-
`rsi_overbought {"threshold": 65}` for a fade book; `volume_surge {"multiplier": 1.5}`).
|
|
532
|
-
`derive_strategy_rule_view` shows which signals a draft report feeds — weighting a signal the
|
|
533
|
-
report never feeds is dead weight.
|
|
534
|
-
|
|
535
|
-
## Routing gates
|
|
536
|
-
|
|
537
|
-
`{ minAggregateScore, minRequiredCount, minAtrPct }` — whether a scored setup may route to a
|
|
538
|
-
trade at all. `minAggregateScore` 0–1 · `minRequiredCount` 0–20 · `minAtrPct` is the dead-market
|
|
539
|
-
floor, with bounds from `get_trading_config_catalog`.
|
|
540
|
-
|
|
541
521
|
## Trade levels
|
|
542
522
|
|
|
543
|
-
`{ minStopLossAtrMultiple, maxStopLossAtrMultiple, minRiskRewardRatio }` — where stops
|
|
544
|
-
targets may sit
|
|
545
|
-
`
|
|
546
|
-
|
|
523
|
+
`{ minStopLossAtrMultiple, maxStopLossAtrMultiple, minRiskRewardRatio, minAtrPct }` — where stops
|
|
524
|
+
and targets may sit, and how much a coin must move before it is worth trading at all.
|
|
525
|
+
`minStopLossAtrMultiple < maxStopLossAtrMultiple` (≤ the 3×ATR structural cap), `minRiskRewardRatio`
|
|
526
|
+
within the served range. `minAtrPct` is the ATR floor: a coin whose ATR% sits below it is refused
|
|
527
|
+
(`ATR_VOLATILITY_BELOW_MIN`) before any condition is read, with bounds from
|
|
528
|
+
`get_trading_config_catalog`; it is multiplied with `maxStopLossAtrMultiple` in the capital check, so
|
|
529
|
+
a high floor with a wide stop needs more capital per trade. The axis is staged whole — all four.
|
|
530
|
+
Sizing is risk-budget based — a wider stop means a smaller position, never more risk.
|
|
547
531
|
|
|
548
532
|
## Position management
|
|
549
533
|
|
|
@@ -583,7 +567,7 @@ rejects an `offset`) belongs in prose above — those are permanent. A claim tha
|
|
|
583
567
|
|
|
584
568
|
## Where the worked material lives
|
|
585
569
|
|
|
586
|
-
This skill's body is the contract — the axes, the header grammar, how conditions and
|
|
570
|
+
This skill's body is the contract — the axes, the header grammar, how conditions and trade levels behave,
|
|
587
571
|
and the absence section above. The worked material is disclosed on demand, so it costs nothing until
|
|
588
572
|
you ask for it. Read a reference with `read_skill_reference` when you reach the work it covers:
|
|
589
573
|
|
|
@@ -26,11 +26,8 @@ Custom `Squeeze Scan` (no `sectionKey` — this is a CREATE): `BB_WIDTH_PCT valu
|
|
|
26
26
|
custom section already carries them.) Conditions: `LIQUID_FLOOR` (required —
|
|
27
27
|
`vol24hUsd gte 25000000`); `SQUEEZE_ON` building block (`bbWidthPct_rank_lo lte 10` AND
|
|
28
28
|
`ADX lt 20`); `BREAK_UP` verdict UP (ref SQUEEZE_ON + `closeChg gt 0` + `RVOL gte 1.5` +
|
|
29
|
-
`pctB gte 0.85`); `BREAK_DOWN` verdict DOWN (mirror with `pctB lte 0.15`).
|
|
30
|
-
|
|
31
|
-
`volatility_atr_expanding` 2 · `sr_resistance_break` 2 · `sr_support_break` 2 ·
|
|
32
|
-
`bollinger_upper_touch` 1 · `bollinger_lower_touch` 1 · `trend_adx_ranging` 1. Gates
|
|
33
|
-
0.55 / 2 / 0.8. Levels 0.75–1.75 ATR, RR 2. PM: BE 1R; trail 1.2R giveback 35 buffer 0.3.
|
|
29
|
+
`pctB gte 0.85`); `BREAK_DOWN` verdict DOWN (mirror with `pctB lte 0.15`). Levels 0.75–1.75 ATR,
|
|
30
|
+
RR 2, ATR floor 0.8% — a compression play needs the expansion to be worth the stop. PM: BE 1R; trail 1.2R giveback 35 buffer 0.3.
|
|
34
31
|
Market Read: "Trade only expansions out of compression: {SQUEEZE_ON} must read TRUE… skip
|
|
35
32
|
anything failing {LIQUID_FLOOR}."
|
|
36
33
|
|
|
@@ -43,11 +40,7 @@ new longs / new shorts / short covering / long liquidation), `MARK spread ORACLE
|
|
|
43
40
|
`NO_LIQUIDATION_TAPE` required NOT-veto (`NOT [oiRegime is "long liquidation"]`);
|
|
44
41
|
`CROWDED_LONGS` building block (`ann gte 25` + `oiChg gte 3` + `oiRegime is "new longs"`);
|
|
45
42
|
`FADE_SHORT` verdict DOWN (ref + `RSI14 gte 65` + `chg24h gte 5`); mirrored `SQUEEZED_SHORTS`
|
|
46
|
-
/ `SQUEEZE_LONG` verdict UP.
|
|
47
|
-
`{"thresholdAnnualizedPct":100}` · `oi_surge` 2 `{"thresholdPct":0.03}` · `rsi_overbought` 2
|
|
48
|
-
`{"threshold":65}` · `rsi_oversold` 2 `{"threshold":35}` · `cvd_bear_divergence` 2 ·
|
|
49
|
-
`cvd_bull_divergence` 2 · `mfi_overbought` 1 · `mfi_oversold` 1. Gates 0.6 / 1 / 0.5. Levels
|
|
50
|
-
1.0–2.5 ATR, RR 1.5. PM: BE 0.8R, no trail, timeDecay ON (120/60, 10→40, stale 25).
|
|
43
|
+
/ `SQUEEZE_LONG` verdict UP. Levels 1.0–2.5 ATR, RR 1.5, ATR floor 0.5%. PM: BE 0.8R, no trail, timeDecay ON (120/60, 10→40, stale 25).
|
|
51
44
|
|
|
52
45
|
### 3 · Relative-Strength Rotation with a Benchmark Gate — 4h cross-sectional
|
|
53
46
|
|
|
@@ -61,10 +54,8 @@ every row reads BTC. Conditions: `BTC_RISK_ON` building block (`MAalign is "bull
|
|
|
61
54
|
`ADX gte 20` — both read bare, since only this section renders them); `BTC_RISK_OFF`
|
|
62
55
|
(`MAalign is "bearish"`); `LEADER` (`roc12_rank_hi lte 5` + `RVOL_rank_hi lte 10` +
|
|
63
56
|
`vol24hUsd gte 100000000`); `ROTATE_IN` verdict UP (`ALL[ref BTC_RISK_ON, ref LEADER]`);
|
|
64
|
-
`ROTATE_OUT` verdict DOWN (`ALL[ref BTC_RISK_OFF, roc12_rank_lo lte 5]`).
|
|
65
|
-
|
|
66
|
-
`_bear` 2 required · `rel_ppo_bull_cross`/`_bear_cross` 1 · `volume_surge` 1. Gates
|
|
67
|
-
0.5 / 1 / 0.6. Levels 1–2 ATR, RR 1.8. PM: BE 1R; trail 1R giveback 45. Ranked cohort ≥ 40 —
|
|
57
|
+
`ROTATE_OUT` verdict DOWN (`ALL[ref BTC_RISK_OFF, roc12_rank_lo lte 5]`). Levels 1–2 ATR, RR 1.8,
|
|
58
|
+
ATR floor 0.6%. PM: BE 1R; trail 1R giveback 45. Ranked cohort ≥ 40 —
|
|
68
59
|
rank conditions need a cohort wider than their thresholds.
|
|
69
60
|
|
|
70
61
|
### 4 · HTF Trend Pullback — 1h, multi-timeframe confluence
|
|
@@ -77,11 +68,8 @@ would be ambiguous. Conditions: `HTF_UP` building block (`MAalign_htf is "bullis
|
|
|
77
68
|
`ADX_htf_state in ["trending","extreme"]`); `HTF_DOWN` mirror; `TREND_PRESENT` **required**
|
|
78
69
|
`ANY[ref HTF_UP, ref HTF_DOWN]` — chop blocks compose-trade entirely, before billing;
|
|
79
70
|
`PULLBACK_LONG` verdict UP (ref HTF_UP + `RSI14_now between 35 55` +
|
|
80
|
-
`dist_EMA20 between -3 0.5`); `PULLBACK_SHORT` verdict DOWN (mirror, 45–65 / −0.5–3).
|
|
81
|
-
|
|
82
|
-
`htf_trend_adx_trending` 2 · `ma_ema_aligned_bull`/`_bear` 1 · `rsi_oversold` 1
|
|
83
|
-
`{"threshold":40}`. Gates 0.6 / 2 / 0.7 (a pullback signal AND an HTF alignment). Levels
|
|
84
|
-
1–2.5 ATR, RR 2. PM: BE 1R; trail 1.5R giveback 30 buffer 0.3.
|
|
71
|
+
`dist_EMA20 between -3 0.5`); `PULLBACK_SHORT` verdict DOWN (mirror, 45–65 / −0.5–3). Levels
|
|
72
|
+
1–2.5 ATR, RR 2, ATR floor 0.7%. PM: BE 1R; trail 1.5R giveback 30 buffer 0.3.
|
|
85
73
|
|
|
86
74
|
### 5 · Perp/Spot Flow Divergence at Structure — 15m scalp
|
|
87
75
|
|
|
@@ -93,10 +81,8 @@ perp_led_fragile / spot_led_accumulation / neutral), `includeStructureZones`
|
|
|
93
81
|
(`zones_htf_support_dist between 0 2` + `zones_htf_support_age_h gte 12`); `DIP_BID` verdict
|
|
94
82
|
UP — refs plus an `N_OF(2)` quorum over `buyPres gte 0.55` / `RVOL gte 1.2` / `closeChg gt 0`
|
|
95
83
|
(quorum beats a brittle ALL); `FRAGILE_POP` verdict DOWN (`perp_led_fragile` +
|
|
96
|
-
`zones_htf_resist_dist between -2 0` + `RVOL gte 1.3`).
|
|
97
|
-
|
|
98
|
-
`_bear_divergence` 2 · `sr_at_support`/`_at_resistance` 2 · `structure_ob_approach` 1 ·
|
|
99
|
-
`volume_surge` 1. Gates 0.55 / 1 / 0.4. Levels 0.5–1.2 ATR, RR 1.5. PM: BE 0.7R; trail 0.9R
|
|
84
|
+
`zones_htf_resist_dist between -2 0` + `RVOL gte 1.3`). Levels 0.5–1.2 ATR, RR 1.5, ATR floor
|
|
85
|
+
0.4%. PM: BE 0.7R; trail 0.9R
|
|
100
86
|
giveback 30 buffer 0.15; timeDecay ON aggressive (45/15, 15→60, stale 30).
|
|
101
87
|
|
|
102
88
|
## Using a playbook
|
|
@@ -104,7 +90,7 @@ giveback 30 buffer 0.15; timeDecay ON aggressive (45/15, 15→60, stale 30).
|
|
|
104
90
|
Discover → confirm headers (`get_strategy_column_contract`, or one `preview_strategy_report` at
|
|
105
91
|
`detail: "detailed"`, whose `authoring.conditionColumns` lists every addressable header with
|
|
106
92
|
operators and vocabulary) → calibrate literals against the previewed live values → stage the draft
|
|
107
|
-
and fix what its diagnostics name → read it back and review the drafted
|
|
93
|
+
and fix what its diagnostics name → read it back and review the drafted conditions, then the draft's
|
|
108
94
|
own report preview — the conditions register (`gridConditions`), verdict tally, and
|
|
109
95
|
`marketReadMarkers` (fix `unknown` / `ambiguous` markers) → commit per the strategy-authoring flow. Coin selection is call context, not strategy
|
|
110
96
|
state: explicit tickers for focused work, `ranked` (with an optional category) for scanning books.
|
|
@@ -33,7 +33,7 @@ rather than events all live there. This document assumes them.
|
|
|
33
33
|
| Chop filter on the entry rung | `{ "metric": "CLOSE", "transformId": "efficiency", "timeframe": { "rel": "lower" }, "window": 5, "bars": "closed" }` | `close_ltf_er` (≥0.6 directional) |
|
|
34
34
|
| One-bar volume concentration | `{ "metric": "VOLUME", "transformId": "maxShare", "timeframe": { "rel": "lower" }, "window": 4, "bars": "closed" }` | `volBase_ltf_maxShare` |
|
|
35
35
|
| Room to structure | `{ "metric": "STRUCT_ZONES", "transformId": "nearestZoneDist", "timeframe": { "rel": "regime" }, "side": "resistance" }` | `zones_htf_resist_dist` |
|
|
36
|
-
| Last **closed** daily read | `{ "metric": "RSI14", "transformId": "value", "timeframe": { "abs": "1d" }, "
|
|
36
|
+
| Last **closed** daily read | `{ "metric": "RSI14", "transformId": "value", "timeframe": { "abs": "1d" }, "bars": "closed" }` | `RSI14_1d` — the newest completed daily bar |
|
|
37
37
|
|
|
38
38
|
## Cross detection
|
|
39
39
|
|
|
@@ -21,7 +21,7 @@ Players often ask for strategies by the name of a popular TradingView script. Po
|
|
|
21
21
|
**process** (regime filter → setup state → trigger → stop engine), and where the catalog lacks
|
|
22
22
|
the primitive, name the substitution in the spec-lock question — never present a substitute as
|
|
23
23
|
the thing itself. Most TV strategies run on the daily chart: carry that with the
|
|
24
|
-
daily-strategy pattern above (pinned-1d thesis
|
|
24
|
+
daily-strategy pattern above (pinned-1d thesis with `"bars": "closed"` at offset 0 on an intraday anchor), which
|
|
25
25
|
binds decisions to daily closes while the studio keeps managing risk intraday.
|
|
26
26
|
|
|
27
27
|
Event-column behaviour, state-vs-event, previous-session-level binding and the squeeze's anchor calibration are
|
|
@@ -45,8 +45,7 @@ rules about the columns themselves, not about porting — they live in the skill
|
|
|
45
45
|
`ST_DIR enters "bullish"` is TRUE on the one completed bar the direction turned, and
|
|
46
46
|
`ST_DIR exits "bullish"` on the bar it turned back — see `## Conditions` in the skill body.
|
|
47
47
|
- **MACD + 200 MA filter** → `ABOVE_200` building block (`dist_SMA200 gt 0`) referenced by a
|
|
48
|
-
carrier with `MACD_cross is "Bullish"`;
|
|
49
|
-
`ma_sma200_above/below` 2 required; swing-trend geometry.
|
|
48
|
+
carrier with `MACD_cross is "Bullish"`; swing-trend geometry.
|
|
50
49
|
- **Golden / Death Cross** → `SMA50 spread SMA200 × trajectory` gives state and freshness:
|
|
51
50
|
`SMA50_SMA200_spread_now gt 0` AND `_trend is "rising"`; optional breadth gate on
|
|
52
51
|
`mktBreadth_crypto gte 0` — every published scope resolves, not only `all`, because the leg reads
|
|
@@ -54,8 +53,7 @@ rules about the columns themselves, not about porting — they live in the skill
|
|
|
54
53
|
the canonical definition and stays the default port; `EMA50` is available as the crypto variant
|
|
55
54
|
when a player asks for it by name.
|
|
56
55
|
- **RSI-2 (Connors)** → `RSI2` is native, so this ports exactly: `RSI2 lte 10` gated by required
|
|
57
|
-
`ABOVE_200`; the source's fast exit is time — timeDecay ON (180/60, 15→50, stale 20)
|
|
58
|
-
`rsi_oversold` 3 required with a tuned threshold. Keep the literal `lte 10` as the GATE:
|
|
56
|
+
`ABOVE_200`; the source's fast exit is time — timeDecay ON (180/60, 15→50, stale 20). Keep the literal `lte 10` as the GATE:
|
|
59
57
|
`RSI2 × classifyZone` exists and reads on the same Connors bands, but a zone label is a fixed
|
|
60
58
|
reading while the literal is a threshold the author can see and tune. Use the zone as a report
|
|
61
59
|
column, never as the substitute for the gate.
|
|
@@ -63,16 +61,14 @@ rules about the columns themselves, not about porting — they live in the skill
|
|
|
63
61
|
stretch; required `NOT [ADX_state in ["trending","extreme"]]` veto; scalp geometry +
|
|
64
62
|
aggressive timeDecay (VWAP anchors daily at 00:00 UTC).
|
|
65
63
|
- **Donchian / Turtle breakout** → `zone is "breakout high"` + `dist_donchianHi gte 0` +
|
|
66
|
-
`RVOL gte 1.5`;
|
|
64
|
+
`RVOL gte 1.5`; turtle exits = trend preset (trail from
|
|
67
65
|
1R, giveback 50). Mirror with `"breakdown low"`. **Daily-breakout variant on any anchor:**
|
|
68
66
|
pin the structure at 1d — `zone_1d is "breakout high"`, `dist_donchianHi_1d gte 0` (validated).
|
|
69
67
|
**Literal previous-day levels are native**: `dist_PDH gte 0` composes directly. They are TIMELESS
|
|
70
68
|
and take `{rel: 'anchor'}` — see `## Header grammar` in the skill body.
|
|
71
69
|
- **ICT / SMC (FVG + order blocks)** → `STRUCT_ZONES` is the native zone engine:
|
|
72
70
|
`zones_htf_support_type` (`bullish FVG`/`bullish order block`), `zones_htf_support_dist
|
|
73
|
-
between 0 1.5`, `_age_h gte 12`, HTF bias required via `MAalign_htf
|
|
74
|
-
`structure_fvg_approach`/`structure_ob_approach` required (their `proximityPct` is the
|
|
75
|
-
in-zone dial). Liquidity sweeps, displacement, killzones and event *sequencing* are shapes the
|
|
71
|
+
between 0 1.5`, `_age_h gte 12`, HTF bias required via `MAalign_htf`. Liquidity sweeps, displacement, killzones and event *sequencing* are shapes the
|
|
76
72
|
grammar does not have — a clause compares one column with a literal or with its own previous
|
|
77
73
|
completed bar, never with another column or an earlier event, so an ordered sequence of events
|
|
78
74
|
cannot be stated at all. That is a grammar limit, not a missing metric; name it as
|
|
@@ -28,8 +28,8 @@ Not "what were its returns" — whether it did *the thing it was told to do*.
|
|
|
28
28
|
- `get_intelligence_agent` — restate the agent's mandate in one line, in the player's terms. This
|
|
29
29
|
is the yardstick; without it "up 4%" means nothing.
|
|
30
30
|
- `get_strategy` on the `strategyId` that read returns — the mandate is the bound strategy, so the
|
|
31
|
-
yardstick is its
|
|
32
|
-
prose. Read `bindingState` too: at `SYNCING` or `ORPHANED` the agent evaluates a materialized copy
|
|
31
|
+
yardstick is its entry conditions — required and verdict-carrying, the only deterministic entry
|
|
32
|
+
gate — and its trade levels with the ATR floor, not the agent's overlay prose. Read `bindingState` too: at `SYNCING` or `ORPHANED` the agent evaluates a materialized copy
|
|
33
33
|
at its own `strategyRevision`, and judging it against the strategy's current revision measures it
|
|
34
34
|
by rules it is not running.
|
|
35
35
|
- `get_agent_performance` and `list_trade_outcomes` — judge against that mandate.
|
|
@@ -19,14 +19,14 @@ re-sorts a list, re-derives a verdict, or approves on the player's behalf.
|
|
|
19
19
|
## 1. When the player names a coin and not an agent — choose the agent
|
|
20
20
|
|
|
21
21
|
- `scan_coin_agents` for the coin. The rows arrive server-ranked across the player's own agents:
|
|
22
|
-
`qualified`
|
|
22
|
+
`qualified` first, then `rejected` with the first failing gate, then `unscorable` with the
|
|
23
23
|
reason, then `ineligible` with the refusal `propose_entry_decision` would give (`AGENT_NOT_ACTIVE`,
|
|
24
24
|
`MODEL_INACTIVE`, `AGENT_HALTED`). Read them **as written** — never re-sort or re-derive a verdict.
|
|
25
25
|
- **Ask the top-ranked qualifying agent**, and name the other agents that qualified so the player can
|
|
26
26
|
choose one of them instead. One request per coin: the platform holds one pending request per coin
|
|
27
27
|
across all of the player's agents, so ask one agent, not each of them.
|
|
28
28
|
- **When none qualifies, say so plainly.** Name each agent's blocking gate or ineligibility, and offer
|
|
29
|
-
the strategy doctor for the one
|
|
29
|
+
the strategy doctor for the one whose blocking gate is the one to work on. Never propose through an agent the scan
|
|
30
30
|
reports rejected, unscorable or ineligible.
|
|
31
31
|
- **When the player has no agent at all**, the scan is empty: say so, and the next step is building one
|
|
32
32
|
(a strategy first, when they have none).
|
|
@@ -34,8 +34,8 @@ re-sorts a list, re-derives a verdict, or approves on the player's behalf.
|
|
|
34
34
|
|
|
35
35
|
## 2. Which coins fit the agent right now
|
|
36
36
|
|
|
37
|
-
- `scan_agent_coins` for the agent. The rows arrive server-ranked: qualifying coins first by
|
|
38
|
-
then the rest with their first failing gate, then coins that could not be
|
|
37
|
+
- `scan_agent_coins` for the agent. The rows arrive server-ranked: qualifying coins first by ticker,
|
|
38
|
+
then the rest with their first failing gate, then coins that could not be evaluated, with the reason.
|
|
39
39
|
The scan reads the agent's gates and spends no LLM call.
|
|
40
40
|
- Read the rows **as written**: the rank, the verdict, the first failing gate, the unscorable
|
|
41
41
|
label. Never re-sort them and never re-derive a verdict from its numbers — the server's ranking
|