@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.
Files changed (94) hide show
  1. package/dist/cli/composer-commands.d.ts +37 -0
  2. package/dist/cli/composer-commands.d.ts.map +1 -0
  3. package/dist/cli/composer-commands.js +287 -0
  4. package/dist/cli/composer-commands.js.map +1 -0
  5. package/dist/cli/senpi-commands.d.ts.map +1 -1
  6. package/dist/cli/senpi-commands.js +2 -0
  7. package/dist/cli/senpi-commands.js.map +1 -1
  8. package/dist/cli/validate-runtime-config.mjs +124 -0
  9. package/dist/composer/AUTHORING.md +233 -0
  10. package/dist/composer/__init__.py +29 -0
  11. package/dist/composer/authoring/__init__.py +49 -0
  12. package/dist/composer/authoring/answers.py +226 -0
  13. package/dist/composer/authoring/archetypes/__init__.py +25 -0
  14. package/dist/composer/authoring/archetypes/_common.py +218 -0
  15. package/dist/composer/authoring/archetypes/classifier.py +109 -0
  16. package/dist/composer/authoring/archetypes/skeleton.py +54 -0
  17. package/dist/composer/authoring/archetypes/thesis_fund.py +103 -0
  18. package/dist/composer/authoring/archetypes/trend_momentum.py +104 -0
  19. package/dist/composer/authoring/builder.py +191 -0
  20. package/dist/composer/authoring/emit.py +264 -0
  21. package/dist/composer/authoring/gaps.py +115 -0
  22. package/dist/composer/authoring/generate.py +131 -0
  23. package/dist/composer/authoring/presets.py +168 -0
  24. package/dist/composer/authoring/runtime_emit.py +266 -0
  25. package/dist/composer/authoring/strategy_manifest.py +94 -0
  26. package/dist/composer/cli.py +355 -0
  27. package/dist/composer/compiler/__init__.py +22 -0
  28. package/dist/composer/compiler/compile.py +550 -0
  29. package/dist/composer/examples/breakout_swing.graph.yaml +121 -0
  30. package/dist/composer/examples/conviction_scorer.graph.yaml +216 -0
  31. package/dist/composer/examples/macro_thesis_basket.graph.yaml +247 -0
  32. package/dist/composer/examples/pre_listing_classifier.graph.yaml +204 -0
  33. package/dist/composer/examples/trend_momentum_majors.graph.yaml +133 -0
  34. package/dist/composer/generated/README.md +22 -0
  35. package/dist/composer/generated/catalog.md +84 -0
  36. package/dist/composer/generated/describe.md +703 -0
  37. package/dist/composer/generated/graph.schema.json +1203 -0
  38. package/dist/composer/primitives/__init__.py +239 -0
  39. package/dist/composer/primitives/_candles.py +76 -0
  40. package/dist/composer/primitives/adapter.py +120 -0
  41. package/dist/composer/primitives/emitters.py +142 -0
  42. package/dist/composer/primitives/filters.py +71 -0
  43. package/dist/composer/primitives/indicators.py +203 -0
  44. package/dist/composer/primitives/rankers.py +40 -0
  45. package/dist/composer/primitives/scorers.py +100 -0
  46. package/dist/composer/primitives/sources.py +405 -0
  47. package/dist/composer/primitives/stateful.py +52 -0
  48. package/dist/composer/pure_fn/__init__.py +34 -0
  49. package/dist/composer/pure_fn/checks.py +39 -0
  50. package/dist/composer/pure_fn/models.py +177 -0
  51. package/dist/composer/pure_fn/purity.py +311 -0
  52. package/dist/composer/pure_fn/runtests.py +155 -0
  53. package/dist/composer/registry/__init__.py +40 -0
  54. package/dist/composer/registry/generate.py +422 -0
  55. package/dist/composer/registry/models.py +331 -0
  56. package/dist/composer/registry/nodes.py +673 -0
  57. package/dist/composer/requirements.txt +21 -0
  58. package/dist/composer/templates/__init__.py +13 -0
  59. package/dist/composer/templates/scan.py.j2 +31 -0
  60. package/dist/composer/validator/__init__.py +29 -0
  61. package/dist/composer/validator/desugar.py +133 -0
  62. package/dist/composer/validator/errors.py +191 -0
  63. package/dist/composer/validator/graph_checks.py +348 -0
  64. package/dist/composer/validator/loader.py +110 -0
  65. package/dist/composer/validator/schema_checks.py +147 -0
  66. package/dist/composer/validator/validate.py +86 -0
  67. package/dist/composer/verbs/__init__.py +33 -0
  68. package/dist/composer/verbs/check.py +193 -0
  69. package/dist/composer/verbs/deploy.py +223 -0
  70. package/dist/composer/verbs/docs.py +30 -0
  71. package/dist/composer/verbs/runtime_validate.py +262 -0
  72. package/dist/composer/verbs/smoke.py +115 -0
  73. package/dist/composer/verbs/status.py +205 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +2 -9
  76. package/dist/index.js.map +1 -1
  77. package/dist/runtime-api/config.d.ts +2 -2
  78. package/dist/runtime-api/config.js +4 -4
  79. package/dist/runtime-api/config.js.map +1 -1
  80. package/dist/runtime-api/handlers/ingest-signals.d.ts +3 -5
  81. package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
  82. package/dist/runtime-api/handlers/ingest-signals.js +5 -14
  83. package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
  84. package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
  85. package/dist/runtime-api/intake/intake-mount.js +2 -8
  86. package/dist/runtime-api/intake/intake-mount.js.map +1 -1
  87. package/dist/skills-manager/manifest.js +1 -1
  88. package/dist/skills-manager/manifest.js.map +1 -1
  89. package/dist/skills-manager/skills-manifest.json +1 -1
  90. package/package.json +4 -2
  91. package/dist/runtime-api/intake/ingest-mutex.d.ts +0 -16
  92. package/dist/runtime-api/intake/ingest-mutex.d.ts.map +0 -1
  93. package/dist/runtime-api/intake/ingest-mutex.js +0 -18
  94. 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..)