@battlegrid/mcp-server 31.2.5 → 31.2.7

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.
@@ -1,370 +0,0 @@
1
- # Strategy Studio playbooks — validated desk-grade examples
2
-
3
- Five complete composition patterns, modeled on how systematic desks actually structure these
4
- trades. Every header, vocabulary label, bound, and shape below was validated against the live
5
- server (preview + column contracts) on 2026-08-28. Tokens are still illustrative: re-discover
6
- before compiling, and read exact headers from `preview_strategy_report`'s `conditionColumns`.
7
-
8
- Playbook 1 shows the **full** `compile_strategy_plan` CREATE request. Playbooks 2–5 show only
9
- the axes that differ — their envelope (`operation`, `intentSummary`, `assumptions`,
10
- `coinSelection`, identity, timeframe) follows the same shape. Multi-account proxies wrap each as
11
- `{ account, request }`.
12
-
13
- ---
14
-
15
- ## 1 · Volatility Compression Breakout (vol desk, 4h swing)
16
-
17
- **Thesis.** Coins in the tightest Bollinger compression on the board, with trend strength not yet
18
- developed, break hard when volume arrives. Trade the expansion, direction decided by the break.
19
-
20
- **Why this shape.** Cross-sectional `rank` finds compression *relative to the whole universe*
21
- (cheaper and more robust than an absolute width threshold); a building-block condition holds the
22
- squeeze state and two verdict carriers decide direction; a required liquidity floor stops the
23
- agent spending calls on illiquid names; tight stop band + trailing because breakout invalidation
24
- is nearby and winners should run.
25
-
26
- ```json
27
- {
28
- "request": {
29
- "operation": "CREATE",
30
- "intentSummary": "Cross-sectional volatility-compression breakout: enter expansions out of the tightest Bollinger squeezes on the board, direction decided by the breaking bar, volume-confirmed.",
31
- "assumptions": [
32
- "4h anchor: swing cadence, structural zones read on the regime rung",
33
- "Ranked CRYPTO cohort approximates the live tradable universe"
34
- ],
35
- "coinSelection": { "mode": "ranked", "limit": 20, "category": "CRYPTO" },
36
- "name": "Compression Breakout",
37
- "tagline": "Tightest bands on the board, traded on expansion",
38
- "description": "Scans the universe for Bollinger-width compression (bottom-decile rank), requires real participation, and enters the expansion bar in its own direction. Structure zones frame targets.",
39
- "timeframe": "4h",
40
- "sections": [
41
- {
42
- "kind": "custom",
43
- "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5",
44
- "title": "Squeeze Scan",
45
- "benchmarkTicker": null,
46
- "columns": [
47
- { "metric": "BB_WIDTH_PCT", "transformId": "value", "timeframe": { "rel": "anchor" } },
48
- { "metric": "BB_WIDTH_PCT", "transformId": "rank", "timeframe": { "rel": "anchor" }, "ordering": "lo" },
49
- { "metric": "ADX", "transformId": "value", "timeframe": { "rel": "anchor" } },
50
- { "metric": "RVOL", "transformId": "value", "timeframe": { "rel": "anchor" } },
51
- { "metric": "BB_PCT_B", "transformId": "value", "timeframe": { "rel": "anchor" } },
52
- { "metric": "CLOSE_CHANGE", "transformId": "value", "timeframe": { "rel": "anchor" } },
53
- { "metric": "NOTIONAL_VOLUME_1D", "transformId": "value", "timeframe": { "rel": "anchor" } }
54
- ]
55
- },
56
- { "kind": "platform", "sectionKey": "includeBollingerBands" },
57
- { "kind": "platform", "sectionKey": "includeStructureZones" }
58
- ],
59
- "conditions": [
60
- {
61
- "conditionKey": "LIQUID_FLOOR",
62
- "name": "Liquidity floor",
63
- "definition": { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "vol24hUsd" }, "op": "gte", "value": 25000000 },
64
- "verdict": null,
65
- "required": true
66
- },
67
- {
68
- "conditionKey": "SQUEEZE_ON",
69
- "name": "Volatility compression",
70
- "definition": {
71
- "kind": "group", "op": "ALL", "members": [
72
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "bbWidthPct_rank_lo" }, "op": "lte", "value": 10 },
73
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "ADX" }, "op": "lt", "value": 20 }
74
- ]
75
- },
76
- "verdict": null,
77
- "required": false
78
- },
79
- {
80
- "conditionKey": "BREAK_UP",
81
- "name": "Upside expansion",
82
- "definition": {
83
- "kind": "group", "op": "ALL", "members": [
84
- { "kind": "conditionRef", "conditionKey": "SQUEEZE_ON" },
85
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "closeChg" }, "op": "gt", "value": 0 },
86
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "RVOL" }, "op": "gte", "value": 1.5 },
87
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "pctB" }, "op": "gte", "value": 0.85 }
88
- ]
89
- },
90
- "verdict": "UP",
91
- "required": false
92
- },
93
- {
94
- "conditionKey": "BREAK_DOWN",
95
- "name": "Downside expansion",
96
- "definition": {
97
- "kind": "group", "op": "ALL", "members": [
98
- { "kind": "conditionRef", "conditionKey": "SQUEEZE_ON" },
99
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "closeChg" }, "op": "lt", "value": 0 },
100
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "RVOL" }, "op": "gte", "value": 1.5 },
101
- { "kind": "clause", "column": { "sectionKey": "custom:a1a1a1a1-b2b2-4c3c-8d4d-e5e5e5e5e5e5", "header": "pctB" }, "op": "lte", "value": 0.15 }
102
- ]
103
- },
104
- "verdict": "DOWN",
105
- "required": false
106
- }
107
- ],
108
- "rules": [
109
- { "signalId": "bollinger_squeeze", "allocation": 3, "required": true },
110
- { "signalId": "volume_surge", "allocation": 2, "required": true, "params": { "multiplier": 1.5 } },
111
- { "signalId": "volatility_atr_expanding", "allocation": 2, "required": false },
112
- { "signalId": "sr_resistance_break", "allocation": 2, "required": false },
113
- { "signalId": "sr_support_break", "allocation": 2, "required": false },
114
- { "signalId": "bollinger_upper_touch", "allocation": 1, "required": false },
115
- { "signalId": "bollinger_lower_touch", "allocation": 1, "required": false },
116
- { "signalId": "trend_adx_ranging", "allocation": 1, "required": false }
117
- ],
118
- "minAggregateScore": 0.55,
119
- "minRequiredCount": 2,
120
- "minAtrPct": 0.8,
121
- "minStopLossAtrMultiple": 0.75,
122
- "maxStopLossAtrMultiple": 1.75,
123
- "minRiskRewardRatio": 2,
124
- "breakEvenEnabled": true,
125
- "breakEvenTriggerR": 1,
126
- "trailingEnabled": true,
127
- "trailingTriggerR": 1.2,
128
- "trailingGivebackPct": 35,
129
- "trailingBufferPct": 0.3,
130
- "timeDecayEnabled": false,
131
- "marketReadText": "Trade only expansions out of compression: {SQUEEZE_ON} must read TRUE on the setup bar. Board standing {bbWidthPct_rank_lo}; participation {RVOL} must be at least 1.5x. Longs on {BREAK_UP}, shorts on {BREAK_DOWN}; skip anything failing {LIQUID_FLOOR}. Frame targets against the regime-rung zones ({zones_htf_resist_dist} up, {zones_htf_support_dist} down)."
132
- }
133
- }
134
- ```
135
-
136
- **Review focus.** In the compile response: the scorecard should show exactly the eight named
137
- rules scoring (everything else Off); `reviewContext.reportPreview.conditionOutcomes` should show
138
- `SQUEEZE_ON` evidence per coin and the verdict tally; check `marketReadMarkers` all resolve.
139
-
140
- ---
141
-
142
- ## 2 · Crowded-Positioning Fade (derivatives desk, 1h intraday)
143
-
144
- **Thesis.** When funding is paying one side heavily, open interest is building, and the OI·price
145
- regime says the crowd is adding into an extended move, fade it back toward equilibrium.
146
-
147
- **Sections.** Custom `Positioning` (mint key `custom:b2b2…`):
148
- `FUNDING_RATE value` → `rate` · `FUNDING_RATE aggregate w24` → `rate_mean24` (one venue print is
149
- noise; the 24-sample mean is the crowd's bill) · `FUNDING_ANN value` → `ann` · `OI_CHG value` →
150
- `oiChg` · `OI_PX_REGIME value` → `oiRegime` (vocab: `new longs` / `new shorts` /
151
- `short covering` / `long liquidation`) · `MARK spread ORACLE` → `mark_oracle_spread` (perp
152
- premium) · `RSI14 value` · `CHG_24H value` → `chg24h`. Plus platform `includeCvd`.
153
-
154
- **Conditions** (building blocks carry no verdict; NOT as a required veto):
155
-
156
- ```json
157
- [
158
- { "conditionKey": "NO_LIQUIDATION_TAPE", "name": "Not a liquidation knife",
159
- "definition": { "kind": "group", "op": "NOT", "members": [
160
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "oiRegime" }, "op": "is", "label": "long liquidation" } ] },
161
- "verdict": null, "required": true },
162
- { "conditionKey": "CROWDED_LONGS", "name": "Longs overpaying and adding",
163
- "definition": { "kind": "group", "op": "ALL", "members": [
164
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "ann" }, "op": "gte", "value": 25 },
165
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "oiChg" }, "op": "gte", "value": 3 },
166
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "oiRegime" }, "op": "is", "label": "new longs" } ] },
167
- "verdict": null, "required": false },
168
- { "conditionKey": "FADE_SHORT", "name": "Fade the crowded long",
169
- "definition": { "kind": "group", "op": "ALL", "members": [
170
- { "kind": "conditionRef", "conditionKey": "CROWDED_LONGS" },
171
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "RSI14" }, "op": "gte", "value": 65 },
172
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "chg24h" }, "op": "gte", "value": 5 } ] },
173
- "verdict": "DOWN", "required": false },
174
- { "conditionKey": "SQUEEZED_SHORTS", "name": "Shorts overpaying and adding",
175
- "definition": { "kind": "group", "op": "ALL", "members": [
176
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "ann" }, "op": "lte", "value": -25 },
177
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "oiChg" }, "op": "gte", "value": 3 },
178
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "oiRegime" }, "op": "is", "label": "new shorts" } ] },
179
- "verdict": null, "required": false },
180
- { "conditionKey": "SQUEEZE_LONG", "name": "Squeeze the crowded short",
181
- "definition": { "kind": "group", "op": "ALL", "members": [
182
- { "kind": "conditionRef", "conditionKey": "SQUEEZED_SHORTS" },
183
- { "kind": "clause", "column": { "sectionKey": "custom:b2b2b2b2-c3c3-4d4d-8e5e-f6f6f6f6f6f6", "header": "RSI14" }, "op": "lte", "value": 35 } ] },
184
- "verdict": "UP", "required": false }
185
- ]
186
- ```
187
-
188
- **Rules** (note the tuned params — read `get_strategy_signal_definition` first):
189
- `funding_extreme_positive` 3 required, params `{"thresholdPct": 0.001}` ·
190
- `funding_extreme_negative` 3 required, params `{"thresholdPct": 0.001}` · `oi_surge` 2, params
191
- `{"thresholdPct": 0.03}` · `rsi_overbought` 2, params `{"threshold": 65}` · `rsi_oversold` 2,
192
- params `{"threshold": 35}` · `cvd_bear_divergence` 2 · `cvd_bull_divergence` 2 ·
193
- `mfi_overbought` 1 · `mfi_oversold` 1.
194
-
195
- **Gates & geometry.** `minAggregateScore 0.6`, `minRequiredCount 1` (either funding extreme),
196
- `minAtrPct 0.5`. Levels `1.0–2.5` ATR (mean reversion needs room), RR `1.5`. Position
197
- management: break-even at `0.8R`, trailing off, **timeDecay on** (`grace 120`, `interval 60`,
198
- `tighten 10`, `max 40`, `stale 25`) — a fade that hasn't paid in a couple of hours is wrong.
199
-
200
- ---
201
-
202
- ## 3 · Relative-Strength Rotation with a Benchmark Gate (cross-sectional desk, 4h)
203
-
204
- **Thesis.** Own the leaders while the market leader trends up; press the laggards when it rolls
205
- over. Selection is cross-sectional (ranks), regime is read off a **benchmark section**.
206
-
207
- **Sections.** Custom `Leadership` (key `custom:d4d4…`): `CLOSE_CHANGE rank hi` →
208
- `closeChg_rank_hi` · `CLOSE_CHANGE rank lo` → `closeChg_rank_lo` · `RVOL rank hi` →
209
- `RVOL_rank_hi` · `EMA5 spread EMA13 × trajectory w4` → `EMA5_EMA13_spread_now` / `_trend` ·
210
- `NOTIONAL_VOLUME_1D value` → `vol24hUsd`. Custom `BTC Regime` with `"benchmarkTicker": "BTC"`
211
- (key `custom:c3c3…`): `MA_ALIGN value` → `MAalign` (bullish/bearish/mixed) · `ADX value` ·
212
- `REGIME_TREND value` → `regTrend`. Every row of that section reads BTC, not the evaluated coin.
213
-
214
- **Conditions** (refs compose the regime gate with selection; duplicated headers like `ADX`
215
- must be section-qualified — that is why the section keys are minted client-side):
216
-
217
- ```json
218
- [
219
- { "conditionKey": "BTC_RISK_ON", "name": "BTC trending up",
220
- "definition": { "kind": "group", "op": "ALL", "members": [
221
- { "kind": "clause", "column": { "sectionKey": "custom:c3c3c3c3-d4d4-4e5e-8f6f-a7a7a7a7a7a7", "header": "MAalign" }, "op": "is", "label": "bullish" },
222
- { "kind": "clause", "column": { "sectionKey": "custom:c3c3c3c3-d4d4-4e5e-8f6f-a7a7a7a7a7a7", "header": "ADX" }, "op": "gte", "value": 20 } ] },
223
- "verdict": null, "required": false },
224
- { "conditionKey": "BTC_RISK_OFF", "name": "BTC rolling over",
225
- "definition": { "kind": "clause", "column": { "sectionKey": "custom:c3c3c3c3-d4d4-4e5e-8f6f-a7a7a7a7a7a7", "header": "MAalign" }, "op": "is", "label": "bearish" },
226
- "verdict": null, "required": false },
227
- { "conditionKey": "LEADER", "name": "Top-5 leader with participation",
228
- "definition": { "kind": "group", "op": "ALL", "members": [
229
- { "kind": "clause", "column": { "sectionKey": "custom:d4d4d4d4-e5e5-4f6f-8a7a-b8b8b8b8b8b8", "header": "closeChg_rank_hi" }, "op": "lte", "value": 5 },
230
- { "kind": "clause", "column": { "sectionKey": "custom:d4d4d4d4-e5e5-4f6f-8a7a-b8b8b8b8b8b8", "header": "RVOL_rank_hi" }, "op": "lte", "value": 10 },
231
- { "kind": "clause", "column": { "sectionKey": "custom:d4d4d4d4-e5e5-4f6f-8a7a-b8b8b8b8b8b8", "header": "vol24hUsd" }, "op": "gte", "value": 100000000 } ] },
232
- "verdict": null, "required": false },
233
- { "conditionKey": "ROTATE_IN", "name": "Rotate into leadership",
234
- "definition": { "kind": "group", "op": "ALL", "members": [
235
- { "kind": "conditionRef", "conditionKey": "BTC_RISK_ON" },
236
- { "kind": "conditionRef", "conditionKey": "LEADER" } ] },
237
- "verdict": "UP", "required": false },
238
- { "conditionKey": "ROTATE_OUT", "name": "Press laggards in risk-off",
239
- "definition": { "kind": "group", "op": "ALL", "members": [
240
- { "kind": "conditionRef", "conditionKey": "BTC_RISK_OFF" },
241
- { "kind": "clause", "column": { "sectionKey": "custom:d4d4d4d4-e5e5-4f6f-8a7a-b8b8b8b8b8b8", "header": "closeChg_rank_lo" }, "op": "lte", "value": 5 } ] },
242
- "verdict": "DOWN", "required": false }
243
- ]
244
- ```
245
-
246
- **Rules.** `comparison_sector_momentum` 3 · `rel_roc_positive` 2 · `rel_roc_negative` 2 ·
247
- `ma_ema_aligned_bull` 2 required · `ma_ema_aligned_bear` 2 required · `rel_ppo_bull_cross` 1 ·
248
- `rel_ppo_bear_cross` 1 · `volume_surge` 1. Gates: `0.5 / 1 / 0.6`. Levels `1–2` ATR, RR `1.8`.
249
- PM: break-even 1R; trailing at 1R with giveback 45 (let rotation winners run); no timeDecay.
250
- `coinSelection` `{"mode":"ranked","limit":40,"category":"CRYPTO"}` — ranks need a wide cohort.
251
-
252
- ---
253
-
254
- ## 4 · HTF Trend Pullback (CTA desk, 1h, multi-timeframe confluence)
255
-
256
- **Thesis.** Only trade with the higher-timeframe trend; enter on anchor-rung pullbacks to value
257
- while the lower rung has not broken structure. Never spend an LLM call in chop.
258
-
259
- **Sections.** Platform `includeMtfConfluence` (headers per rung: `MAalign_ltf` / `MAalign` /
260
- `MAalign_htf`, `RSI14_*_zone`, `ADX_*_state` with vocab weak/developing/trending/extreme),
261
- platform `includeMovingAverages` (`dist_SMA20`, `dist_EMA20`, …), platform `includeRsi`
262
- (`RSI14_now`, `RSI14_zone`). Platform section keys are their literal `sectionKey` — qualify
263
- clauses with e.g. `"sectionKey": "includeMtfConfluence"` where headers collide.
264
-
265
- **Conditions** — the `ANY`-of-trends required gate is the key move: chop (neither trend) blocks
266
- compose-trade entirely, before billing:
267
-
268
- ```json
269
- [
270
- { "conditionKey": "HTF_UP", "name": "HTF uptrend",
271
- "definition": { "kind": "group", "op": "ALL", "members": [
272
- { "kind": "clause", "column": { "sectionKey": "includeMtfConfluence", "header": "MAalign_htf" }, "op": "is", "label": "bullish" },
273
- { "kind": "clause", "column": { "sectionKey": "includeMtfConfluence", "header": "ADX_htf_state" }, "op": "in", "labels": ["trending", "extreme"] } ] },
274
- "verdict": null, "required": false },
275
- { "conditionKey": "HTF_DOWN", "name": "HTF downtrend",
276
- "definition": { "kind": "group", "op": "ALL", "members": [
277
- { "kind": "clause", "column": { "sectionKey": "includeMtfConfluence", "header": "MAalign_htf" }, "op": "is", "label": "bearish" },
278
- { "kind": "clause", "column": { "sectionKey": "includeMtfConfluence", "header": "ADX_htf_state" }, "op": "in", "labels": ["trending", "extreme"] } ] },
279
- "verdict": null, "required": false },
280
- { "conditionKey": "TREND_PRESENT", "name": "Some HTF trend exists",
281
- "definition": { "kind": "group", "op": "ANY", "members": [
282
- { "kind": "conditionRef", "conditionKey": "HTF_UP" },
283
- { "kind": "conditionRef", "conditionKey": "HTF_DOWN" } ] },
284
- "verdict": null, "required": true },
285
- { "conditionKey": "PULLBACK_LONG", "name": "Pullback to value in uptrend",
286
- "definition": { "kind": "group", "op": "ALL", "members": [
287
- { "kind": "conditionRef", "conditionKey": "HTF_UP" },
288
- { "kind": "clause", "column": { "sectionKey": "includeRsi", "header": "RSI14_now" }, "op": "between", "low": 35, "high": 55 },
289
- { "kind": "clause", "column": { "sectionKey": "includeMovingAverages", "header": "dist_EMA20" }, "op": "between", "low": -3, "high": 0.5 } ] },
290
- "verdict": "UP", "required": false },
291
- { "conditionKey": "PULLBACK_SHORT", "name": "Rally to value in downtrend",
292
- "definition": { "kind": "group", "op": "ALL", "members": [
293
- { "kind": "conditionRef", "conditionKey": "HTF_DOWN" },
294
- { "kind": "clause", "column": { "sectionKey": "includeRsi", "header": "RSI14_now" }, "op": "between", "low": 45, "high": 65 },
295
- { "kind": "clause", "column": { "sectionKey": "includeMovingAverages", "header": "dist_EMA20" }, "op": "between", "low": -0.5, "high": 3 } ] },
296
- "verdict": "DOWN", "required": false }
297
- ]
298
- ```
299
-
300
- **Rules.** `mtf_pullback_long` 3 required · `mtf_pullback_short` 3 required ·
301
- `htf_ma_aligned_bull` 2 required · `htf_ma_aligned_bear` 2 required · `htf_trend_adx_trending`
302
- 2 · `ma_ema_aligned_bull` 1 · `ma_ema_aligned_bear` 1 · `rsi_oversold` 1 params
303
- `{"threshold": 40}` (pullback depth, not capitulation). Gates: `minAggregateScore 0.6`,
304
- `minRequiredCount 2` (a pullback signal *and* an HTF alignment), `minAtrPct 0.7`. Levels
305
- `1–2.5` ATR, RR `2`. PM: break-even 1R; trailing 1.5R giveback 30 buffer 0.3; no timeDecay.
306
-
307
- ---
308
-
309
- ## 5 · Perp/Spot Flow Divergence at Structure (microstructure desk, 15m scalp)
310
-
311
- **Thesis.** When spot flow leads (accumulation) and price sits just above a standing support
312
- zone, buy the dip; when a move is perp-led and fragile into resistance, fade it. Structure comes
313
- from the platform zones section; flow from the perp/spot module.
314
-
315
- **Sections.** Platform `includePerpSpotFlow` (`perpSpotFlow` vocab: `confirmed_bull` /
316
- `confirmed_bear` / `perp_led_fragile` / `spot_led_accumulation` / `neutral`; plus
317
- `perpSpotStr`, `spotCVD`), platform `includeStructureZones` (`zones_htf_support_dist` — signed %
318
- from price, support below price is negative; `zones_htf_resist_dist`, `_age_h`, `_type`),
319
- custom `Tape` (key `custom:e5e5…`): `BUY_PRESSURE value` → `buyPres` (0–1) · `RVOL value` ·
320
- `CLOSE_CHANGE value` → `closeChg`.
321
-
322
- **Conditions** — `N_OF` requires 2-of-3 tape confirmations instead of a brittle ALL:
323
-
324
- ```json
325
- [
326
- { "conditionKey": "SPOT_ACCUM", "name": "Spot-led accumulation",
327
- "definition": { "kind": "clause", "column": { "sectionKey": "includePerpSpotFlow", "header": "perpSpotFlow" }, "op": "is", "label": "spot_led_accumulation" },
328
- "verdict": null, "required": false },
329
- { "conditionKey": "NEAR_SUPPORT", "name": "Sitting on a standing zone",
330
- "definition": { "kind": "group", "op": "ALL", "members": [
331
- { "kind": "clause", "column": { "sectionKey": "includeStructureZones", "header": "zones_htf_support_dist" }, "op": "between", "low": -2, "high": 0 },
332
- { "kind": "clause", "column": { "sectionKey": "includeStructureZones", "header": "zones_htf_support_age_h" }, "op": "gte", "value": 12 } ] },
333
- "verdict": null, "required": false },
334
- { "conditionKey": "DIP_BID", "name": "Buy the dip into support",
335
- "definition": { "kind": "group", "op": "ALL", "members": [
336
- { "kind": "conditionRef", "conditionKey": "SPOT_ACCUM" },
337
- { "kind": "conditionRef", "conditionKey": "NEAR_SUPPORT" },
338
- { "kind": "group", "op": "N_OF", "n": 2, "members": [
339
- { "kind": "clause", "column": { "sectionKey": "custom:e5e5e5e5-f6f6-4a7a-8b8b-c9c9c9c9c9c9", "header": "buyPres" }, "op": "gte", "value": 0.55 },
340
- { "kind": "clause", "column": { "sectionKey": "custom:e5e5e5e5-f6f6-4a7a-8b8b-c9c9c9c9c9c9", "header": "RVOL" }, "op": "gte", "value": 1.2 },
341
- { "kind": "clause", "column": { "sectionKey": "custom:e5e5e5e5-f6f6-4a7a-8b8b-c9c9c9c9c9c9", "header": "closeChg" }, "op": "gt", "value": 0 } ] } ] },
342
- "verdict": "UP", "required": false },
343
- { "conditionKey": "FRAGILE_POP", "name": "Perp-led pop into resistance",
344
- "definition": { "kind": "group", "op": "ALL", "members": [
345
- { "kind": "clause", "column": { "sectionKey": "includePerpSpotFlow", "header": "perpSpotFlow" }, "op": "is", "label": "perp_led_fragile" },
346
- { "kind": "clause", "column": { "sectionKey": "includeStructureZones", "header": "zones_htf_resist_dist" }, "op": "between", "low": 0, "high": 2 },
347
- { "kind": "clause", "column": { "sectionKey": "custom:e5e5e5e5-f6f6-4a7a-8b8b-c9c9c9c9c9c9", "header": "RVOL" }, "op": "gte", "value": 1.3 } ] },
348
- "verdict": "DOWN", "required": false }
349
- ]
350
- ```
351
-
352
- **Rules.** `flow_perp_spot_bull_divergence` 3 required · `flow_perp_spot_bear_divergence` 3
353
- required · `cvd_bull_divergence` 2 · `cvd_bear_divergence` 2 · `sr_at_support` 2 ·
354
- `sr_at_resistance` 2 · `structure_ob_approach` 1 · `volume_surge` 1. Gates: `0.55 / 1 / 0.4`
355
- (15m: lower ATR floor). Levels `0.5–1.2` ATR, RR `1.5` — scalp geometry. PM: break-even
356
- `0.7R`; trailing `0.9R`, giveback 30, buffer 0.15; **timeDecay on and aggressive** (`grace 45`,
357
- `interval 15`, `tighten 15`, `max 60`, `stale 30`). `coinSelection`
358
- `{"mode":"ranked","limit":15,"category":"CRYPTO"}`.
359
-
360
- ---
361
-
362
- ## Using a playbook
363
-
364
- 1. Re-discover the vocabulary; confirm each header via `get_strategy_column_contract` or one
365
- `preview_strategy_report` over your sections (read `conditionColumns`).
366
- 2. Adapt thresholds to the current market — preview shows live values beside each clause, so
367
- calibrate literals against what the table actually renders.
368
- 3. Compile once, read `approvedPlan` (scorecard, diff, viability) and
369
- `reviewContext.reportPreview` (condition outcomes, verdict tally, budgets), fix, recompile.
370
- 4. Apply with `{ "request": { "planToken": "<verbatim>", "confirm": true } }` after review.
@@ -1,173 +0,0 @@
1
- # Strategy Studio recipes — copy-adaptable fragments
2
-
3
- Validated against the live server 2026-08-28; shapes binding, tokens illustrative — re-discover
4
- before compiling. Column recipes are objects for a custom section's `columns[]`; condition
5
- recipes drop into `conditions[]`.
6
-
7
- ## Column recipes
8
-
9
- | Intent | Column | Header it generates |
10
- |---|---|---|
11
- | Live traded price | `{ "metric": "LAST", "transformId": "value", "timeframe": { "rel": "anchor" } }` | `last` |
12
- | Momentum build-up | `{ "metric": "RSI14", "transformId": "trajectory", "timeframe": { "rel": "anchor" }, "window": 4 }` | `RSI14_t3…_now`, `RSI14_trend` |
13
- | Closed-bar-only trajectory (no forming-bar noise) | add `"bars": "closed"` to any trajectory | same, drawn from closed bars |
14
- | Extension from trend | `{ "metric": "SMA50", "transformId": "distance", "timeframe": { "rel": "anchor" } }` | `dist_SMA50` (signed %) |
15
- | Perp premium | `{ "metric": "MARK", "transformId": "spread", "timeframe": { "rel": "anchor" }, "inputs": [{ "metric": "ORACLE" }] }` | `mark_oracle_spread` |
16
- | Cross-venue basis | `MARK spread SPOT_CLOSE_BN` (or `SPOT_CLOSE_CB`) | `mark_bnClose_spread` |
17
- | Funding paid over a day | `{ "metric": "FUNDING_RATE", "transformId": "aggregate", "timeframe": { "rel": "anchor" }, "window": 24 }` | `rate_mean24` |
18
- | Board-wide standing | `{ "metric": "ATR_PCT", "transformId": "rank", "timeframe": { "rel": "anchor" }, "ordering": "hi" }` | `atrPct_rank_hi` (1 = most volatile) |
19
- | Biggest movers, sign-agnostic | `CLOSE_CHANGE rank far` | `closeChg_rank_far` |
20
- | Most extended from VWAP on the board | `{ "metric": "VWAP", "transformId": "distance", "chainedTransformId": "rank", "timeframe": { "rel": "anchor" }, "ordering": "far" }` | `dist_VWAP_rank_far` (confirm via contract) |
21
- | EMA ribbon compression trend | `{ "metric": "EMA5", "transformId": "spread", "chainedTransformId": "trajectory", "timeframe": { "rel": "anchor" }, "inputs": [{ "metric": "EMA13" }], "window": 4 }` | `EMA5_EMA13_spread_now`, `_trend` |
22
- | Chop filter on the entry rung | `{ "metric": "CLOSE", "transformId": "efficiency", "timeframe": { "rel": "lower" }, "window": 5, "bars": "closed" }` | `close_ltf_er` (≥0.6 = directional) |
23
- | One-bar volume concentration | `{ "metric": "VOLUME", "transformId": "maxShare", "timeframe": { "rel": "lower" }, "window": 4, "bars": "closed" }` | `volBase_ltf_maxShare` |
24
- | Room to structure | `{ "metric": "STRUCT_ZONES", "transformId": "nearestZoneDist", "timeframe": { "rel": "regime" }, "side": "resistance" }` | `zones_htf_resist_dist` |
25
- | Crowd fade input | `{ "metric": "CROWD_UPBIAS", "transformId": "value", "timeframe": { "rel": "anchor" } }` | `upBias` (%, last 4 settled sessions) |
26
- | Daily trend state on any anchor | `{ "metric": "MA_ALIGN", "transformId": "value", "timeframe": { "abs": "1d" } }` | `MAalign_1d` |
27
- | Last **closed** daily read (deterministic) | `{ "metric": "RSI14", "transformId": "value", "timeframe": { "abs": "1d" }, "offset": 1 }` | `RSI14_1d` — formula `RSI14[t - 1]` |
28
- | Daily extension from the 200 | `{ "metric": "SMA200", "transformId": "distance", "timeframe": { "abs": "1d" } }` | `dist_SMA200_1d` |
29
- | Daily-structure breakout state | `{ "metric": "PRICE_ZONE", "transformId": "value", "timeframe": { "abs": "1d" } }` | `zone_1d` — `is "breakout high"` / `"breakdown low"` |
30
- | Room to the daily swing high | `{ "metric": "SWING_HIGH", "transformId": "distance", "timeframe": { "abs": "1d" } }` | `dist_swingHi_1d` (signed %; `gte 0` = above it) |
31
-
32
- Rung suffixes: `{ "rel": "lower" }` → `_ltf`, `{ "rel": "regime" }` → `_htf` (the anchor's
33
- ladder successor — 1d for a 4h anchor), pinned `{ "abs": "<tf>" }` → `_<tf>` (e.g. `_1d`).
34
- Pins bind to discovery's `rankedTimeframes` (a superset of the anchor set), are fixed across
35
- anchor retunes, and `offset` does not change the header — one offset per `metric × timeframe`
36
- per section. `offset` is a `value`-transform parameter only: `distance` rejects it (typed
37
- error), so a level is always measured as it stands now. That is a statement about `offset`, not
38
- about prior-day levels: `PDH`/`PDL` are published structure metrics at the daily anchor and take
39
- `distance` and `crossDetect`, so the literal previous-session extreme is authored as
40
- `dist_PDH_1d` rather than reconstructed from an offset. The daily *swing* levels (`zone_1d`,
41
- `dist_swingHi_1d`) are the tracked pivot — a different level, not a substitute. Conditions
42
- compare a column against a literal, never against another column. Rank ordering semantics:
43
- `hi` most positive, `lo` most negative, `far`/`near` by magnitude (offered only where sign
44
- matters).
45
-
46
- ## Condition patterns
47
-
48
- **Band (between).** RSI pullback zone rather than a single threshold:
49
- `{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "between", "low": 35, "high": 55 }`
50
- (`sectionKey: null` is legal only while the header is unique report-wide.)
51
-
52
- **Label membership (in).** Accept two of a classification's states:
53
- `{ "kind": "clause", "column": { "sectionKey": "includeMtfConfluence", "header": "ADX_htf_state" }, "op": "in", "labels": ["trending", "extreme"] }`
54
-
55
- **Veto (NOT + required).** Block the whole compose-trade path on a disqualifier — evaluated
56
- before any billing or LLM call:
57
-
58
- ```json
59
- { "conditionKey": "NO_EVENT_RISK", "name": "No liquidation tape", "verdict": null, "required": true,
60
- "exit": false, "clock": "LIVE", "closes": 1,
61
- "definition": { "kind": "group", "op": "NOT", "members": [
62
- { "kind": "clause", "column": { "sectionKey": null, "header": "oiRegime" }, "op": "is", "label": "long liquidation" } ] } }
63
- ```
64
-
65
- All eight keys are required on every condition — `exit`, `clock` and `closes` included. `clock`
66
- selects the evidence frame (`LIVE` reads the forming bar, `CLOSE` reads settled bars) and `closes`
67
- (1–5) is how many consecutive closed bars must hold; `closes` is always `1` under `LIVE`. `exit:
68
- true` closes open positions the verdict opposes and is legal only under `clock: "CLOSE"`.
69
-
70
- **Quorum (N_OF).** Robust confirmation instead of a brittle ALL:
71
-
72
- ```json
73
- { "kind": "group", "op": "N_OF", "n": 2, "members": [
74
- { "kind": "clause", "column": { "sectionKey": null, "header": "buyPres" }, "op": "gte", "value": 0.55 },
75
- { "kind": "clause", "column": { "sectionKey": null, "header": "RVOL" }, "op": "gte", "value": 1.2 },
76
- { "kind": "clause", "column": { "sectionKey": null, "header": "closeChg" }, "op": "gt", "value": 0 } ] }
77
- ```
78
-
79
- **Building block + carriers.** Factor shared state once (`verdict: null`), reference it from
80
- directional carriers; the first TRUE carrier **in declaration order** decides — order carriers
81
- most-specific first.
82
-
83
- **Benchmark gate.** Read regime off a `benchmarkTicker` section (all rows are the benchmark's
84
- values) and `conditionRef` it from every carrier — one place to flip the book risk-on/off. Keep that
85
- section to indicators: crowd/session metrics and `rank` transforms are refused on a bound section
86
- (contract 49) — rank the coins on an ordinary section and `conditionRef` the two together.
87
-
88
- **Required-count trap.** `required: true` at `allocation: 0` on a *signal rule* is rejected
89
- (contract 34). A required *condition* is independent of signal weights — the two gates stack.
90
-
91
- ## Entry discipline recipes
92
-
93
- The `entry` object is required on every CREATE, all seven keys, no defaults.
94
-
95
- | Intent | Object |
96
- |---|---|
97
- | Today's behaviour, unchanged | `{ "trigger": "AT_SIGNAL", "confirmTf": "<strategy tf>", "closes": 1, "bandAtrMultiple": 1.0, "levelSource": "SWING_HIGH", "levelOffsetAtrMultiple": 0, "validForBars": 4 }` |
98
- | Wait for the bar to close, skip a runaway | `{ "trigger": "ON_CANDLE_CLOSE", "confirmTf": "<strategy tf>", "closes": 1, "bandAtrMultiple": 1.0, … }` |
99
- | Two-close confirmation on the lower rung | `{ "trigger": "ON_CANDLE_CLOSE", "confirmTf": "<lower rung>", "closes": 2, "bandAtrMultiple": 0.75, … }` |
100
- | Break of the swing high, half an ATR through | `{ "trigger": "STOP_THROUGH_LEVEL", "levelSource": "SWING_HIGH", "levelOffsetAtrMultiple": 0.5, "validForBars": 8, "closes": 1, … }` |
101
- | Buy the retest of the broken level | `{ "trigger": "ON_RETEST", "levelSource": "SWING_HIGH", "levelOffsetAtrMultiple": 0, "validForBars": 12, "closes": 1, … }` |
102
-
103
- Bounds: `closes` 1–5 and `1` unless `ON_CANDLE_CLOSE`; `bandAtrMultiple` > 0 and ≤ the platform's
104
- `defaultMaxEntryDeviationAtrMultiple`; `levelOffsetAtrMultiple` 0–2 unsigned and `0` unless a level
105
- trigger; `validForBars` 1–24. `confirmTf` is the strategy timeframe or the rung below it, nothing
106
- else. A meaningful value under a trigger that ignores it is REFUSED, not ignored — that is
107
- deliberate, so a dial never silently does nothing.
108
-
109
- ## Custom section shape
110
-
111
- `{ kind, sectionKey, title, benchmarkTicker, notes, columns }`. `benchmarkTicker` and
112
- `notes` are **required-nullable** — send explicit `null` rather than omitting them, because the
113
- section is rebuilt whole on save and an omitted key clears the value. **Omit `sectionKey` on a
114
- CREATE**: the server derives it from the section.
115
-
116
- A section carries **no `timeframe`** (48.0.0). Its relative columns resolve against the strategy
117
- timeframe; a column reaches any other timeframe by pinning it — `timeframe: { abs: '4h' }` on the
118
- column, which it could always do.
119
-
120
- ## Weight matrices (rules)
121
-
122
- **Conviction pyramid (default).** 1–2 × Critical (the thesis signals, usually `required`),
123
- 2–4 × Important (independent confirmation — different modules, not correlated oscillators),
124
- 1–3 × Normal (context), everything else Off. With weights 3/2/2/1 and the Critical + one
125
- Important triggered at score 1.0: aggregate = (3+2)/(3+2+2+1) = 0.625 → a gate of 0.6 means
126
- "thesis + one confirmation, minimum".
127
-
128
- **Gate math check.** Before setting `minAggregateScore`, list the trigger combinations that
129
- should route, compute Σ(score×alloc)/Σ(alloc) for the weakest acceptable one, and gate just
130
- below it. `simulate_aggregate_score` does this arithmetic for you from compiled values.
131
-
132
- **Directional symmetry.** A both-ways book weights bull/bear siblings identically
133
- (`ma_ema_aligned_bull`/`_bear` both 2-required) and lets conditions decide direction.
134
-
135
- **Param tuning.** Always read `get_strategy_signal_definition({ signalId, timeframe })` first;
136
- send the full replacement object. Examples validated as canonical defaults: `volume_surge`
137
- `{"multiplier": 2}`, `rsi_overbought` `{"threshold": 70}`, `funding_extreme_positive`
138
- `{"thresholdPct": 0.0005}`, `trend_adx_trending` `{"threshold": 25}`,
139
- `comparison_btc_decorrelation` `{"maxCorrelation": 0.3}`.
140
-
141
- ## Trade-level + position-management presets by persona
142
-
143
- | Persona (anchor) | Stop band (ATR) | RR | Break-even | Trailing | Time decay |
144
- |---|---|---|---|---|---|
145
- | Scalper (5m/15m) | 0.5 – 1.2 | 1.5 | 0.7R | 0.9R, giveback 30, buffer 0.15 | ON: 45/15 min, tighten 15 → max 60, stale 30 |
146
- | Intraday mean-revert (1h) | 1.0 – 2.5 | 1.5 | 0.8R | off | ON: 120/60 min, tighten 10 → max 40, stale 25 |
147
- | Swing breakout (4h) | 0.75 – 1.75 | 2 | 1R | 1.2R, giveback 35, buffer 0.3 | off |
148
- | Swing trend (4h) | 1.0 – 2.5 | 2 | 1R | 1.5R, giveback 45–55, buffer 0.3 | off |
149
-
150
- Post-entry invalidation: `decisionInvalidationExitEnabled: true` closes a filled position when a
151
- **closed** strategy-timeframe candle finishes beyond the decision's invalidation level, reduce-only.
152
- Bar-close only — the protective stop still owns intrabar moves.
153
-
154
- Bounds to respect (validated): break-even trigger 0.5–2R; trailing trigger 0–2R step 0.01
155
- (0 = trail from entry); giveback 25–55%; buffer 0.01–1%; grace ≥ interval; stop-band floor <
156
- ceiling ≤ the 3×ATR structural cap; RR within the catalog's served range (0.5–3 today). Wider
157
- stop ⇒ smaller position (risk-budget sizing), never more risk.
158
-
159
- ## Coin selection patterns
160
-
161
- - Focused edit / review: `{ "mode": "explicit", "tickers": ["BTC", "ETH", "SOL"] }`
162
- - Scanning book: `{ "mode": "ranked", "limit": 40, "category": "CRYPTO" }`
163
- - Sector books: `category` from the served list (`L1`, `MEMES`, `DEFI`, `TRADFI`, `STOCKS`,
164
- `INDICES`, `COMMODITIES`) — e.g. a memes-only fade book previews against `MEMES`.
165
- - Rank-based conditions need a cohort at least as wide as the rank thresholds they test.
166
-
167
- ## Market Read patterns
168
-
169
- - Reference the decision, not just data: `"Act only while {SQUEEZE_ON} is TRUE"` renders the
170
- condition's outcome *with its evidence*.
171
- - Qualify on collision: `{custom:<uuid>.MAalign}` / `{includeMtfConfluence.MAalign}`.
172
- - After previewing, check `marketReadMarkers[].status` — fix every `unknown` / `ambiguous`
173
- marker before compiling; `qualifiedForms` lists the exact replacements.