@senpi/runtime 2.0.2-dev.openclaw-upgrade-mai.20260622175851 → 3.0.0-dev.runtime-phase-2.20260623210537

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 (209) hide show
  1. package/README.md +9 -10
  2. package/dist/actions/decision-engine.d.ts.map +1 -1
  3. package/dist/actions/decision-engine.js +0 -3
  4. package/dist/actions/decision-engine.js.map +1 -1
  5. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  6. package/dist/actions/open-position/open-position.action.js +2 -6
  7. package/dist/actions/open-position/open-position.action.js.map +1 -1
  8. package/dist/cli/guide-commands.d.ts.map +1 -1
  9. package/dist/cli/guide-commands.js +56 -43
  10. package/dist/cli/guide-commands.js.map +1 -1
  11. package/dist/cli/senpi-commands.d.ts.map +1 -1
  12. package/dist/cli/senpi-commands.js +108 -0
  13. package/dist/cli/senpi-commands.js.map +1 -1
  14. package/dist/constants/dsl/index.d.ts +0 -2
  15. package/dist/constants/dsl/index.d.ts.map +1 -1
  16. package/dist/constants/dsl/index.js +0 -2
  17. package/dist/constants/dsl/index.js.map +1 -1
  18. package/dist/dsl/engine-client/config-mapping.d.ts +0 -7
  19. package/dist/dsl/engine-client/config-mapping.d.ts.map +1 -1
  20. package/dist/dsl/engine-client/config-mapping.js +2 -16
  21. package/dist/dsl/engine-client/config-mapping.js.map +1 -1
  22. package/dist/dsl/events/handlers.d.ts +2 -18
  23. package/dist/dsl/events/handlers.d.ts.map +1 -1
  24. package/dist/dsl/events/handlers.js +213 -302
  25. package/dist/dsl/events/handlers.js.map +1 -1
  26. package/dist/dsl/monitor/create-monitor.d.ts +0 -15
  27. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  28. package/dist/dsl/monitor/create-monitor.js +9 -44
  29. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  30. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  31. package/dist/dsl/monitor/process-one-position.js +1 -24
  32. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  33. package/dist/dsl/plugin/index.d.ts +1 -16
  34. package/dist/dsl/plugin/index.d.ts.map +1 -1
  35. package/dist/dsl/plugin/index.js +4 -35
  36. package/dist/dsl/plugin/index.js.map +1 -1
  37. package/dist/dsl/plugin/options.d.ts +0 -18
  38. package/dist/dsl/plugin/options.d.ts.map +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +10 -4
  41. package/dist/index.js.map +1 -1
  42. package/dist/runtime/create-scanner-module.d.ts +3 -4
  43. package/dist/runtime/create-scanner-module.d.ts.map +1 -1
  44. package/dist/runtime/create-scanner-module.js +5 -14
  45. package/dist/runtime/create-scanner-module.js.map +1 -1
  46. package/dist/runtime/create-scanner-providers-for-run.d.ts.map +1 -1
  47. package/dist/runtime/create-scanner-providers-for-run.js +1 -12
  48. package/dist/runtime/create-scanner-providers-for-run.js.map +1 -1
  49. package/dist/runtime/load-runtime-config.js +1 -1
  50. package/dist/runtime/load-runtime-config.js.map +1 -1
  51. package/dist/runtime/map-strategies-registration.js +8 -7
  52. package/dist/runtime/map-strategies-registration.js.map +1 -1
  53. package/dist/runtime/map-strategies.d.ts.map +1 -1
  54. package/dist/runtime/map-strategies.js +3 -12
  55. package/dist/runtime/map-strategies.js.map +1 -1
  56. package/dist/runtime/reconcile-state.d.ts +0 -44
  57. package/dist/runtime/reconcile-state.d.ts.map +1 -1
  58. package/dist/runtime/reconcile-state.js +44 -80
  59. package/dist/runtime/reconcile-state.js.map +1 -1
  60. package/dist/runtime/risk-guard.d.ts.map +1 -1
  61. package/dist/runtime/risk-guard.js +12 -17
  62. package/dist/runtime/risk-guard.js.map +1 -1
  63. package/dist/runtime/runtime-schema.d.ts +995 -2855
  64. package/dist/runtime/runtime-schema.d.ts.map +1 -1
  65. package/dist/runtime/runtime-schema.js +40 -133
  66. package/dist/runtime/runtime-schema.js.map +1 -1
  67. package/dist/runtime/runtime.d.ts +0 -26
  68. package/dist/runtime/runtime.d.ts.map +1 -1
  69. package/dist/runtime/runtime.js +5 -233
  70. package/dist/runtime/runtime.js.map +1 -1
  71. package/dist/runtime/scanner-registry.d.ts +1 -1
  72. package/dist/runtime/scanner-registry.d.ts.map +1 -1
  73. package/dist/runtime/scanner-registry.js +12 -3
  74. package/dist/runtime/scanner-registry.js.map +1 -1
  75. package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
  76. package/dist/runtime/supervisor/long-running-supervisor.js +1 -1
  77. package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
  78. package/dist/runtime/supervisor/orphan-sweep.js +1 -1
  79. package/dist/runtime/supervisor/orphan-sweep.js.map +1 -1
  80. package/dist/runtime/supervisor/supervisor-utils.d.ts +3 -3
  81. package/dist/runtime/supervisor/supervisor-utils.d.ts.map +1 -1
  82. package/dist/runtime/supervisor/supervisor-utils.js +3 -3
  83. package/dist/runtime/supervisor/supervisor-utils.js.map +1 -1
  84. package/dist/runtime-api/intake/intake-mount.d.ts +3 -3
  85. package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
  86. package/dist/runtime-api/intake/intake-mount.js +36 -28
  87. package/dist/runtime-api/intake/intake-mount.js.map +1 -1
  88. package/dist/runtime-api/intake/liveness-store.d.ts +6 -2
  89. package/dist/runtime-api/intake/liveness-store.d.ts.map +1 -1
  90. package/dist/runtime-api/intake/liveness-store.js +6 -2
  91. package/dist/runtime-api/intake/liveness-store.js.map +1 -1
  92. package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
  93. package/dist/runtime-api/intake/process-signal-post.js +0 -0
  94. package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
  95. package/dist/runtime-api/intake/scanner-launcher.d.ts +29 -24
  96. package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
  97. package/dist/runtime-api/intake/scanner-launcher.js +3 -24
  98. package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
  99. package/dist/runtime-api/intake/types.d.ts +0 -6
  100. package/dist/runtime-api/intake/types.d.ts.map +1 -1
  101. package/dist/runtime-api/routes/signals.d.ts +6 -0
  102. package/dist/runtime-api/routes/signals.d.ts.map +1 -1
  103. package/dist/runtime-api/routes/signals.js +14 -0
  104. package/dist/runtime-api/routes/signals.js.map +1 -1
  105. package/dist/runtime-api/routes/signals.schema.d.ts +0 -1
  106. package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
  107. package/dist/runtime-api/routes/signals.schema.js +0 -5
  108. package/dist/runtime-api/routes/signals.schema.js.map +1 -1
  109. package/dist/runtime-api/server.d.ts.map +1 -1
  110. package/dist/runtime-api/server.js +1 -0
  111. package/dist/runtime-api/server.js.map +1 -1
  112. package/dist/scanners/external/liquidation-watchdog/README.md +107 -0
  113. package/dist/scanners/external/liquidation-watchdog/liquidation-watchdog.yaml +48 -0
  114. package/dist/scanners/external/liquidation-watchdog/producer.mjs +336 -0
  115. package/dist/scanners/external/momentum/README.md +148 -0
  116. package/dist/scanners/external/momentum/momentum.yaml +116 -0
  117. package/dist/scanners/external/momentum/producer.mjs +251 -0
  118. package/dist/scanners/external/scaffold/__main__.py +24 -65
  119. package/dist/scanners/external/scaffold/delivery.py +22 -56
  120. package/dist/scanners/external/scaffold/entrypoint_loader.py +48 -42
  121. package/dist/scanners/external/scaffold/journal.py +22 -15
  122. package/dist/scanners/external/scaffold/scaffold.py +128 -159
  123. package/dist/scanners/external/scaffold/signal_envelope.py +34 -177
  124. package/dist/scanners/external/shared/ingest.mjs +112 -0
  125. package/dist/scanners/external-scanner-receiver.d.ts +0 -6
  126. package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
  127. package/dist/scanners/external-scanner-receiver.js +1 -14
  128. package/dist/scanners/external-scanner-receiver.js.map +1 -1
  129. package/dist/scripts/run-dsl-standalone-live.d.ts +1 -1
  130. package/dist/scripts/run-dsl-standalone-live.js +3 -5
  131. package/dist/scripts/run-dsl-standalone-live.js.map +1 -1
  132. package/dist/senpi/client.d.ts +0 -12
  133. package/dist/senpi/client.d.ts.map +1 -1
  134. package/dist/senpi/client.js +2 -31
  135. package/dist/senpi/client.js.map +1 -1
  136. package/dist/state/state-manager.d.ts +0 -17
  137. package/dist/state/state-manager.d.ts.map +1 -1
  138. package/dist/state/state-manager.js +0 -28
  139. package/dist/state/state-manager.js.map +1 -1
  140. package/dist/strategy/strategy-state.d.ts.map +1 -1
  141. package/dist/strategy/strategy-state.js +1 -7
  142. package/dist/strategy/strategy-state.js.map +1 -1
  143. package/dist/tracking/constants.d.ts.map +1 -1
  144. package/dist/tracking/constants.js +0 -2
  145. package/dist/tracking/constants.js.map +1 -1
  146. package/dist/types/dsl/index.d.ts +1 -1
  147. package/dist/types/dsl/index.d.ts.map +1 -1
  148. package/dist/types/scanner.d.ts +0 -7
  149. package/dist/types/scanner.d.ts.map +1 -1
  150. package/examples/README.md +89 -0
  151. package/examples/scanners-consumer-quickstart.mjs +134 -0
  152. package/examples/scanners-emerging-movers-v4.mjs +287 -0
  153. package/examples/scanners-liquidation-watchdog.mjs +341 -0
  154. package/examples/scanners-live-mcp.mjs +208 -0
  155. package/examples/scanners-multi-strategy.mjs +165 -0
  156. package/examples/scanners-position-tracker-e2e.mjs +225 -0
  157. package/examples/scanners-scheduled-events.mjs +96 -0
  158. package/examples/scanners-senpi-provider-client.mjs +182 -0
  159. package/examples/scanners-single-strategy.mjs +198 -0
  160. package/examples/strategies/README.md +12 -17
  161. package/examples/strategies/dsl-showcase.yaml +68 -0
  162. package/examples/strategies/dsl.yaml +51 -0
  163. package/examples/strategies/fox-minimal-loosened.yaml +240 -0
  164. package/examples/strategies/fox-minimal.yaml +242 -0
  165. package/examples/strategies/minimal.yaml +46 -0
  166. package/examples/strategies/momentum/how-it-works.md +48 -0
  167. package/examples/strategies/momentum/momentum-guarded.yaml +161 -0
  168. package/examples/strategies/risk-showcase.yaml +93 -0
  169. package/examples/strategies/viper.yaml +67 -0
  170. package/examples/strategies/wolf.yaml +72 -0
  171. package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +123 -0
  172. package/openclaw.plugin.json +1 -1
  173. package/package.json +1 -1
  174. package/dist/runtime/reconcile-decide.d.ts +0 -73
  175. package/dist/runtime/reconcile-decide.d.ts.map +0 -1
  176. package/dist/runtime/reconcile-decide.js +0 -166
  177. package/dist/runtime/reconcile-decide.js.map +0 -1
  178. package/dist/runtime/reconcile-run.d.ts +0 -62
  179. package/dist/runtime/reconcile-run.d.ts.map +0 -1
  180. package/dist/runtime/reconcile-run.js +0 -173
  181. package/dist/runtime/reconcile-run.js.map +0 -1
  182. package/dist/scanners/external/scaffold/ctx.py +0 -78
  183. package/dist/scanners/external/scaffold/requirements.txt +0 -11
  184. package/dist/scanners/external/scaffold/senpi_mcp.py +0 -250
  185. package/dist/scanners/external/scaffold/state_manager.py +0 -175
  186. package/dist/utils/keyed-mutex.d.ts +0 -37
  187. package/dist/utils/keyed-mutex.d.ts.map +0 -1
  188. package/dist/utils/keyed-mutex.js +0 -77
  189. package/dist/utils/keyed-mutex.js.map +0 -1
  190. package/examples/strategies/iguana/README.md +0 -135
  191. package/examples/strategies/iguana/recipe.yaml +0 -137
  192. package/examples/strategies/iguana/scanners/scan.py +0 -243
  193. package/examples/strategies/iguana/scanners/scoring.py +0 -152
  194. package/examples/strategies/raptor/README.md +0 -156
  195. package/examples/strategies/raptor/recipe.yaml +0 -154
  196. package/examples/strategies/raptor/scanners/scan.py +0 -349
  197. package/examples/strategies/raptor/scanners/scoring.py +0 -452
  198. package/examples/strategies/spider/README.md +0 -97
  199. package/examples/strategies/spider/scalp/recipe.yaml +0 -129
  200. package/examples/strategies/spider/scalp/scanners/scan.py +0 -219
  201. package/examples/strategies/spider/scalp/scanners/scoring.py +0 -179
  202. package/examples/strategies/spider/swing/recipe.yaml +0 -141
  203. package/examples/strategies/spider/swing/scanners/scan.py +0 -334
  204. package/examples/strategies/spider/swing/scanners/scoring.py +0 -184
  205. package/examples/strategies/turbine/README.md +0 -167
  206. package/examples/strategies/turbine/recipe-runners.yaml +0 -123
  207. package/examples/strategies/turbine/recipe-volume.yaml +0 -129
  208. package/examples/strategies/turbine/scanners/scan.py +0 -283
  209. package/examples/strategies/turbine/scanners/scoring.py +0 -190
@@ -0,0 +1,72 @@
1
+ name: wolf
2
+ version: 1.0.0
3
+ description: Aggressive — early entry on FIRST_JUMP from emerging_movers.
4
+
5
+ strategy:
6
+ wallet: "${WALLET_ADDRESS}"
7
+ slots: 3
8
+ margin_pct: 15
9
+ trading_risk: aggressive
10
+ enabled: true
11
+
12
+ scanners:
13
+ - name: emerging_movers
14
+ type: emerging_movers
15
+ interval: 20s
16
+ config:
17
+ topN: 25
18
+ minRankJump: 5
19
+ minTopTradersGain: 0.1
20
+ minScansBeforeSignals: 2
21
+ historyLimit: 60
22
+ immediateJumpThreshold: 10
23
+ deepClimbRankThreshold: 25
24
+ contribExplosionMultiplier: 3.0
25
+ firstJumpMinPrevRank: 30
26
+
27
+ actions:
28
+ - name: open_on_jump
29
+ action_type: OPEN_POSITION
30
+ decision_mode: llm
31
+ decision_model: claude-sonnet-4-20250514
32
+ scanners: [emerging_movers]
33
+ min_confidence: 6
34
+ params:
35
+ order_type: FEE_OPTIMIZED_LIMIT
36
+ fee_optimized_limit_options:
37
+ ensure_execution_as_taker: true
38
+ execution_timeout_seconds: 10
39
+ context: [signal]
40
+ decision_prompt: |
41
+ Evaluate the signal. Reply with JSON: {"execute": true|false, "actionType": "OPEN_POSITION", "confidence": 1-10, "reasoning": "...", "payload": {"signals": [{"asset": "SYMBOL", "direction": "LONG"|"SHORT", "reason": "...", "leverage": <optional number>, "margin": <optional $ amount>}]}}.
42
+
43
+ exit:
44
+ engine: dsl
45
+ interval_seconds: 30
46
+ order_type: FEE_OPTIMIZED_LIMIT
47
+ fee_optimized_limit_options:
48
+ ensure_execution_as_taker: true
49
+ execution_timeout_seconds: 10
50
+ dsl_preset:
51
+ hard_timeout:
52
+ enabled: true
53
+ interval_in_minutes: 90
54
+ weak_peak_cut:
55
+ enabled: true
56
+ interval_in_minutes: 45
57
+ min_value: 3
58
+ dead_weight_cut:
59
+ enabled: true
60
+ interval_in_minutes: 30
61
+ phase1:
62
+ enabled: true
63
+ max_loss_pct: 3.0
64
+ retrace_threshold: 7
65
+ consecutive_breaches_required: 3
66
+ phase2:
67
+ enabled: true
68
+ tiers:
69
+ - { trigger_pct: 7, lock_hw_pct: 40 }
70
+ - { trigger_pct: 12, lock_hw_pct: 55 }
71
+ - { trigger_pct: 15, lock_hw_pct: 75 }
72
+ - { trigger_pct: 20, lock_hw_pct: 85 }
@@ -0,0 +1,123 @@
1
+ name: wolf #required - name of the trading-recipe
2
+ version: 1.0.0 #required
3
+ description: > #required
4
+ Autonomous aggressive multi-strategy trading. Enter early on emerging movers,
5
+ protect with tight DSL, cut dead weight fast, rotate into strength.
6
+
7
+ # Optional: send run summaries and alerts to Telegram (requires OpenClaw channels.telegram configured)
8
+ # notifications:
9
+ # telegram_chat_id: "123456789"
10
+
11
+ # ── STRATEGY ──
12
+ strategy: #required
13
+ wallet: "0x71ce3f0e27c178cbdcf01c4d068278034df75fbc"
14
+ slots: 3
15
+ margin_pct: 10
16
+ trading_risk: aggressive
17
+ enabled: true
18
+
19
+ # ── SCANNERS ──
20
+ scanners: #required
21
+ - name: emerging_movers #required
22
+ type: emerging_movers #required
23
+ interval: 20s #required
24
+ blocked_assets: [] #optional
25
+ config: #Can be different for each scanner.
26
+ topN: 25
27
+ minRankJump: 5
28
+ minTopTradersGain: 0.1
29
+ minScansBeforeSignals: 2
30
+ historyLimit: 60
31
+
32
+ actions: #required
33
+ - name: wolf_entry #required
34
+ action_type: OPEN_POSITION #required
35
+ decision_mode: llm #required
36
+ decision_model: claude-sonnet-4-6 #required
37
+ scanners: [emerging_movers] #required
38
+ min_confidence: 2 #required
39
+ params:
40
+ order_type: FEE_OPTIMIZED_LIMIT
41
+ fee_optimized_limit_options:
42
+ ensure_execution_as_taker: true
43
+ execution_timeout_seconds: 15
44
+ context: #optional
45
+ - type: signal
46
+ value: emerging_movers
47
+ decision_prompt: | #optional
48
+ You evaluate emerging mover signals for the WOLF multi-strategy system.
49
+ WOLF enters early on first jumps — before the peak, not at it. Speed is edge.
50
+
51
+ SIGNAL DATA:
52
+ {{emerging_movers}}
53
+
54
+ SIGNAL PRIORITY (strict — act on highest priority first):
55
+ 1. FIRST_JUMP: Jumped 10+ ranks from #25+ in one scan, wasn't in top 50 before.
56
+ ENTER IMMEDIATELY. 2 reasons is enough. vel > 0 is enough.
57
+ 2. CONTRIB_EXPLOSION: 3x+ contribution spike from rank #20+. ENTER.
58
+ Never downgrade for erratic history.
59
+ 3. IMMEDIATE_MOVER: 10+ rank jump from #25+ but not first jump.
60
+ ENTER if not erratic and not low velocity.
61
+ 4. DEEP_CLIMBER: Steady climb from #30+, vel >= 0.03, 3+ reasons.
62
+ Route to conservative strategy if available.
63
+
64
+ ROUTING:
65
+ - FIRST_JUMP/CONTRIB_EXPLOSION → aggressive strategy
66
+ - DEEP_CLIMBER → conservative if available, else aggressive
67
+ - Never duplicate same asset within one strategy (cross-strategy OK)
68
+
69
+ ANTI-PATTERNS:
70
+ - Rank #1-10 for 2+ scans = SKIP
71
+ - 4+ reasons at rank #5 = SKIP
72
+ - Counter to BTC hourly trend = SKIP
73
+ - Burned asset today = SKIP
74
+
75
+ ROTATION (slots full + FIRST_JUMP):
76
+ - Weakest has negative ROE + SM conviction <= 1 → CUT, ENTER new
77
+ - Weakest is Tier 2+ or SM conviction 3+ → HOLD
78
+ - Positions younger than {{rotation_cooldown_minutes}}min → never rotate out
79
+
80
+ XYZ EQUITIES: Ignore trader count. Use reasons + rank velocity.
81
+
82
+ Respond with execute=true and actionType="OPEN_POSITION".
83
+ Put trade details in the payload object:
84
+ {
85
+ "execute": true,
86
+ "actionType": "OPEN_POSITION",
87
+ "confidence": 1-10,
88
+ "reasoning": "one sentence",
89
+ "payload": {
90
+ "signals": [
91
+ { "asset": "<coin_ticker>", "direction": "LONG" or "SHORT", "reason": "one sentence", "rotate_out": "<asset_to_cut>", "leverage": "<optional number>", "margin": "<optional $ amount>" }
92
+ ]
93
+ }
94
+ }
95
+ Set execute=false if no trade should be taken.
96
+
97
+ # ── EXIT ──
98
+ exit: #required
99
+ engine: dsl
100
+ interval_seconds: 30
101
+ order_type: FEE_OPTIMIZED_LIMIT
102
+ fee_optimized_limit_options:
103
+ ensure_execution_as_taker: true
104
+ execution_timeout_seconds: 15
105
+ dsl_preset:
106
+ phase1:
107
+ enabled: true
108
+ consecutive_breaches_required: 3
109
+ max_loss_pct: 3.0
110
+ retrace_threshold: 10
111
+ phase2:
112
+ enabled: true
113
+ tiers:
114
+ - { trigger_pct: 10, lock_hw_pct: 50 }
115
+ - { trigger_pct: 20, lock_hw_pct: 70 }
116
+ - { trigger_pct: 30, lock_hw_pct: 73 }
117
+ - { trigger_pct: 50, lock_hw_pct: 80 }
118
+ - { trigger_pct: 75, lock_hw_pct: 85 }
119
+ - { trigger_pct: 100, lock_hw_pct: 90 }
120
+
121
+ # Send run summaries and alerts to this Telegram chat (requires OpenClaw channels.telegram configured)
122
+ notifications:
123
+ telegram_chat_id: "6263059192"
@@ -2,7 +2,7 @@
2
2
  "id": "runtime",
3
3
  "name": "Senpi Runtime",
4
4
  "description": "Senpi runtime plugin for OpenClaw. Orchestrates scanners, LLM-based trade decisions, and a DSL trailing stop-loss exit engine.",
5
- "version": "2.0.2",
5
+ "version": "3.0.0",
6
6
  "commandAliases": [{ "name": "senpi" }],
7
7
  "activation": {
8
8
  "onStartup": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@senpi/runtime",
3
- "version": "2.0.2-dev.openclaw-upgrade-mai.20260622175851",
3
+ "version": "3.0.0-dev.runtime-phase-2.20260623210537",
4
4
  "description": "Senpi runtime plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,73 +0,0 @@
1
- /**
2
- * Pure decision function: given the exchange's truth (open positions) and the runtime's DSL state,
3
- * returns the list of reconcile actions required to bring runtime state in sync.
4
- *
5
- * No I/O, no imports of SenpiClient, no disk access, no Date.now, no side effects.
6
- */
7
- import type { OpenPosition } from "../senpi/types.js";
8
- import type { DslState } from "../types/dsl/index.js";
9
- /**
10
- * SIZE_EPS — absolute threshold below which a position size is treated as "flat" (no position).
11
- * Mirrors position-tracker.ts `DEFAULT_SIZE_CHANGE_EPSILON = 1e-9`:
12
- * sub-unit IEEE-754 drift on perp venues is typically < 1e-12; any real sub-unit trade
13
- * is ≥ 0.001 on the smallest venues, so 1e-9 cleanly separates float noise from real size.
14
- * Boundary: |szi| <= SIZE_EPS → flat (ignored); |size diff| > SIZE_EPS → resize trigger.
15
- */
16
- export declare const SIZE_EPS = 1e-9;
17
- /**
18
- * ENTRY_EPS — relative tolerance for entry-price comparison.
19
- * Entry prices can be large (BTC ~60 000, ETH ~3 000) so an absolute epsilon
20
- * would need per-asset tuning. A relative tolerance of 1e-6 (0.0001%) is
21
- * large enough to suppress harmless floating-point serialisation drift
22
- * (e.g. 60000.000000001 vs 60000.0) while small enough to catch any real
23
- * re-entry/average-down event. Formula: |a - b| / max(|b|, 1) > ENTRY_EPS → drift.
24
- */
25
- export declare const ENTRY_EPS = 0.000001;
26
- export interface ReconcileInputs {
27
- /** Strategy wallet address — used only for context in returned actions (not for filtering). */
28
- address: string;
29
- /** All positions from the exchange for this wallet (both DEXes; may include zero-size rows). */
30
- exchangePositions: OpenPosition[];
31
- /** All DSL states for this wallet — function filters to active ones internally. */
32
- runtimeDslStates: DslState[];
33
- }
34
- export type ReconcileAction = {
35
- kind: "adopt";
36
- coin: string;
37
- dex: string;
38
- position: OpenPosition;
39
- } | {
40
- kind: "gone";
41
- coin: string;
42
- dex: string;
43
- state: DslState;
44
- } | {
45
- kind: "resize";
46
- coin: string;
47
- dex: string;
48
- position: OpenPosition;
49
- state: DslState;
50
- };
51
- export interface ReconcileResult {
52
- actions: ReconcileAction[];
53
- counts: {
54
- toAdopt: number;
55
- toArchive: number;
56
- toResize: number;
57
- };
58
- }
59
- /**
60
- * Pure, idempotent reconcile decision function.
61
- *
62
- * Exchange is the source of truth. Running this on a converged state
63
- * (after all returned actions have been applied) yields an empty action list.
64
- *
65
- * Duplicate exchange rows for the same (coin, dex) key: last-wins (later index in the
66
- * array wins). This matches typical clearing-house payloads where the last row is freshest.
67
- *
68
- * Malformed rows (missing coin, NaN/Infinity size or entry, negative coin string) are
69
- * silently skipped without throwing. This prevents a single bad row from blocking all
70
- * reconciliation.
71
- */
72
- export declare function decideReconcile(inputs: ReconcileInputs): ReconcileResult;
73
- //# sourceMappingURL=reconcile-decide.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile-decide.d.ts","sourceRoot":"","sources":["../../src/runtime/reconcile-decide.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKtD;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,OAAO,CAAC;AAE7B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,WAAO,CAAC;AAI9B,MAAM,WAAW,eAAe;IAC9B,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,iBAAiB,EAAE,YAAY,EAAE,CAAC;IAClC,mFAAmF;IACnF,gBAAgB,EAAE,QAAQ,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAE3F,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE;AA2CD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CA8FxE"}
@@ -1,166 +0,0 @@
1
- /**
2
- * Pure decision function: given the exchange's truth (open positions) and the runtime's DSL state,
3
- * returns the list of reconcile actions required to bring runtime state in sync.
4
- *
5
- * No I/O, no imports of SenpiClient, no disk access, no Date.now, no side effects.
6
- */
7
- import { normalizeDslCoinDex } from "../utils/perp-coin.js";
8
- // ─── Epsilon constants ────────────────────────────────────────────────────────
9
- /**
10
- * SIZE_EPS — absolute threshold below which a position size is treated as "flat" (no position).
11
- * Mirrors position-tracker.ts `DEFAULT_SIZE_CHANGE_EPSILON = 1e-9`:
12
- * sub-unit IEEE-754 drift on perp venues is typically < 1e-12; any real sub-unit trade
13
- * is ≥ 0.001 on the smallest venues, so 1e-9 cleanly separates float noise from real size.
14
- * Boundary: |szi| <= SIZE_EPS → flat (ignored); |size diff| > SIZE_EPS → resize trigger.
15
- */
16
- export const SIZE_EPS = 1e-9;
17
- /**
18
- * ENTRY_EPS — relative tolerance for entry-price comparison.
19
- * Entry prices can be large (BTC ~60 000, ETH ~3 000) so an absolute epsilon
20
- * would need per-asset tuning. A relative tolerance of 1e-6 (0.0001%) is
21
- * large enough to suppress harmless floating-point serialisation drift
22
- * (e.g. 60000.000000001 vs 60000.0) while small enough to catch any real
23
- * re-entry/average-down event. Formula: |a - b| / max(|b|, 1) > ENTRY_EPS → drift.
24
- */
25
- export const ENTRY_EPS = 1e-6;
26
- // ─── Helpers ──────────────────────────────────────────────────────────────────
27
- /** Canonical key for matching exchange position vs DSL state. */
28
- function makeKey(coin, dex) {
29
- const n = normalizeDslCoinDex(coin, dex);
30
- return `${n.coin}:${n.dex}`;
31
- }
32
- /** Absolute position size as a number; returns 0 for missing/NaN/Infinity. */
33
- function safeAbsSize(v) {
34
- if (v === undefined || v === null)
35
- return 0;
36
- if (!isFinite(v) || isNaN(v))
37
- return 0;
38
- return Math.abs(v);
39
- }
40
- /** Entry price as a number; returns NaN for missing/NaN/Infinity. */
41
- function safeEntry(v) {
42
- if (v === undefined || v === null)
43
- return NaN;
44
- if (!isFinite(v) || isNaN(v))
45
- return NaN;
46
- return v;
47
- }
48
- /** Relative entry-price comparison: true if prices differ beyond ENTRY_EPS. */
49
- function entryDrifted(exchangeEntry, dslEntry) {
50
- if (!isFinite(exchangeEntry) || !isFinite(dslEntry))
51
- return false; // malformed: skip
52
- const ref = Math.max(Math.abs(dslEntry), 1);
53
- return Math.abs(exchangeEntry - dslEntry) / ref > ENTRY_EPS;
54
- }
55
- /** Direction derived from signed size (positive = LONG, negative = SHORT). */
56
- function directionFromSzi(szi) {
57
- return szi >= 0 ? "LONG" : "SHORT";
58
- }
59
- /** Deterministic sort comparator for actions. */
60
- function actionSortKey(a) {
61
- return `${a.coin}:${a.dex}:${a.kind}`;
62
- }
63
- // ─── Core decision function ───────────────────────────────────────────────────
64
- /**
65
- * Pure, idempotent reconcile decision function.
66
- *
67
- * Exchange is the source of truth. Running this on a converged state
68
- * (after all returned actions have been applied) yields an empty action list.
69
- *
70
- * Duplicate exchange rows for the same (coin, dex) key: last-wins (later index in the
71
- * array wins). This matches typical clearing-house payloads where the last row is freshest.
72
- *
73
- * Malformed rows (missing coin, NaN/Infinity size or entry, negative coin string) are
74
- * silently skipped without throwing. This prevents a single bad row from blocking all
75
- * reconciliation.
76
- */
77
- export function decideReconcile(inputs) {
78
- const { exchangePositions, runtimeDslStates } = inputs;
79
- // ── 1. Build exchange map — last-wins on duplicate (coin, dex) ──────────────
80
- // ambiguousKeys: rows with a valid coin but a MALFORMED size (NaN/Infinity/missing).
81
- // We cannot tell whether such a row is a live position or not. Fail-safe (R7):
82
- // mark the key ambiguous so it NEITHER adopts (can't size it) NOR lets a matching
83
- // DSL state be archived as "gone". Archiving a live position on bad data is the
84
- // worst outcome D2 exists to prevent — so a malformed row freezes that market's
85
- // reconcile until clean data arrives, rather than acting on garbage.
86
- const exchangeMap = new Map();
87
- const ambiguousKeys = new Set();
88
- for (const pos of exchangePositions) {
89
- const coin = (pos.coin ?? "").trim();
90
- if (!coin)
91
- continue; // malformed coin: skip entirely
92
- const dex = (pos.dex ?? "").trim();
93
- const key = makeKey(coin, dex);
94
- const szi = pos.szi;
95
- if (szi === undefined || szi === null || !isFinite(szi) || isNaN(szi)) {
96
- // Malformed size → ambiguous: do not adopt, do not let it archive a DSL state.
97
- ambiguousKeys.add(key);
98
- continue;
99
- }
100
- const absSize = Math.abs(szi);
101
- // Genuinely flat (finite, near-zero) → treat as absence: allows "gone" archival.
102
- if (absSize <= SIZE_EPS)
103
- continue;
104
- exchangeMap.set(key, pos); // last-wins for duplicates
105
- }
106
- // ── 2. Build active DSL state map ───────────────────────────────────────────
107
- const dslMap = new Map();
108
- for (const state of runtimeDslStates) {
109
- if (!state.active)
110
- continue; // only compare active states
111
- const key = makeKey(state.asset, state.dex ?? "");
112
- // If duplicate keys in DSL (shouldn't happen), last-wins
113
- dslMap.set(key, state);
114
- }
115
- // ── 3. Compute actions ───────────────────────────────────────────────────────
116
- const actions = [];
117
- // Check exchange positions against DSL
118
- for (const [key, pos] of exchangeMap) {
119
- const { coin: normCoin, dex: normDex } = normalizeDslCoinDex(pos.coin ?? "", pos.dex ?? "");
120
- const dslState = dslMap.get(key);
121
- if (!dslState) {
122
- // adopt: exchange has a live position, DSL has no active state for it
123
- actions.push({ kind: "adopt", coin: normCoin, dex: normDex, position: pos });
124
- }
125
- else {
126
- // Check for drift: size, entry, or direction
127
- const exchAbsSize = safeAbsSize(pos.szi);
128
- const dslAbsSize = Math.abs(dslState.size);
129
- const sizeDrifted = Math.abs(exchAbsSize - dslAbsSize) > SIZE_EPS;
130
- const exchEntry = safeEntry(pos.entryPx);
131
- const dslEntry = safeEntry(dslState.entryPrice);
132
- const _entryDrifted = isNaN(exchEntry) || isNaN(dslEntry)
133
- ? false // malformed: skip entry comparison
134
- : entryDrifted(exchEntry, dslEntry);
135
- const exchDir = pos.szi !== undefined && isFinite(pos.szi) && !isNaN(pos.szi)
136
- ? directionFromSzi(pos.szi)
137
- : null;
138
- const dirDrifted = exchDir !== null && exchDir !== dslState.direction;
139
- if (sizeDrifted || _entryDrifted || dirDrifted) {
140
- actions.push({ kind: "resize", coin: normCoin, dex: normDex, position: pos, state: dslState });
141
- }
142
- // else: in-sync → no action
143
- }
144
- }
145
- // Check DSL states against exchange (find gone positions)
146
- for (const [key, state] of dslMap) {
147
- if (exchangeMap.has(key))
148
- continue; // matched → handled in resize/in-sync loop above
149
- // Fail-safe: a malformed exchange row for this market means we cannot confirm the
150
- // position is closed. Do NOT archive a possibly-live position on ambiguous data.
151
- if (ambiguousKeys.has(key))
152
- continue;
153
- const { coin: normCoin, dex: normDex } = normalizeDslCoinDex(state.asset, state.dex ?? "");
154
- actions.push({ kind: "gone", coin: normCoin, dex: normDex, state });
155
- }
156
- // ── 4. Sort deterministically (coin → dex → kind) ────────────────────────────
157
- actions.sort((a, b) => actionSortKey(a).localeCompare(actionSortKey(b)));
158
- // ── 5. Compute counts ────────────────────────────────────────────────────────
159
- const counts = {
160
- toAdopt: actions.filter((a) => a.kind === "adopt").length,
161
- toArchive: actions.filter((a) => a.kind === "gone").length,
162
- toResize: actions.filter((a) => a.kind === "resize").length,
163
- };
164
- return { actions, counts };
165
- }
166
- //# sourceMappingURL=reconcile-decide.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile-decide.js","sourceRoot":"","sources":["../../src/runtime/reconcile-decide.ts"],"names":[],"mappings":"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"}
@@ -1,62 +0,0 @@
1
- /**
2
- * Impure reconcile executor: wires decideReconcile (pure) with the I/O side-effects
3
- * (adoptPosition, resizePosition, archiveGoneState).
4
- *
5
- * Design contract:
6
- * - decideReconcile is the SOLE decision source (no second gone-computation here).
7
- * - CH fetch returning null/undefined → success:false, zero mutations (R7 fail-safe).
8
- * - getOpenPositions undefined (CH never fetched) → success:false, zero mutations.
9
- * - Execution order within the serialize pass: archive gone FIRST, then adopt/resize
10
- * (frees state before re-adopting; mirrors monitor order).
11
- * - Each action is individually try/caught; one failure does not abort the rest.
12
- * - Only successfully applied actions count toward ReconcileCounts.
13
- */
14
- import type { SenpiClient } from "../senpi/client.js";
15
- import type { StrategyState } from "../types/strategy.js";
16
- import type { StateManager } from "../state/index.js";
17
- import type { SenpiEventBus } from "../types/event-bus.js";
18
- import type { PositionOpenedEvent } from "../types/dsl/index.js";
19
- import type { OpenPosition } from "../senpi/types.js";
20
- export interface RunReconcileDeps {
21
- address: string;
22
- strategyState: StrategyState;
23
- senpi: SenpiClient;
24
- stateManager: StateManager;
25
- /** adoptPosition + resizePosition — satisfied by DslPlugin or a compatible adopter. */
26
- adopter: {
27
- adoptPosition(p: PositionOpenedEvent): Promise<void>;
28
- resizePosition(p: PositionOpenedEvent): Promise<void>;
29
- };
30
- bus?: SenpiEventBus;
31
- /**
32
- * Serializes the whole fetch+decide+execute pass against the trade loop / other reconciles.
33
- * Default: run directly (T5 will pass a reconcileMutex-backed serializer).
34
- */
35
- serialize?: <T>(fn: () => Promise<T>) => Promise<T>;
36
- }
37
- export interface ReconcileCounts {
38
- adopted: number;
39
- resized: number;
40
- archived: number;
41
- }
42
- /**
43
- * Map an OpenPosition (from clearinghouse) to the PositionOpenedEvent shape expected
44
- * by adoptPosition / resizePosition.
45
- *
46
- * Field mapping:
47
- * address → address (strategy wallet; same as deps.address)
48
- * wallet → position.wallet if set, else address (clearinghouse rows rarely carry wallet)
49
- * coin → position.coin
50
- * szi → String(position.szi) — signed; positive=LONG, negative=SHORT
51
- * entryPx → String(position.entryPx ?? 0)
52
- * leverage → position.leverage ?? 1
53
- * dex → position.dex if non-empty, else undefined (handlePositionOpened normalizes "")
54
- *
55
- * Note: PositionOpenedEvent.szi is a string (the handler parses it); OpenPosition.szi is a number.
56
- */
57
- export declare function openPositionToPayload(pos: OpenPosition, address: string): PositionOpenedEvent;
58
- export declare function runReconcile(deps: RunReconcileDeps): Promise<{
59
- success: boolean;
60
- counts: ReconcileCounts;
61
- }>;
62
- //# sourceMappingURL=reconcile-run.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile-run.d.ts","sourceRoot":"","sources":["../../src/runtime/reconcile-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAStD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,uFAAuF;IACvF,OAAO,EAAE;QACP,aAAa,CAAC,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACrD,cAAc,CAAC,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACvD,CAAC;IACF,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,MAAM,GACd,mBAAmB,CAWrB;AAID,wBAAsB,YAAY,CAChC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC,CA2IxD"}