@raintree-technology/perps 0.1.0
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/CHANGELOG.md +33 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/adapters/aevo.d.ts +64 -0
- package/dist/adapters/aevo.js +899 -0
- package/dist/adapters/certification.d.ts +33 -0
- package/dist/adapters/certification.js +99 -0
- package/dist/adapters/decibel/order-manager.d.ts +45 -0
- package/dist/adapters/decibel/order-manager.js +140 -0
- package/dist/adapters/decibel/rest-client.d.ts +176 -0
- package/dist/adapters/decibel/rest-client.js +155 -0
- package/dist/adapters/decibel/ws-feed.d.ts +28 -0
- package/dist/adapters/decibel/ws-feed.js +166 -0
- package/dist/adapters/decibel.d.ts +108 -0
- package/dist/adapters/decibel.js +1377 -0
- package/dist/adapters/hyperliquid.d.ts +63 -0
- package/dist/adapters/hyperliquid.js +797 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/interface.d.ts +310 -0
- package/dist/adapters/interface.js +15 -0
- package/dist/adapters/orderly.d.ts +70 -0
- package/dist/adapters/orderly.js +936 -0
- package/dist/adapters/paradex.d.ts +69 -0
- package/dist/adapters/paradex.js +862 -0
- package/dist/adapters/utils.d.ts +17 -0
- package/dist/adapters/utils.js +122 -0
- package/dist/cli/command-metadata.d.ts +2 -0
- package/dist/cli/command-metadata.js +44 -0
- package/dist/cli/context.d.ts +14 -0
- package/dist/cli/context.js +59 -0
- package/dist/cli/experience.d.ts +48 -0
- package/dist/cli/experience.js +243 -0
- package/dist/cli/ink/app/AppShell.d.ts +12 -0
- package/dist/cli/ink/app/AppShell.js +32 -0
- package/dist/cli/ink/app/MetricStrip.d.ts +6 -0
- package/dist/cli/ink/app/MetricStrip.js +14 -0
- package/dist/cli/ink/app/Panel.d.ts +9 -0
- package/dist/cli/ink/app/Panel.js +7 -0
- package/dist/cli/ink/app/ascii.d.ts +2 -0
- package/dist/cli/ink/app/ascii.js +46 -0
- package/dist/cli/ink/app/index.d.ts +5 -0
- package/dist/cli/ink/app/index.js +4 -0
- package/dist/cli/ink/app/types.d.ts +15 -0
- package/dist/cli/ink/app/types.js +1 -0
- package/dist/cli/ink/components/PnL.d.ts +12 -0
- package/dist/cli/ink/components/PnL.js +23 -0
- package/dist/cli/ink/components/Spinner.d.ts +13 -0
- package/dist/cli/ink/components/Spinner.js +13 -0
- package/dist/cli/ink/components/Table.d.ts +14 -0
- package/dist/cli/ink/components/Table.js +42 -0
- package/dist/cli/ink/components/WatchHeader.d.ts +10 -0
- package/dist/cli/ink/components/WatchHeader.js +18 -0
- package/dist/cli/ink/components/index.d.ts +4 -0
- package/dist/cli/ink/components/index.js +4 -0
- package/dist/cli/ink/index.d.ts +4 -0
- package/dist/cli/ink/index.js +4 -0
- package/dist/cli/ink/render.d.ts +12 -0
- package/dist/cli/ink/render.js +21 -0
- package/dist/cli/ink/theme.d.ts +29 -0
- package/dist/cli/ink/theme.js +40 -0
- package/dist/cli/network-defaults.d.ts +10 -0
- package/dist/cli/network-defaults.js +35 -0
- package/dist/cli/output.d.ts +11 -0
- package/dist/cli/output.js +115 -0
- package/dist/cli/program.d.ts +18 -0
- package/dist/cli/program.js +164 -0
- package/dist/cli/watch.d.ts +19 -0
- package/dist/cli/watch.js +35 -0
- package/dist/client/index.d.ts +55 -0
- package/dist/client/index.js +157 -0
- package/dist/commands/account/add.d.ts +2 -0
- package/dist/commands/account/add.js +510 -0
- package/dist/commands/account/balances-simple.d.ts +5 -0
- package/dist/commands/account/balances-simple.js +63 -0
- package/dist/commands/account/index.d.ts +2 -0
- package/dist/commands/account/index.js +17 -0
- package/dist/commands/account/ls.d.ts +2 -0
- package/dist/commands/account/ls.js +95 -0
- package/dist/commands/account/positions-simple.d.ts +5 -0
- package/dist/commands/account/positions-simple.js +77 -0
- package/dist/commands/account/remove.d.ts +2 -0
- package/dist/commands/account/remove.js +47 -0
- package/dist/commands/account/set-default.d.ts +2 -0
- package/dist/commands/account/set-default.js +47 -0
- package/dist/commands/agent/index.d.ts +2 -0
- package/dist/commands/agent/index.js +126 -0
- package/dist/commands/arb/alert.d.ts +6 -0
- package/dist/commands/arb/alert.js +88 -0
- package/dist/commands/arb/basis-execute.d.ts +6 -0
- package/dist/commands/arb/basis-execute.js +332 -0
- package/dist/commands/arb/basis.d.ts +6 -0
- package/dist/commands/arb/basis.js +181 -0
- package/dist/commands/arb/compare.d.ts +6 -0
- package/dist/commands/arb/compare.js +216 -0
- package/dist/commands/arb/execute.d.ts +6 -0
- package/dist/commands/arb/execute.js +467 -0
- package/dist/commands/arb/funding.d.ts +6 -0
- package/dist/commands/arb/funding.js +201 -0
- package/dist/commands/arb/history.d.ts +6 -0
- package/dist/commands/arb/history.js +153 -0
- package/dist/commands/arb/index.d.ts +6 -0
- package/dist/commands/arb/index.js +29 -0
- package/dist/commands/arb/positions.d.ts +6 -0
- package/dist/commands/arb/positions.js +158 -0
- package/dist/commands/arb/spread.d.ts +6 -0
- package/dist/commands/arb/spread.js +253 -0
- package/dist/commands/arb/track.d.ts +6 -0
- package/dist/commands/arb/track.js +259 -0
- package/dist/commands/asset/book-simple.d.ts +5 -0
- package/dist/commands/asset/book-simple.js +77 -0
- package/dist/commands/asset/index.d.ts +2 -0
- package/dist/commands/asset/index.js +5 -0
- package/dist/commands/completion.d.ts +2 -0
- package/dist/commands/completion.js +161 -0
- package/dist/commands/config/index.d.ts +5 -0
- package/dist/commands/config/index.js +109 -0
- package/dist/commands/data/index.d.ts +31 -0
- package/dist/commands/data/index.js +1466 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +201 -0
- package/dist/commands/exchange/index.d.ts +2 -0
- package/dist/commands/exchange/index.js +107 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +48 -0
- package/dist/commands/markets/index.d.ts +2 -0
- package/dist/commands/markets/index.js +5 -0
- package/dist/commands/markets/ls-simple.d.ts +7 -0
- package/dist/commands/markets/ls-simple.js +277 -0
- package/dist/commands/operator/index.d.ts +2 -0
- package/dist/commands/operator/index.js +146 -0
- package/dist/commands/order/cancel-simple.d.ts +5 -0
- package/dist/commands/order/cancel-simple.js +104 -0
- package/dist/commands/order/index.d.ts +2 -0
- package/dist/commands/order/index.js +13 -0
- package/dist/commands/order/limit-simple.d.ts +5 -0
- package/dist/commands/order/limit-simple.js +195 -0
- package/dist/commands/order/market-simple.d.ts +5 -0
- package/dist/commands/order/market-simple.js +190 -0
- package/dist/commands/order/shared.d.ts +17 -0
- package/dist/commands/order/shared.js +51 -0
- package/dist/commands/order/trigger-simple.d.ts +5 -0
- package/dist/commands/order/trigger-simple.js +246 -0
- package/dist/commands/referral/index.d.ts +2 -0
- package/dist/commands/referral/index.js +7 -0
- package/dist/commands/referral/set.d.ts +2 -0
- package/dist/commands/referral/set.js +26 -0
- package/dist/commands/referral/status.d.ts +2 -0
- package/dist/commands/referral/status.js +31 -0
- package/dist/commands/replay/index.d.ts +2 -0
- package/dist/commands/replay/index.js +152 -0
- package/dist/commands/risk/analytics.d.ts +2 -0
- package/dist/commands/risk/analytics.js +64 -0
- package/dist/commands/risk/audit.d.ts +2 -0
- package/dist/commands/risk/audit.js +52 -0
- package/dist/commands/risk/index.d.ts +2 -0
- package/dist/commands/risk/index.js +9 -0
- package/dist/commands/risk/rules.d.ts +2 -0
- package/dist/commands/risk/rules.js +102 -0
- package/dist/commands/server.d.ts +2 -0
- package/dist/commands/server.js +208 -0
- package/dist/commands/setup/index.d.ts +2 -0
- package/dist/commands/setup/index.js +478 -0
- package/dist/commands/signal/index.d.ts +2 -0
- package/dist/commands/signal/index.js +129 -0
- package/dist/commands/state/index.d.ts +2 -0
- package/dist/commands/state/index.js +5 -0
- package/dist/commands/state/show.d.ts +2 -0
- package/dist/commands/state/show.js +105 -0
- package/dist/commands/strategy/index.d.ts +4 -0
- package/dist/commands/strategy/index.js +73 -0
- package/dist/commands/traces/index.d.ts +2 -0
- package/dist/commands/traces/index.js +76 -0
- package/dist/commands/ui/demo.d.ts +9 -0
- package/dist/commands/ui/demo.js +195 -0
- package/dist/commands/ui/index.d.ts +2 -0
- package/dist/commands/ui/index.js +7 -0
- package/dist/commands/ui/terminal.d.ts +2 -0
- package/dist/commands/ui/terminal.js +255 -0
- package/dist/commands/upgrade.d.ts +2 -0
- package/dist/commands/upgrade.js +98 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/lib/agent/audit.d.ts +12 -0
- package/dist/lib/agent/audit.js +13 -0
- package/dist/lib/agent/gateway.d.ts +13 -0
- package/dist/lib/agent/gateway.js +598 -0
- package/dist/lib/agent/metrics.d.ts +33 -0
- package/dist/lib/agent/metrics.js +175 -0
- package/dist/lib/agent/signature.d.ts +8 -0
- package/dist/lib/agent/signature.js +28 -0
- package/dist/lib/agent/tools.d.ts +28 -0
- package/dist/lib/agent/tools.js +453 -0
- package/dist/lib/agent/x402.d.ts +23 -0
- package/dist/lib/agent/x402.js +62 -0
- package/dist/lib/api-wallet.d.ts +69 -0
- package/dist/lib/api-wallet.js +101 -0
- package/dist/lib/balance-watcher.d.ts +25 -0
- package/dist/lib/balance-watcher.js +83 -0
- package/dist/lib/book-watcher.d.ts +25 -0
- package/dist/lib/book-watcher.js +48 -0
- package/dist/lib/config.d.ts +88 -0
- package/dist/lib/config.js +427 -0
- package/dist/lib/constants.d.ts +50 -0
- package/dist/lib/constants.js +84 -0
- package/dist/lib/contracts.d.ts +7 -0
- package/dist/lib/contracts.js +8 -0
- package/dist/lib/credential-vault.d.ts +22 -0
- package/dist/lib/credential-vault.js +109 -0
- package/dist/lib/db/accounts.d.ts +83 -0
- package/dist/lib/db/accounts.js +203 -0
- package/dist/lib/db/funding-history.d.ts +69 -0
- package/dist/lib/db/funding-history.js +183 -0
- package/dist/lib/db/index.d.ts +11 -0
- package/dist/lib/db/index.js +272 -0
- package/dist/lib/events/bus.d.ts +10 -0
- package/dist/lib/events/bus.js +17 -0
- package/dist/lib/events/types.d.ts +51 -0
- package/dist/lib/events/types.js +1 -0
- package/dist/lib/exchange.d.ts +30 -0
- package/dist/lib/exchange.js +84 -0
- package/dist/lib/execution/journal.d.ts +25 -0
- package/dist/lib/execution/journal.js +158 -0
- package/dist/lib/execution/safety.d.ts +34 -0
- package/dist/lib/execution/safety.js +197 -0
- package/dist/lib/exit-codes.d.ts +18 -0
- package/dist/lib/exit-codes.js +60 -0
- package/dist/lib/fetch.d.ts +18 -0
- package/dist/lib/fetch.js +66 -0
- package/dist/lib/fs-security.d.ts +10 -0
- package/dist/lib/fs-security.js +26 -0
- package/dist/lib/funding-tracker.d.ts +40 -0
- package/dist/lib/funding-tracker.js +118 -0
- package/dist/lib/logger.d.ts +27 -0
- package/dist/lib/logger.js +82 -0
- package/dist/lib/network-model.d.ts +13 -0
- package/dist/lib/network-model.js +30 -0
- package/dist/lib/onboarding.d.ts +133 -0
- package/dist/lib/onboarding.js +1459 -0
- package/dist/lib/operator-state.d.ts +25 -0
- package/dist/lib/operator-state.js +82 -0
- package/dist/lib/orders-watcher.d.ts +24 -0
- package/dist/lib/orders-watcher.js +74 -0
- package/dist/lib/paths.d.ts +20 -0
- package/dist/lib/paths.js +23 -0
- package/dist/lib/portfolio-watcher.d.ts +33 -0
- package/dist/lib/portfolio-watcher.js +95 -0
- package/dist/lib/position-watcher.d.ts +16 -0
- package/dist/lib/position-watcher.js +44 -0
- package/dist/lib/price-watcher.d.ts +15 -0
- package/dist/lib/price-watcher.js +84 -0
- package/dist/lib/prompts.d.ts +32 -0
- package/dist/lib/prompts.js +105 -0
- package/dist/lib/rate-limit.d.ts +32 -0
- package/dist/lib/rate-limit.js +88 -0
- package/dist/lib/risk/analytics.d.ts +39 -0
- package/dist/lib/risk/analytics.js +98 -0
- package/dist/lib/risk/drawdown.d.ts +18 -0
- package/dist/lib/risk/drawdown.js +49 -0
- package/dist/lib/risk/evaluation-log.d.ts +29 -0
- package/dist/lib/risk/evaluation-log.js +61 -0
- package/dist/lib/risk/index.d.ts +4 -0
- package/dist/lib/risk/index.js +4 -0
- package/dist/lib/risk/limits.d.ts +23 -0
- package/dist/lib/risk/limits.js +27 -0
- package/dist/lib/risk/manager.d.ts +32 -0
- package/dist/lib/risk/manager.js +85 -0
- package/dist/lib/risk/policy-middleware.d.ts +33 -0
- package/dist/lib/risk/policy-middleware.js +267 -0
- package/dist/lib/risk/position-sizer.d.ts +9 -0
- package/dist/lib/risk/position-sizer.js +14 -0
- package/dist/lib/risk/rules-store.d.ts +16 -0
- package/dist/lib/risk/rules-store.js +47 -0
- package/dist/lib/schema.d.ts +254 -0
- package/dist/lib/schema.js +199 -0
- package/dist/lib/secrets.d.ts +3 -0
- package/dist/lib/secrets.js +62 -0
- package/dist/lib/settings.d.ts +24 -0
- package/dist/lib/settings.js +86 -0
- package/dist/lib/signals.d.ts +73 -0
- package/dist/lib/signals.js +136 -0
- package/dist/lib/stable-stringify.d.ts +6 -0
- package/dist/lib/stable-stringify.js +17 -0
- package/dist/lib/state-context.d.ts +44 -0
- package/dist/lib/state-context.js +133 -0
- package/dist/lib/strategy/basis-trade.d.ts +2 -0
- package/dist/lib/strategy/basis-trade.js +24 -0
- package/dist/lib/strategy/funding-arb.d.ts +2 -0
- package/dist/lib/strategy/funding-arb.js +23 -0
- package/dist/lib/strategy/interface.d.ts +23 -0
- package/dist/lib/strategy/interface.js +1 -0
- package/dist/lib/strategy/registry.d.ts +4 -0
- package/dist/lib/strategy/registry.js +10 -0
- package/dist/lib/telemetry.d.ts +25 -0
- package/dist/lib/telemetry.js +101 -0
- package/dist/lib/trace-queries.d.ts +20 -0
- package/dist/lib/trace-queries.js +133 -0
- package/dist/lib/trace.d.ts +1 -0
- package/dist/lib/trace.js +4 -0
- package/dist/lib/trade-reputation.d.ts +6 -0
- package/dist/lib/trade-reputation.js +99 -0
- package/dist/lib/ui-tokens.d.ts +21 -0
- package/dist/lib/ui-tokens.js +26 -0
- package/dist/lib/validate.d.ts +39 -0
- package/dist/lib/validate.js +108 -0
- package/dist/lib/validation.d.ts +9 -0
- package/dist/lib/validation.js +64 -0
- package/dist/server/cache.d.ts +38 -0
- package/dist/server/cache.js +56 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +89 -0
- package/dist/server/ipc.d.ts +18 -0
- package/dist/server/ipc.js +159 -0
- package/dist/server/subscriptions.d.ts +18 -0
- package/dist/server/subscriptions.js +114 -0
- package/package.json +124 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Utilities
|
|
3
|
+
* Prevents API abuse and handles concurrent requests
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Simple semaphore for limiting concurrent operations
|
|
7
|
+
*/
|
|
8
|
+
export declare class Semaphore {
|
|
9
|
+
private permits;
|
|
10
|
+
private queue;
|
|
11
|
+
constructor(permits: number);
|
|
12
|
+
acquire(): Promise<void>;
|
|
13
|
+
release(): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Run promises with concurrency limit
|
|
17
|
+
*/
|
|
18
|
+
export declare function pLimit<T>(tasks: Array<() => Promise<T>>, concurrency?: number): Promise<Array<PromiseSettledResult<T>>>;
|
|
19
|
+
/**
|
|
20
|
+
* Run promises sequentially with delay between each
|
|
21
|
+
*/
|
|
22
|
+
export declare function pSequential<T>(tasks: Array<() => Promise<T>>, delayMs?: number): Promise<T[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Rate limiter with sliding window
|
|
25
|
+
*/
|
|
26
|
+
export declare class RateLimiter {
|
|
27
|
+
private timestamps;
|
|
28
|
+
private readonly maxRequests;
|
|
29
|
+
private readonly windowMs;
|
|
30
|
+
constructor(maxRequests: number, windowMs: number);
|
|
31
|
+
acquire(): Promise<void>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Utilities
|
|
3
|
+
* Prevents API abuse and handles concurrent requests
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Simple semaphore for limiting concurrent operations
|
|
7
|
+
*/
|
|
8
|
+
export class Semaphore {
|
|
9
|
+
permits;
|
|
10
|
+
queue = [];
|
|
11
|
+
constructor(permits) {
|
|
12
|
+
this.permits = permits;
|
|
13
|
+
}
|
|
14
|
+
async acquire() {
|
|
15
|
+
if (this.permits > 0) {
|
|
16
|
+
this.permits--;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return new Promise(resolve => {
|
|
20
|
+
this.queue.push(resolve);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
release() {
|
|
24
|
+
const next = this.queue.shift();
|
|
25
|
+
if (next) {
|
|
26
|
+
next();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.permits++;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Run promises with concurrency limit
|
|
35
|
+
*/
|
|
36
|
+
export async function pLimit(tasks, concurrency = 3) {
|
|
37
|
+
const semaphore = new Semaphore(concurrency);
|
|
38
|
+
const wrappedTasks = tasks.map(async (task) => {
|
|
39
|
+
await semaphore.acquire();
|
|
40
|
+
try {
|
|
41
|
+
return await task();
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
semaphore.release();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return Promise.allSettled(wrappedTasks);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run promises sequentially with delay between each
|
|
51
|
+
*/
|
|
52
|
+
export async function pSequential(tasks, delayMs = 100) {
|
|
53
|
+
const results = [];
|
|
54
|
+
for (const task of tasks) {
|
|
55
|
+
results.push(await task());
|
|
56
|
+
if (delayMs > 0) {
|
|
57
|
+
await sleep(delayMs);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Rate limiter with sliding window
|
|
64
|
+
*/
|
|
65
|
+
export class RateLimiter {
|
|
66
|
+
timestamps = [];
|
|
67
|
+
maxRequests;
|
|
68
|
+
windowMs;
|
|
69
|
+
constructor(maxRequests, windowMs) {
|
|
70
|
+
this.maxRequests = maxRequests;
|
|
71
|
+
this.windowMs = windowMs;
|
|
72
|
+
}
|
|
73
|
+
async acquire() {
|
|
74
|
+
while (true) {
|
|
75
|
+
const now = Date.now();
|
|
76
|
+
this.timestamps = this.timestamps.filter(t => now - t < this.windowMs);
|
|
77
|
+
if (this.timestamps.length < this.maxRequests) {
|
|
78
|
+
this.timestamps.push(now);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const waitTime = this.timestamps[0] + this.windowMs - now;
|
|
82
|
+
await sleep(Math.max(0, waitTime));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function sleep(ms) {
|
|
87
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
88
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface DenialSummary {
|
|
2
|
+
reason: string;
|
|
3
|
+
count: number;
|
|
4
|
+
lastSeen: number;
|
|
5
|
+
markets: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface EvalWindow {
|
|
8
|
+
total: number;
|
|
9
|
+
allowed: number;
|
|
10
|
+
denied: number;
|
|
11
|
+
denialRate: number;
|
|
12
|
+
windowStartMs: number;
|
|
13
|
+
windowEndMs: number;
|
|
14
|
+
}
|
|
15
|
+
export interface AnomalyAlert {
|
|
16
|
+
type: "high_denial_rate" | "repeated_denial" | "exposure_spike";
|
|
17
|
+
severity: "warning" | "critical";
|
|
18
|
+
message: string;
|
|
19
|
+
data: Record<string, unknown>;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get denials grouped by reason in the last N minutes.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getDenialsByReason(minutes?: number): DenialSummary[];
|
|
26
|
+
/**
|
|
27
|
+
* Get evaluation stats in sliding windows.
|
|
28
|
+
*
|
|
29
|
+
* Breaks the last `spanMinutes` into `windowMinutes`-sized buckets. For each
|
|
30
|
+
* bucket, counts total/allowed/denied and computes denial rate.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getEvalWindows(windowMinutes?: number, spanMinutes?: number): EvalWindow[];
|
|
33
|
+
/**
|
|
34
|
+
* Detect anomalies based on recent evaluation patterns.
|
|
35
|
+
*/
|
|
36
|
+
export declare function detectAnomalies(options?: {
|
|
37
|
+
denialRateThreshold?: number;
|
|
38
|
+
windowMinutes?: number;
|
|
39
|
+
}): AnomalyAlert[];
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { getDb } from "../db/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Get denials grouped by reason in the last N minutes.
|
|
4
|
+
*/
|
|
5
|
+
export function getDenialsByReason(minutes = 60) {
|
|
6
|
+
const db = getDb();
|
|
7
|
+
const cutoff = Date.now() - minutes * 60_000;
|
|
8
|
+
const rows = db
|
|
9
|
+
.prepare(`SELECT reason, COUNT(*) as count, MAX(created_at) as last_seen,
|
|
10
|
+
GROUP_CONCAT(DISTINCT market) as markets
|
|
11
|
+
FROM risk_evaluation_log
|
|
12
|
+
WHERE allowed = 0 AND created_at > ?
|
|
13
|
+
GROUP BY reason
|
|
14
|
+
ORDER BY count DESC`)
|
|
15
|
+
.all(cutoff);
|
|
16
|
+
return rows.map((r) => ({
|
|
17
|
+
reason: r.reason ?? "unknown",
|
|
18
|
+
count: r.count,
|
|
19
|
+
lastSeen: r.last_seen,
|
|
20
|
+
markets: r.markets ? r.markets.split(",").filter(Boolean) : [],
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get evaluation stats in sliding windows.
|
|
25
|
+
*
|
|
26
|
+
* Breaks the last `spanMinutes` into `windowMinutes`-sized buckets. For each
|
|
27
|
+
* bucket, counts total/allowed/denied and computes denial rate.
|
|
28
|
+
*/
|
|
29
|
+
export function getEvalWindows(windowMinutes = 5, spanMinutes = 60) {
|
|
30
|
+
const db = getDb();
|
|
31
|
+
const bucketMs = windowMinutes * 60_000;
|
|
32
|
+
const cutoff = Date.now() - spanMinutes * 60_000;
|
|
33
|
+
const rows = db
|
|
34
|
+
.prepare(`SELECT
|
|
35
|
+
(created_at / ?) * ? as bucket,
|
|
36
|
+
COUNT(*) as total,
|
|
37
|
+
SUM(CASE WHEN allowed = 1 THEN 1 ELSE 0 END) as allowed,
|
|
38
|
+
SUM(CASE WHEN allowed = 0 THEN 1 ELSE 0 END) as denied
|
|
39
|
+
FROM risk_evaluation_log
|
|
40
|
+
WHERE created_at > ?
|
|
41
|
+
GROUP BY bucket
|
|
42
|
+
ORDER BY bucket`)
|
|
43
|
+
.all(bucketMs, bucketMs, cutoff);
|
|
44
|
+
return rows.map((r) => ({
|
|
45
|
+
total: r.total,
|
|
46
|
+
allowed: r.allowed,
|
|
47
|
+
denied: r.denied,
|
|
48
|
+
denialRate: r.total > 0 ? r.denied / r.total : 0,
|
|
49
|
+
windowStartMs: r.bucket,
|
|
50
|
+
windowEndMs: r.bucket + bucketMs,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Detect anomalies based on recent evaluation patterns.
|
|
55
|
+
*/
|
|
56
|
+
export function detectAnomalies(options) {
|
|
57
|
+
const threshold = options?.denialRateThreshold ?? 0.5;
|
|
58
|
+
const windowMinutes = options?.windowMinutes ?? 5;
|
|
59
|
+
const alerts = [];
|
|
60
|
+
const now = Date.now();
|
|
61
|
+
// Check the most recent window for high denial rate
|
|
62
|
+
const windows = getEvalWindows(windowMinutes, windowMinutes);
|
|
63
|
+
if (windows.length > 0) {
|
|
64
|
+
const latest = windows[windows.length - 1];
|
|
65
|
+
if (latest.denialRate > threshold && latest.total > 3) {
|
|
66
|
+
alerts.push({
|
|
67
|
+
type: "high_denial_rate",
|
|
68
|
+
severity: latest.denialRate > 0.8 ? "critical" : "warning",
|
|
69
|
+
message: `Denial rate ${(latest.denialRate * 100).toFixed(0)}% (${latest.denied}/${latest.total}) in last ${windowMinutes} min`,
|
|
70
|
+
data: {
|
|
71
|
+
denialRate: latest.denialRate,
|
|
72
|
+
denied: latest.denied,
|
|
73
|
+
total: latest.total,
|
|
74
|
+
windowMinutes,
|
|
75
|
+
},
|
|
76
|
+
timestamp: now,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Check for repeated denials by reason
|
|
81
|
+
const denials = getDenialsByReason(windowMinutes);
|
|
82
|
+
for (const d of denials) {
|
|
83
|
+
if (d.count > 5) {
|
|
84
|
+
alerts.push({
|
|
85
|
+
type: "repeated_denial",
|
|
86
|
+
severity: d.count > 10 ? "critical" : "warning",
|
|
87
|
+
message: `"${d.reason}" denied ${d.count} times in last ${windowMinutes} min`,
|
|
88
|
+
data: {
|
|
89
|
+
reason: d.reason,
|
|
90
|
+
count: d.count,
|
|
91
|
+
markets: d.markets,
|
|
92
|
+
},
|
|
93
|
+
timestamp: now,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return alerts;
|
|
98
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface DrawdownState {
|
|
2
|
+
peakEquity: number;
|
|
3
|
+
halted: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare class DrawdownMonitor {
|
|
6
|
+
private peakEquity;
|
|
7
|
+
private readonly maxDrawdownPct;
|
|
8
|
+
private haltedState;
|
|
9
|
+
constructor(maxDrawdownPct: number, initialState?: Partial<DrawdownState>);
|
|
10
|
+
get halted(): boolean;
|
|
11
|
+
get peak(): number;
|
|
12
|
+
update(equity: number): {
|
|
13
|
+
drawdownPct: number;
|
|
14
|
+
halted: boolean;
|
|
15
|
+
peakEquity: number;
|
|
16
|
+
};
|
|
17
|
+
reset(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { eventBus } from "../events/bus.js";
|
|
2
|
+
import { createLogger } from "../logger.js";
|
|
3
|
+
const log = createLogger("risk:drawdown");
|
|
4
|
+
export class DrawdownMonitor {
|
|
5
|
+
peakEquity = 0;
|
|
6
|
+
maxDrawdownPct;
|
|
7
|
+
haltedState = false;
|
|
8
|
+
constructor(maxDrawdownPct, initialState) {
|
|
9
|
+
this.maxDrawdownPct = maxDrawdownPct;
|
|
10
|
+
this.peakEquity = initialState?.peakEquity ?? 0;
|
|
11
|
+
this.haltedState = initialState?.halted ?? false;
|
|
12
|
+
}
|
|
13
|
+
get halted() {
|
|
14
|
+
return this.haltedState;
|
|
15
|
+
}
|
|
16
|
+
get peak() {
|
|
17
|
+
return this.peakEquity;
|
|
18
|
+
}
|
|
19
|
+
update(equity) {
|
|
20
|
+
if (equity > this.peakEquity) {
|
|
21
|
+
this.peakEquity = equity;
|
|
22
|
+
}
|
|
23
|
+
const drawdownPct = this.peakEquity > 0
|
|
24
|
+
? ((this.peakEquity - equity) / this.peakEquity) * 100
|
|
25
|
+
: 0;
|
|
26
|
+
if (drawdownPct >= this.maxDrawdownPct && !this.haltedState) {
|
|
27
|
+
this.haltedState = true;
|
|
28
|
+
log.error("CIRCUIT BREAKER: max drawdown exceeded", {
|
|
29
|
+
drawdownPct: drawdownPct.toFixed(2),
|
|
30
|
+
maxAllowed: this.maxDrawdownPct,
|
|
31
|
+
equity,
|
|
32
|
+
peak: this.peakEquity,
|
|
33
|
+
});
|
|
34
|
+
eventBus.emit("risk.circuit_breaker.tripped", {
|
|
35
|
+
exchange: "",
|
|
36
|
+
drawdownPct,
|
|
37
|
+
peakEquity: this.peakEquity,
|
|
38
|
+
currentEquity: equity,
|
|
39
|
+
timestamp: Date.now(),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return { drawdownPct, halted: this.haltedState, peakEquity: this.peakEquity };
|
|
43
|
+
}
|
|
44
|
+
reset() {
|
|
45
|
+
this.haltedState = false;
|
|
46
|
+
this.peakEquity = 0;
|
|
47
|
+
log.info("Drawdown monitor reset");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface RiskEvaluationInput {
|
|
2
|
+
traceId?: string;
|
|
3
|
+
exchange: string;
|
|
4
|
+
market?: string;
|
|
5
|
+
side?: string;
|
|
6
|
+
requestedSizeUsd: number;
|
|
7
|
+
equity: number;
|
|
8
|
+
exposureUsd: number;
|
|
9
|
+
confidence?: number;
|
|
10
|
+
allowed: boolean;
|
|
11
|
+
adjustedSizeUsd?: number;
|
|
12
|
+
drawdownPct?: number;
|
|
13
|
+
rulesEvaluated: string[];
|
|
14
|
+
rulesFired: string[];
|
|
15
|
+
reason: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface RiskEvaluationRecord extends RiskEvaluationInput {
|
|
18
|
+
id: number;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RiskEvaluationQuery {
|
|
22
|
+
traceId?: string;
|
|
23
|
+
market?: string;
|
|
24
|
+
exchange?: string;
|
|
25
|
+
allowed?: boolean;
|
|
26
|
+
limit?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function logRiskEvaluation(input: RiskEvaluationInput): number;
|
|
29
|
+
export declare function queryRiskEvaluations(query?: RiskEvaluationQuery): RiskEvaluationRecord[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getDb } from "../db/index.js";
|
|
2
|
+
function rowToRecord(row) {
|
|
3
|
+
return {
|
|
4
|
+
id: row.id,
|
|
5
|
+
traceId: row.trace_id ?? undefined,
|
|
6
|
+
exchange: row.exchange,
|
|
7
|
+
market: row.market ?? undefined,
|
|
8
|
+
side: row.side ?? undefined,
|
|
9
|
+
requestedSizeUsd: row.requested_size_usd,
|
|
10
|
+
equity: row.equity,
|
|
11
|
+
exposureUsd: row.exposure_usd,
|
|
12
|
+
confidence: row.confidence ?? undefined,
|
|
13
|
+
allowed: row.allowed === 1,
|
|
14
|
+
adjustedSizeUsd: row.adjusted_size_usd ?? undefined,
|
|
15
|
+
drawdownPct: row.drawdown_pct ?? undefined,
|
|
16
|
+
rulesEvaluated: row.rules_evaluated
|
|
17
|
+
? JSON.parse(row.rules_evaluated)
|
|
18
|
+
: [],
|
|
19
|
+
rulesFired: row.rules_fired
|
|
20
|
+
? JSON.parse(row.rules_fired)
|
|
21
|
+
: [],
|
|
22
|
+
reason: row.reason,
|
|
23
|
+
createdAt: row.created_at,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function logRiskEvaluation(input) {
|
|
27
|
+
const db = getDb();
|
|
28
|
+
const stmt = db.prepare(`INSERT INTO risk_evaluation_log
|
|
29
|
+
(trace_id, exchange, market, side, requested_size_usd, equity, exposure_usd,
|
|
30
|
+
confidence, allowed, adjusted_size_usd, drawdown_pct, rules_evaluated, rules_fired, reason)
|
|
31
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
32
|
+
const result = stmt.run(input.traceId ?? null, input.exchange, input.market ?? null, input.side ?? null, input.requestedSizeUsd, input.equity, input.exposureUsd, input.confidence ?? null, input.allowed ? 1 : 0, input.adjustedSizeUsd ?? null, input.drawdownPct ?? null, JSON.stringify(input.rulesEvaluated), JSON.stringify(input.rulesFired), input.reason);
|
|
33
|
+
return Number(result.lastInsertRowid);
|
|
34
|
+
}
|
|
35
|
+
export function queryRiskEvaluations(query = {}) {
|
|
36
|
+
const db = getDb();
|
|
37
|
+
const conditions = [];
|
|
38
|
+
const params = [];
|
|
39
|
+
if (query.traceId !== undefined) {
|
|
40
|
+
conditions.push("trace_id = ?");
|
|
41
|
+
params.push(query.traceId);
|
|
42
|
+
}
|
|
43
|
+
if (query.market !== undefined) {
|
|
44
|
+
conditions.push("market = ?");
|
|
45
|
+
params.push(query.market);
|
|
46
|
+
}
|
|
47
|
+
if (query.exchange !== undefined) {
|
|
48
|
+
conditions.push("exchange = ?");
|
|
49
|
+
params.push(query.exchange);
|
|
50
|
+
}
|
|
51
|
+
if (query.allowed !== undefined) {
|
|
52
|
+
conditions.push("allowed = ?");
|
|
53
|
+
params.push(query.allowed ? 1 : 0);
|
|
54
|
+
}
|
|
55
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
56
|
+
const limit = query.limit ?? 100;
|
|
57
|
+
const rows = db
|
|
58
|
+
.prepare(`SELECT * FROM risk_evaluation_log ${where} ORDER BY created_at DESC LIMIT ?`)
|
|
59
|
+
.all(...params, limit);
|
|
60
|
+
return rows.map(rowToRecord);
|
|
61
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface RiskLimitsConfig {
|
|
2
|
+
maxPositionSizeUsd: number;
|
|
3
|
+
maxTotalExposureUsd: number;
|
|
4
|
+
maxLeverage: number;
|
|
5
|
+
minSignalConfidence: number;
|
|
6
|
+
}
|
|
7
|
+
export interface RiskSignal {
|
|
8
|
+
market: string;
|
|
9
|
+
side: "long" | "short" | "close";
|
|
10
|
+
confidence: number;
|
|
11
|
+
reason?: string;
|
|
12
|
+
timestamp?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RiskCheck {
|
|
15
|
+
allowed: boolean;
|
|
16
|
+
reason?: string;
|
|
17
|
+
adjustedSizeUsd?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class RiskLimits {
|
|
20
|
+
private readonly config;
|
|
21
|
+
constructor(config: RiskLimitsConfig);
|
|
22
|
+
check(signal: RiskSignal, proposedSizeUsd: number, currentExposureUsd: number, equity: number): RiskCheck;
|
|
23
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class RiskLimits {
|
|
2
|
+
config;
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.config = config;
|
|
5
|
+
}
|
|
6
|
+
check(signal, proposedSizeUsd, currentExposureUsd, equity) {
|
|
7
|
+
if (signal.confidence < this.config.minSignalConfidence) {
|
|
8
|
+
return {
|
|
9
|
+
allowed: false,
|
|
10
|
+
reason: `Confidence ${signal.confidence.toFixed(3)} below min ${this.config.minSignalConfidence}`,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (proposedSizeUsd > this.config.maxPositionSizeUsd) {
|
|
14
|
+
proposedSizeUsd = this.config.maxPositionSizeUsd;
|
|
15
|
+
}
|
|
16
|
+
const newTotalExposure = currentExposureUsd + proposedSizeUsd;
|
|
17
|
+
const maxExposure = Math.min(this.config.maxTotalExposureUsd, equity * this.config.maxLeverage);
|
|
18
|
+
if (newTotalExposure > maxExposure) {
|
|
19
|
+
const available = maxExposure - currentExposureUsd;
|
|
20
|
+
if (available <= 0) {
|
|
21
|
+
return { allowed: false, reason: "Max exposure reached" };
|
|
22
|
+
}
|
|
23
|
+
proposedSizeUsd = available;
|
|
24
|
+
}
|
|
25
|
+
return { allowed: true, adjustedSizeUsd: proposedSizeUsd };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type DrawdownState } from "./drawdown.js";
|
|
2
|
+
import { type RiskLimitsConfig, type RiskSignal } from "./limits.js";
|
|
3
|
+
import { type PositionSizerConfig } from "./position-sizer.js";
|
|
4
|
+
export interface RiskManagerConfig {
|
|
5
|
+
positionSizer: PositionSizerConfig;
|
|
6
|
+
limits: RiskLimitsConfig;
|
|
7
|
+
maxDrawdownPct: number;
|
|
8
|
+
initialDrawdownState?: Partial<DrawdownState>;
|
|
9
|
+
}
|
|
10
|
+
export interface RiskEvaluation {
|
|
11
|
+
allowed: boolean;
|
|
12
|
+
sizeUsd: number;
|
|
13
|
+
reason?: string;
|
|
14
|
+
drawdownPct: number;
|
|
15
|
+
peakEquity: number;
|
|
16
|
+
halted: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class RiskManager {
|
|
19
|
+
private readonly sizer;
|
|
20
|
+
private readonly drawdown;
|
|
21
|
+
private readonly limits;
|
|
22
|
+
constructor(config: RiskManagerConfig);
|
|
23
|
+
evaluate(signal: RiskSignal, equity: number, currentExposureUsd: number, proposedSizeUsd?: number): RiskEvaluation;
|
|
24
|
+
updateEquity(equity: number): {
|
|
25
|
+
drawdownPct: number;
|
|
26
|
+
halted: boolean;
|
|
27
|
+
peakEquity: number;
|
|
28
|
+
};
|
|
29
|
+
get isHalted(): boolean;
|
|
30
|
+
get drawdownState(): DrawdownState;
|
|
31
|
+
resetCircuitBreaker(): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createLogger } from "../logger.js";
|
|
2
|
+
import { DrawdownMonitor } from "./drawdown.js";
|
|
3
|
+
import { RiskLimits } from "./limits.js";
|
|
4
|
+
import { PositionSizer } from "./position-sizer.js";
|
|
5
|
+
const log = createLogger("risk:manager");
|
|
6
|
+
export class RiskManager {
|
|
7
|
+
sizer;
|
|
8
|
+
drawdown;
|
|
9
|
+
limits;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.sizer = new PositionSizer(config.positionSizer);
|
|
12
|
+
this.drawdown = new DrawdownMonitor(config.maxDrawdownPct, config.initialDrawdownState);
|
|
13
|
+
this.limits = new RiskLimits(config.limits);
|
|
14
|
+
}
|
|
15
|
+
evaluate(signal, equity, currentExposureUsd, proposedSizeUsd) {
|
|
16
|
+
const dd = this.drawdown.update(equity);
|
|
17
|
+
if (dd.halted) {
|
|
18
|
+
return {
|
|
19
|
+
allowed: false,
|
|
20
|
+
sizeUsd: 0,
|
|
21
|
+
reason: "Trading halted: max drawdown exceeded",
|
|
22
|
+
drawdownPct: dd.drawdownPct,
|
|
23
|
+
peakEquity: dd.peakEquity,
|
|
24
|
+
halted: dd.halted,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (signal.side === "close") {
|
|
28
|
+
return {
|
|
29
|
+
allowed: true,
|
|
30
|
+
sizeUsd: 0,
|
|
31
|
+
drawdownPct: dd.drawdownPct,
|
|
32
|
+
peakEquity: dd.peakEquity,
|
|
33
|
+
halted: dd.halted,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const sizedByPolicy = this.sizer.calculate(equity, signal.confidence, currentExposureUsd);
|
|
37
|
+
const effectiveProposed = proposedSizeUsd !== undefined
|
|
38
|
+
? Math.min(proposedSizeUsd, sizedByPolicy)
|
|
39
|
+
: sizedByPolicy;
|
|
40
|
+
if (effectiveProposed <= 0) {
|
|
41
|
+
return {
|
|
42
|
+
allowed: false,
|
|
43
|
+
sizeUsd: 0,
|
|
44
|
+
reason: "Position sizer returned 0",
|
|
45
|
+
drawdownPct: dd.drawdownPct,
|
|
46
|
+
peakEquity: dd.peakEquity,
|
|
47
|
+
halted: dd.halted,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const check = this.limits.check(signal, effectiveProposed, currentExposureUsd, equity);
|
|
51
|
+
if (!check.allowed) {
|
|
52
|
+
log.info("Risk rejected signal", { market: signal.market, reason: check.reason });
|
|
53
|
+
return {
|
|
54
|
+
allowed: false,
|
|
55
|
+
sizeUsd: 0,
|
|
56
|
+
reason: check.reason,
|
|
57
|
+
drawdownPct: dd.drawdownPct,
|
|
58
|
+
peakEquity: dd.peakEquity,
|
|
59
|
+
halted: dd.halted,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
allowed: true,
|
|
64
|
+
sizeUsd: check.adjustedSizeUsd ?? effectiveProposed,
|
|
65
|
+
drawdownPct: dd.drawdownPct,
|
|
66
|
+
peakEquity: dd.peakEquity,
|
|
67
|
+
halted: dd.halted,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
updateEquity(equity) {
|
|
71
|
+
return this.drawdown.update(equity);
|
|
72
|
+
}
|
|
73
|
+
get isHalted() {
|
|
74
|
+
return this.drawdown.halted;
|
|
75
|
+
}
|
|
76
|
+
get drawdownState() {
|
|
77
|
+
return {
|
|
78
|
+
peakEquity: this.drawdown.peak,
|
|
79
|
+
halted: this.drawdown.halted,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
resetCircuitBreaker() {
|
|
83
|
+
this.drawdown.reset();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { PerpDEXAdapter } from "../../adapters/interface.js";
|
|
2
|
+
import type { Config } from "../config.js";
|
|
3
|
+
import type { RiskSignal } from "./limits.js";
|
|
4
|
+
export interface RiskOrderInput {
|
|
5
|
+
market: string;
|
|
6
|
+
side: "long" | "short";
|
|
7
|
+
requestedSizeBase: number;
|
|
8
|
+
confidence?: number;
|
|
9
|
+
referencePriceUsd?: number;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RiskOrderDecision {
|
|
13
|
+
allowed: boolean;
|
|
14
|
+
adjustedSizeBase: number;
|
|
15
|
+
adjustedSizeUsd: number;
|
|
16
|
+
referencePriceUsd: number;
|
|
17
|
+
reason?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class RiskPolicyMiddleware {
|
|
20
|
+
private readonly config;
|
|
21
|
+
private readonly exchangeId;
|
|
22
|
+
private readonly manager;
|
|
23
|
+
constructor(config: Config, exchangeId: string);
|
|
24
|
+
evaluateUsdSignal(adapter: PerpDEXAdapter, signal: RiskSignal, proposedSizeUsd: number, traceId?: string): Promise<{
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
sizeUsd: number;
|
|
27
|
+
reason?: string;
|
|
28
|
+
}>;
|
|
29
|
+
evaluateOrder(adapter: PerpDEXAdapter, input: RiskOrderInput, traceId?: string): Promise<RiskOrderDecision>;
|
|
30
|
+
private resolveReferencePrice;
|
|
31
|
+
private loadAccountMetrics;
|
|
32
|
+
private recordHeartbeat;
|
|
33
|
+
}
|