@senpi/runtime 3.0.0-dev.openclaw-upgrade-mai.20260623210452 → 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.
- package/README.md +9 -10
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +0 -3
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +2 -6
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +56 -43
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +108 -0
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/constants/dsl/index.d.ts +0 -2
- package/dist/constants/dsl/index.d.ts.map +1 -1
- package/dist/constants/dsl/index.js +0 -2
- package/dist/constants/dsl/index.js.map +1 -1
- package/dist/dsl/engine-client/config-mapping.d.ts +0 -7
- package/dist/dsl/engine-client/config-mapping.d.ts.map +1 -1
- package/dist/dsl/engine-client/config-mapping.js +2 -16
- package/dist/dsl/engine-client/config-mapping.js.map +1 -1
- package/dist/dsl/events/handlers.d.ts +2 -18
- package/dist/dsl/events/handlers.d.ts.map +1 -1
- package/dist/dsl/events/handlers.js +213 -302
- package/dist/dsl/events/handlers.js.map +1 -1
- package/dist/dsl/monitor/create-monitor.d.ts +0 -15
- package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
- package/dist/dsl/monitor/create-monitor.js +9 -44
- package/dist/dsl/monitor/create-monitor.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +1 -24
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/plugin/index.d.ts +1 -16
- package/dist/dsl/plugin/index.d.ts.map +1 -1
- package/dist/dsl/plugin/index.js +4 -35
- package/dist/dsl/plugin/index.js.map +1 -1
- package/dist/dsl/plugin/options.d.ts +0 -18
- package/dist/dsl/plugin/options.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/runtime/create-scanner-module.d.ts +3 -4
- package/dist/runtime/create-scanner-module.d.ts.map +1 -1
- package/dist/runtime/create-scanner-module.js +5 -14
- package/dist/runtime/create-scanner-module.js.map +1 -1
- package/dist/runtime/create-scanner-providers-for-run.d.ts.map +1 -1
- package/dist/runtime/create-scanner-providers-for-run.js +1 -12
- package/dist/runtime/create-scanner-providers-for-run.js.map +1 -1
- package/dist/runtime/load-runtime-config.js +1 -1
- package/dist/runtime/load-runtime-config.js.map +1 -1
- package/dist/runtime/map-strategies-registration.js +8 -7
- package/dist/runtime/map-strategies-registration.js.map +1 -1
- package/dist/runtime/map-strategies.d.ts.map +1 -1
- package/dist/runtime/map-strategies.js +3 -12
- package/dist/runtime/map-strategies.js.map +1 -1
- package/dist/runtime/reconcile-state.d.ts +0 -44
- package/dist/runtime/reconcile-state.d.ts.map +1 -1
- package/dist/runtime/reconcile-state.js +44 -80
- package/dist/runtime/reconcile-state.js.map +1 -1
- package/dist/runtime/risk-guard.d.ts.map +1 -1
- package/dist/runtime/risk-guard.js +12 -17
- package/dist/runtime/risk-guard.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +995 -2855
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +40 -133
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts +0 -26
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +5 -233
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/scanner-registry.d.ts +1 -1
- package/dist/runtime/scanner-registry.d.ts.map +1 -1
- package/dist/runtime/scanner-registry.js +12 -3
- package/dist/runtime/scanner-registry.js.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
- package/dist/runtime/supervisor/orphan-sweep.js +1 -1
- package/dist/runtime/supervisor/orphan-sweep.js.map +1 -1
- package/dist/runtime/supervisor/supervisor-utils.d.ts +1 -1
- package/dist/runtime/supervisor/supervisor-utils.d.ts.map +1 -1
- package/dist/runtime/supervisor/supervisor-utils.js +1 -1
- package/dist/runtime/supervisor/supervisor-utils.js.map +1 -1
- package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-mount.js +36 -28
- package/dist/runtime-api/intake/intake-mount.js.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.js +0 -0
- package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.d.ts +4 -18
- package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.js +3 -24
- package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
- package/dist/runtime-api/intake/types.d.ts +0 -6
- package/dist/runtime-api/intake/types.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.d.ts +0 -1
- package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.js +0 -5
- package/dist/runtime-api/routes/signals.schema.js.map +1 -1
- package/dist/scanners/external/liquidation-watchdog/README.md +107 -0
- package/dist/scanners/external/liquidation-watchdog/liquidation-watchdog.yaml +48 -0
- package/dist/scanners/external/liquidation-watchdog/producer.mjs +336 -0
- package/dist/scanners/external/momentum/README.md +148 -0
- package/dist/scanners/external/momentum/momentum.yaml +116 -0
- package/dist/scanners/external/momentum/producer.mjs +251 -0
- package/dist/scanners/external/scaffold/__main__.py +24 -65
- package/dist/scanners/external/scaffold/delivery.py +22 -56
- package/dist/scanners/external/scaffold/entrypoint_loader.py +48 -42
- package/dist/scanners/external/scaffold/journal.py +2 -13
- package/dist/scanners/external/scaffold/scaffold.py +128 -159
- package/dist/scanners/external/scaffold/signal_envelope.py +34 -177
- package/dist/scanners/external/shared/ingest.mjs +112 -0
- package/dist/scanners/external-scanner-receiver.d.ts +0 -6
- package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
- package/dist/scanners/external-scanner-receiver.js +1 -14
- package/dist/scanners/external-scanner-receiver.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-live.d.ts +1 -1
- package/dist/scripts/run-dsl-standalone-live.js +3 -5
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -1
- package/dist/senpi/client.d.ts +0 -12
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +2 -31
- package/dist/senpi/client.js.map +1 -1
- package/dist/state/state-manager.d.ts +0 -17
- package/dist/state/state-manager.d.ts.map +1 -1
- package/dist/state/state-manager.js +0 -28
- package/dist/state/state-manager.js.map +1 -1
- package/dist/strategy/strategy-state.d.ts.map +1 -1
- package/dist/strategy/strategy-state.js +1 -7
- package/dist/strategy/strategy-state.js.map +1 -1
- package/dist/tracking/constants.d.ts.map +1 -1
- package/dist/tracking/constants.js +0 -2
- package/dist/tracking/constants.js.map +1 -1
- package/dist/types/dsl/index.d.ts +1 -1
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/types/scanner.d.ts +0 -7
- package/dist/types/scanner.d.ts.map +1 -1
- package/examples/README.md +89 -0
- package/examples/scanners-consumer-quickstart.mjs +134 -0
- package/examples/scanners-emerging-movers-v4.mjs +287 -0
- package/examples/scanners-liquidation-watchdog.mjs +341 -0
- package/examples/scanners-live-mcp.mjs +208 -0
- package/examples/scanners-multi-strategy.mjs +165 -0
- package/examples/scanners-position-tracker-e2e.mjs +225 -0
- package/examples/scanners-scheduled-events.mjs +96 -0
- package/examples/scanners-senpi-provider-client.mjs +182 -0
- package/examples/scanners-single-strategy.mjs +198 -0
- package/examples/strategies/README.md +12 -17
- package/examples/strategies/dsl-showcase.yaml +68 -0
- package/examples/strategies/dsl.yaml +51 -0
- package/examples/strategies/fox-minimal-loosened.yaml +240 -0
- package/examples/strategies/fox-minimal.yaml +242 -0
- package/examples/strategies/minimal.yaml +46 -0
- package/examples/strategies/momentum/how-it-works.md +48 -0
- package/examples/strategies/momentum/momentum-guarded.yaml +161 -0
- package/examples/strategies/risk-showcase.yaml +93 -0
- package/examples/strategies/viper.yaml +67 -0
- package/examples/strategies/wolf.yaml +72 -0
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +123 -0
- package/package.json +1 -1
- package/dist/runtime/reconcile-decide.d.ts +0 -73
- package/dist/runtime/reconcile-decide.d.ts.map +0 -1
- package/dist/runtime/reconcile-decide.js +0 -166
- package/dist/runtime/reconcile-decide.js.map +0 -1
- package/dist/runtime/reconcile-run.d.ts +0 -62
- package/dist/runtime/reconcile-run.d.ts.map +0 -1
- package/dist/runtime/reconcile-run.js +0 -173
- package/dist/runtime/reconcile-run.js.map +0 -1
- package/dist/scanners/external/scaffold/ctx.py +0 -78
- package/dist/scanners/external/scaffold/requirements.txt +0 -11
- package/dist/scanners/external/scaffold/senpi_mcp.py +0 -250
- package/dist/scanners/external/scaffold/state_manager.py +0 -175
- package/dist/utils/keyed-mutex.d.ts +0 -37
- package/dist/utils/keyed-mutex.d.ts.map +0 -1
- package/dist/utils/keyed-mutex.js +0 -77
- package/dist/utils/keyed-mutex.js.map +0 -1
- package/examples/strategies/iguana/README.md +0 -135
- package/examples/strategies/iguana/recipe.yaml +0 -137
- package/examples/strategies/iguana/scanners/scan.py +0 -243
- package/examples/strategies/iguana/scanners/scoring.py +0 -152
- package/examples/strategies/raptor/README.md +0 -156
- package/examples/strategies/raptor/recipe.yaml +0 -154
- package/examples/strategies/raptor/scanners/scan.py +0 -349
- package/examples/strategies/raptor/scanners/scoring.py +0 -452
- package/examples/strategies/spider/README.md +0 -97
- package/examples/strategies/spider/scalp/recipe.yaml +0 -129
- package/examples/strategies/spider/scalp/scanners/scan.py +0 -219
- package/examples/strategies/spider/scalp/scanners/scoring.py +0 -179
- package/examples/strategies/spider/swing/recipe.yaml +0 -141
- package/examples/strategies/spider/swing/scanners/scan.py +0 -334
- package/examples/strategies/spider/swing/scanners/scoring.py +0 -184
- package/examples/strategies/turbine/README.md +0 -167
- package/examples/strategies/turbine/recipe-runners.yaml +0 -123
- package/examples/strategies/turbine/recipe-volume.yaml +0 -129
- package/examples/strategies/turbine/scanners/scan.py +0 -283
- 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"
|
package/package.json
CHANGED
|
@@ -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":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,iFAAiF;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC;AAuB9B,iFAAiF;AAEjF,iEAAiE;AACjE,SAAS,OAAO,CAAC,IAAY,EAAE,GAAW;IACxC,MAAM,CAAC,GAAG,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzC,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;AAC9B,CAAC;AAED,8EAA8E;AAC9E,SAAS,WAAW,CAAC,CAAqB;IACxC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC;AAED,qEAAqE;AACrE,SAAS,SAAS,CAAC,CAAqB;IACtC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAC9C,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC;IACzC,OAAO,CAAC,CAAC;AACX,CAAC;AAED,+EAA+E;AAC/E,SAAS,YAAY,CAAC,aAAqB,EAAE,QAAgB;IAC3D,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,kBAAkB;IACrF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC;AAC9D,CAAC;AAED,8EAA8E;AAC9E,SAAS,gBAAgB,CAAC,GAAW;IACnC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AACrC,CAAC;AAED,iDAAiD;AACjD,SAAS,aAAa,CAAC,CAAkB;IACvC,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AACxC,CAAC;AAED,iFAAiF;AAEjF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,MAAuB;IACrD,MAAM,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAAC;IAEvD,+EAA+E;IAC/E,qFAAqF;IACrF,+EAA+E;IAC/E,kFAAkF;IAClF,gFAAgF;IAChF,gFAAgF;IAChF,qEAAqE;IACrE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAwB,CAAC;IACpD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,SAAS,CAAC,gCAAgC;QACrD,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;QACpB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACtE,+EAA+E;YAC/E,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,iFAAiF;QACjF,IAAI,OAAO,IAAI,QAAQ;YAAE,SAAS;QAClC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,2BAA2B;IACxD,CAAC;IAED,+EAA+E;IAC/E,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,SAAS,CAAC,6BAA6B;QAC1D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAClD,yDAAyD;QACzD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,gFAAgF;IAChF,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,uCAAuC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAC5F,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEjC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,sEAAsE;YACtE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/E,CAAC;aAAM,CAAC;YACN,6CAA6C;YAC7C,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC;YAElE,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAChD,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC;gBACvD,CAAC,CAAC,KAAK,CAAC,mCAAmC;gBAC3C,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAEtC,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;gBAC3E,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;gBAC3B,CAAC,CAAC,IAAI,CAAC;YACT,MAAM,UAAU,GAAG,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,CAAC;YAEtE,IAAI,WAAW,IAAI,aAAa,IAAI,UAAU,EAAE,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACjG,CAAC;YACD,4BAA4B;QAC9B,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,iDAAiD;QACrF,kFAAkF;QAClF,iFAAiF;QACjF,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACrC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAC3F,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,gFAAgF;IAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzE,gFAAgF;IAChF,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,MAAM;QACzD,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,MAAM;QAC1D,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM;KAC5D,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -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"}
|