bfxsentry-agent 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.
Files changed (187) hide show
  1. package/config/default.yaml +137 -0
  2. package/config/phase1-safety.yaml +24 -0
  3. package/dist/bin/sentry.d.ts +3 -0
  4. package/dist/bin/sentry.d.ts.map +1 -0
  5. package/dist/bin/sentry.js +124 -0
  6. package/dist/bin/sentry.js.map +1 -0
  7. package/dist/src/backtest/fill-simulator.d.ts +5 -0
  8. package/dist/src/backtest/fill-simulator.d.ts.map +1 -0
  9. package/dist/src/backtest/fill-simulator.js +43 -0
  10. package/dist/src/backtest/fill-simulator.js.map +1 -0
  11. package/dist/src/backtest/report.d.ts +3 -0
  12. package/dist/src/backtest/report.d.ts.map +1 -0
  13. package/dist/src/backtest/report.js +43 -0
  14. package/dist/src/backtest/report.js.map +1 -0
  15. package/dist/src/backtest/runner.d.ts +34 -0
  16. package/dist/src/backtest/runner.d.ts.map +1 -0
  17. package/dist/src/backtest/runner.js +132 -0
  18. package/dist/src/backtest/runner.js.map +1 -0
  19. package/dist/src/collector/basis-monitor.d.ts +9 -0
  20. package/dist/src/collector/basis-monitor.d.ts.map +1 -0
  21. package/dist/src/collector/basis-monitor.js +52 -0
  22. package/dist/src/collector/basis-monitor.js.map +1 -0
  23. package/dist/src/collector/bitfinex-rest.d.ts +20 -0
  24. package/dist/src/collector/bitfinex-rest.d.ts.map +1 -0
  25. package/dist/src/collector/bitfinex-rest.js +350 -0
  26. package/dist/src/collector/bitfinex-rest.js.map +1 -0
  27. package/dist/src/collector/event-detector.d.ts +3 -0
  28. package/dist/src/collector/event-detector.d.ts.map +1 -0
  29. package/dist/src/collector/event-detector.js +41 -0
  30. package/dist/src/collector/event-detector.js.map +1 -0
  31. package/dist/src/collector/polymarket.d.ts +32 -0
  32. package/dist/src/collector/polymarket.d.ts.map +1 -0
  33. package/dist/src/collector/polymarket.js +89 -0
  34. package/dist/src/collector/polymarket.js.map +1 -0
  35. package/dist/src/collector/types.d.ts +114 -0
  36. package/dist/src/collector/types.d.ts.map +1 -0
  37. package/dist/src/collector/types.js +2 -0
  38. package/dist/src/collector/types.js.map +1 -0
  39. package/dist/src/core/config.d.ts +67 -0
  40. package/dist/src/core/config.d.ts.map +1 -0
  41. package/dist/src/core/config.js +27 -0
  42. package/dist/src/core/config.js.map +1 -0
  43. package/dist/src/core/decision-log.d.ts +7 -0
  44. package/dist/src/core/decision-log.d.ts.map +1 -0
  45. package/dist/src/core/decision-log.js +69 -0
  46. package/dist/src/core/decision-log.js.map +1 -0
  47. package/dist/src/core/engine.d.ts +19 -0
  48. package/dist/src/core/engine.d.ts.map +1 -0
  49. package/dist/src/core/engine.js +148 -0
  50. package/dist/src/core/engine.js.map +1 -0
  51. package/dist/src/core/event-bus.d.ts +12 -0
  52. package/dist/src/core/event-bus.d.ts.map +1 -0
  53. package/dist/src/core/event-bus.js +21 -0
  54. package/dist/src/core/event-bus.js.map +1 -0
  55. package/dist/src/core/logger.d.ts +4 -0
  56. package/dist/src/core/logger.d.ts.map +1 -0
  57. package/dist/src/core/logger.js +22 -0
  58. package/dist/src/core/logger.js.map +1 -0
  59. package/dist/src/core/recorder.d.ts +7 -0
  60. package/dist/src/core/recorder.d.ts.map +1 -0
  61. package/dist/src/core/recorder.js +42 -0
  62. package/dist/src/core/recorder.js.map +1 -0
  63. package/dist/src/executor/bitfinex-trader.d.ts +3 -0
  64. package/dist/src/executor/bitfinex-trader.d.ts.map +1 -0
  65. package/dist/src/executor/bitfinex-trader.js +119 -0
  66. package/dist/src/executor/bitfinex-trader.js.map +1 -0
  67. package/dist/src/executor/dry-run.d.ts +4 -0
  68. package/dist/src/executor/dry-run.d.ts.map +1 -0
  69. package/dist/src/executor/dry-run.js +39 -0
  70. package/dist/src/executor/dry-run.js.map +1 -0
  71. package/dist/src/executor/order-id.d.ts +5 -0
  72. package/dist/src/executor/order-id.d.ts.map +1 -0
  73. package/dist/src/executor/order-id.js +20 -0
  74. package/dist/src/executor/order-id.js.map +1 -0
  75. package/dist/src/executor/reconciler.d.ts +8 -0
  76. package/dist/src/executor/reconciler.d.ts.map +1 -0
  77. package/dist/src/executor/reconciler.js +44 -0
  78. package/dist/src/executor/reconciler.js.map +1 -0
  79. package/dist/src/executor/types.d.ts +19 -0
  80. package/dist/src/executor/types.d.ts.map +1 -0
  81. package/dist/src/executor/types.js +2 -0
  82. package/dist/src/executor/types.js.map +1 -0
  83. package/dist/src/risk/cooldown.d.ts +8 -0
  84. package/dist/src/risk/cooldown.d.ts.map +1 -0
  85. package/dist/src/risk/cooldown.js +30 -0
  86. package/dist/src/risk/cooldown.js.map +1 -0
  87. package/dist/src/risk/portfolio-filter.d.ts +9 -0
  88. package/dist/src/risk/portfolio-filter.d.ts.map +1 -0
  89. package/dist/src/risk/portfolio-filter.js +58 -0
  90. package/dist/src/risk/portfolio-filter.js.map +1 -0
  91. package/dist/src/risk/position-manager.d.ts +19 -0
  92. package/dist/src/risk/position-manager.d.ts.map +1 -0
  93. package/dist/src/risk/position-manager.js +171 -0
  94. package/dist/src/risk/position-manager.js.map +1 -0
  95. package/dist/src/risk/strategy-filter.d.ts +8 -0
  96. package/dist/src/risk/strategy-filter.d.ts.map +1 -0
  97. package/dist/src/risk/strategy-filter.js +40 -0
  98. package/dist/src/risk/strategy-filter.js.map +1 -0
  99. package/dist/src/risk/var-calculator.d.ts +10 -0
  100. package/dist/src/risk/var-calculator.d.ts.map +1 -0
  101. package/dist/src/risk/var-calculator.js +38 -0
  102. package/dist/src/risk/var-calculator.js.map +1 -0
  103. package/dist/src/signal/funding-radar.d.ts +4 -0
  104. package/dist/src/signal/funding-radar.d.ts.map +1 -0
  105. package/dist/src/signal/funding-radar.js +92 -0
  106. package/dist/src/signal/funding-radar.js.map +1 -0
  107. package/dist/src/signal/index.d.ts +12 -0
  108. package/dist/src/signal/index.d.ts.map +1 -0
  109. package/dist/src/signal/index.js +37 -0
  110. package/dist/src/signal/index.js.map +1 -0
  111. package/dist/src/signal/liquidation.d.ts +4 -0
  112. package/dist/src/signal/liquidation.d.ts.map +1 -0
  113. package/dist/src/signal/liquidation.js +83 -0
  114. package/dist/src/signal/liquidation.js.map +1 -0
  115. package/dist/src/signal/orderbook.d.ts +4 -0
  116. package/dist/src/signal/orderbook.d.ts.map +1 -0
  117. package/dist/src/signal/orderbook.js +100 -0
  118. package/dist/src/signal/orderbook.js.map +1 -0
  119. package/dist/src/signal/smart-money.d.ts +4 -0
  120. package/dist/src/signal/smart-money.d.ts.map +1 -0
  121. package/dist/src/signal/smart-money.js +39 -0
  122. package/dist/src/signal/smart-money.js.map +1 -0
  123. package/dist/src/signal/types.d.ts +13 -0
  124. package/dist/src/signal/types.d.ts.map +1 -0
  125. package/dist/src/signal/types.js +2 -0
  126. package/dist/src/signal/types.js.map +1 -0
  127. package/dist/src/skill/backtest.d.ts +5 -0
  128. package/dist/src/skill/backtest.d.ts.map +1 -0
  129. package/dist/src/skill/backtest.js +14 -0
  130. package/dist/src/skill/backtest.js.map +1 -0
  131. package/dist/src/skill/config.d.ts +4 -0
  132. package/dist/src/skill/config.d.ts.map +1 -0
  133. package/dist/src/skill/config.js +35 -0
  134. package/dist/src/skill/config.js.map +1 -0
  135. package/dist/src/skill/logs.d.ts +5 -0
  136. package/dist/src/skill/logs.d.ts.map +1 -0
  137. package/dist/src/skill/logs.js +37 -0
  138. package/dist/src/skill/logs.js.map +1 -0
  139. package/dist/src/skill/scan.d.ts +5 -0
  140. package/dist/src/skill/scan.d.ts.map +1 -0
  141. package/dist/src/skill/scan.js +75 -0
  142. package/dist/src/skill/scan.js.map +1 -0
  143. package/dist/src/skill/signal.d.ts +4 -0
  144. package/dist/src/skill/signal.d.ts.map +1 -0
  145. package/dist/src/skill/signal.js +63 -0
  146. package/dist/src/skill/signal.js.map +1 -0
  147. package/dist/src/skill/status.d.ts +2 -0
  148. package/dist/src/skill/status.d.ts.map +1 -0
  149. package/dist/src/skill/status.js +58 -0
  150. package/dist/src/skill/status.js.map +1 -0
  151. package/dist/src/skill/strategy.d.ts +4 -0
  152. package/dist/src/skill/strategy.d.ts.map +1 -0
  153. package/dist/src/skill/strategy.js +44 -0
  154. package/dist/src/skill/strategy.js.map +1 -0
  155. package/dist/src/skill/trade.d.ts +6 -0
  156. package/dist/src/skill/trade.d.ts.map +1 -0
  157. package/dist/src/skill/trade.js +58 -0
  158. package/dist/src/skill/trade.js.map +1 -0
  159. package/dist/src/strategy/funding-arb.d.ts +6 -0
  160. package/dist/src/strategy/funding-arb.d.ts.map +1 -0
  161. package/dist/src/strategy/funding-arb.js +57 -0
  162. package/dist/src/strategy/funding-arb.js.map +1 -0
  163. package/dist/src/strategy/index.d.ts +7 -0
  164. package/dist/src/strategy/index.d.ts.map +1 -0
  165. package/dist/src/strategy/index.js +27 -0
  166. package/dist/src/strategy/index.js.map +1 -0
  167. package/dist/src/strategy/liq-hunter.d.ts +6 -0
  168. package/dist/src/strategy/liq-hunter.d.ts.map +1 -0
  169. package/dist/src/strategy/liq-hunter.js +61 -0
  170. package/dist/src/strategy/liq-hunter.js.map +1 -0
  171. package/dist/src/strategy/ob-sniper.d.ts +6 -0
  172. package/dist/src/strategy/ob-sniper.d.ts.map +1 -0
  173. package/dist/src/strategy/ob-sniper.js +47 -0
  174. package/dist/src/strategy/ob-sniper.js.map +1 -0
  175. package/dist/src/strategy/pm-hedge.d.ts +6 -0
  176. package/dist/src/strategy/pm-hedge.d.ts.map +1 -0
  177. package/dist/src/strategy/pm-hedge.js +55 -0
  178. package/dist/src/strategy/pm-hedge.js.map +1 -0
  179. package/dist/src/strategy/smart-follow.d.ts +6 -0
  180. package/dist/src/strategy/smart-follow.d.ts.map +1 -0
  181. package/dist/src/strategy/smart-follow.js +44 -0
  182. package/dist/src/strategy/smart-follow.js.map +1 -0
  183. package/dist/src/strategy/types.d.ts +58 -0
  184. package/dist/src/strategy/types.d.ts.map +1 -0
  185. package/dist/src/strategy/types.js +2 -0
  186. package/dist/src/strategy/types.js.map +1 -0
  187. package/package.json +54 -0
@@ -0,0 +1,42 @@
1
+ import Database from 'better-sqlite3';
2
+ import { resolve } from 'node:path';
3
+ import { getLogger } from './logger.js';
4
+ const log = () => getLogger();
5
+ let db = null;
6
+ const DB_PATH = resolve(import.meta.dirname, '..', '..', 'data', 'sentry.db');
7
+ export function initRecorder() {
8
+ db = new Database(DB_PATH);
9
+ db.pragma('journal_mode = WAL');
10
+ db.exec(`
11
+ CREATE TABLE IF NOT EXISTS snapshots (
12
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
13
+ timestamp INTEGER NOT NULL,
14
+ data_json TEXT NOT NULL,
15
+ signals_json TEXT
16
+ );
17
+ CREATE INDEX IF NOT EXISTS idx_snapshots_ts ON snapshots(timestamp);
18
+ `);
19
+ log().info({ path: DB_PATH }, 'Recorder initialized');
20
+ }
21
+ export function recordSnapshot(snapshot, signals) {
22
+ if (!db)
23
+ return;
24
+ const stmt = db.prepare('INSERT INTO snapshots (timestamp, data_json, signals_json) VALUES (?, ?, ?)');
25
+ stmt.run(snapshot.timestamp, JSON.stringify(snapshot), JSON.stringify(signals));
26
+ }
27
+ export function cleanOldSnapshots(retentionDays) {
28
+ if (!db)
29
+ return;
30
+ const cutoff = Date.now() - retentionDays * 86400_000;
31
+ const result = db.prepare('DELETE FROM snapshots WHERE timestamp < ?').run(cutoff);
32
+ if (result.changes > 0) {
33
+ log().info({ deleted: result.changes, retentionDays }, 'Cleaned old snapshots');
34
+ }
35
+ }
36
+ export function closeRecorder() {
37
+ if (db) {
38
+ db.close();
39
+ db = null;
40
+ }
41
+ }
42
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../../src/core/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAIvC,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;AAE7B,IAAI,EAAE,GAA6B,IAAI,CAAA;AAEvC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;AAE7E,MAAM,UAAU,YAAY;IAC1B,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC1B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;IAC/B,EAAE,CAAC,IAAI,CAAC;;;;;;;;GAQP,CAAC,CAAA;IACF,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,sBAAsB,CAAC,CAAA;AACvD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAwB,EAAE,OAAiB;IACxE,IAAI,CAAC,EAAE;QAAE,OAAM;IACf,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,6EAA6E,CAC9E,CAAA;IACD,IAAI,CAAC,GAAG,CACN,QAAQ,CAAC,SAAS,EAClB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EACxB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CACxB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,aAAqB;IACrD,IAAI,CAAC,EAAE;QAAE,OAAM;IACf,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,GAAG,SAAS,CAAA;IACrD,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAClF,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACvB,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,uBAAuB,CAAC,CAAA;IACjF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAA;QACV,EAAE,GAAG,IAAI,CAAA;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TradeIntent, ExecutionResult } from '../strategy/types.js';
2
+ export declare function liveExecute(intent: TradeIntent): Promise<ExecutionResult>;
3
+ //# sourceMappingURL=bitfinex-trader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitfinex-trader.d.ts","sourceRoot":"","sources":["../../../src/executor/bitfinex-trader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAqExE,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CA2D/E"}
@@ -0,0 +1,119 @@
1
+ import crypto from 'node:crypto';
2
+ import https from 'node:https';
3
+ import { SocksProxyAgent } from 'socks-proxy-agent';
4
+ import { generateCid, markCidSubmitted } from './order-id.js';
5
+ import { getLogger } from '../core/logger.js';
6
+ const log = () => getLogger();
7
+ const BFX_API_URL = 'api.bitfinex.com';
8
+ function getCredentials() {
9
+ const apiKey = process.env.BFX_API_KEY;
10
+ const apiSecret = process.env.BFX_API_SECRET;
11
+ if (!apiKey || !apiSecret)
12
+ return null;
13
+ return { apiKey, apiSecret };
14
+ }
15
+ function createSignature(path, nonce, body, secret) {
16
+ const payload = `/api/${path}${nonce}${body}`;
17
+ return crypto.createHmac('sha384', secret).update(payload).digest('hex');
18
+ }
19
+ function getAgent() {
20
+ const proxy = process.env.SOCKS_PROXY || process.env.ALL_PROXY || 'socks5h://127.0.0.1:7897';
21
+ try {
22
+ return new SocksProxyAgent(proxy);
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ }
28
+ async function authRequest(path, body, creds) {
29
+ const nonce = Date.now().toString();
30
+ const bodyStr = JSON.stringify(body);
31
+ const sig = createSignature(path, nonce, bodyStr, creds.apiSecret);
32
+ return new Promise((resolve, reject) => {
33
+ const agent = getAgent();
34
+ const options = {
35
+ hostname: BFX_API_URL,
36
+ port: 443,
37
+ path: `/api/${path}`,
38
+ method: 'POST',
39
+ headers: {
40
+ 'Content-Type': 'application/json',
41
+ 'bfx-nonce': nonce,
42
+ 'bfx-apikey': creds.apiKey,
43
+ 'bfx-signature': sig,
44
+ },
45
+ agent,
46
+ };
47
+ const req = https.request(options, (res) => {
48
+ let data = '';
49
+ res.on('data', chunk => { data += chunk; });
50
+ res.on('end', () => {
51
+ try {
52
+ resolve(JSON.parse(data));
53
+ }
54
+ catch {
55
+ reject(new Error(data));
56
+ }
57
+ });
58
+ });
59
+ req.on('error', reject);
60
+ req.setTimeout(30_000, () => { req.destroy(); reject(new Error('Timeout')); });
61
+ req.write(bodyStr);
62
+ req.end();
63
+ });
64
+ }
65
+ export async function liveExecute(intent) {
66
+ const creds = getCredentials();
67
+ if (!creds) {
68
+ return {
69
+ success: false,
70
+ error: 'BFX_API_KEY / BFX_API_SECRET not set',
71
+ timestamp: Date.now(),
72
+ };
73
+ }
74
+ const cid = generateCid(intent.strategy);
75
+ markCidSubmitted(cid);
76
+ const amount = intent.direction === 'long'
77
+ ? intent.sizePct / 100 * 5000 / intent.entryPrice // simplified
78
+ : -(intent.sizePct / 100 * 5000 / intent.entryPrice);
79
+ const orderType = 'EXCHANGE LIMIT';
80
+ const price = intent.direction === 'long'
81
+ ? intent.entryPrice * (1 + 0.0002) // slight offset for limit
82
+ : intent.entryPrice * (1 - 0.0002);
83
+ try {
84
+ const result = await authRequest('v2/auth/w/order/submit', {
85
+ type: orderType,
86
+ symbol: intent.instrument,
87
+ amount: amount.toString(),
88
+ price: price.toString(),
89
+ cid: parseInt(cid.replace(/\D/g, '').slice(-10)),
90
+ meta: { aff_code: 'bfxsentry' },
91
+ }, creds);
92
+ const data = result;
93
+ if (Array.isArray(data) && data[6] === 'SUCCESS') {
94
+ const order = data[4]?.[0];
95
+ log().info({
96
+ cid,
97
+ orderId: order?.[0],
98
+ price: order?.[16],
99
+ amount: order?.[6],
100
+ }, 'Order submitted successfully');
101
+ return {
102
+ success: true,
103
+ orderId: String(order?.[0] || cid),
104
+ fillPrice: Number(order?.[16]) || price,
105
+ fillSize: Math.abs(amount),
106
+ fee: 0,
107
+ timestamp: Date.now(),
108
+ };
109
+ }
110
+ const errMsg = Array.isArray(data) ? String(data[6] || data[2] || 'Unknown') : 'Unknown error';
111
+ log().error({ result: data }, 'Order submission failed');
112
+ return { success: false, error: errMsg, timestamp: Date.now() };
113
+ }
114
+ catch (err) {
115
+ log().error({ err }, 'Order execution error');
116
+ return { success: false, error: err.message, timestamp: Date.now() };
117
+ }
118
+ }
119
+ //# sourceMappingURL=bitfinex-trader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitfinex-trader.js","sourceRoot":"","sources":["../../../src/executor/bitfinex-trader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { TradeIntent, ExecutionResult } from '../strategy/types.js';
2
+ import type { MarketSnapshot } from '../collector/types.js';
3
+ export declare function dryRunExecute(intent: TradeIntent, snapshot: MarketSnapshot): ExecutionResult;
4
+ //# sourceMappingURL=dry-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run.d.ts","sourceRoot":"","sources":["../../../src/executor/dry-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAM3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,eAAe,CAqC5F"}
@@ -0,0 +1,39 @@
1
+ import { getLogger } from '../core/logger.js';
2
+ import { generateCid } from './order-id.js';
3
+ const log = () => getLogger();
4
+ export function dryRunExecute(intent, snapshot) {
5
+ const price = snapshot.ticker.lastPrice;
6
+ // Simulate slippage: 0.01-0.05%
7
+ const slippage = (Math.random() * 0.04 + 0.01) / 100;
8
+ const fillPrice = intent.direction === 'long'
9
+ ? price * (1 + slippage)
10
+ : price * (1 - slippage);
11
+ // Calculate size from sizePct or from meta (PM hedge uses fixed stake)
12
+ const capitalUsd = 5000; // simulated capital
13
+ let sizeUsd = capitalUsd * (intent.sizePct / 100);
14
+ if (sizeUsd === 0 && intent.meta?.stakeUsdc) {
15
+ sizeUsd = intent.meta.stakeUsdc;
16
+ }
17
+ if (sizeUsd === 0)
18
+ sizeUsd = 100; // minimum fallback
19
+ const fillSize = sizeUsd / fillPrice;
20
+ const cid = generateCid(intent.strategy);
21
+ log().info({
22
+ strategy: intent.strategy,
23
+ direction: intent.direction,
24
+ price: fillPrice.toFixed(2),
25
+ size: fillSize.toFixed(6),
26
+ sizeUsd: sizeUsd.toFixed(2),
27
+ cid,
28
+ mode: 'DRY-RUN',
29
+ }, `[DRY-RUN] ${intent.direction.toUpperCase()} ${intent.instrument}`);
30
+ return {
31
+ success: true,
32
+ orderId: cid,
33
+ fillPrice,
34
+ fillSize,
35
+ fee: sizeUsd * 0.001, // simulated 0.1% fee
36
+ timestamp: Date.now(),
37
+ };
38
+ }
39
+ //# sourceMappingURL=dry-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run.js","sourceRoot":"","sources":["../../../src/executor/dry-run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;AAE7B,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,QAAwB;IACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAA;IACvC,gCAAgC;IAChC,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAA;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,KAAK,MAAM;QAC3C,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;QACxB,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAA;IAE1B,uEAAuE;IACvE,MAAM,UAAU,GAAG,IAAI,CAAA,CAAC,oBAAoB;IAC5C,IAAI,OAAO,GAAG,UAAU,GAAG,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,CAAA;IACjD,IAAI,OAAO,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;QAC5C,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,SAAmB,CAAA;IAC3C,CAAC;IACD,IAAI,OAAO,KAAK,CAAC;QAAE,OAAO,GAAG,GAAG,CAAA,CAAC,mBAAmB;IACpD,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;IAEpC,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAExC,GAAG,EAAE,CAAC,IAAI,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3B,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACzB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3B,GAAG;QACH,IAAI,EAAE,SAAS;KAChB,EAAE,aAAa,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,CAAA;IAEtE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,GAAG;QACZ,SAAS;QACT,QAAQ;QACR,GAAG,EAAE,OAAO,GAAG,KAAK,EAAE,qBAAqB;QAC3C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAA;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function generateCid(strategy: string): string;
2
+ export declare function markCidSubmitted(cid: string): void;
3
+ export declare function isCidSubmitted(cid: string): boolean;
4
+ export declare function clearCids(): void;
5
+ //# sourceMappingURL=order-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order-id.d.ts","sourceRoot":"","sources":["../../../src/executor/order-id.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIpD;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,QAE3C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,SAAS,SAExB"}
@@ -0,0 +1,20 @@
1
+ import crypto from 'node:crypto';
2
+ // Generate a unique, idempotent client order ID
3
+ // Format: sentry-{strategy}-{timestamp}-{nonce}
4
+ export function generateCid(strategy) {
5
+ const ts = Math.floor(Date.now() / 1000);
6
+ const nonce = crypto.randomBytes(2).toString('hex');
7
+ return `sentry-${strategy.replace(/[^a-z0-9]/gi, '')}-${ts}-${nonce}`;
8
+ }
9
+ // Track submitted CIDs to prevent duplicates
10
+ const submittedCids = new Set();
11
+ export function markCidSubmitted(cid) {
12
+ submittedCids.add(cid);
13
+ }
14
+ export function isCidSubmitted(cid) {
15
+ return submittedCids.has(cid);
16
+ }
17
+ export function clearCids() {
18
+ submittedCids.clear();
19
+ }
20
+ //# sourceMappingURL=order-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order-id.js","sourceRoot":"","sources":["../../../src/executor/order-id.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAEhC,gDAAgD;AAChD,gDAAgD;AAChD,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnD,OAAO,UAAU,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,EAAE,CAAA;AACvE,CAAC;AAED,6CAA6C;AAC7C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAA;AAEvC,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,aAAa,CAAC,KAAK,EAAE,CAAA;AACvB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Order, OrderStatus } from './types.js';
2
+ export declare function trackOrder(order: Order): void;
3
+ export declare function getOrder(cid: string): Order | undefined;
4
+ export declare function updateOrderStatus(cid: string, status: OrderStatus, updates?: Partial<Order>): void;
5
+ export declare function getPendingOrders(): Order[];
6
+ export declare function getRecentOrders(limit?: number): Order[];
7
+ export declare function reconcile(): Promise<void>;
8
+ //# sourceMappingURL=reconciler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciler.d.ts","sourceRoot":"","sources":["../../../src/executor/reconciler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAOpD,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,QAEtC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAEvD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,QAM3F;AAED,wBAAgB,gBAAgB,IAAI,KAAK,EAAE,CAE1C;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAK,GAAG,KAAK,EAAE,CAInD;AAID,wBAAsB,SAAS,kBAe9B"}
@@ -0,0 +1,44 @@
1
+ import { getLogger } from '../core/logger.js';
2
+ const log = () => getLogger();
3
+ // In-memory order store (will be persisted to SQLite in future)
4
+ const orders = new Map();
5
+ export function trackOrder(order) {
6
+ orders.set(order.cid, order);
7
+ }
8
+ export function getOrder(cid) {
9
+ return orders.get(cid);
10
+ }
11
+ export function updateOrderStatus(cid, status, updates) {
12
+ const order = orders.get(cid);
13
+ if (!order)
14
+ return;
15
+ order.status = status;
16
+ order.updatedAt = Date.now();
17
+ if (updates)
18
+ Object.assign(order, updates);
19
+ }
20
+ export function getPendingOrders() {
21
+ return [...orders.values()].filter(o => o.status === 'PENDING' || o.status === 'ACCEPTED');
22
+ }
23
+ export function getRecentOrders(limit = 20) {
24
+ return [...orders.values()]
25
+ .sort((a, b) => b.createdAt - a.createdAt)
26
+ .slice(0, limit);
27
+ }
28
+ // Reconciliation: compare local state vs exchange state
29
+ // In a full implementation, this would call Bitfinex auth API
30
+ export async function reconcile() {
31
+ const pending = getPendingOrders();
32
+ if (pending.length === 0)
33
+ return;
34
+ log().info({ count: pending.length }, 'Reconciling pending orders');
35
+ for (const order of pending) {
36
+ const ageSec = (Date.now() - order.createdAt) / 1000;
37
+ // Timeout orders older than 5 minutes
38
+ if (ageSec > 300 && order.status === 'PENDING') {
39
+ updateOrderStatus(order.cid, 'TIMEOUT');
40
+ log().warn({ cid: order.cid, ageSec }, 'Order timed out');
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciler.js","sourceRoot":"","sources":["../../../src/executor/reconciler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAG7C,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;AAE7B,gEAAgE;AAChE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAA;AAEvC,MAAM,UAAU,UAAU,CAAC,KAAY;IACrC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,MAAmB,EAAE,OAAwB;IAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC7B,IAAI,CAAC,KAAK;QAAE,OAAM;IAClB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;IACrB,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC5B,IAAI,OAAO;QAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAA;AAC5F,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAK,GAAG,EAAE;IACxC,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;SACxB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;SACzC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AACpB,CAAC;AAED,wDAAwD;AACxD,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAA;IAClC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAEhC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAA;IAEnE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAA;QAEpD,sCAAsC;QACtC,IAAI,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/C,iBAAiB,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;YACvC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ export type OrderStatus = 'DRAFT' | 'PENDING' | 'ACCEPTED' | 'FILLED' | 'PARTIALLY_FILLED' | 'CANCELLED' | 'TIMEOUT' | 'RECONCILED';
2
+ export interface Order {
3
+ cid: string;
4
+ status: OrderStatus;
5
+ instrument: string;
6
+ direction: 'long' | 'short';
7
+ size: number;
8
+ price: number;
9
+ orderType: 'limit' | 'market';
10
+ exchangeOrderId?: string;
11
+ fillPrice?: number;
12
+ fillSize?: number;
13
+ fee?: number;
14
+ createdAt: number;
15
+ updatedAt: number;
16
+ retryCount: number;
17
+ strategyId: string;
18
+ }
19
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/executor/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,kBAAkB,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAA;AAEnI,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,WAAW,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/executor/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export declare function addCooldown(strategy: string, direction: 'long' | 'short', durationSec: number, reason: string): void;
2
+ export declare function isCoolingDown(strategy: string, direction: 'long' | 'short'): {
3
+ cooling: boolean;
4
+ reason?: string;
5
+ remainingSec?: number;
6
+ };
7
+ export declare function clearCooldowns(): void;
8
+ //# sourceMappingURL=cooldown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cooldown.d.ts","sourceRoot":"","sources":["../../../src/risk/cooldown.ts"],"names":[],"mappings":"AASA,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAO7G;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBzI;AAED,wBAAgB,cAAc,SAE7B"}
@@ -0,0 +1,30 @@
1
+ const cooldowns = [];
2
+ export function addCooldown(strategy, direction, durationSec, reason) {
3
+ cooldowns.push({
4
+ strategy,
5
+ direction,
6
+ reason,
7
+ expiresAt: Date.now() + durationSec * 1000,
8
+ });
9
+ }
10
+ export function isCoolingDown(strategy, direction) {
11
+ const now = Date.now();
12
+ // Clean expired
13
+ for (let i = cooldowns.length - 1; i >= 0; i--) {
14
+ if (cooldowns[i].expiresAt <= now)
15
+ cooldowns.splice(i, 1);
16
+ }
17
+ const active = cooldowns.find(c => c.strategy === strategy && c.direction === direction);
18
+ if (active) {
19
+ return {
20
+ cooling: true,
21
+ reason: active.reason,
22
+ remainingSec: Math.ceil((active.expiresAt - now) / 1000),
23
+ };
24
+ }
25
+ return { cooling: false };
26
+ }
27
+ export function clearCooldowns() {
28
+ cooldowns.length = 0;
29
+ }
30
+ //# sourceMappingURL=cooldown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cooldown.js","sourceRoot":"","sources":["../../../src/risk/cooldown.ts"],"names":[],"mappings":"AAOA,MAAM,SAAS,GAAoB,EAAE,CAAA;AAErC,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,SAA2B,EAAE,WAAmB,EAAE,MAAc;IAC5G,SAAS,CAAC,IAAI,CAAC;QACb,QAAQ;QACR,SAAS;QACT,MAAM;QACN,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,IAAI;KAC3C,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,SAA2B;IACzE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,gBAAgB;IAChB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG;YAAE,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA;IACxF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;SACzD,CAAA;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,SAAS,CAAC,MAAM,GAAG,CAAC,CAAA;AACtB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { TradeIntent } from '../strategy/types.js';
2
+ import type { AgentConfig } from '../core/config.js';
3
+ export interface PortfolioFilterResult {
4
+ passed: boolean;
5
+ reason?: string;
6
+ }
7
+ export declare function portfolioFilter(intent: TradeIntent, config: AgentConfig): PortfolioFilterResult;
8
+ export declare function resetCircuitBreaker(): void;
9
+ //# sourceMappingURL=portfolio-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio-filter.d.ts","sourceRoot":"","sources":["../../../src/risk/portfolio-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAYpD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAID,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,qBAAqB,CA0D/F;AAED,wBAAgB,mBAAmB,SAElC"}
@@ -0,0 +1,58 @@
1
+ import { getSameDirectionPct, getDailyPnl, getConsecutiveLosses, getLossStreakUsd, } from './position-manager.js';
2
+ import { wouldExceedVaR } from './var-calculator.js';
3
+ import { getLogger } from '../core/logger.js';
4
+ const log = () => getLogger();
5
+ let circuitBreakerUntil = 0;
6
+ export function portfolioFilter(intent, config) {
7
+ const portfolio = config.risk.portfolio;
8
+ // 1. Circuit breaker
9
+ if (Date.now() < circuitBreakerUntil) {
10
+ const remaining = Math.ceil((circuitBreakerUntil - Date.now()) / 60000);
11
+ return { passed: false, reason: `熔断中, ${remaining}min 后恢复` };
12
+ }
13
+ const cb = portfolio.circuit_breaker;
14
+ if (getConsecutiveLosses() >= cb.consecutive_losses) {
15
+ circuitBreakerUntil = Date.now() + cb.cooldown_minutes * 60000;
16
+ log().warn({ consecutiveLosses: getConsecutiveLosses() }, 'Circuit breaker triggered');
17
+ return { passed: false, reason: `连续亏损 ${getConsecutiveLosses()} 笔, 熔断 ${cb.cooldown_minutes}min` };
18
+ }
19
+ if (getLossStreakUsd() >= cb.loss_streak_usd) {
20
+ circuitBreakerUntil = Date.now() + cb.cooldown_minutes * 60000;
21
+ log().warn({ lossStreakUsd: getLossStreakUsd() }, 'Circuit breaker triggered (USD)');
22
+ return { passed: false, reason: `连亏 $${getLossStreakUsd().toFixed(0)}, 熔断 ${cb.cooldown_minutes}min` };
23
+ }
24
+ // 2. Daily loss limit
25
+ const maxDailyLoss = config.risk.max_daily_loss_usd;
26
+ if (Math.abs(getDailyPnl()) > maxDailyLoss && getDailyPnl() < 0) {
27
+ return { passed: false, reason: `日亏损已达 $${Math.abs(getDailyPnl()).toFixed(0)} (限额 $${maxDailyLoss})` };
28
+ }
29
+ // 3. Same direction concentration
30
+ const dirPct = getSameDirectionPct(intent.direction);
31
+ if (dirPct > portfolio.max_same_direction_pct) {
32
+ return { passed: false, reason: `${intent.direction} 方向集中度 ${dirPct.toFixed(0)}% > ${portfolio.max_same_direction_pct}%` };
33
+ }
34
+ // 4. VaR check
35
+ const intentUsd = intent.entryPrice * (intent.sizePct / 100) * config.risk.max_total_position_usd;
36
+ if (wouldExceedVaR(intentUsd, portfolio.max_portfolio_var_pct, config.risk.max_total_position_usd)) {
37
+ return { passed: false, reason: `VaR 将超限 (>${portfolio.max_portfolio_var_pct}%)` };
38
+ }
39
+ // 5. Trading hours (if enabled)
40
+ if (portfolio.trading_hours?.enabled && portfolio.trading_hours.active_windows) {
41
+ const now = new Date();
42
+ const utcHour = now.getUTCHours();
43
+ const utcMin = now.getUTCMinutes();
44
+ const utcTime = `${String(utcHour).padStart(2, '0')}:${String(utcMin).padStart(2, '0')}`;
45
+ const inWindow = portfolio.trading_hours.active_windows.some(w => {
46
+ return utcTime >= w.start && utcTime <= w.end;
47
+ });
48
+ if (!inWindow) {
49
+ return { passed: false, reason: `非交易时段 (UTC ${utcTime}), 仅允许平仓` };
50
+ }
51
+ }
52
+ log().debug({ strategy: intent.strategy }, 'Portfolio filter passed');
53
+ return { passed: true };
54
+ }
55
+ export function resetCircuitBreaker() {
56
+ circuitBreakerUntil = 0;
57
+ }
58
+ //# sourceMappingURL=portfolio-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio-filter.js","sourceRoot":"","sources":["../../../src/risk/portfolio-filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Position, TradeIntent, ExecutionResult } from '../strategy/types.js';
2
+ export declare function getPositions(): Position[];
3
+ export declare function getOpenPositionCount(): number;
4
+ export declare function getTotalPositionUsd(): number;
5
+ export declare function getSameDirectionPct(direction: 'long' | 'short'): number;
6
+ export declare function getDailyTrades(): number;
7
+ export declare function getDailyPnl(): number;
8
+ export declare function getConsecutiveLosses(): number;
9
+ export declare function getLossStreakUsd(): number;
10
+ export declare function openPosition(intent: TradeIntent, result: ExecutionResult): Position | null;
11
+ export declare function closePosition(posId: string, exitPrice: number, reason: string): number;
12
+ export declare function updatePositionPrices(currentPrice: number): void;
13
+ export declare function checkStopLossAndTakeProfit(currentPrice: number): {
14
+ posId: string;
15
+ reason: string;
16
+ pnl: number;
17
+ }[];
18
+ export declare function closeAllPositions(currentPrice: number): number;
19
+ //# sourceMappingURL=position-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"position-manager.d.ts","sourceRoot":"","sources":["../../../src/risk/position-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAuBlF,wBAAgB,YAAY,IAAI,QAAQ,EAAE,CAEzC;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAKvE;AAED,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAGpC;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,QAAQ,GAAG,IAAI,CA+B1F;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAwBtF;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,QAexD;AAED,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAkCjH;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAM9D"}