@senpi/runtime 3.0.135 → 3.0.139
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/action-events.d.ts +7 -21
- package/dist/actions/action-events.d.ts.map +1 -1
- package/dist/actions/action-events.js +26 -54
- package/dist/actions/action-events.js.map +1 -1
- package/dist/actions/action-runtime-module.d.ts.map +1 -1
- package/dist/actions/action-runtime-module.js +7 -38
- package/dist/actions/action-runtime-module.js.map +1 -1
- package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
- package/dist/actions/close-position/close-position.action.js +15 -122
- package/dist/actions/close-position/close-position.action.js.map +1 -1
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +2 -15
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/actions/event-derivation.d.ts +2 -71
- package/dist/actions/event-derivation.d.ts.map +1 -1
- package/dist/actions/event-derivation.js +8 -251
- package/dist/actions/event-derivation.js.map +1 -1
- package/dist/actions/open-position/open-position.action.d.ts +2 -12
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +41 -141
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/actions/position-tracker/position-tracker.action.d.ts +1 -2
- package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
- package/dist/actions/position-tracker/position-tracker.action.js +17 -62
- package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
- package/dist/actions/store/types.d.ts +2 -9
- package/dist/actions/store/types.d.ts.map +1 -1
- package/dist/actions/store/types.js.map +1 -1
- package/dist/actions/types.d.ts +0 -13
- package/dist/actions/types.d.ts.map +1 -1
- package/dist/actions/types.js +0 -13
- package/dist/actions/types.js.map +1 -1
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +7 -4
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/constants/dsl/index.d.ts +0 -6
- package/dist/constants/dsl/index.d.ts.map +1 -1
- package/dist/constants/dsl/index.js +0 -6
- package/dist/constants/dsl/index.js.map +1 -1
- package/dist/constants/telemetry.d.ts +15 -0
- package/dist/constants/telemetry.d.ts.map +1 -0
- package/dist/constants/telemetry.js +28 -0
- package/dist/constants/telemetry.js.map +1 -0
- package/dist/dsl/engine-client/event-mapping.d.ts.map +1 -1
- package/dist/dsl/engine-client/event-mapping.js +0 -14
- package/dist/dsl/engine-client/event-mapping.js.map +1 -1
- package/dist/dsl/events/build-closed-event.d.ts +1 -16
- package/dist/dsl/events/build-closed-event.d.ts.map +1 -1
- package/dist/dsl/events/build-closed-event.js +0 -6
- package/dist/dsl/events/build-closed-event.js.map +1 -1
- package/dist/dsl/events/handlers.d.ts +0 -7
- package/dist/dsl/events/handlers.d.ts.map +1 -1
- package/dist/dsl/events/handlers.js +7 -37
- package/dist/dsl/events/handlers.js.map +1 -1
- package/dist/dsl/monitor/create-monitor.d.ts +2 -6
- package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
- package/dist/dsl/monitor/create-monitor.js +9 -82
- package/dist/dsl/monitor/create-monitor.js.map +1 -1
- package/dist/dsl/monitor/dsl-failure-events.d.ts +2 -45
- package/dist/dsl/monitor/dsl-failure-events.d.ts.map +1 -1
- package/dist/dsl/monitor/dsl-failure-events.js +3 -52
- package/dist/dsl/monitor/dsl-failure-events.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts +0 -1
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +36 -159
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/plugin/index.d.ts +2 -8
- package/dist/dsl/plugin/index.d.ts.map +1 -1
- package/dist/dsl/plugin/index.js +8 -20
- package/dist/dsl/plugin/index.js.map +1 -1
- package/dist/health/types.d.ts +0 -13
- package/dist/health/types.d.ts.map +1 -1
- package/dist/health/types.js +0 -12
- package/dist/health/types.js.map +1 -1
- package/dist/index.d.ts +8 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +105 -272
- package/dist/index.js.map +1 -1
- package/dist/runtime/action-registry.d.ts.map +1 -1
- package/dist/runtime/action-registry.js +3 -4
- package/dist/runtime/action-registry.js.map +1 -1
- package/dist/runtime/domain-events.d.ts.map +1 -1
- package/dist/runtime/domain-events.js +0 -7
- package/dist/runtime/domain-events.js.map +1 -1
- package/dist/runtime/events-telemetry.d.ts +96 -0
- package/dist/runtime/events-telemetry.d.ts.map +1 -0
- package/dist/runtime/events-telemetry.js +232 -0
- package/dist/runtime/events-telemetry.js.map +1 -0
- package/dist/runtime/lifecycle-events.d.ts +3 -15
- package/dist/runtime/lifecycle-events.d.ts.map +1 -1
- package/dist/runtime/lifecycle-events.js +3 -17
- package/dist/runtime/lifecycle-events.js.map +1 -1
- package/dist/runtime/lifecycle-reaper.d.ts +6 -4
- package/dist/runtime/lifecycle-reaper.d.ts.map +1 -1
- package/dist/runtime/lifecycle-reaper.js +6 -4
- package/dist/runtime/lifecycle-reaper.js.map +1 -1
- package/dist/runtime/reconcile-run.d.ts +3 -13
- package/dist/runtime/reconcile-run.d.ts.map +1 -1
- package/dist/runtime/reconcile-run.js +3 -4
- package/dist/runtime/reconcile-run.js.map +1 -1
- package/dist/runtime/reconcile-state.d.ts +0 -8
- package/dist/runtime/reconcile-state.d.ts.map +1 -1
- package/dist/runtime/reconcile-state.js +1 -4
- package/dist/runtime/reconcile-state.js.map +1 -1
- package/dist/runtime/risk-guard.d.ts +20 -1
- package/dist/runtime/risk-guard.d.ts.map +1 -1
- package/dist/runtime/risk-guard.js +47 -6
- package/dist/runtime/risk-guard.js.map +1 -1
- package/dist/runtime/run.d.ts +7 -1
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +7 -0
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/runtime-schema.js +3 -3
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts +22 -2
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +74 -39
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/strategies-store.d.ts +26 -0
- package/dist/runtime/strategies-store.d.ts.map +1 -0
- package/dist/runtime/strategies-store.js +47 -0
- package/dist/runtime/strategies-store.js.map +1 -0
- package/dist/runtime/strategies-telemetry.d.ts +91 -0
- package/dist/runtime/strategies-telemetry.d.ts.map +1 -0
- package/dist/runtime/strategies-telemetry.js +128 -0
- package/dist/runtime/strategies-telemetry.js.map +1 -0
- package/dist/runtime/strategy-lifecycle.d.ts +108 -2
- package/dist/runtime/strategy-lifecycle.d.ts.map +1 -1
- package/dist/runtime/strategy-lifecycle.js +325 -4
- package/dist/runtime/strategy-lifecycle.js.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.d.ts +0 -13
- package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js +0 -1
- package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
- package/dist/runtime/validate-dsl-position-tracking.d.ts.map +1 -1
- package/dist/runtime/validate-dsl-position-tracking.js +1 -2
- package/dist/runtime/validate-dsl-position-tracking.js.map +1 -1
- package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
- package/dist/runtime-api/handlers/ingest-signals.js +0 -1
- package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
- package/dist/runtime-api/handlers/types.d.ts +0 -5
- package/dist/runtime-api/handlers/types.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-events.d.ts +1 -1
- package/dist/runtime-api/intake/intake-events.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-events.js +3 -9
- package/dist/runtime-api/intake/intake-events.js.map +1 -1
- package/dist/runtime-api/intake/intake-mount.d.ts +2 -0
- package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-mount.js +25 -7
- package/dist/runtime-api/intake/intake-mount.js.map +1 -1
- package/dist/runtime-api/intake/process-error-post.d.ts +1 -6
- package/dist/runtime-api/intake/process-error-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-error-post.js +1 -5
- package/dist/runtime-api/intake/process-error-post.js.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts +1 -7
- package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.js +0 -5
- package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
- package/dist/runtime-api/intake/scaffold-error-router.js.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.js +0 -15
- package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
- package/dist/runtime-api/intake/types.d.ts +0 -55
- package/dist/runtime-api/intake/types.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.d.ts +0 -2
- package/dist/runtime-api/routes/signals.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.js +11 -5
- package/dist/runtime-api/routes/signals.js.map +1 -1
- package/dist/runtime-api/routes/signals.schema.d.ts +0 -43
- package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.js +0 -43
- package/dist/runtime-api/routes/signals.schema.js.map +1 -1
- package/dist/runtime-api/server.d.ts +1 -7
- package/dist/runtime-api/server.d.ts.map +1 -1
- package/dist/runtime-api/server.js +0 -1
- package/dist/runtime-api/server.js.map +1 -1
- package/dist/scanners/engine/engine.d.ts +1 -22
- package/dist/scanners/engine/engine.d.ts.map +1 -1
- package/dist/scanners/engine/engine.js +11 -78
- package/dist/scanners/engine/engine.js.map +1 -1
- package/dist/scanners/engine/lifecycle.d.ts +1 -7
- package/dist/scanners/engine/lifecycle.d.ts.map +1 -1
- package/dist/scanners/events.d.ts +0 -4
- package/dist/scanners/events.d.ts.map +1 -1
- package/dist/scanners/events.js +0 -2
- package/dist/scanners/events.js.map +1 -1
- package/dist/scanners/external/scaffold/delivery.py +25 -194
- package/dist/scanners/external/scaffold/scaffold.py +31 -172
- package/dist/scanners/external/scaffold/senpi_mcp.py +8 -150
- package/dist/scanners/external-scanner-receiver.d.ts +0 -17
- package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
- package/dist/scanners/external-scanner-receiver.js +0 -8
- package/dist/scanners/external-scanner-receiver.js.map +1 -1
- package/dist/scanners/runtime-module.d.ts +0 -1
- package/dist/scanners/runtime-module.d.ts.map +1 -1
- package/dist/scanners/runtime-module.js +9 -66
- package/dist/scanners/runtime-module.js.map +1 -1
- package/dist/state/state-manager.d.ts +2 -0
- package/dist/state/state-manager.d.ts.map +1 -1
- package/dist/state/state-manager.js +8 -0
- package/dist/state/state-manager.js.map +1 -1
- package/dist/telemetry/attributes.d.ts +0 -20
- package/dist/telemetry/attributes.d.ts.map +1 -1
- package/dist/telemetry/attributes.js +0 -24
- package/dist/telemetry/attributes.js.map +1 -1
- package/dist/telemetry/event-builders.d.ts +6 -81
- package/dist/telemetry/event-builders.d.ts.map +1 -1
- package/dist/telemetry/event-builders.js +17 -141
- package/dist/telemetry/event-builders.js.map +1 -1
- package/dist/telemetry/event-store.d.ts.map +1 -1
- package/dist/telemetry/event-store.js +2 -6
- package/dist/telemetry/event-store.js.map +1 -1
- package/dist/telemetry/metrics.d.ts +2 -14
- package/dist/telemetry/metrics.d.ts.map +1 -1
- package/dist/telemetry/metrics.js +4 -19
- package/dist/telemetry/metrics.js.map +1 -1
- package/dist/telemetry/spans/redact-pii.d.ts.map +1 -1
- package/dist/telemetry/spans/redact-pii.js +11 -16
- package/dist/telemetry/spans/redact-pii.js.map +1 -1
- package/dist/telemetry/tracing.d.ts +0 -9
- package/dist/telemetry/tracing.d.ts.map +1 -1
- package/dist/telemetry/tracing.js +0 -36
- package/dist/telemetry/tracing.js.map +1 -1
- package/dist/types/dsl/index.d.ts +0 -48
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/types/scanner.d.ts +0 -15
- package/dist/types/scanner.d.ts.map +1 -1
- package/dist/utils/event-catalog.d.ts +0 -202
- package/dist/utils/event-catalog.d.ts.map +1 -1
- package/dist/utils/event-catalog.js +0 -26
- package/dist/utils/event-catalog.js.map +1 -1
- package/dist/utils/logger.d.ts +1 -4
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/validate/recipe-checks.d.ts.map +1 -1
- package/dist/validate/recipe-checks.js +2 -2
- package/dist/validate/recipe-checks.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/actions/skipped-signal-results.d.ts +0 -25
- package/dist/actions/skipped-signal-results.d.ts.map +0 -1
- package/dist/actions/skipped-signal-results.js +0 -71
- package/dist/actions/skipped-signal-results.js.map +0 -1
- package/dist/runtime-api/intake/ingest-request.d.ts +0 -17
- package/dist/runtime-api/intake/ingest-request.d.ts.map +0 -1
- package/dist/runtime-api/intake/ingest-request.js +0 -34
- package/dist/runtime-api/intake/ingest-request.js.map +0 -1
- package/dist/runtime-api/intake/scaffold-tick-router.d.ts +0 -39
- package/dist/runtime-api/intake/scaffold-tick-router.d.ts.map +0 -1
- package/dist/runtime-api/intake/scaffold-tick-router.js +0 -122
- package/dist/runtime-api/intake/scaffold-tick-router.js.map +0 -1
- package/dist/scanners/external/scaffold/tick_facts.py +0 -130
- package/dist/scanners/external/scaffold/ulid.py +0 -58
- package/dist/telemetry/dsl-positions.d.ts +0 -111
- package/dist/telemetry/dsl-positions.d.ts.map +0 -1
- package/dist/telemetry/dsl-positions.js +0 -118
- package/dist/telemetry/dsl-positions.js.map +0 -1
- package/dist/telemetry/live-telemetry.d.ts +0 -257
- package/dist/telemetry/live-telemetry.d.ts.map +0 -1
- package/dist/telemetry/live-telemetry.js +0 -959
- package/dist/telemetry/live-telemetry.js.map +0 -1
- package/dist/telemetry/scanner-stats.d.ts +0 -143
- package/dist/telemetry/scanner-stats.d.ts.map +0 -1
- package/dist/telemetry/scanner-stats.js +0 -426
- package/dist/telemetry/scanner-stats.js.map +0 -1
- package/dist/telemetry/scanner-tick-feed.d.ts +0 -87
- package/dist/telemetry/scanner-tick-feed.d.ts.map +0 -1
- package/dist/telemetry/scanner-tick-feed.js +0 -48
- package/dist/telemetry/scanner-tick-feed.js.map +0 -1
- package/dist/telemetry/strategy-topology.d.ts +0 -99
- package/dist/telemetry/strategy-topology.d.ts.map +0 -1
- package/dist/telemetry/strategy-topology.js +0 -93
- package/dist/telemetry/strategy-topology.js.map +0 -1
- package/dist/telemetry/telemetry-publisher.d.ts +0 -83
- package/dist/telemetry/telemetry-publisher.d.ts.map +0 -1
- package/dist/telemetry/telemetry-publisher.js +0 -256
- package/dist/telemetry/telemetry-publisher.js.map +0 -1
- package/dist/telemetry/tick-frame.d.ts +0 -212
- package/dist/telemetry/tick-frame.d.ts.map +0 -1
- package/dist/telemetry/tick-frame.js +0 -421
- package/dist/telemetry/tick-frame.js.map +0 -1
- package/dist/telemetry/timeline-buffer.d.ts +0 -95
- package/dist/telemetry/timeline-buffer.d.ts.map +0 -1
- package/dist/telemetry/timeline-buffer.js +0 -237
- package/dist/telemetry/timeline-buffer.js.map +0 -1
- package/dist/utils/telemetry-required-log.d.ts +0 -60
- package/dist/utils/telemetry-required-log.d.ts.map +0 -1
- package/dist/utils/telemetry-required-log.js +0 -105
- package/dist/utils/telemetry-required-log.js.map +0 -1
- package/dist/utils/ulid.d.ts +0 -9
- package/dist/utils/ulid.d.ts.map +0 -1
- package/dist/utils/ulid.js +0 -43
- package/dist/utils/ulid.js.map +0 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategies telemetry: the payload built from the strategies store, and the loop that broadcasts
|
|
3
|
+
* that payload as `plugin.senpi.strategies`.
|
|
4
|
+
*/
|
|
5
|
+
import type { DslState } from "../types/dsl/index.js";
|
|
6
|
+
import type { StrategyRecord } from "./strategies-store.js";
|
|
7
|
+
/** Minted once per plugin process. `plugin.senpi.events` carries the same value. */
|
|
8
|
+
export declare const PROCESS_EPOCH: `${string}-${string}-${string}-${string}-${string}`;
|
|
9
|
+
export interface StrategyScannerPayload {
|
|
10
|
+
scannerId: string;
|
|
11
|
+
intervalSeconds: number;
|
|
12
|
+
lastAliveAt: number | null;
|
|
13
|
+
}
|
|
14
|
+
export interface StrategyDslTierPayload {
|
|
15
|
+
triggerPct: number;
|
|
16
|
+
lockHwPct: number;
|
|
17
|
+
triggerPrice: number;
|
|
18
|
+
reached: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface StrategyDslPayload {
|
|
21
|
+
asset: string;
|
|
22
|
+
dex: string;
|
|
23
|
+
direction: "LONG" | "SHORT";
|
|
24
|
+
entryPrice: number;
|
|
25
|
+
leverage: number;
|
|
26
|
+
phase: 1 | 2;
|
|
27
|
+
firstStopLoss: number;
|
|
28
|
+
lastPrice: number;
|
|
29
|
+
lastPriceAt: number | null;
|
|
30
|
+
floorPrice: number;
|
|
31
|
+
currentTierIndex: number | null;
|
|
32
|
+
tierSince: number | null;
|
|
33
|
+
tiers: StrategyDslTierPayload[];
|
|
34
|
+
}
|
|
35
|
+
export interface StrategyPayload {
|
|
36
|
+
address: string;
|
|
37
|
+
name: string;
|
|
38
|
+
scanners: StrategyScannerPayload[];
|
|
39
|
+
dsl: StrategyDslPayload[];
|
|
40
|
+
}
|
|
41
|
+
export interface StrategiesPayload {
|
|
42
|
+
v: 1;
|
|
43
|
+
epoch: string;
|
|
44
|
+
generatedAt: number;
|
|
45
|
+
strategies: StrategyPayload[];
|
|
46
|
+
}
|
|
47
|
+
/** Liveness of one external scanner, epoch ms, or `null` when nothing was heard since the child (re)started. */
|
|
48
|
+
export type LastAliveAtFn = (runtimeId: string, scannerName: string) => number | null;
|
|
49
|
+
/** Active DSL states of one runtime, read from memory. `[]` when the runtime has no handle or no DSL. */
|
|
50
|
+
export type DslStatesFn = (runtimeId: string) => readonly DslState[];
|
|
51
|
+
export type StrategiesBroadcastFn = (event: string, payload: unknown, opts?: {
|
|
52
|
+
dropIfSlow?: boolean;
|
|
53
|
+
}) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Builds the payload from the store and the DSL states. Copies only the payload fields from each
|
|
56
|
+
* DSL state. A runtime's state manager loads every address directory under its state directory.
|
|
57
|
+
* Only DSL states with a string `address` equal to the strategy wallet are kept.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildStrategiesPayload(input: {
|
|
60
|
+
epoch: string;
|
|
61
|
+
generatedAt: number;
|
|
62
|
+
store: ReadonlyMap<string, StrategyRecord>;
|
|
63
|
+
lastAliveAt: LastAliveAtFn;
|
|
64
|
+
dslStates: DslStatesFn;
|
|
65
|
+
/** Called with the runtime id when reading or copying that runtime's DSL states throws. */
|
|
66
|
+
onDslError?: (runtimeId: string, err: unknown) => void;
|
|
67
|
+
}): StrategiesPayload;
|
|
68
|
+
export interface StrategiesPublisher {
|
|
69
|
+
/** Ticks once, then every interval. A second call while running does nothing. */
|
|
70
|
+
start(): void;
|
|
71
|
+
/** Stops the ticks and resets the last payload to `strategies: []`. */
|
|
72
|
+
stop(): void;
|
|
73
|
+
/** The payload of the last tick. Before the first tick and after stop: `strategies: []`. */
|
|
74
|
+
lastPayload(): StrategiesPayload;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Each tick builds the payload from the store, the liveness reader and the DSL state reader, keeps
|
|
78
|
+
* it as the last payload, and broadcasts it when a broadcast function is available. The loop reads
|
|
79
|
+
* the store and never writes it.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createStrategiesPublisher(deps: {
|
|
82
|
+
store: ReadonlyMap<string, StrategyRecord>;
|
|
83
|
+
lastAliveAt: LastAliveAtFn;
|
|
84
|
+
dslStates: DslStatesFn;
|
|
85
|
+
getBroadcast: () => StrategiesBroadcastFn | undefined;
|
|
86
|
+
onError?: (err: unknown) => void;
|
|
87
|
+
onDslError?: (runtimeId: string, err: unknown) => void;
|
|
88
|
+
epoch?: string;
|
|
89
|
+
now?: () => number;
|
|
90
|
+
}): StrategiesPublisher;
|
|
91
|
+
//# sourceMappingURL=strategies-telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies-telemetry.d.ts","sourceRoot":"","sources":["../../src/runtime/strategies-telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategies telemetry: the payload built from the strategies store, and the loop that broadcasts
|
|
3
|
+
* that payload as `plugin.senpi.strategies`.
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { STRATEGIES_EVENT_NAME, STRATEGIES_PUBLISH_INTERVAL_MS } from "../constants/telemetry.js";
|
|
7
|
+
/** Minted once per plugin process. `plugin.senpi.events` carries the same value. */
|
|
8
|
+
export const PROCESS_EPOCH = randomUUID();
|
|
9
|
+
function normalizeAddress(address) {
|
|
10
|
+
return address.trim().toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
/** Epoch ms of an ISO string, or `null` when it does not parse. */
|
|
13
|
+
function epochMsOrNull(iso) {
|
|
14
|
+
const ms = Date.parse(iso);
|
|
15
|
+
return Number.isNaN(ms) ? null : ms;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Copies the payload fields of one DSL state into new objects.
|
|
19
|
+
*
|
|
20
|
+
* `triggerPrice` solves the move check of `tierIndexFromPrice` (`src/dsl/engine/floors.ts`) for
|
|
21
|
+
* equality: the price move from entry, times leverage, in percent, equals `triggerPct`. In floating
|
|
22
|
+
* point, `tierIndexFromPrice` at exactly `triggerPrice` can compute a move a few ulps below
|
|
23
|
+
* `triggerPct`.
|
|
24
|
+
*/
|
|
25
|
+
function dslPayloadFromState(state) {
|
|
26
|
+
const sign = state.direction === "LONG" ? 1 : -1;
|
|
27
|
+
const current = state.currentTierIndex;
|
|
28
|
+
return {
|
|
29
|
+
asset: state.asset,
|
|
30
|
+
dex: state.dex,
|
|
31
|
+
direction: state.direction,
|
|
32
|
+
entryPrice: state.entryPrice,
|
|
33
|
+
leverage: state.leverage,
|
|
34
|
+
phase: state.phase,
|
|
35
|
+
firstStopLoss: state.phase1.absoluteFloor,
|
|
36
|
+
lastPrice: state.lastPrice,
|
|
37
|
+
lastPriceAt: epochMsOrNull(state.lastCheck),
|
|
38
|
+
floorPrice: state.floorPrice,
|
|
39
|
+
currentTierIndex: current,
|
|
40
|
+
tierSince: state.tierSince === null ? null : epochMsOrNull(state.tierSince),
|
|
41
|
+
tiers: state.tiers.map((tier, i) => ({
|
|
42
|
+
triggerPct: tier.triggerPct,
|
|
43
|
+
lockHwPct: tier.lockHwPct,
|
|
44
|
+
triggerPrice: state.entryPrice * (1 + (sign * tier.triggerPct) / 100 / state.leverage),
|
|
45
|
+
reached: current !== null && i <= current,
|
|
46
|
+
})),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Builds the payload from the store and the DSL states. Copies only the payload fields from each
|
|
51
|
+
* DSL state. A runtime's state manager loads every address directory under its state directory.
|
|
52
|
+
* Only DSL states with a string `address` equal to the strategy wallet are kept.
|
|
53
|
+
*/
|
|
54
|
+
export function buildStrategiesPayload(input) {
|
|
55
|
+
const strategies = [];
|
|
56
|
+
// A throw while reading or copying one runtime's DSL states gives that strategy `dsl: []`.
|
|
57
|
+
const dslRows = (runtimeId, address) => {
|
|
58
|
+
try {
|
|
59
|
+
return input
|
|
60
|
+
.dslStates(runtimeId)
|
|
61
|
+
.filter((state) => typeof state.address === "string" && normalizeAddress(state.address) === address)
|
|
62
|
+
.map(dslPayloadFromState);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
input.onDslError?.(runtimeId, err);
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
for (const [runtimeId, record] of input.store) {
|
|
70
|
+
const address = normalizeAddress(record.address);
|
|
71
|
+
strategies.push({
|
|
72
|
+
address,
|
|
73
|
+
name: record.name,
|
|
74
|
+
scanners: record.scanners.map((scanner) => ({
|
|
75
|
+
scannerId: scanner.scannerId,
|
|
76
|
+
intervalSeconds: scanner.intervalSeconds,
|
|
77
|
+
lastAliveAt: input.lastAliveAt(runtimeId, scanner.scannerId),
|
|
78
|
+
})),
|
|
79
|
+
dsl: dslRows(runtimeId, address),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return { v: 1, epoch: input.epoch, generatedAt: input.generatedAt, strategies };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Each tick builds the payload from the store, the liveness reader and the DSL state reader, keeps
|
|
86
|
+
* it as the last payload, and broadcasts it when a broadcast function is available. The loop reads
|
|
87
|
+
* the store and never writes it.
|
|
88
|
+
*/
|
|
89
|
+
export function createStrategiesPublisher(deps) {
|
|
90
|
+
const epoch = deps.epoch ?? PROCESS_EPOCH;
|
|
91
|
+
const now = deps.now ?? Date.now;
|
|
92
|
+
const empty = () => ({ v: 1, epoch, generatedAt: now(), strategies: [] });
|
|
93
|
+
let last = empty();
|
|
94
|
+
let timer;
|
|
95
|
+
const tick = () => {
|
|
96
|
+
try {
|
|
97
|
+
last = buildStrategiesPayload({
|
|
98
|
+
epoch,
|
|
99
|
+
generatedAt: now(),
|
|
100
|
+
store: deps.store,
|
|
101
|
+
lastAliveAt: deps.lastAliveAt,
|
|
102
|
+
dslStates: deps.dslStates,
|
|
103
|
+
onDslError: deps.onDslError,
|
|
104
|
+
});
|
|
105
|
+
deps.getBroadcast()?.(STRATEGIES_EVENT_NAME, last, { dropIfSlow: true });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
deps.onError?.(err);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
start() {
|
|
113
|
+
if (timer !== undefined)
|
|
114
|
+
return;
|
|
115
|
+
tick();
|
|
116
|
+
timer = setInterval(tick, STRATEGIES_PUBLISH_INTERVAL_MS);
|
|
117
|
+
timer.unref?.();
|
|
118
|
+
},
|
|
119
|
+
stop() {
|
|
120
|
+
if (timer !== undefined)
|
|
121
|
+
clearInterval(timer);
|
|
122
|
+
timer = undefined;
|
|
123
|
+
last = empty();
|
|
124
|
+
},
|
|
125
|
+
lastPayload: () => last,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=strategies-telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies-telemetry.js","sourceRoot":"","sources":["../../src/runtime/strategies-telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Seed of the Theme-4 strategy lifecycle state machine (running→paused→stopped). The self-pause
|
|
3
|
+
* state is in memory; the halt latches are persisted (below). Short-term (§4); the durable
|
|
4
|
+
* crash-safe (SQLite) version is §5 merge work.
|
|
4
5
|
*
|
|
5
6
|
* Owns the self-pause state that RiskGuard used to hold. RiskGuard is now a stateless
|
|
6
7
|
* gate evaluator that only reports; this component remembers which gates are currently
|
|
7
8
|
* paused per strategy and fires the hook event + user notification on a genuine
|
|
8
9
|
* running→paused transition, deduped so it alerts once per breach and re-arms only on
|
|
9
10
|
* an explicit OPEN (re-running) of the same gate.
|
|
11
|
+
*
|
|
12
|
+
* It also owns the halt LATCH for the halt-class gates in {@link LATCHED_GATES}
|
|
13
|
+
* (daily loss, drawdown). Their live inputs are mark-to-market, so a strategy sitting
|
|
14
|
+
* near its limit reads breached / not-breached on every price bounce; without a latch
|
|
15
|
+
* each bounce reopened entries mid-day. {@link StrategyLifecycle.applyLatch} is called by
|
|
16
|
+
* the risk guard on every evaluation of those gates and overrides a fresh OPEN with
|
|
17
|
+
* CLOSED until the latch's release rule fires:
|
|
18
|
+
* - daily_loss_halt: the next UTC day (day taken from the MCP snapshot, not the box clock);
|
|
19
|
+
* - drawdown_halt: the next UTC day only when `drawdown_reset_on_day_rollover` is true;
|
|
20
|
+
* otherwise never.
|
|
21
|
+
* A latch for a gate that is no longer configured is dropped when the recipe is rebuilt
|
|
22
|
+
* ({@link StrategyLifecycle.pruneLatches}), so re-adding the rail later starts clean.
|
|
23
|
+
*
|
|
24
|
+
* Latches are persisted per strategy through {@link StrategyLifecycleDeps.latchStore} (the
|
|
25
|
+
* runtime's StateManager, file `<stateDir>/<address>/risk-halt-latch.json`), so a latch survives
|
|
26
|
+
* a gateway restart, an npm auto-update and a fleet redeploy: the restarted runtime reloads it on
|
|
27
|
+
* the strategy's first halt check and enforces it exactly as before, with the same release rules.
|
|
28
|
+
* The self-pause state above is still in memory only, so a restored latch announces its pause
|
|
29
|
+
* once more after a restart.
|
|
10
30
|
*/
|
|
11
31
|
import type { RiskGateEvaluation, RiskGateId, RiskSource } from "../health/types.js";
|
|
12
32
|
import type { HookSystem } from "../types/hooks.js";
|
|
@@ -43,6 +63,62 @@ export interface StrategyLifecycleDeps {
|
|
|
43
63
|
notifications?: NotificationService;
|
|
44
64
|
/** Runtime name attached to fired hook events (defaults to "runtime"). */
|
|
45
65
|
runtimeName?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Durable home for the halt latches (the runtime passes its StateManager). Without it the
|
|
68
|
+
* latches live in memory only and a gateway restart forgets them, which is the behaviour tests
|
|
69
|
+
* and the stub path get.
|
|
70
|
+
*/
|
|
71
|
+
latchStore?: HaltLatchStore;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The slice of StateManager the halt latch persists through. Typed structurally so a test can
|
|
75
|
+
* hand in a fake; StateManager satisfies it as-is.
|
|
76
|
+
*
|
|
77
|
+
* Contract relied on: `getOrLoad` resolves undefined when nothing is stored (StateManager also
|
|
78
|
+
* resolves undefined for a corrupt file, which it tombstones and warns about) and REJECTS on a
|
|
79
|
+
* transient IO error; `set` persists durably or rejects.
|
|
80
|
+
*/
|
|
81
|
+
export interface HaltLatchStore {
|
|
82
|
+
getOrLoad(key: string): Promise<unknown>;
|
|
83
|
+
set(key: string, value: unknown): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* State key of a strategy's persisted halt latches. StateManager maps it to
|
|
87
|
+
* `<stateDir>/<address>/risk-halt-latch.json`: inside the strategy's own dir, so it is archived
|
|
88
|
+
* with the strategy, and not `strategy` / `dsl-*`, so hydrate and the DSL listings ignore it.
|
|
89
|
+
*/
|
|
90
|
+
export declare function haltLatchKey(address: string): string;
|
|
91
|
+
/** Schema version of the persisted latch file; any other version is read as "no latch". */
|
|
92
|
+
export declare const HALT_LATCH_STATE_VERSION = 1;
|
|
93
|
+
/**
|
|
94
|
+
* Halt-class gates whose genuine breach latches until its release rule fires, instead of
|
|
95
|
+
* reopening on the next non-breached reading. `max_entries_day` is deliberately absent:
|
|
96
|
+
* its mid-day reopen is tracked separately and keeps the pre-latch behaviour here.
|
|
97
|
+
*/
|
|
98
|
+
export declare const LATCHED_GATES: ReadonlySet<RiskGateId>;
|
|
99
|
+
export interface ApplyLatchOpts {
|
|
100
|
+
/**
|
|
101
|
+
* Release the latch when an evaluation from a later UTC day arrives. Always true for
|
|
102
|
+
* daily_loss_halt; `drawdown_reset_on_day_rollover` for drawdown_halt.
|
|
103
|
+
*/
|
|
104
|
+
releaseOnDayRollover: boolean;
|
|
105
|
+
}
|
|
106
|
+
/** What a latch remembers about the breach that set it. Also its persisted per-gate shape. */
|
|
107
|
+
export interface HaltLatch {
|
|
108
|
+
/** UTC day (YYYY-MM-DD) of the snapshot that tripped the gate. */
|
|
109
|
+
utcDay: string;
|
|
110
|
+
/** Wall-clock ISO time the latch was set. */
|
|
111
|
+
latchedAt: string;
|
|
112
|
+
/** The breaching evaluation's own reason (live numbers at trip time). */
|
|
113
|
+
trippedReason: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* On-disk shape of one strategy's halt latches. An address with nothing latched is written as
|
|
117
|
+
* `{ version: 1, gates: {} }` rather than deleted, so "cleared" is a durable fact too.
|
|
118
|
+
*/
|
|
119
|
+
export interface PersistedHaltLatches {
|
|
120
|
+
version: typeof HALT_LATCH_STATE_VERSION;
|
|
121
|
+
gates: Partial<Record<RiskGateId, HaltLatch>>;
|
|
46
122
|
}
|
|
47
123
|
export interface StrategyLifecycle {
|
|
48
124
|
/**
|
|
@@ -53,6 +129,36 @@ export interface StrategyLifecycle {
|
|
|
53
129
|
* @param source evaluation source (runtime / cli)
|
|
54
130
|
*/
|
|
55
131
|
observe(address: string, label: string, evaluations: RiskGateEvaluation[], source: RiskSource): void;
|
|
132
|
+
/**
|
|
133
|
+
* Apply the halt latch to one fresh evaluation of a {@link LATCHED_GATES} gate and return
|
|
134
|
+
* the evaluation to enforce (other gates pass through untouched).
|
|
135
|
+
*
|
|
136
|
+
* - A genuine breach (CLOSED + evaluationOk + no fallback) sets the latch if none is held.
|
|
137
|
+
* Fail-closed / fallback evaluations never set it.
|
|
138
|
+
* - While latched, a fresh OPEN is overridden to CLOSED with a latched reason and
|
|
139
|
+
* `evaluationOk: true` — the evaluation itself succeeded; the gate is closed by the latch.
|
|
140
|
+
* - The latch is released only by a successful evaluation from a later UTC day, and only
|
|
141
|
+
* when `opts.releaseOnDayRollover` is true. The fresh evaluation is then enforced as-is.
|
|
142
|
+
*
|
|
143
|
+
* Async because of persistence: the strategy's persisted latches are loaded on its first call,
|
|
144
|
+
* and a set or release is written before the verdict returns. It cannot throw.
|
|
145
|
+
* - A failed load fails closed for that call: CLOSED with `evaluationOk: false`,
|
|
146
|
+
* `fallbackApplied: true`, `failureKind: "transport"`, like a failed snapshot fetch. A latch on
|
|
147
|
+
* disk this process has not read must not read as OPEN. Nothing is set or released on that
|
|
148
|
+
* call, so no pause fires; the next call retries the load.
|
|
149
|
+
* - A failed write is logged and never changes the verdict: the in-memory latch keeps enforcing.
|
|
150
|
+
*/
|
|
151
|
+
applyLatch(address: string, evaluation: RiskGateEvaluation, opts: ApplyLatchOpts): Promise<RiskGateEvaluation>;
|
|
152
|
+
/**
|
|
153
|
+
* Drop the latches (and the matching pause state) of latched gates that are no longer
|
|
154
|
+
* configured for `address`. Called when the recipe is rebuilt: a gate whose rail was removed
|
|
155
|
+
* no longer enforces anything, so its latch must not resurface if the rail is added back later.
|
|
156
|
+
* Emits `runtime.resumed` for a dropped gate that was paused.
|
|
157
|
+
*
|
|
158
|
+
* Loads the persisted latches first (so a latch saved by an earlier process is pruned too) and
|
|
159
|
+
* writes the result. Never throws: the rebuild commit that calls it must not fail on disk IO.
|
|
160
|
+
*/
|
|
161
|
+
pruneLatches(address: string, configured: ReadonlySet<RiskGateId>): Promise<void>;
|
|
56
162
|
}
|
|
57
163
|
export declare function createStrategyLifecycle(deps?: StrategyLifecycleDeps): StrategyLifecycle;
|
|
58
164
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strategy-lifecycle.d.ts","sourceRoot":"","sources":["../../src/runtime/strategy-lifecycle.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"strategy-lifecycle.d.ts","sourceRoot":"","sources":["../../src/runtime/strategy-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,gBAAgB,EAAuB,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAO3G;;;kEAGkE;AAClE,UAAU,SAAS;IACjB,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd;2DACuD;IACvD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAIrE,CAAC;AAkIF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EACnD,MAAM,EAAE,MAAM,GACb,gBAAgB,CAGlB;AAED,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,yEAAyE;IACzE,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,UAAU,CAGhD,CAAC;AAEH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,8FAA8F;AAC9F,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,aAAa,EAAE,MAAM,CAAC;CACvB;AAgBD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,wBAAwB,CAAC;IACzC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;CAC/C;AA6ED,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,kBAAkB,EAAE,EACjC,MAAM,EAAE,UAAU,GACjB,IAAI,CAAC;IAER;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,CACR,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,EAC9B,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE/B;;;;;;;;OAQG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,GAAE,qBAA0B,GAAG,iBAAiB,CAsQ3F"}
|