@battlegrid/mcp-server 31.0.3 → 31.1.5
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 +264 -5
- package/SKILL.md +110 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -2
- package/skills/battlegrid-strategy-studio/SKILL.md +254 -0
- package/skills/battlegrid-strategy-studio/references/playbooks.md +370 -0
- package/skills/battlegrid-strategy-studio/references/recipes.md +170 -0
- package/skills/battlegrid-strategy-studio/references/tradingview-ports.md +235 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: battlegrid-strategy-studio
|
|
3
|
+
description: Author full-power BattleGrid trading strategies over MCP — multi-section reports, benchmark sections, layered conditions with verdicts and enforcement gates, tiered signal weights, routing gates, ATR trade levels, and post-entry position management. Use whenever building or upgrading a strategy so it uses the whole studio, not a bare template. Companion to the `battlegrid` skill, which owns connection and the compile → review → apply workflow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# BattleGrid Strategy Studio — full-power authoring
|
|
7
|
+
|
|
8
|
+
A default strategy — a few platform sections, no conditions, untouched weights — wastes the
|
|
9
|
+
studio. This skill teaches every axis the strategy aggregate owns and how professional desks
|
|
10
|
+
compose them. Workflow, envelopes, and error recovery live in the `battlegrid` skill; this one
|
|
11
|
+
is about *what to author*.
|
|
12
|
+
|
|
13
|
+
**Ground rule: shapes here are binding, tokens are illustrative.** Every metric code, signal id,
|
|
14
|
+
header, and bound in this skill was validated against the live server, but the server's
|
|
15
|
+
vocabulary moves with deployments. Before compiling, re-discover (`list_strategy_categories` →
|
|
16
|
+
`list_strategy_vocabulary` → `get_metric_construction_hints` → `get_strategy_column_contract`,
|
|
17
|
+
`list_strategy_signals` → `get_strategy_signal_definition`) and prefer what discovery returns
|
|
18
|
+
over anything printed here.
|
|
19
|
+
|
|
20
|
+
## What a strategy owns (author all of it, deliberately)
|
|
21
|
+
|
|
22
|
+
| Axis | Fields | What it does |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Identity | `name` ≤50, `tagline` ≤80, `description` ≤500 | How agents and humans find it |
|
|
25
|
+
| Timeframe | `timeframe` (from discovery's enabled list) | Anchor rung; cadence persona and regime rung derive from it |
|
|
26
|
+
| Report | `sections[]` — platform + custom columns | The per-coin table the agent LLM actually reads |
|
|
27
|
+
| Conditions | `conditions[]` — typed boolean trees | Deterministic verdicts (UP/DOWN/NEITHER) + hard enforcement gates |
|
|
28
|
+
| Signal rules | `rules[]` — `{signalId, allocation 0–3, required, params?}` | What scores, how much it counts, what must fire |
|
|
29
|
+
| Routing gates | `minAggregateScore` 0–1, `minRequiredCount` 0–20, `minAtrPct` | Whether a scored setup may route to a trade |
|
|
30
|
+
| Trade levels | `minStopLossAtrMultiple` < `maxStopLossAtrMultiple`, `minRiskRewardRatio` | Where stops/targets may sit |
|
|
31
|
+
| Position management | breakEven / trailing / timeDecay dials | How the stop moves after entry |
|
|
32
|
+
| Market Read | `marketReadText` ≤2000 with `{...}` markers | Standing orders rendered with live values |
|
|
33
|
+
|
|
34
|
+
A compile also always carries `intentSummary`, `assumptions[]`, and `coinSelection` — call
|
|
35
|
+
context, not strategy state (see the `battlegrid` skill).
|
|
36
|
+
|
|
37
|
+
## The full-power checklist
|
|
38
|
+
|
|
39
|
+
Before compiling a CREATE, confirm all six; a "no" is a decision, not an omission:
|
|
40
|
+
|
|
41
|
+
1. Report has at least one **custom section** whose columns encode the thesis (not only platform
|
|
42
|
+
modules), and every column earns its tokens.
|
|
43
|
+
2. **Conditions** encode the entry logic deterministically — building blocks + verdict carriers —
|
|
44
|
+
and at least one `required: true` condition guards spend on obvious disqualifiers.
|
|
45
|
+
3. **Every signal you want scoring is named in `rules`** with a deliberate tier; signals you do
|
|
46
|
+
not name keep server defaults (typically Off). Verify in the compiled scorecard, never assume.
|
|
47
|
+
4. **Gates** are set against the weight budget you chose (see scoring math below).
|
|
48
|
+
5. **Trade levels + position management** match the setup's geometry and holding period.
|
|
49
|
+
6. `marketReadText` states the standing orders with markers so the agent sees live values inline.
|
|
50
|
+
|
|
51
|
+
## Report grammar — sections and columns
|
|
52
|
+
|
|
53
|
+
A custom column is `metric × transform (± chained transform) × timeframe ref (± params)`.
|
|
54
|
+
Headers are **system-generated, never named by you**. Validated affix patterns:
|
|
55
|
+
|
|
56
|
+
| Transform | Header shape | Example (validated) |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `value` | `<code>` | `bbWidthPct`, `RVOL`, `rate` |
|
|
59
|
+
| `trajectory` (window 4) | `<code>_t3 … _t1`, `<code>_now`, `<code>_trend` (rising/falling/flat) | `RSI14_now`, `RSI14_trend` |
|
|
60
|
+
| `distance` (price → level) | `dist_<code>` (signed %) | `dist_SMA50` |
|
|
61
|
+
| `spread` (base vs operand) | `<base>_<operand>_spread` | `mark_oracle_spread`, `EMA5_EMA13_spread` |
|
|
62
|
+
| `aggregate` (window N) | `<code>_mean<N>` | `rate_mean24` |
|
|
63
|
+
| `rank` (ordering hi/lo/far/near) | `<code>_rank_<ordering>` — ordinal, 1 = best; compare with `lte N` for top-N | `bbWidthPct_rank_lo`, `closeChg_rank_far` |
|
|
64
|
+
| `efficiency` (window N) | `<code>_er` (0–1; 1 = straight move, ~0 = chop) | `close_ltf_er` |
|
|
65
|
+
| `maxShare` (window N) | `<code>_maxShare` (0–1 concentration) | `volBase_ltf_maxShare` |
|
|
66
|
+
| `classifyZone` / `classifyState` | `<code>_zone` / `<code>_state` | `RSI14_zone` (overbought/oversold/neutral), `ADX_state` (weak/developing/trending/extreme) |
|
|
67
|
+
|
|
68
|
+
Non-anchor rungs add a rung affix: `_ltf` (lower) / `_htf` (regime), e.g. `MAalign_htf`,
|
|
69
|
+
`zones_htf_support_dist`. Chains are bounded at two: inner `distance`/`spread` → outer
|
|
70
|
+
`trajectory`/`aggregate`/`efficiency`/`maxShare`/`rank` (e.g. EMA5 `spread` EMA13 ×
|
|
71
|
+
`trajectory` → `EMA5_EMA13_spread_now` + `_trend`). Read exact headers from
|
|
72
|
+
`get_strategy_column_contract` or a `preview_strategy_report`'s `conditionColumns` before
|
|
73
|
+
writing conditions against them.
|
|
74
|
+
|
|
75
|
+
**Timeframe references — two families.** *Relative* (`{rel: "anchor" | "lower" | "regime"}`)
|
|
76
|
+
re-resolve when the strategy timeframe changes; `regime` is the anchor's ladder successor (a 4h
|
|
77
|
+
anchor's regime rung is 1d today). *Pinned* (`{abs: "<tf>"}`) is fixed and ignores anchor
|
|
78
|
+
retunes; its legal set is discovery's `rankedTimeframes` — a **superset** of the authorable
|
|
79
|
+
anchor set (`timeframes`), so `{abs: "1d"}` is valid while `1d` is not an anchor. Pinned
|
|
80
|
+
headers suffix the literal: `RSI14_1d`, `dist_SMA200_1d`, `MAalign_1d` (validated). `offset: 1`
|
|
81
|
+
on a pinned `value` column reads the **last closed** bar of that timeframe — the deterministic
|
|
82
|
+
daily-close read; offset does not change the header, so one section carries one offset per
|
|
83
|
+
`metric × timeframe`. This is how higher-timeframe theses (daily-chart strategies included)
|
|
84
|
+
are authored on an intraday anchor — see the daily pattern in `references/tradingview-ports.md`.
|
|
85
|
+
|
|
86
|
+
**Benchmark sections** (`benchmarkTicker: "BTC"` on a custom section) read the *benchmark's*
|
|
87
|
+
values instead of the evaluated coin's — the standard way to gate a whole book on market-leader
|
|
88
|
+
regime. `benchmarkTicker` is required-nullable on every custom section: send `null` for an
|
|
89
|
+
ordinary section, never omit it.
|
|
90
|
+
|
|
91
|
+
A bound section takes **indicator** columns only. Crowd/session metrics (the `CROWD_*` family,
|
|
92
|
+
`FLOW_ALIGN`, `SMART_RETAIL`, `CAPTAIN_CONF`, `CONFIDENCE`, `SETTLED_AT`, `PERP_SPOT_*`) and any
|
|
93
|
+
`rank` transform are refused there (contract 49), because both are defined relative to the cohort
|
|
94
|
+
being evaluated and a benchmark sits outside it — a crowd reading is what this session's players
|
|
95
|
+
did, a rank is a position among the coins under evaluation. Neither has a value for BTC-as-yardstick.
|
|
96
|
+
Put those columns on an ordinary section and `conditionRef` across.
|
|
97
|
+
|
|
98
|
+
Budgets are served by discovery (validated today: 32 sections, 32 custom columns, 8 distinct
|
|
99
|
+
timeframes, 16 conditions, 16 clauses, 16k estimated report tokens). `preview_strategy_report`
|
|
100
|
+
echoes your usage against each cap.
|
|
101
|
+
|
|
102
|
+
## Conditions — deterministic logic over your own report
|
|
103
|
+
|
|
104
|
+
Each condition: `{ conditionKey, name, definition, verdict, required, exit, clock, closes }` —
|
|
105
|
+
all eight required, no defaults. The conditions axis saves by whole-set replacement, so an omitted
|
|
106
|
+
key would silently un-clock a money gate on the next unrelated edit rather than be refused.
|
|
107
|
+
|
|
108
|
+
- **Clauses** compare one column: numeric/rank headers take `lt|lte|gte|gt|between`;
|
|
109
|
+
classification/direction/event headers take `is|in` with the column's exact vocabulary
|
|
110
|
+
(served per header in `conditionColumns` / the column contract).
|
|
111
|
+
- **Groups**: `ALL`, `ANY`, `NOT`, `N_OF` (with `n`), depth ≤ 2 (an inner group holds leaves
|
|
112
|
+
only).
|
|
113
|
+
- **References** (`{kind:"conditionRef", conditionKey}`) compose named conditions; cycles are
|
|
114
|
+
rejected, forward references are legal.
|
|
115
|
+
- **Column addressing**: `{sectionKey, header}`. `sectionKey: null` is authoring sugar for a
|
|
116
|
+
header unique across the whole report; a duplicated header (e.g. `ADX` in two sections) must
|
|
117
|
+
be section-qualified. On a **CREATE you omit `sectionKey` entirely** — the server derives it
|
|
118
|
+
from the section itself, so the same submitted section yields the same key on every compile, and
|
|
119
|
+
minting a `custom:<uuid>` yourself is refused. On an UPDATE or RESTORE, send back the keys
|
|
120
|
+
`get_strategy` returned. To qualify a duplicated header, read the key from a preview's
|
|
121
|
+
`conditionColumns` or from the candidates a `CONDITION_COLUMN_AMBIGUOUS` refusal offers.
|
|
122
|
+
- **Verdict**: `UP` | `DOWN` | `NEITHER` on deciding conditions, explicit `null` on building
|
|
123
|
+
blocks. Declaration order is precedence: the first TRUE condition with a non-null verdict
|
|
124
|
+
decides the coin's verdict. Put the more specific carrier first.
|
|
125
|
+
- **`required: true`** makes a FALSE reading a hard gate: the compose-trade evaluation is
|
|
126
|
+
blocked *before any billing or LLM call*. This is the cheapest risk control in the studio —
|
|
127
|
+
use it for liquidity floors, regime vetoes, and "never fight the HTF" rules.
|
|
128
|
+
- Evaluation is three-valued: `UNRESOLVED` (missing input) is never collapsed to FALSE, and
|
|
129
|
+
outcomes read from a still-forming bar are marked provisional.
|
|
130
|
+
- **The evidence clock.** `clock: "LIVE"` reads the forming bar; `clock: "CLOSE"` reads settled
|
|
131
|
+
bars, and `closes` (1–5) is how many consecutive closed bars must read TRUE — always `1` under
|
|
132
|
+
LIVE, which has exactly one frame. A CLOSE clock is legal **only** over a header resolved from
|
|
133
|
+
the coin's own candle series at offset 0; frame-inert operands (perp-payload scalars, published
|
|
134
|
+
rolling changes, ranks, zone entities, regime labels, enrichment metrics, session scalars) are
|
|
135
|
+
refused with `CONDITION_CLOCK_OPERAND_ILLEGAL`. The remedy is a split, not a re-clock: move that
|
|
136
|
+
clause into its own LIVE condition and `conditionRef` it.
|
|
137
|
+
- **The exit role.** `exit: true` makes a settled TRUE reading close open positions its verdict
|
|
138
|
+
opposes — UP exits SHORTs, DOWN exits LONGs, a `NEITHER` or `null` verdict exits both. Legal only
|
|
139
|
+
under `clock: "CLOSE"`, because an exit fired on a forming bar is an intrabar exit. Orthogonal to
|
|
140
|
+
`required`: the two act on disjoint lifecycles, pre-entry versus open.
|
|
141
|
+
|
|
142
|
+
## Entry — when, and where, an entry is taken
|
|
143
|
+
|
|
144
|
+
`{ trigger, confirmTf, closes, bandAtrMultiple, levelSource, levelOffsetAtrMultiple, validForBars }`
|
|
145
|
+
— all seven required on every CREATE, no defaults. Replaced WHOLE on save, so an omitted key
|
|
146
|
+
reverts an author's discipline silently rather than being refused.
|
|
147
|
+
|
|
148
|
+
| `trigger` | What it does |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `AT_SIGNAL` | Fire on the qualification flip, at whatever bar is on the tape. The platform's flat wall-clock entry window applies. |
|
|
151
|
+
| `ON_CANDLE_CLOSE` | The flip ARMS the pair; entry is taken only after a `confirmTf` close that still reads the conditions true and has not displaced beyond the band. |
|
|
152
|
+
| `STOP_THROUGH_LEVEL` | A TRIGGER order rests at the level ± offset; the exchange book is the watcher. |
|
|
153
|
+
| `ON_RETEST` | A LIMIT order rests at the broken level. Not filling is a correct outcome, not a failure. |
|
|
154
|
+
|
|
155
|
+
- `confirmTf` — exactly two values are legal: the strategy's own timeframe and the rung below it
|
|
156
|
+
(one only, at the ladder floor). Not the authorable main-candle set.
|
|
157
|
+
- `closes` — 1–5 consecutive confirming closes. Must be `1` under any trigger but `ON_CANDLE_CLOSE`.
|
|
158
|
+
- `bandAtrMultiple` — the veto width. The entry is VOIDED when the confirming close moved at or
|
|
159
|
+
beyond that many ATR against the armed verdict. Strictly `> 0` (zero voids on any adverse move,
|
|
160
|
+
which is a filter, not "off"), and at or below the platform's own entry-deviation gate — read it
|
|
161
|
+
from `get_trading_config_catalog`.
|
|
162
|
+
- `levelSource` — `SWING_HIGH` | `SWING_LOW` | `BOLLINGER_UPPER` | `BOLLINGER_LOWER`, resolved once
|
|
163
|
+
at decision time.
|
|
164
|
+
- `levelOffsetAtrMultiple` — 0–2, UNSIGNED. Direction is implied by the trigger and the verdict, so
|
|
165
|
+
a signed value would invert the trigger's meaning. Must be `0` under a non-level trigger.
|
|
166
|
+
- `validForBars` — 1–24 of the strategy's OWN bars, not minutes: a 1h setup waiting for a retest has
|
|
167
|
+
not failed after fifteen minutes.
|
|
168
|
+
|
|
169
|
+
The legality matrix runs **one way**: all seven keys are always present, so the question is never
|
|
170
|
+
"is it set" but "is it set to something that MEANS anything under this trigger". Leave a dial at its
|
|
171
|
+
inert value rather than setting one the platform will ignore.
|
|
172
|
+
|
|
173
|
+
## Signal weights — the scorecard is a weighted average, budget it
|
|
174
|
+
|
|
175
|
+
Allocation tiers: `0` Off, `1` Normal, `2` Important, `3` Critical.
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
aggregateScore = Σ(score × allocation) / Σ(allocation) over triggered signals
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Consequences worth designing around:
|
|
182
|
+
|
|
183
|
+
- Weights are **relative**: one Critical among Normals dominates; all-Critical equals all-Normal.
|
|
184
|
+
Build a pyramid — 1–2 Critical (the thesis), 2–4 Important (confirmation), a few Normal
|
|
185
|
+
(context) — and turn everything else Off so noise cannot dilute the average.
|
|
186
|
+
- `required: true` on a rule does two things: the signal counts toward `minRequiredCount` when
|
|
187
|
+
it triggers, and the gate blocks routing when too few required signals fired. A rule with
|
|
188
|
+
`required: true` at allocation 0 is **rejected** (contract 34) — raise the allocation or clear
|
|
189
|
+
the flag.
|
|
190
|
+
- `params` are per-signal and replace canonical defaults only when present and valid — tune
|
|
191
|
+
thresholds to the strategy (e.g. an RSI-overbought at 65 for a fade book) after reading
|
|
192
|
+
`get_strategy_signal_definition({signalId, timeframe})`. Omitted `params` preserve defaults
|
|
193
|
+
byte-for-byte.
|
|
194
|
+
- Which signals *can* trigger follows from your report's sections/columns
|
|
195
|
+
(`derive_strategy_rule_view` shows in-report membership for a draft). Weighting a signal your
|
|
196
|
+
report never feeds is dead weight.
|
|
197
|
+
|
|
198
|
+
## Routing gates
|
|
199
|
+
|
|
200
|
+
- `minAggregateScore` (0–1): floor on the weighted average above. Set it from your pyramid: if
|
|
201
|
+
routing should need the Critical thesis plus one Important confirmation, compute that mix's
|
|
202
|
+
aggregate and gate just under it.
|
|
203
|
+
- `minRequiredCount` (0–20): how many `required` signals must be among the triggered set.
|
|
204
|
+
- `minAtrPct`: minimum ATR as % of price — a dead-market filter; bounds come from
|
|
205
|
+
`get_trading_config_catalog` (validated today: 0.1–10).
|
|
206
|
+
|
|
207
|
+
## Trade levels (ATR geometry)
|
|
208
|
+
|
|
209
|
+
`minStopLossAtrMultiple < maxStopLossAtrMultiple` (band where the stop may sit; ceiling capped
|
|
210
|
+
at the structural 3×ATR), `minRiskRewardRatio` (catalog bounds today: 0.5–3). Position size is
|
|
211
|
+
risk-budget based (`riskPct / stopDistancePct` — see the `battlegrid` skill's contract notes),
|
|
212
|
+
so a *wider* stop means a *smaller* position, not more risk. Tight bands suit breakout entries;
|
|
213
|
+
wide bands suit mean reversion that needs room.
|
|
214
|
+
|
|
215
|
+
## Position management (how the stop moves)
|
|
216
|
+
|
|
217
|
+
Validated live bounds: `breakEvenTriggerR` 0.5–2 · `trailingTriggerR` 0–2 step 0.01 (0 = trail
|
|
218
|
+
from entry) · `trailingGivebackPct` 25–55 · `trailingBufferPct` 0.01–1 · `timeDecay` grace
|
|
219
|
+
1–1440 min ≥ interval 1–480 min, tighten 0.1–50%, max 1–100%, stale threshold 0–100% of TP
|
|
220
|
+
progress. Each mechanism has its own enabled flag; there is no umbrella switch. Trend books:
|
|
221
|
+
arm break-even ~1R, trail late with a generous giveback (40–55). Mean-reversion/scalp books:
|
|
222
|
+
break-even early, tight giveback, and **timeDecay on** — a thesis that hasn't paid within its
|
|
223
|
+
horizon should be squeezed out.
|
|
224
|
+
|
|
225
|
+
## Coin selection (per compile, not persisted)
|
|
226
|
+
|
|
227
|
+
`{mode:"ranked", limit, category?}` (categories today: ALL, CRYPTO, L1, MEMES, DEFI, TRADFI,
|
|
228
|
+
STOCKS, INDICES, COMMODITIES) or `{mode:"explicit", tickers[]}`. Choose the cohort the review
|
|
229
|
+
should render over — explicit tickers for a focused edit, ranked for a scanning book.
|
|
230
|
+
|
|
231
|
+
## Market Read markers
|
|
232
|
+
|
|
233
|
+
`marketReadText` renders with live values wherever a `{...}` marker names a column header
|
|
234
|
+
(`{RVOL}`), a condition (`{SQUEEZE_ON}` — renders outcome plus evidence), or a section-qualified
|
|
235
|
+
form on collision (`{custom:<uuid>.MAalign}`). The preview returns `marketReadMarkers` with each
|
|
236
|
+
marker's resolution status — fix `unknown`/`ambiguous` markers before compiling.
|
|
237
|
+
|
|
238
|
+
## References
|
|
239
|
+
|
|
240
|
+
- `references/playbooks.md` — five validated desk-grade playbooks with full payloads: volatility
|
|
241
|
+
compression breakout, crowded-positioning fade, relative-strength rotation with a benchmark
|
|
242
|
+
gate, HTF trend pullback, perp/spot flow divergence at structure.
|
|
243
|
+
- `references/recipes.md` — copy-adaptable column recipes, condition patterns, weight matrices,
|
|
244
|
+
and trade-level/position-management presets per trading persona.
|
|
245
|
+
- `references/tradingview-ports.md` — the most popular TradingView community scripts (Squeeze
|
|
246
|
+
Momentum [LazyBear], Supertrend/UT Bot, Chandelier Exit, MACD + 200 MA, golden cross, RSI-2,
|
|
247
|
+
VWAP reversion, Donchian/Turtle, ICT FVG/order blocks) translated process-for-process onto
|
|
248
|
+
the studio's vocabulary, with an expressibility triage and honest named substitutions for
|
|
249
|
+
what the grammar cannot carry.
|
|
250
|
+
|
|
251
|
+
Validate a draft cheaply before compiling: `derive_strategy_rule_view` (report membership +
|
|
252
|
+
rule defaults, no write) and `preview_strategy_report` (rendered tables, condition outcomes
|
|
253
|
+
with evidence, verdict tally, budget usage, marker resolution). Then compile once, review the
|
|
254
|
+
compiled truth, and apply.
|
|
@@ -0,0 +1,370 @@
|
|
|
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.
|