perp-cli 0.9.8 → 0.12.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/README.md +30 -25
- package/dist/_stderr-filter.d.ts +0 -0
- package/dist/_stderr-filter.js +30 -0
- package/dist/agent-wallet/expiry.d.ts +15 -0
- package/dist/agent-wallet/expiry.js +26 -0
- package/dist/agent-wallet/lighter-keystore.d.ts +34 -0
- package/dist/agent-wallet/lighter-keystore.js +232 -0
- package/dist/agent-wallet/passphrase.d.ts +13 -0
- package/dist/agent-wallet/passphrase.js +54 -0
- package/dist/agent-wallet/signing-strategy.d.ts +67 -0
- package/dist/agent-wallet/signing-strategy.js +51 -0
- package/dist/agent-wallet/store.d.ts +37 -0
- package/dist/agent-wallet/store.js +172 -0
- package/dist/api/public/_http.d.ts +15 -0
- package/dist/api/public/_http.js +24 -0
- package/dist/api/public/hyperliquid.js +36 -24
- package/dist/api/public/lighter.d.ts +7 -1
- package/dist/api/public/lighter.js +85 -37
- package/dist/api/public/pacifica.js +47 -18
- package/dist/bot/engine.js +23 -4
- package/dist/bot/presets.js +3 -3
- package/dist/bot/strategies/funding-arb-strategy.d.ts +0 -23
- package/dist/bot/strategies/funding-arb-strategy.js +41 -176
- package/dist/bot/strategies/funding-auto.js +2 -2
- package/dist/bridge-engine.js +102 -49
- package/dist/cli-spec.js +1 -2
- package/dist/commands/account.js +2 -500
- package/dist/commands/agent.d.ts +8 -2
- package/dist/commands/agent.js +1903 -366
- package/dist/commands/alerts.js +3 -1
- package/dist/commands/arb/index.js +37 -7
- package/dist/commands/arb-auto.js +44 -11
- package/dist/commands/arb.js +83 -34
- package/dist/commands/bot.d.ts +1 -1
- package/dist/commands/bot.js +20 -16
- package/dist/commands/bridge.d.ts +1 -1
- package/dist/commands/bridge.js +4 -4
- package/dist/commands/funds.d.ts +1 -1
- package/dist/commands/funds.js +18 -68
- package/dist/commands/jobs.d.ts +1 -1
- package/dist/commands/jobs.js +2 -2
- package/dist/commands/manage.d.ts +1 -1
- package/dist/commands/manage.js +12 -84
- package/dist/commands/plan.d.ts +1 -1
- package/dist/commands/plan.js +2 -2
- package/dist/commands/portfolio.d.ts +19 -3
- package/dist/commands/portfolio.js +747 -163
- package/dist/commands/rebalance.d.ts +1 -1
- package/dist/commands/rebalance.js +18 -12
- package/dist/commands/risk.js +2 -6
- package/dist/commands/settings.js +30 -53
- package/dist/commands/trade.js +16 -15
- package/dist/commands/wallet.d.ts +2 -1
- package/dist/commands/wallet.js +1122 -176
- package/dist/config.d.ts +9 -0
- package/dist/config.js +55 -9
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +82 -2
- package/dist/event-stream.js +12 -1
- package/dist/exchanges/aster-typed-data.d.ts +156 -0
- package/dist/exchanges/aster-typed-data.js +189 -0
- package/dist/exchanges/aster.d.ts +60 -11
- package/dist/exchanges/aster.js +278 -136
- package/dist/exchanges/hyperliquid.d.ts +14 -0
- package/dist/exchanges/hyperliquid.js +88 -34
- package/dist/exchanges/lighter-spot.js +19 -5
- package/dist/exchanges/lighter.d.ts +66 -0
- package/dist/exchanges/lighter.js +213 -31
- package/dist/exchanges/pacifica-typed-data.d.ts +75 -0
- package/dist/exchanges/pacifica-typed-data.js +74 -0
- package/dist/exchanges/pacifica.d.ts +29 -1
- package/dist/exchanges/pacifica.js +94 -6
- package/dist/funding/rates.js +59 -21
- package/dist/guardrail/contracts.d.ts +14 -0
- package/dist/guardrail/contracts.js +72 -0
- package/dist/guardrail/perp-guardrail.d.ts +21 -0
- package/dist/guardrail/perp-guardrail.js +145 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +307 -362
- package/dist/jobs.js +3 -1
- package/dist/mcp-server.js +92 -88
- package/dist/position-history.js +47 -4
- package/dist/settings.d.ts +69 -3
- package/dist/settings.js +3 -2
- package/dist/signer/index.d.ts +2 -0
- package/dist/signer/index.js +2 -0
- package/dist/signer/ows-evm.d.ts +32 -0
- package/dist/signer/ows-evm.js +86 -0
- package/dist/signer/ows-loader.d.ts +2 -0
- package/dist/signer/ows-loader.js +6 -0
- package/dist/signer/ows-solana.d.ts +25 -0
- package/dist/signer/ows-solana.js +56 -0
- package/dist/smart-order.d.ts +8 -2
- package/dist/smart-order.js +46 -11
- package/dist/strategies/funding-arb.js +29 -8
- package/dist/trade-validator.js +30 -5
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +19 -0
- package/package.json +4 -2
- package/skills/perp-cli/SKILL.md +23 -14
- package/skills/perp-cli/references/agent-operations.md +6 -4
- package/skills/perp-cli/references/commands.md +55 -34
- package/skills/perp-cli/scripts/preflight.sh +4 -4
- package/skills/perp-cli/scripts/spot-perp-scan.sh +2 -2
- package/dist/__tests__/alert-logic.test.d.ts +0 -1
- package/dist/__tests__/alert-logic.test.js +0 -107
- package/dist/__tests__/arb-auto-3dex.test.d.ts +0 -1
- package/dist/__tests__/arb-auto-3dex.test.js +0 -397
- package/dist/__tests__/arb-history-stats.test.d.ts +0 -1
- package/dist/__tests__/arb-history-stats.test.js +0 -176
- package/dist/__tests__/arb-logic.test.d.ts +0 -1
- package/dist/__tests__/arb-logic.test.js +0 -84
- package/dist/__tests__/arb-manage.test.d.ts +0 -1
- package/dist/__tests__/arb-manage.test.js +0 -253
- package/dist/__tests__/arb-new-features.test.d.ts +0 -1
- package/dist/__tests__/arb-new-features.test.js +0 -457
- package/dist/__tests__/arb-sizing.test.d.ts +0 -1
- package/dist/__tests__/arb-sizing.test.js +0 -48
- package/dist/__tests__/arb-state.test.d.ts +0 -1
- package/dist/__tests__/arb-state.test.js +0 -284
- package/dist/__tests__/arb-userflow.test.d.ts +0 -1
- package/dist/__tests__/arb-userflow.test.js +0 -945
- package/dist/__tests__/arb-utils.test.d.ts +0 -1
- package/dist/__tests__/arb-utils.test.js +0 -264
- package/dist/__tests__/bot-conditions.test.d.ts +0 -1
- package/dist/__tests__/bot-conditions.test.js +0 -341
- package/dist/__tests__/client-id-tracker.test.d.ts +0 -1
- package/dist/__tests__/client-id-tracker.test.js +0 -137
- package/dist/__tests__/commands/new-atomic-commands.test.d.ts +0 -1
- package/dist/__tests__/commands/new-atomic-commands.test.js +0 -502
- package/dist/__tests__/commands/order-intent.test.d.ts +0 -1
- package/dist/__tests__/commands/order-intent.test.js +0 -600
- package/dist/__tests__/commands/trade-commands.test.d.ts +0 -1
- package/dist/__tests__/commands/trade-commands.test.js +0 -821
- package/dist/__tests__/config.test.d.ts +0 -1
- package/dist/__tests__/config.test.js +0 -86
- package/dist/__tests__/cross-chain-margin.test.d.ts +0 -1
- package/dist/__tests__/cross-chain-margin.test.js +0 -287
- package/dist/__tests__/dex-asset-map.test.d.ts +0 -1
- package/dist/__tests__/dex-asset-map.test.js +0 -191
- package/dist/__tests__/errors.test.d.ts +0 -1
- package/dist/__tests__/errors.test.js +0 -110
- package/dist/__tests__/event-stream.test.d.ts +0 -1
- package/dist/__tests__/event-stream.test.js +0 -276
- package/dist/__tests__/exchanges/interface.test.d.ts +0 -1
- package/dist/__tests__/exchanges/interface.test.js +0 -132
- package/dist/__tests__/exchanges/mock-adapter.d.ts +0 -69
- package/dist/__tests__/exchanges/mock-adapter.js +0 -137
- package/dist/__tests__/execution-log.test.d.ts +0 -1
- package/dist/__tests__/execution-log.test.js +0 -106
- package/dist/__tests__/funding-calc.test.d.ts +0 -1
- package/dist/__tests__/funding-calc.test.js +0 -71
- package/dist/__tests__/funding-history.test.d.ts +0 -1
- package/dist/__tests__/funding-history.test.js +0 -343
- package/dist/__tests__/funding-rates.test.d.ts +0 -1
- package/dist/__tests__/funding-rates.test.js +0 -342
- package/dist/__tests__/funding.test.d.ts +0 -1
- package/dist/__tests__/funding.test.js +0 -173
- package/dist/__tests__/gap-logic.test.d.ts +0 -1
- package/dist/__tests__/gap-logic.test.js +0 -43
- package/dist/__tests__/hip3-dex.test.d.ts +0 -1
- package/dist/__tests__/hip3-dex.test.js +0 -234
- package/dist/__tests__/integration/agent-features.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/agent-features.integration.test.js +0 -553
- package/dist/__tests__/integration/atomic-commands.integration.test.d.ts +0 -13
- package/dist/__tests__/integration/atomic-commands.integration.test.js +0 -246
- package/dist/__tests__/integration/bridge-simulation.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/bridge-simulation.integration.test.js +0 -453
- package/dist/__tests__/integration/bridge-strict.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/bridge-strict.integration.test.js +0 -812
- package/dist/__tests__/integration/bridge.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/bridge.integration.test.js +0 -309
- package/dist/__tests__/integration/cli-e2e.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/cli-e2e.integration.test.js +0 -202
- package/dist/__tests__/integration/dex-arb.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/dex-arb.integration.test.js +0 -116
- package/dist/__tests__/integration/envelope-consistency.integration.test.d.ts +0 -13
- package/dist/__tests__/integration/envelope-consistency.integration.test.js +0 -205
- package/dist/__tests__/integration/hip3-dex.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/hip3-dex.integration.test.js +0 -147
- package/dist/__tests__/integration/hyperliquid.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/hyperliquid.integration.test.js +0 -79
- package/dist/__tests__/integration/lighter.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/lighter.integration.test.js +0 -53
- package/dist/__tests__/integration/new-commands-e2e.integration.test.d.ts +0 -9
- package/dist/__tests__/integration/new-commands-e2e.integration.test.js +0 -236
- package/dist/__tests__/integration/order-verification.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/order-verification.integration.test.js +0 -321
- package/dist/__tests__/integration/pacifica.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/pacifica.integration.test.js +0 -75
- package/dist/__tests__/integration/response-shapes.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/response-shapes.integration.test.js +0 -278
- package/dist/__tests__/liquidity.test.d.ts +0 -1
- package/dist/__tests__/liquidity.test.js +0 -225
- package/dist/__tests__/plan-executor.test.d.ts +0 -1
- package/dist/__tests__/plan-executor.test.js +0 -314
- package/dist/__tests__/position-history.test.d.ts +0 -1
- package/dist/__tests__/position-history.test.js +0 -367
- package/dist/__tests__/retry.test.d.ts +0 -1
- package/dist/__tests__/retry.test.js +0 -310
- package/dist/__tests__/risk-assessment.test.d.ts +0 -1
- package/dist/__tests__/risk-assessment.test.js +0 -288
- package/dist/__tests__/security-adversarial.test.d.ts +0 -1
- package/dist/__tests__/security-adversarial.test.js +0 -574
- package/dist/__tests__/strategies.test.d.ts +0 -1
- package/dist/__tests__/strategies.test.js +0 -539
- package/dist/__tests__/trade-execution.test.d.ts +0 -1
- package/dist/__tests__/trade-execution.test.js +0 -129
- package/dist/__tests__/trade-validator.test.d.ts +0 -1
- package/dist/__tests__/trade-validator.test.js +0 -655
- package/dist/__tests__/utils.test.d.ts +0 -1
- package/dist/__tests__/utils.test.js +0 -76
- package/dist/arb/reconcile.d.ts +0 -28
- package/dist/arb/reconcile.js +0 -162
- package/dist/commands/alert.d.ts +0 -2
- package/dist/commands/alert.js +0 -421
- package/dist/commands/analytics.d.ts +0 -3
- package/dist/commands/analytics.js +0 -311
- package/dist/commands/arb-manage.d.ts +0 -5
- package/dist/commands/arb-manage.js +0 -5
- package/dist/commands/dashboard.d.ts +0 -3
- package/dist/commands/dashboard.js +0 -176
- package/dist/commands/deposit.d.ts +0 -4
- package/dist/commands/deposit.js +0 -573
- package/dist/commands/dex.d.ts +0 -3
- package/dist/commands/dex.js +0 -120
- package/dist/commands/env.d.ts +0 -2
- package/dist/commands/env.js +0 -136
- package/dist/commands/funding.d.ts +0 -3
- package/dist/commands/funding.js +0 -554
- package/dist/commands/gap.d.ts +0 -2
- package/dist/commands/gap.js +0 -305
- package/dist/commands/health.d.ts +0 -2
- package/dist/commands/health.js +0 -67
- package/dist/commands/multileg.d.ts +0 -16
- package/dist/commands/multileg.js +0 -174
- package/dist/commands/pnl.d.ts +0 -12
- package/dist/commands/pnl.js +0 -243
- package/dist/commands/run.d.ts +0 -3
- package/dist/commands/run.js +0 -202
- package/dist/commands/stream.d.ts +0 -5
- package/dist/commands/stream.js +0 -200
- package/dist/commands/withdraw.d.ts +0 -3
- package/dist/commands/withdraw.js +0 -187
- package/dist/exchanges/edgex.d.ts +0 -62
- package/dist/exchanges/edgex.js +0 -552
- package/dist/exchanges/nado.d.ts +0 -52
- package/dist/exchanges/nado.js +0 -223
- package/dist/funding/index.d.ts +0 -3
- package/dist/funding/index.js +0 -3
- package/dist/retry.d.ts +0 -74
- package/dist/retry.js +0 -129
- package/dist/ws/market-feed.d.ts +0 -74
- package/dist/ws/market-feed.js +0 -227
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { formatUsd, formatPnl, formatPercent, printJson } from "../utils.js";
|
|
3
|
-
describe("formatUsd", () => {
|
|
4
|
-
it("formats numeric strings", () => {
|
|
5
|
-
expect(formatUsd("1234.5")).toBe("1,234.50");
|
|
6
|
-
});
|
|
7
|
-
it("formats numbers", () => {
|
|
8
|
-
expect(formatUsd(99999.999)).toBe("100,000.00");
|
|
9
|
-
});
|
|
10
|
-
it("returns original string for NaN", () => {
|
|
11
|
-
expect(formatUsd("abc")).toBe("abc");
|
|
12
|
-
});
|
|
13
|
-
it("formats zero", () => {
|
|
14
|
-
expect(formatUsd(0)).toBe("0.00");
|
|
15
|
-
});
|
|
16
|
-
it("formats negative numbers", () => {
|
|
17
|
-
expect(formatUsd(-42.1)).toBe("-42.10");
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
describe("formatPnl", () => {
|
|
21
|
-
it("positive PnL has + prefix", () => {
|
|
22
|
-
const result = formatPnl(100);
|
|
23
|
-
expect(result).toContain("+$100.00");
|
|
24
|
-
});
|
|
25
|
-
it("negative PnL has - prefix", () => {
|
|
26
|
-
const result = formatPnl(-50);
|
|
27
|
-
expect(result).toContain("-$50.00");
|
|
28
|
-
});
|
|
29
|
-
it("zero PnL", () => {
|
|
30
|
-
const result = formatPnl(0);
|
|
31
|
-
expect(result).toContain("$0.00");
|
|
32
|
-
});
|
|
33
|
-
it("handles string input", () => {
|
|
34
|
-
const result = formatPnl("123.456");
|
|
35
|
-
expect(result).toContain("$123.46");
|
|
36
|
-
});
|
|
37
|
-
it("handles NaN", () => {
|
|
38
|
-
expect(formatPnl("abc")).toBe("abc");
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
describe("formatPercent", () => {
|
|
42
|
-
it("positive percent", () => {
|
|
43
|
-
const result = formatPercent(0.0015);
|
|
44
|
-
expect(result).toContain("+0.1500%");
|
|
45
|
-
});
|
|
46
|
-
it("negative percent", () => {
|
|
47
|
-
const result = formatPercent(-0.0025);
|
|
48
|
-
expect(result).toContain("-0.2500%");
|
|
49
|
-
});
|
|
50
|
-
it("zero percent", () => {
|
|
51
|
-
const result = formatPercent(0);
|
|
52
|
-
expect(result).toContain("0.0000%");
|
|
53
|
-
});
|
|
54
|
-
it("handles NaN", () => {
|
|
55
|
-
expect(formatPercent("abc")).toBe("abc");
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
describe("printJson", () => {
|
|
59
|
-
it("outputs valid JSON to console", () => {
|
|
60
|
-
const logs = [];
|
|
61
|
-
const origLog = console.log;
|
|
62
|
-
console.log = (...args) => logs.push(args.join(" "));
|
|
63
|
-
printJson({ a: 1, b: "hello" });
|
|
64
|
-
console.log = origLog;
|
|
65
|
-
const parsed = JSON.parse(logs[0]);
|
|
66
|
-
expect(parsed).toEqual({ a: 1, b: "hello" });
|
|
67
|
-
});
|
|
68
|
-
it("handles arrays", () => {
|
|
69
|
-
const logs = [];
|
|
70
|
-
const origLog = console.log;
|
|
71
|
-
console.log = (...args) => logs.push(args.join(" "));
|
|
72
|
-
printJson([1, 2, 3]);
|
|
73
|
-
console.log = origLog;
|
|
74
|
-
expect(JSON.parse(logs[0])).toEqual([1, 2, 3]);
|
|
75
|
-
});
|
|
76
|
-
});
|
package/dist/arb/reconcile.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { ExchangeAdapter } from "../exchanges/interface.js";
|
|
2
|
-
export interface ReconciliationIssue {
|
|
3
|
-
type: "orphan" | "phantom" | "size_mismatch";
|
|
4
|
-
symbol: string;
|
|
5
|
-
exchange: string;
|
|
6
|
-
side: "long" | "short";
|
|
7
|
-
localSize: number | null;
|
|
8
|
-
exchangeSize: number | null;
|
|
9
|
-
severity: "warning" | "critical";
|
|
10
|
-
suggestion: string;
|
|
11
|
-
}
|
|
12
|
-
export interface ReconciliationResult {
|
|
13
|
-
issues: ReconciliationIssue[];
|
|
14
|
-
healthy: number;
|
|
15
|
-
fixesApplied?: string[];
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Reconcile local arb state with actual exchange positions.
|
|
19
|
-
*
|
|
20
|
-
* Detects three types of issues:
|
|
21
|
-
* - **Orphan**: Position exists on exchange but not in local arb state (manual entry?)
|
|
22
|
-
* - **Phantom**: Position exists in local state but not on exchange (liquidated? manually closed?)
|
|
23
|
-
* - **Size mismatch**: Both exist but sizes differ beyond tolerance
|
|
24
|
-
*/
|
|
25
|
-
export declare function reconcileArbPositions(adapters: Map<string, ExchangeAdapter>, opts?: {
|
|
26
|
-
fix?: boolean;
|
|
27
|
-
tolerancePct?: number;
|
|
28
|
-
}): Promise<ReconciliationResult>;
|
package/dist/arb/reconcile.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { getPositions, removePosition, updatePosition } from "./state.js";
|
|
2
|
-
/** Normalize symbol for comparison (strip -PERP suffix, uppercase) */
|
|
3
|
-
function normalizeSymbol(symbol) {
|
|
4
|
-
return symbol.toUpperCase().replace(/-PERP$/, "");
|
|
5
|
-
}
|
|
6
|
-
/** Find a matching exchange position by symbol */
|
|
7
|
-
function findExchangePosition(positions, symbol, side) {
|
|
8
|
-
const norm = normalizeSymbol(symbol);
|
|
9
|
-
return positions.find(p => normalizeSymbol(p.symbol) === norm && p.side === side);
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Reconcile local arb state with actual exchange positions.
|
|
13
|
-
*
|
|
14
|
-
* Detects three types of issues:
|
|
15
|
-
* - **Orphan**: Position exists on exchange but not in local arb state (manual entry?)
|
|
16
|
-
* - **Phantom**: Position exists in local state but not on exchange (liquidated? manually closed?)
|
|
17
|
-
* - **Size mismatch**: Both exist but sizes differ beyond tolerance
|
|
18
|
-
*/
|
|
19
|
-
export async function reconcileArbPositions(adapters, opts) {
|
|
20
|
-
const tolerancePct = opts?.tolerancePct ?? 1;
|
|
21
|
-
const shouldFix = opts?.fix ?? false;
|
|
22
|
-
const issues = [];
|
|
23
|
-
const fixesApplied = [];
|
|
24
|
-
let healthy = 0;
|
|
25
|
-
const localPositions = getPositions();
|
|
26
|
-
// Fetch all exchange positions
|
|
27
|
-
const exchangePositions = new Map();
|
|
28
|
-
for (const [name, adapter] of adapters) {
|
|
29
|
-
try {
|
|
30
|
-
const pos = await adapter.getPositions();
|
|
31
|
-
exchangePositions.set(name, pos);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
exchangePositions.set(name, []);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Track which exchange positions are accounted for
|
|
38
|
-
const accountedFor = new Set(); // "exchange:symbol:side"
|
|
39
|
-
// Check each local arb position against exchange
|
|
40
|
-
for (const arb of localPositions) {
|
|
41
|
-
// Check long leg
|
|
42
|
-
const longPositions = exchangePositions.get(arb.longExchange) ?? [];
|
|
43
|
-
const longMatch = findExchangePosition(longPositions, arb.symbol, "long");
|
|
44
|
-
if (!longMatch) {
|
|
45
|
-
issues.push({
|
|
46
|
-
type: "phantom",
|
|
47
|
-
symbol: arb.symbol,
|
|
48
|
-
exchange: arb.longExchange,
|
|
49
|
-
side: "long",
|
|
50
|
-
localSize: arb.longSize,
|
|
51
|
-
exchangeSize: null,
|
|
52
|
-
severity: "critical",
|
|
53
|
-
suggestion: `Local state has long ${arb.symbol} on ${arb.longExchange} but exchange has no position. May have been liquidated or manually closed.`,
|
|
54
|
-
});
|
|
55
|
-
if (shouldFix) {
|
|
56
|
-
removePosition(arb.symbol);
|
|
57
|
-
fixesApplied.push(`Removed phantom position ${arb.symbol} (long leg missing on ${arb.longExchange})`);
|
|
58
|
-
continue; // Skip short leg check since we removed the position
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
accountedFor.add(`${arb.longExchange}:${normalizeSymbol(arb.symbol)}:long`);
|
|
63
|
-
const exchangeSize = Math.abs(Number(longMatch.size));
|
|
64
|
-
const localSize = Math.abs(arb.longSize);
|
|
65
|
-
const diffPct = localSize > 0 ? (Math.abs(exchangeSize - localSize) / localSize) * 100 : 0;
|
|
66
|
-
if (diffPct > tolerancePct) {
|
|
67
|
-
issues.push({
|
|
68
|
-
type: "size_mismatch",
|
|
69
|
-
symbol: arb.symbol,
|
|
70
|
-
exchange: arb.longExchange,
|
|
71
|
-
side: "long",
|
|
72
|
-
localSize,
|
|
73
|
-
exchangeSize,
|
|
74
|
-
severity: "warning",
|
|
75
|
-
suggestion: `Long size mismatch: local ${localSize} vs exchange ${exchangeSize} (${diffPct.toFixed(1)}% diff). Partial fill or manual adjustment?`,
|
|
76
|
-
});
|
|
77
|
-
if (shouldFix) {
|
|
78
|
-
updatePosition(arb.symbol, { longSize: exchangeSize });
|
|
79
|
-
fixesApplied.push(`Updated ${arb.symbol} long size: ${localSize} → ${exchangeSize}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
healthy++;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// Check short leg
|
|
87
|
-
const shortPositions = exchangePositions.get(arb.shortExchange) ?? [];
|
|
88
|
-
const shortMatch = findExchangePosition(shortPositions, arb.symbol, "short");
|
|
89
|
-
if (!shortMatch) {
|
|
90
|
-
// Don't double-report if we already removed via fix
|
|
91
|
-
if (shouldFix && !getPositions().find(p => p.symbol === arb.symbol))
|
|
92
|
-
continue;
|
|
93
|
-
issues.push({
|
|
94
|
-
type: "phantom",
|
|
95
|
-
symbol: arb.symbol,
|
|
96
|
-
exchange: arb.shortExchange,
|
|
97
|
-
side: "short",
|
|
98
|
-
localSize: arb.shortSize,
|
|
99
|
-
exchangeSize: null,
|
|
100
|
-
severity: "critical",
|
|
101
|
-
suggestion: `Local state has short ${arb.symbol} on ${arb.shortExchange} but exchange has no position. May have been liquidated or manually closed.`,
|
|
102
|
-
});
|
|
103
|
-
if (shouldFix) {
|
|
104
|
-
removePosition(arb.symbol);
|
|
105
|
-
fixesApplied.push(`Removed phantom position ${arb.symbol} (short leg missing on ${arb.shortExchange})`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
accountedFor.add(`${arb.shortExchange}:${normalizeSymbol(arb.symbol)}:short`);
|
|
110
|
-
const exchangeSize = Math.abs(Number(shortMatch.size));
|
|
111
|
-
const localSize = Math.abs(arb.shortSize);
|
|
112
|
-
const diffPct = localSize > 0 ? (Math.abs(exchangeSize - localSize) / localSize) * 100 : 0;
|
|
113
|
-
if (diffPct > tolerancePct) {
|
|
114
|
-
issues.push({
|
|
115
|
-
type: "size_mismatch",
|
|
116
|
-
symbol: arb.symbol,
|
|
117
|
-
exchange: arb.shortExchange,
|
|
118
|
-
side: "short",
|
|
119
|
-
localSize,
|
|
120
|
-
exchangeSize,
|
|
121
|
-
severity: "warning",
|
|
122
|
-
suggestion: `Short size mismatch: local ${localSize} vs exchange ${exchangeSize} (${diffPct.toFixed(1)}% diff). Partial fill or manual adjustment?`,
|
|
123
|
-
});
|
|
124
|
-
if (shouldFix) {
|
|
125
|
-
updatePosition(arb.symbol, { shortSize: exchangeSize });
|
|
126
|
-
fixesApplied.push(`Updated ${arb.symbol} short size: ${localSize} → ${exchangeSize}`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
healthy++;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
// Check for orphan positions (on exchange but not in local state)
|
|
135
|
-
for (const [exchangeName, positions] of exchangePositions) {
|
|
136
|
-
for (const pos of positions) {
|
|
137
|
-
const key = `${exchangeName}:${normalizeSymbol(pos.symbol)}:${pos.side}`;
|
|
138
|
-
if (!accountedFor.has(key)) {
|
|
139
|
-
// Check if this exchange is used in any arb position
|
|
140
|
-
const isArbExchange = localPositions.some(p => p.longExchange === exchangeName || p.shortExchange === exchangeName);
|
|
141
|
-
// Only report orphans on exchanges that are part of arb state
|
|
142
|
-
if (isArbExchange || localPositions.length > 0) {
|
|
143
|
-
issues.push({
|
|
144
|
-
type: "orphan",
|
|
145
|
-
symbol: pos.symbol,
|
|
146
|
-
exchange: exchangeName,
|
|
147
|
-
side: pos.side,
|
|
148
|
-
localSize: null,
|
|
149
|
-
exchangeSize: Math.abs(Number(pos.size)),
|
|
150
|
-
severity: "warning",
|
|
151
|
-
suggestion: `Position on ${exchangeName} not tracked in arb state. Manual entry or untracked strategy?`,
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return {
|
|
158
|
-
issues,
|
|
159
|
-
healthy,
|
|
160
|
-
...(fixesApplied.length > 0 ? { fixesApplied } : {}),
|
|
161
|
-
};
|
|
162
|
-
}
|
package/dist/commands/alert.d.ts
DELETED