@senpi/runtime 3.0.9-dev.20260710204324 → 3.0.9-dev.feat-strategy-compos.20260716013009
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/dist/cli/composer-commands.d.ts +37 -0
- package/dist/cli/composer-commands.d.ts.map +1 -0
- package/dist/cli/composer-commands.js +287 -0
- package/dist/cli/composer-commands.js.map +1 -0
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +2 -0
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/cli/validate-runtime-config.mjs +124 -0
- package/dist/composer/AUTHORING.md +233 -0
- package/dist/composer/__init__.py +29 -0
- package/dist/composer/authoring/__init__.py +49 -0
- package/dist/composer/authoring/answers.py +226 -0
- package/dist/composer/authoring/archetypes/__init__.py +25 -0
- package/dist/composer/authoring/archetypes/_common.py +218 -0
- package/dist/composer/authoring/archetypes/classifier.py +109 -0
- package/dist/composer/authoring/archetypes/skeleton.py +54 -0
- package/dist/composer/authoring/archetypes/thesis_fund.py +103 -0
- package/dist/composer/authoring/archetypes/trend_momentum.py +104 -0
- package/dist/composer/authoring/builder.py +191 -0
- package/dist/composer/authoring/emit.py +264 -0
- package/dist/composer/authoring/gaps.py +115 -0
- package/dist/composer/authoring/generate.py +131 -0
- package/dist/composer/authoring/presets.py +168 -0
- package/dist/composer/authoring/runtime_emit.py +266 -0
- package/dist/composer/authoring/strategy_manifest.py +94 -0
- package/dist/composer/cli.py +355 -0
- package/dist/composer/compiler/__init__.py +22 -0
- package/dist/composer/compiler/compile.py +550 -0
- package/dist/composer/examples/breakout_swing.graph.yaml +121 -0
- package/dist/composer/examples/conviction_scorer.graph.yaml +216 -0
- package/dist/composer/examples/macro_thesis_basket.graph.yaml +247 -0
- package/dist/composer/examples/pre_listing_classifier.graph.yaml +204 -0
- package/dist/composer/examples/trend_momentum_majors.graph.yaml +133 -0
- package/dist/composer/generated/README.md +22 -0
- package/dist/composer/generated/catalog.md +84 -0
- package/dist/composer/generated/describe.md +703 -0
- package/dist/composer/generated/graph.schema.json +1203 -0
- package/dist/composer/primitives/__init__.py +239 -0
- package/dist/composer/primitives/_candles.py +76 -0
- package/dist/composer/primitives/adapter.py +120 -0
- package/dist/composer/primitives/emitters.py +142 -0
- package/dist/composer/primitives/filters.py +71 -0
- package/dist/composer/primitives/indicators.py +203 -0
- package/dist/composer/primitives/rankers.py +40 -0
- package/dist/composer/primitives/scorers.py +100 -0
- package/dist/composer/primitives/sources.py +405 -0
- package/dist/composer/primitives/stateful.py +52 -0
- package/dist/composer/pure_fn/__init__.py +34 -0
- package/dist/composer/pure_fn/checks.py +39 -0
- package/dist/composer/pure_fn/models.py +177 -0
- package/dist/composer/pure_fn/purity.py +311 -0
- package/dist/composer/pure_fn/runtests.py +155 -0
- package/dist/composer/registry/__init__.py +40 -0
- package/dist/composer/registry/generate.py +422 -0
- package/dist/composer/registry/models.py +331 -0
- package/dist/composer/registry/nodes.py +673 -0
- package/dist/composer/requirements.txt +21 -0
- package/dist/composer/templates/__init__.py +13 -0
- package/dist/composer/templates/scan.py.j2 +31 -0
- package/dist/composer/validator/__init__.py +29 -0
- package/dist/composer/validator/desugar.py +133 -0
- package/dist/composer/validator/errors.py +191 -0
- package/dist/composer/validator/graph_checks.py +348 -0
- package/dist/composer/validator/loader.py +110 -0
- package/dist/composer/validator/schema_checks.py +147 -0
- package/dist/composer/validator/validate.py +86 -0
- package/dist/composer/verbs/__init__.py +33 -0
- package/dist/composer/verbs/check.py +193 -0
- package/dist/composer/verbs/deploy.py +223 -0
- package/dist/composer/verbs/docs.py +30 -0
- package/dist/composer/verbs/runtime_validate.py +262 -0
- package/dist/composer/verbs/smoke.py +115 -0
- package/dist/composer/verbs/status.py +205 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -9
- package/dist/index.js.map +1 -1
- package/dist/runtime-api/config.d.ts +2 -2
- package/dist/runtime-api/config.js +4 -4
- package/dist/runtime-api/config.js.map +1 -1
- package/dist/runtime-api/handlers/ingest-signals.d.ts +3 -5
- package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
- package/dist/runtime-api/handlers/ingest-signals.js +5 -14
- package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
- package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-mount.js +2 -8
- package/dist/runtime-api/intake/intake-mount.js.map +1 -1
- package/dist/skills-manager/manifest.js +1 -1
- package/dist/skills-manager/manifest.js.map +1 -1
- package/dist/skills-manager/skills-manifest.json +1 -1
- package/package.json +4 -2
- package/dist/runtime-api/intake/ingest-mutex.d.ts +0 -16
- package/dist/runtime-api/intake/ingest-mutex.d.ts.map +0 -1
- package/dist/runtime-api/intake/ingest-mutex.js +0 -18
- package/dist/runtime-api/intake/ingest-mutex.js.map +0 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# trend_momentum_majors — parabolic trend-momentum strategy (tier 1, LONG-only) over a
|
|
2
|
+
# fixed 4-asset majors whitelist, as a typed dataflow DAG.
|
|
3
|
+
#
|
|
4
|
+
# Hand-authored from the corpus-recon inventory (stag section): a fixed 4-asset whitelist
|
|
5
|
+
# scanned on 4h candles, gated by five hard conditions (above SMA-200, +trend%, volume
|
|
6
|
+
# surge, acceleration, smart-money alignment), single-best emission, and the universal
|
|
7
|
+
# TTL signal-dedup on ctx.state. This is the slice-2 "validates clean" fixture and the
|
|
8
|
+
# slice-3 compile target. Re-expression of corpus package stag; semantics cited to
|
|
9
|
+
# skills/strategies/stag/... throughout.
|
|
10
|
+
#
|
|
11
|
+
# Shape (why it is a DAG, not a pipeline): candles fan out to five indicators whose
|
|
12
|
+
# per-asset features MERGE into the scorer; the universe is first narrowed by held-asset
|
|
13
|
+
# exclusion and TTL dedup. The ttl_dedup_state node closes the dedup loop through
|
|
14
|
+
# ctx.state (its `recent` output is prior-tick data, so it does not form a cycle).
|
|
15
|
+
|
|
16
|
+
version: 1
|
|
17
|
+
|
|
18
|
+
metadata:
|
|
19
|
+
archetype: trend_momentum
|
|
20
|
+
strategy: trend_momentum_majors
|
|
21
|
+
corpus_origin: stag # provenance only, for fidelity replay — not user-facing
|
|
22
|
+
exit_preset: protected_wide # slice 9: emitted as runtime.yaml exit: (stag = let the runner breathe)
|
|
23
|
+
# EDGE (verbatim, machine never interprets): "ride assets breaking to fresh highs with
|
|
24
|
+
# accelerating momentum, volume confirmation, and smart money leaning the same way."
|
|
25
|
+
|
|
26
|
+
nodes:
|
|
27
|
+
# --- sources ---
|
|
28
|
+
- id: account
|
|
29
|
+
node: clearinghouse_state # held-asset set + account equity
|
|
30
|
+
|
|
31
|
+
- id: dedup_state
|
|
32
|
+
node: ttl_dedup_state # ctx.state TTL dedup; `recent` = assets within TTL
|
|
33
|
+
with:
|
|
34
|
+
ttl_seconds: 240
|
|
35
|
+
|
|
36
|
+
# --- universe narrowing (held-exclusion then recent-signal dedup) ---
|
|
37
|
+
- id: exclude_held
|
|
38
|
+
node: held_asset_exclusion # candidates default to the whitelist universe
|
|
39
|
+
|
|
40
|
+
- id: exclude_recent
|
|
41
|
+
node: recent_signal_ttl_dedup
|
|
42
|
+
|
|
43
|
+
# --- candle + leaderboard reads over the narrowed universe ---
|
|
44
|
+
- id: candles
|
|
45
|
+
node: candles_fetch
|
|
46
|
+
with:
|
|
47
|
+
whitelist: ["BTC", "ETH", "SOL", "HYPE"]
|
|
48
|
+
intervals: ["4h"]
|
|
49
|
+
|
|
50
|
+
- id: lean
|
|
51
|
+
node: sm_lean
|
|
52
|
+
with:
|
|
53
|
+
agree_threshold: 0.6 # trend_momentum_majors requires >=60% SM alignment
|
|
54
|
+
|
|
55
|
+
# --- indicators (candles -> per-asset features) ---
|
|
56
|
+
- id: trend_sma
|
|
57
|
+
node: sma
|
|
58
|
+
with:
|
|
59
|
+
period: 200
|
|
60
|
+
interval: "4h"
|
|
61
|
+
|
|
62
|
+
- id: fresh_high
|
|
63
|
+
node: recent_high_bars_ago
|
|
64
|
+
with:
|
|
65
|
+
window: 60
|
|
66
|
+
|
|
67
|
+
- id: trend_pct
|
|
68
|
+
node: pct_change
|
|
69
|
+
with:
|
|
70
|
+
lookback: 42 # ~7d of 4h bars
|
|
71
|
+
interval: "4h"
|
|
72
|
+
|
|
73
|
+
- id: vol_surge
|
|
74
|
+
node: volume_surge_ratio
|
|
75
|
+
with:
|
|
76
|
+
recent_window: 6
|
|
77
|
+
baseline_window: 42
|
|
78
|
+
|
|
79
|
+
- id: accel
|
|
80
|
+
node: acceleration
|
|
81
|
+
with:
|
|
82
|
+
short_window: 3
|
|
83
|
+
long_window: 6
|
|
84
|
+
|
|
85
|
+
# --- scorer: five hard gates + weighted score (bespoke edge slot) ---
|
|
86
|
+
- id: gates
|
|
87
|
+
node: hard_gates_all
|
|
88
|
+
with:
|
|
89
|
+
# gate/weight keys are SOURCE NODE IDs (the compiler merges features keyed by the
|
|
90
|
+
# producing node id — collision-free even when two producers share a port name).
|
|
91
|
+
required_gates: ["trend_sma", "accel"] # above-SMA AND accelerating (both boolean)
|
|
92
|
+
# TODO(edge): tune these weights — the strategy's real edge lives here.
|
|
93
|
+
weights: { trend_pct: 1.0, vol_surge: 1.0, lean: 1.0 }
|
|
94
|
+
min_score: 3
|
|
95
|
+
|
|
96
|
+
# --- ranker + emitter ---
|
|
97
|
+
- id: best
|
|
98
|
+
node: emit_single_best
|
|
99
|
+
with:
|
|
100
|
+
min_score: 3
|
|
101
|
+
|
|
102
|
+
- id: emit
|
|
103
|
+
node: signal_envelope
|
|
104
|
+
with:
|
|
105
|
+
margin_pct: 5
|
|
106
|
+
leverage: 3
|
|
107
|
+
|
|
108
|
+
edges:
|
|
109
|
+
# universe narrowing chain
|
|
110
|
+
- { from: account.held, to: exclude_held.held }
|
|
111
|
+
- { from: exclude_held.kept, to: exclude_recent.candidates }
|
|
112
|
+
- { from: dedup_state.recent, to: exclude_recent.recent }
|
|
113
|
+
- { from: exclude_recent.kept, to: candles.assets }
|
|
114
|
+
- { from: exclude_recent.kept, to: lean.assets }
|
|
115
|
+
# candles fan out to indicators
|
|
116
|
+
- { from: candles.candles, to: trend_sma.candles }
|
|
117
|
+
- { from: candles.candles, to: fresh_high.candles }
|
|
118
|
+
- { from: candles.candles, to: trend_pct.candles }
|
|
119
|
+
- { from: candles.candles, to: vol_surge.candles }
|
|
120
|
+
- { from: candles.candles, to: accel.candles }
|
|
121
|
+
# per-asset features MERGE into the scorer (feature_map inputs merge)
|
|
122
|
+
- { from: trend_sma.above, to: gates.features }
|
|
123
|
+
- { from: fresh_high.bars_ago, to: gates.features }
|
|
124
|
+
- { from: trend_pct.pct, to: gates.features }
|
|
125
|
+
- { from: vol_surge.ratio, to: gates.features }
|
|
126
|
+
- { from: accel.accelerating, to: gates.features }
|
|
127
|
+
- { from: lean.lean, to: gates.features }
|
|
128
|
+
# score -> rank -> emit
|
|
129
|
+
- { from: gates.scores, to: best.scores }
|
|
130
|
+
- { from: best.selected, to: emit.selected }
|
|
131
|
+
- { from: account.equity, to: emit.equity }
|
|
132
|
+
# close the dedup loop: this tick's signals are recorded in ctx.state
|
|
133
|
+
- { from: emit.signals, to: dedup_state.emitted }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# composer/generated/ — registry-derived artifacts (DO NOT EDIT)
|
|
2
|
+
|
|
3
|
+
These files are generated from the node registry (`composer/registry/nodes.py`) — the
|
|
4
|
+
single source of truth (D4). They are committed so the agent skill, the TS rim, and CI
|
|
5
|
+
can read them without a build step, and so drift is caught by a golden-file diff.
|
|
6
|
+
|
|
7
|
+
| File | What it is |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `graph.schema.json` | JSON Schema for the graph document format (D6). YAML is authored; this JSON Schema is canonical. Per-node param constraints derive via `if`/`then` on the node name. YAML anchors/merge keys are banned at the document level (noted in the schema; enforced in the validator, slice 2). |
|
|
10
|
+
| `catalog.md` | The ~1–2k-token progressive-disclosure index: node names, one-liners, param summaries. |
|
|
11
|
+
| `describe.md` | Full ports / params / example / cost per node (`composer describe <node>`). |
|
|
12
|
+
|
|
13
|
+
Regenerate after any registry change:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
python -m composer.registry.generate # rewrite the artifacts
|
|
17
|
+
python -m composer.registry.generate --check # CI-style: exit 1 if stale
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Generation is deterministic (stable ordering, sorted JSON keys, no timestamps): running
|
|
21
|
+
it twice produces byte-identical output. The golden-file tests in
|
|
22
|
+
`python-tests/composer/` regenerate and diff against these committed files.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Strategy Composer — Node Catalog
|
|
2
|
+
|
|
3
|
+
Schema version: 1. Generated from composer/registry/nodes.py — do not edit by hand.
|
|
4
|
+
|
|
5
|
+
Progressive-disclosure index (D4): node names, one-liners, and param summaries. Use `composer describe <node>` for full ports/params/examples.
|
|
6
|
+
|
|
7
|
+
## scoring
|
|
8
|
+
|
|
9
|
+
Bespoke scoring/classification belongs in a `kind: pure_fn` node (typed ports, one `def`, math/statistics only, inline tests) — not a new primitive. `hard_gates_all` covers the simple gate-and-weigh case (required gates + a weighted sum). Repeated pure_fn shapes get promoted to primitives post-MVP via the telemetry loop.
|
|
10
|
+
|
|
11
|
+
## source
|
|
12
|
+
|
|
13
|
+
- **asset_trading_limits_fetch** — Per-asset venue max-leverage limit for the own wallet.
|
|
14
|
+
- params: dex (str='')
|
|
15
|
+
- **candles_fetch** — Fetch multi-interval OHLCV candles for a universe of assets.
|
|
16
|
+
- params: whitelist (list[str]=[]); intervals (list[str]=[4h]); include_funding (bool=False); include_asset_context (bool=False)
|
|
17
|
+
- **clearinghouse_state** — Read account equity and the set of currently-held positions.
|
|
18
|
+
- **instrument_list** — List live tradeable instruments with venue metadata.
|
|
19
|
+
- params: dex (str='')
|
|
20
|
+
- **market_prices_fetch** — Latest per-asset mark prices for a venue.
|
|
21
|
+
- params: dex (str='')
|
|
22
|
+
- **open_orders_fetch** — Open resting orders for the strategy's own wallet.
|
|
23
|
+
- **own_return_24h** — Per-asset 24h return derived from markPx/prevDayPx asset_context.
|
|
24
|
+
- **sm_lean** — Smart-money net long/short lean per asset from the leaderboard.
|
|
25
|
+
- params: agree_threshold (float=0.55, 0.0..1.0)
|
|
26
|
+
- **strategy_list_fetch** — List strategy-metadata records (id, wallet, status, type, funded).
|
|
27
|
+
- params: status (str=''); strategy_type (str='')
|
|
28
|
+
- **strategy_pnl_snapshot** — Today's PnL / account-value / drawdown snapshot for the own wallet.
|
|
29
|
+
- params: period (str=''); drawdown_reset_on_day_rollover (bool=False)
|
|
30
|
+
- **trader_history_fetch** — Closed-trade history for an arbitrary trader address.
|
|
31
|
+
- params: trader_address (str=required); limit (int=100, 1..1000)
|
|
32
|
+
- **trader_state_fetch** — An arbitrary trader's current book: held set + account equity.
|
|
33
|
+
- params: trader_address (str=required)
|
|
34
|
+
- **universe_discover** — Derive a tradeable universe by filtering live instruments on a predicate.
|
|
35
|
+
- params: min_day_volume (float=0.0, 0.0..); max_leverage_cap (float=5.0, 1.0..); name_prefix (str='')
|
|
36
|
+
|
|
37
|
+
## indicator
|
|
38
|
+
|
|
39
|
+
- **acceleration** — Whether a short-window move is at least half a long-window move.
|
|
40
|
+
- params: short_window (int=3, 1..); long_window (int=6, 2..); interval (str='4h')
|
|
41
|
+
- **breakout_detect** — Directional breakout of the prior-window high/low.
|
|
42
|
+
- params: window (int=168, 2..); interval (str='1h')
|
|
43
|
+
- **pct_change** — Percent change of close over a lookback window.
|
|
44
|
+
- params: lookback (int=42, 1..); interval (str='4h')
|
|
45
|
+
- **recent_high_bars_ago** — Bars elapsed since the highest high in a window (fresh-high check).
|
|
46
|
+
- params: window (int=60, 2..); interval (str='4h')
|
|
47
|
+
- **rsi** — Relative Strength Index over the last N bars.
|
|
48
|
+
- params: period (int=14, 2..100); interval (str='1h')
|
|
49
|
+
- **sma** — Simple moving average of close and an above/below flag.
|
|
50
|
+
- params: period (int=200, 1..1000); interval (str='4h')
|
|
51
|
+
- **trend_structure** — Higher-lows / lower-highs trend direction over a lookback.
|
|
52
|
+
- params: lookback (int=6, 2..); interval (str='4h')
|
|
53
|
+
- **volume_surge_ratio** — Recent-window mean volume divided by a baseline-window mean.
|
|
54
|
+
- params: recent_window (int=6, 1..); baseline_window (int=42, 1..); interval (str='4h')
|
|
55
|
+
|
|
56
|
+
## filter
|
|
57
|
+
|
|
58
|
+
- **classifier_predicate** — Gate universe membership on a set of instrument-field predicates.
|
|
59
|
+
- params: max_funding_abs (float=1e-07, 0.0..); max_leverage (float=5.0, 1.0..); exclude_delisted (bool=True)
|
|
60
|
+
- **held_asset_exclusion** — Drop candidates already held in the account.
|
|
61
|
+
- **live_instrument_validation** — Keep only candidates still live on the venue board.
|
|
62
|
+
- **recent_signal_ttl_dedup** — Drop candidates signaled within the dedup TTL.
|
|
63
|
+
|
|
64
|
+
## scorer
|
|
65
|
+
|
|
66
|
+
- **hard_gates_all** — Require all named gates to pass, then score the survivors.
|
|
67
|
+
- params: required_gates (list[str]=[]); weights (map_str_float={}); min_score (float=0.0, 0.0..)
|
|
68
|
+
|
|
69
|
+
## ranker
|
|
70
|
+
|
|
71
|
+
- **emit_single_best** — Sort by score and select the single best candidate.
|
|
72
|
+
- params: min_score (float=0.0)
|
|
73
|
+
- **rank_pool_cap_to_open_slots** — Sort by score and take the top (max_slots - held) candidates.
|
|
74
|
+
- params: max_slots (int=5, 1..50); min_score (float=0.0)
|
|
75
|
+
|
|
76
|
+
## emitter
|
|
77
|
+
|
|
78
|
+
- **signal_envelope** — Build the scan() signal list from selected candidates.
|
|
79
|
+
- params: margin_pct (float=5.0, 0.0001..100.0); leverage (float=3.0, 1.0..50.0); clamp_leverage_to_venue (bool=True); valid_for_seconds (int=0, 0..); signal_type (str='')
|
|
80
|
+
|
|
81
|
+
## stateful
|
|
82
|
+
|
|
83
|
+
- **ttl_dedup_state** — Track recently-signaled assets in ctx.state with a TTL and pruning.
|
|
84
|
+
- params: ttl_seconds (int=240, 1..); prune_factor (int=4, 1..)
|