@reefclaw/openclaw-plugin 0.1.5 → 0.1.6
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/ccxt/binance-private.d.ts +21 -0
- package/ccxt/binance-private.js +132 -22
- package/config/plugin-config-io.d.ts +6 -0
- package/config/tool-gate.js +3 -0
- package/exchange-adapter.d.ts +16 -0
- package/index.js +551 -54
- package/lifecycle/trading-operation-lock.d.ts +17 -0
- package/lifecycle/trading-operation-lock.js +14 -0
- package/live/bracket-id.d.ts +2 -3
- package/live/bracket-id.js +22 -9
- package/live/live-adapter.d.ts +24 -1
- package/live/live-adapter.js +114 -2
- package/live/local-signal-service.js +11 -6
- package/live/local-strategy-evaluator.js +4 -0
- package/live/proposal-decision-listener.d.ts +6 -0
- package/live/proposal-decision-listener.js +4 -0
- package/live/stop-watcher.d.ts +27 -1
- package/live/stop-watcher.js +59 -2
- package/onboarding/runtime.d.ts +13 -0
- package/onboarding/runtime.js +22 -2
- package/openclaw.plugin.json +1 -0
- package/package.json +1 -1
- package/portfolio/wave9-admission.d.ts +67 -0
- package/portfolio/wave9-admission.js +262 -0
- package/portfolio/wave9-policy.d.ts +36 -0
- package/portfolio/wave9-policy.js +183 -0
- package/signals/conditions/registry.js +50 -0
- package/simulator/exchange-simulator.js +5 -0
- package/simulator/fill-engine.js +5 -1
- package/simulator/types.d.ts +6 -1
- package/strategy/evaluator.d.ts +3 -0
- package/strategy/evaluator.js +5 -0
- package/tools/assessment-validation.d.ts +2 -0
- package/tools/attach-brackets.d.ts +7 -2
- package/tools/attach-brackets.js +36 -0
- package/tools/cancel-all-orders.d.ts +2 -0
- package/tools/cancel-all-orders.js +4 -1
- package/tools/cancel-order.d.ts +4 -0
- package/tools/cancel-order.js +49 -3
- package/tools/close-position.d.ts +23 -0
- package/tools/close-position.js +286 -13
- package/tools/create-order.d.ts +28 -0
- package/tools/create-order.js +1364 -192
- package/tools/get-analytics.js +2 -2
- package/tools/get-basis.js +2 -2
- package/tools/get-cascade-risk.js +2 -2
- package/tools/get-crypto-metrics.js +14 -4
- package/tools/get-cvd.js +2 -2
- package/tools/get-divergences.js +2 -2
- package/tools/get-funding-context.js +2 -2
- package/tools/get-liquidation-levels.js +2 -2
- package/tools/get-liquidation-pulse.js +2 -2
- package/tools/get-pattern-scan.js +2 -2
- package/tools/get-regime.js +2 -2
- package/tools/get-resting-liquidity.js +2 -2
- package/tools/get-risk-scenario.js +2 -2
- package/tools/get-session-review.js +2 -2
- package/tools/get-setup-detail.js +9 -1
- package/tools/get-signals.js +2 -2
- package/tools/get-sizing.js +2 -2
- package/tools/get-trade-feedback.js +2 -2
- package/tools/get-trade-flow.js +2 -2
- package/tools/get-volume-profile.js +2 -2
- package/tools/get-wave9-status.d.ts +127 -0
- package/tools/get-wave9-status.js +796 -0
- package/tools/intel-api.d.ts +20 -0
- package/tools/intel-api.js +67 -0
- package/tools/intel-cache.d.ts +1 -1
- package/tools/intel-cache.js +20 -5
- package/tools/list-strategies.d.ts +11 -1
- package/tools/list-strategies.js +17 -0
- package/tools/modify-stop.d.ts +4 -0
- package/tools/modify-stop.js +63 -24
- package/tools/modify-target.d.ts +4 -0
- package/tools/modify-target.js +62 -23
- package/tools/scan-pairs.js +19 -8
- package/tools/toggle-strategy.js +7 -0
- package/types.d.ts +5 -0
- package/venues/hyperliquid/hl-balance.d.ts +116 -0
- package/venues/hyperliquid/hl-balance.js +145 -0
- package/venues/hyperliquid/hl-brackets.d.ts +102 -0
- package/venues/hyperliquid/hl-brackets.js +172 -0
- package/venues/hyperliquid/hl-cloid.d.ts +22 -0
- package/venues/hyperliquid/hl-cloid.js +82 -0
- package/venues/hyperliquid/hl-info-cache.d.ts +46 -0
- package/venues/hyperliquid/hl-info-cache.js +125 -0
- package/venues/hyperliquid/hl-live-adapter.d.ts +88 -0
- package/venues/hyperliquid/hl-live-adapter.js +353 -0
- package/venues/hyperliquid/hl-precision.d.ts +61 -0
- package/venues/hyperliquid/hl-precision.js +176 -0
- package/venues/hyperliquid/hl-private.d.ts +88 -0
- package/venues/hyperliquid/hl-private.js +357 -0
- package/venues/hyperliquid/hl-public.d.ts +31 -4
- package/venues/hyperliquid/hl-public.js +155 -11
- package/venues/hyperliquid/hl-rate-gate.d.ts +57 -0
- package/venues/hyperliquid/hl-rate-gate.js +220 -0
- package/venues/hyperliquid/hl-user-stream.d.ts +90 -0
- package/venues/hyperliquid/hl-user-stream.js +220 -0
- package/venues/registry.d.ts +23 -9
- package/venues/registry.js +12 -13
- package/venues/symbols.d.ts +43 -0
- package/venues/symbols.js +107 -0
- package/wave9/live-account-capture.d.ts +67 -0
- package/wave9/live-account-capture.js +435 -0
- package/wave9/live-autonomous-protection.d.ts +39 -0
- package/wave9/live-autonomous-protection.js +112 -0
- package/wave9/live-durable-reconciliation-scheduler.d.ts +33 -0
- package/wave9/live-durable-reconciliation-scheduler.js +115 -0
- package/wave9/live-execution-ledger.d.ts +107 -0
- package/wave9/live-execution-ledger.js +498 -0
- package/wave9/live-position-confirmation.d.ts +18 -0
- package/wave9/live-position-confirmation.js +111 -0
- package/wave9/live-residual-protection.d.ts +18 -0
- package/wave9/live-residual-protection.js +250 -0
- package/wave9/live-startup-reconciliation.d.ts +38 -0
- package/wave9/live-startup-reconciliation.js +454 -0
- package/wave9/live-symbol-ownership.d.ts +20 -0
- package/wave9/live-symbol-ownership.js +132 -0
- package/wave9/paper-admission-guard.d.ts +199 -0
- package/wave9/paper-admission-guard.js +650 -0
- package/wave9/usdm-evidence-provider.d.ts +42 -0
- package/wave9/usdm-evidence-provider.js +133 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const DEFAULT_RETRY_DELAYS_MS = [1_000, 3_000, 10_000];
|
|
2
|
+
const DEFAULT_PERIODIC_MS = 60_000;
|
|
3
|
+
/**
|
|
4
|
+
* Source-bound READY/periodic driver for durable Wave 9 recovery. At most one
|
|
5
|
+
* timer and one lock-serialized pass exist for the active adapter. A replaced
|
|
6
|
+
* adapter is stopped synchronously and an in-flight old pass cannot reschedule
|
|
7
|
+
* itself. Timers are unref'ed so this safety loop never keeps Node alive.
|
|
8
|
+
*/
|
|
9
|
+
export class Wave9LiveDurableReconciliationScheduler {
|
|
10
|
+
options;
|
|
11
|
+
retryDelaysMs;
|
|
12
|
+
periodicMs;
|
|
13
|
+
active;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.retryDelaysMs = options.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS;
|
|
17
|
+
this.periodicMs = options.periodicMs ?? DEFAULT_PERIODIC_MS;
|
|
18
|
+
if (this.retryDelaysMs.some((delay) => !Number.isFinite(delay) || delay < 0)) {
|
|
19
|
+
throw new Error('Wave 9 reconciliation retry delays must be finite and non-negative');
|
|
20
|
+
}
|
|
21
|
+
if (!Number.isFinite(this.periodicMs) || this.periodicMs <= 0) {
|
|
22
|
+
throw new Error('Wave 9 reconciliation periodic interval must be positive and finite');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
attach(source) {
|
|
26
|
+
if (this.active?.source === source && !this.active.stopped)
|
|
27
|
+
return;
|
|
28
|
+
this.stop();
|
|
29
|
+
const state = { source, stopped: false };
|
|
30
|
+
this.active = state;
|
|
31
|
+
source.on('readiness_changed', (readiness) => {
|
|
32
|
+
// Runtime installs this listener immediately before it publishes a
|
|
33
|
+
// reconnect adapter. Queue first, then let the timer callback verify
|
|
34
|
+
// current source identity, so a synchronously-fast READY cannot be lost.
|
|
35
|
+
if (readiness === 'READY' && !state.stopped) {
|
|
36
|
+
this.schedule(state, 0, 0, 'ready');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (source.readiness === 'READY') {
|
|
40
|
+
this.schedule(state, 0, 0, 'ready_replay');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
stopIfSourceChanged(current) {
|
|
44
|
+
if (this.active && this.active.source !== current)
|
|
45
|
+
this.stop();
|
|
46
|
+
}
|
|
47
|
+
stop() {
|
|
48
|
+
const state = this.active;
|
|
49
|
+
if (!state)
|
|
50
|
+
return;
|
|
51
|
+
state.stopped = true;
|
|
52
|
+
if (state.timer !== undefined)
|
|
53
|
+
clearTimeout(state.timer);
|
|
54
|
+
state.timer = undefined;
|
|
55
|
+
this.active = undefined;
|
|
56
|
+
}
|
|
57
|
+
isCurrentReady(state) {
|
|
58
|
+
const source = state.source;
|
|
59
|
+
return !state.stopped
|
|
60
|
+
&& this.active === state
|
|
61
|
+
&& this.options.isCurrentSource(source)
|
|
62
|
+
&& source.isLive
|
|
63
|
+
&& source.mode === 'LIVE'
|
|
64
|
+
&& source.readiness === 'READY';
|
|
65
|
+
}
|
|
66
|
+
schedule(state, delayMs, retryIndex, trigger) {
|
|
67
|
+
if (state.stopped || this.active !== state || state.timer !== undefined || state.inFlight) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const timer = setTimeout(() => {
|
|
71
|
+
state.timer = undefined;
|
|
72
|
+
if (!this.isCurrentReady(state)) {
|
|
73
|
+
if (!this.options.isCurrentSource(state.source)) {
|
|
74
|
+
state.stopped = true;
|
|
75
|
+
if (this.active === state)
|
|
76
|
+
this.active = undefined;
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
let passResult;
|
|
81
|
+
let passFailed = false;
|
|
82
|
+
const pass = this.options.operationLock.withAccountLock(`wave9_live_durable_reconciliation:${trigger}`, async () => {
|
|
83
|
+
if (!this.isCurrentReady(state))
|
|
84
|
+
return;
|
|
85
|
+
passResult = await this.options.reconcile(state.source);
|
|
86
|
+
this.options.onResult?.(trigger, passResult);
|
|
87
|
+
}).catch((error) => {
|
|
88
|
+
passFailed = true;
|
|
89
|
+
this.options.onError?.(trigger, error);
|
|
90
|
+
}).finally(() => {
|
|
91
|
+
state.inFlight = undefined;
|
|
92
|
+
if (!this.isCurrentReady(state)) {
|
|
93
|
+
if (!this.options.isCurrentSource(state.source)) {
|
|
94
|
+
state.stopped = true;
|
|
95
|
+
if (this.active === state)
|
|
96
|
+
this.active = undefined;
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const retryable = passFailed || passResult?.retryable === true;
|
|
101
|
+
if (retryable && retryIndex < this.retryDelaysMs.length) {
|
|
102
|
+
this.schedule(state, this.retryDelaysMs[retryIndex], retryIndex + 1, `ready_retry_${retryIndex + 1}`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Always retain a periodic pass. It catches ATTEMPTED/OPEN rows born
|
|
106
|
+
// after READY when a live submit's exact CID read was transiently
|
|
107
|
+
// unknown, while healthy rows are a cheap exact-stop no-op.
|
|
108
|
+
this.schedule(state, this.periodicMs, 0, 'periodic');
|
|
109
|
+
});
|
|
110
|
+
state.inFlight = pass;
|
|
111
|
+
}, delayMs);
|
|
112
|
+
timer.unref();
|
|
113
|
+
state.timer = timer;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type Wave9StrategyName } from '../portfolio/wave9-policy.js';
|
|
2
|
+
export type Wave9LiveExecutionState = 'attempted' | 'open' | 'closed';
|
|
3
|
+
export type Wave9LiveDirection = 'LONG' | 'SHORT';
|
|
4
|
+
export type Wave9LiveOrderSide = 'buy' | 'sell';
|
|
5
|
+
export type Wave9LivePositionSide = 'long' | 'short';
|
|
6
|
+
export interface Wave9LiveExecutionRecord {
|
|
7
|
+
candidateId: string;
|
|
8
|
+
missionId: string;
|
|
9
|
+
eventTime: string;
|
|
10
|
+
/** Canonical frozen-universe form, e.g. BTCUSDT. */
|
|
11
|
+
symbol: string;
|
|
12
|
+
strategy: Wave9StrategyName;
|
|
13
|
+
direction: Wave9LiveDirection;
|
|
14
|
+
side: Wave9LiveOrderSide;
|
|
15
|
+
/** Exact quantity authorized for the market-order attempt. */
|
|
16
|
+
quantity: number;
|
|
17
|
+
initialStop: number;
|
|
18
|
+
/** Deterministic Binance-safe idempotency key. */
|
|
19
|
+
clientOrderId: string;
|
|
20
|
+
state: Wave9LiveExecutionState;
|
|
21
|
+
attemptedAt: number;
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
openedAt?: number;
|
|
24
|
+
closedAt?: number;
|
|
25
|
+
filledQuantity?: number;
|
|
26
|
+
entryPrice?: number;
|
|
27
|
+
exchangeOrderId?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface Wave9LiveAttemptInput {
|
|
30
|
+
candidateId: string;
|
|
31
|
+
missionId: string;
|
|
32
|
+
eventTime: string;
|
|
33
|
+
symbol: string;
|
|
34
|
+
strategy: Wave9StrategyName;
|
|
35
|
+
direction: Wave9LiveDirection;
|
|
36
|
+
side: Wave9LiveOrderSide;
|
|
37
|
+
quantity: number;
|
|
38
|
+
initialStop: number;
|
|
39
|
+
clientOrderId: string;
|
|
40
|
+
}
|
|
41
|
+
export interface Wave9LiveOpenInput {
|
|
42
|
+
filledQuantity?: number;
|
|
43
|
+
entryPrice?: number;
|
|
44
|
+
exchangeOrderId?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Final fill learned by resolving the exact deterministic entry CID. */
|
|
47
|
+
export interface Wave9LiveExactOrderFillInput {
|
|
48
|
+
filledQuantity: number;
|
|
49
|
+
exchangeOrderId: string;
|
|
50
|
+
entryPrice?: number;
|
|
51
|
+
}
|
|
52
|
+
export interface Wave9LiveExecutionLedgerOptions {
|
|
53
|
+
pluginId?: string;
|
|
54
|
+
basePath?: string;
|
|
55
|
+
now?: () => number;
|
|
56
|
+
}
|
|
57
|
+
/** Stable Binance-compatible client order id (35 chars; Binance max is 36). */
|
|
58
|
+
export declare function wave9ClientOrderId(candidateId: string): string;
|
|
59
|
+
/** Backwards-compatible descriptive alias. */
|
|
60
|
+
export declare const wave9LiveClientOrderId: typeof wave9ClientOrderId;
|
|
61
|
+
export declare class Wave9LiveExecutionLedger {
|
|
62
|
+
private readonly filePath;
|
|
63
|
+
private readonly dir;
|
|
64
|
+
private readonly now;
|
|
65
|
+
private readonly entries;
|
|
66
|
+
constructor(options?: Wave9LiveExecutionLedgerOptions);
|
|
67
|
+
/**
|
|
68
|
+
* Persist an execution attempt before exchange submission. Repeating the
|
|
69
|
+
* exact immutable authorization is idempotent; any mismatch fails closed.
|
|
70
|
+
*/
|
|
71
|
+
recordAttempt(input: Wave9LiveAttemptInput): Wave9LiveExecutionRecord;
|
|
72
|
+
/** Mark a confirmed fill. Repeating the exact confirmation is idempotent. */
|
|
73
|
+
markOpen(candidateId: string, input?: Wave9LiveOpenInput): Wave9LiveExecutionRecord;
|
|
74
|
+
/**
|
|
75
|
+
* Enrich an already-OPEN row after an exact deterministic entry lookup has
|
|
76
|
+
* proven the order terminal. This is deliberately narrower than markOpen:
|
|
77
|
+
* the final fill may populate a previously missing value or increase a
|
|
78
|
+
* crash-time partial fill, but it can never decrease, exceed authorization,
|
|
79
|
+
* or replace an already-bound exchange order identity.
|
|
80
|
+
*/
|
|
81
|
+
reconcileOpenFillFromExactOrder(candidateId: string, input: Wave9LiveExactOrderFillInput): Wave9LiveExecutionRecord;
|
|
82
|
+
/** Mark an attempted/open record terminal. Terminal rows are never deleted. */
|
|
83
|
+
markClosed(candidateId: string): Wave9LiveExecutionRecord;
|
|
84
|
+
getByCandidateId(candidateId: string): Wave9LiveExecutionRecord | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Latest confirmed-open row matching an exchange position.
|
|
87
|
+
*
|
|
88
|
+
* An `attempted` row is a durable replay tombstone: the exchange outcome
|
|
89
|
+
* may be ambiguous, so the candidate must never execute again, but the row
|
|
90
|
+
* is not proof that a later same-symbol/same-side position belongs to Wave 9.
|
|
91
|
+
* Only `markOpen()` establishes durable position ownership.
|
|
92
|
+
*/
|
|
93
|
+
findLatestForPosition(symbol: string, side: Wave9LivePositionSide | Wave9LiveOrderSide): Wave9LiveExecutionRecord | undefined;
|
|
94
|
+
/** Attempts count as executed because exchange outcome can be crash-ambiguous. */
|
|
95
|
+
getExecutedCandidateIds(): string[];
|
|
96
|
+
getAll(): Wave9LiveExecutionRecord[];
|
|
97
|
+
getFilePath(): string;
|
|
98
|
+
private currentTimestamp;
|
|
99
|
+
private requireCandidate;
|
|
100
|
+
private validateAttemptInput;
|
|
101
|
+
private validateOpenInput;
|
|
102
|
+
private sameAttempt;
|
|
103
|
+
private loadOrInit;
|
|
104
|
+
private persist;
|
|
105
|
+
private validateFile;
|
|
106
|
+
private validateStoredRecord;
|
|
107
|
+
}
|