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,171 @@
1
+ import { addCooldown } from './cooldown.js';
2
+ const positions = [];
3
+ let dailyTrades = 0;
4
+ let dailyPnl = 0;
5
+ let consecutiveLosses = 0;
6
+ let lossStreakUsd = 0;
7
+ let lastResetDate = '';
8
+ function todayKey() {
9
+ return new Date().toISOString().slice(0, 10);
10
+ }
11
+ function resetDailyIfNeeded() {
12
+ const today = todayKey();
13
+ if (lastResetDate !== today) {
14
+ dailyTrades = 0;
15
+ dailyPnl = 0;
16
+ lastResetDate = today;
17
+ }
18
+ }
19
+ export function getPositions() {
20
+ return [...positions];
21
+ }
22
+ export function getOpenPositionCount() {
23
+ return positions.length;
24
+ }
25
+ export function getTotalPositionUsd() {
26
+ return positions.reduce((s, p) => s + p.sizeUsd, 0);
27
+ }
28
+ export function getSameDirectionPct(direction) {
29
+ const total = getTotalPositionUsd();
30
+ if (total === 0)
31
+ return 0;
32
+ const sameDir = positions.filter(p => p.direction === direction).reduce((s, p) => s + p.sizeUsd, 0);
33
+ return (sameDir / total) * 100;
34
+ }
35
+ export function getDailyTrades() {
36
+ resetDailyIfNeeded();
37
+ return dailyTrades;
38
+ }
39
+ export function getDailyPnl() {
40
+ resetDailyIfNeeded();
41
+ return dailyPnl;
42
+ }
43
+ export function getConsecutiveLosses() {
44
+ return consecutiveLosses;
45
+ }
46
+ export function getLossStreakUsd() {
47
+ return lossStreakUsd;
48
+ }
49
+ export function openPosition(intent, result) {
50
+ if (!result.success || !result.fillPrice || !result.fillSize)
51
+ return null;
52
+ resetDailyIfNeeded();
53
+ dailyTrades++;
54
+ const pos = {
55
+ id: intent.id,
56
+ strategy: intent.strategy,
57
+ direction: intent.direction,
58
+ instrument: intent.instrument,
59
+ entryPrice: result.fillPrice,
60
+ currentPrice: result.fillPrice,
61
+ size: result.fillSize,
62
+ sizeUsd: result.fillSize * result.fillPrice,
63
+ leverage: intent.leverage,
64
+ unrealizedPnl: 0,
65
+ unrealizedPnlPct: 0,
66
+ stopLoss: intent.direction === 'long'
67
+ ? result.fillPrice * (1 - intent.stopLossPct / 100)
68
+ : result.fillPrice * (1 + intent.stopLossPct / 100),
69
+ takeProfit: intent.direction === 'long'
70
+ ? result.fillPrice * (1 + intent.takeProfitPct / 100)
71
+ : result.fillPrice * (1 - intent.takeProfitPct / 100),
72
+ openedAt: Date.now(),
73
+ highWatermark: result.fillPrice,
74
+ trailingStopPct: intent.takeProfitPct,
75
+ };
76
+ positions.push(pos);
77
+ return pos;
78
+ }
79
+ export function closePosition(posId, exitPrice, reason) {
80
+ const idx = positions.findIndex(p => p.id === posId);
81
+ if (idx === -1)
82
+ return 0;
83
+ const pos = positions[idx];
84
+ const pnl = pos.direction === 'long'
85
+ ? (exitPrice - pos.entryPrice) * pos.size
86
+ : (pos.entryPrice - exitPrice) * pos.size;
87
+ resetDailyIfNeeded();
88
+ dailyPnl += pnl;
89
+ if (pnl < 0) {
90
+ consecutiveLosses++;
91
+ lossStreakUsd += Math.abs(pnl);
92
+ // Add cooldown on loss
93
+ addCooldown(pos.strategy, pos.direction, 300, `止损: ${reason}`);
94
+ }
95
+ else {
96
+ consecutiveLosses = 0;
97
+ lossStreakUsd = 0;
98
+ }
99
+ positions.splice(idx, 1);
100
+ return pnl;
101
+ }
102
+ export function updatePositionPrices(currentPrice) {
103
+ for (const pos of positions) {
104
+ pos.currentPrice = currentPrice;
105
+ pos.unrealizedPnl = pos.direction === 'long'
106
+ ? (currentPrice - pos.entryPrice) * pos.size
107
+ : (pos.entryPrice - currentPrice) * pos.size;
108
+ pos.unrealizedPnlPct = (pos.unrealizedPnl / pos.sizeUsd) * 100;
109
+ // Update high watermark for trailing stop
110
+ if (pos.direction === 'long' && currentPrice > pos.highWatermark) {
111
+ pos.highWatermark = currentPrice;
112
+ }
113
+ else if (pos.direction === 'short' && currentPrice < pos.highWatermark) {
114
+ pos.highWatermark = currentPrice;
115
+ }
116
+ }
117
+ }
118
+ export function checkStopLossAndTakeProfit(currentPrice) {
119
+ const closed = [];
120
+ for (const pos of [...positions]) {
121
+ let shouldClose = false;
122
+ let reason = '';
123
+ if (pos.direction === 'long') {
124
+ if (currentPrice <= pos.stopLoss) {
125
+ shouldClose = true;
126
+ reason = '触发止损';
127
+ }
128
+ if (currentPrice >= pos.takeProfit) {
129
+ shouldClose = true;
130
+ reason = '触发止盈';
131
+ }
132
+ }
133
+ else {
134
+ if (currentPrice >= pos.stopLoss) {
135
+ shouldClose = true;
136
+ reason = '触发止损';
137
+ }
138
+ if (currentPrice <= pos.takeProfit) {
139
+ shouldClose = true;
140
+ reason = '触发止盈';
141
+ }
142
+ }
143
+ // Trailing stop
144
+ if (pos.trailingStopPct && !shouldClose) {
145
+ const trailPrice = pos.direction === 'long'
146
+ ? pos.highWatermark * (1 - pos.trailingStopPct / 100)
147
+ : pos.highWatermark * (1 + pos.trailingStopPct / 100);
148
+ if (pos.direction === 'long' && currentPrice <= trailPrice) {
149
+ shouldClose = true;
150
+ reason = '移动止损';
151
+ }
152
+ else if (pos.direction === 'short' && currentPrice >= trailPrice) {
153
+ shouldClose = true;
154
+ reason = '移动止损';
155
+ }
156
+ }
157
+ if (shouldClose) {
158
+ const pnl = closePosition(pos.id, currentPrice, reason);
159
+ closed.push({ posId: pos.id, reason, pnl });
160
+ }
161
+ }
162
+ return closed;
163
+ }
164
+ export function closeAllPositions(currentPrice) {
165
+ let totalPnl = 0;
166
+ for (const pos of [...positions]) {
167
+ totalPnl += closePosition(pos.id, currentPrice, '手动全平');
168
+ }
169
+ return totalPnl;
170
+ }
171
+ //# sourceMappingURL=position-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"position-manager.js","sourceRoot":"","sources":["../../../src/risk/position-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,MAAM,SAAS,GAAe,EAAE,CAAA;AAChC,IAAI,WAAW,GAAG,CAAC,CAAA;AACnB,IAAI,QAAQ,GAAG,CAAC,CAAA;AAChB,IAAI,iBAAiB,GAAG,CAAC,CAAA;AACzB,IAAI,aAAa,GAAG,CAAC,CAAA;AACrB,IAAI,aAAa,GAAG,EAAE,CAAA;AAEtB,SAAS,QAAQ;IACf,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAC9C,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;IACxB,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;QAC5B,WAAW,GAAG,CAAC,CAAA;QACf,QAAQ,GAAG,CAAC,CAAA;QACZ,aAAa,GAAG,KAAK,CAAA;IACvB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,SAAS,CAAC,MAAM,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAA2B;IAC7D,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAA;IACnC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IACzB,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;IACnG,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,GAAG,CAAA;AAChC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,kBAAkB,EAAE,CAAA;IACpB,OAAO,WAAW,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,kBAAkB,EAAE,CAAA;IACpB,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,iBAAiB,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,CAAA;AACtB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,MAAuB;IACvE,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAEzE,kBAAkB,EAAE,CAAA;IACpB,WAAW,EAAE,CAAA;IAEb,MAAM,GAAG,GAAa;QACpB,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,MAAM,CAAC,SAAS;QAC5B,YAAY,EAAE,MAAM,CAAC,SAAS;QAC9B,IAAI,EAAE,MAAM,CAAC,QAAQ;QACrB,OAAO,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS;QAC3C,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,aAAa,EAAE,CAAC;QAChB,gBAAgB,EAAE,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC,SAAS,KAAK,MAAM;YACnC,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC;YACnD,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC;QACrD,UAAU,EAAE,MAAM,CAAC,SAAS,KAAK,MAAM;YACrC,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,GAAG,GAAG,CAAC;YACrD,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,GAAG,GAAG,CAAC;QACvD,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;QACpB,aAAa,EAAE,MAAM,CAAC,SAAS;QAC/B,eAAe,EAAE,MAAM,CAAC,aAAa;KACtC,CAAA;IAED,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACnB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,SAAiB,EAAE,MAAc;IAC5E,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAA;IACpD,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,CAAC,CAAA;IAExB,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC1B,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,KAAK,MAAM;QAClC,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,IAAI;QACzC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC,IAAI,CAAA;IAE3C,kBAAkB,EAAE,CAAA;IACpB,QAAQ,IAAI,GAAG,CAAA;IAEf,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAA;QACnB,aAAa,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC9B,uBAAuB;QACvB,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,MAAM,EAAE,CAAC,CAAA;IAChE,CAAC;SAAM,CAAC;QACN,iBAAiB,GAAG,CAAC,CAAA;QACrB,aAAa,GAAG,CAAC,CAAA;IACnB,CAAC;IAED,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACxB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,YAAoB;IACvD,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,GAAG,CAAC,YAAY,GAAG,YAAY,CAAA;QAC/B,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,SAAS,KAAK,MAAM;YAC1C,CAAC,CAAC,CAAC,YAAY,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,IAAI;YAC5C,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,YAAY,CAAC,GAAG,GAAG,CAAC,IAAI,CAAA;QAC9C,GAAG,CAAC,gBAAgB,GAAG,CAAC,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAA;QAE9D,0CAA0C;QAC1C,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,IAAI,YAAY,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC;YACjE,GAAG,CAAC,aAAa,GAAG,YAAY,CAAA;QAClC,CAAC;aAAM,IAAI,GAAG,CAAC,SAAS,KAAK,OAAO,IAAI,YAAY,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC;YACzE,GAAG,CAAC,aAAa,GAAG,YAAY,CAAA;QAClC,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,YAAoB;IAC7D,MAAM,MAAM,GAAqD,EAAE,CAAA;IAEnE,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;QACjC,IAAI,WAAW,GAAG,KAAK,CAAA;QACvB,IAAI,MAAM,GAAG,EAAE,CAAA;QAEf,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YAC7B,IAAI,YAAY,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAAC,WAAW,GAAG,IAAI,CAAC;gBAAC,MAAM,GAAG,MAAM,CAAA;YAAC,CAAC;YACzE,IAAI,YAAY,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;gBAAC,WAAW,GAAG,IAAI,CAAC;gBAAC,MAAM,GAAG,MAAM,CAAA;YAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,IAAI,YAAY,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAAC,WAAW,GAAG,IAAI,CAAC;gBAAC,MAAM,GAAG,MAAM,CAAA;YAAC,CAAC;YACzE,IAAI,YAAY,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;gBAAC,WAAW,GAAG,IAAI,CAAC;gBAAC,MAAM,GAAG,MAAM,CAAA;YAAC,CAAC;QAC7E,CAAC;QAED,gBAAgB;QAChB,IAAI,GAAG,CAAC,eAAe,IAAI,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,KAAK,MAAM;gBACzC,CAAC,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC;gBACrD,CAAC,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,CAAA;YACvD,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,IAAI,YAAY,IAAI,UAAU,EAAE,CAAC;gBAC3D,WAAW,GAAG,IAAI,CAAC;gBAAC,MAAM,GAAG,MAAM,CAAA;YACrC,CAAC;iBAAM,IAAI,GAAG,CAAC,SAAS,KAAK,OAAO,IAAI,YAAY,IAAI,UAAU,EAAE,CAAC;gBACnE,WAAW,GAAG,IAAI,CAAC;gBAAC,MAAM,GAAG,MAAM,CAAA;YACrC,CAAC;QACH,CAAC;QAED,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,CAAA;YACvD,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;QACjC,QAAQ,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,CAAA;IACzD,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { TradeIntent } from '../strategy/types.js';
2
+ import type { AgentConfig } from '../core/config.js';
3
+ export interface FilterResult {
4
+ passed: boolean;
5
+ reason?: string;
6
+ }
7
+ export declare function strategyFilter(intent: TradeIntent, config: AgentConfig): FilterResult;
8
+ //# sourceMappingURL=strategy-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy-filter.d.ts","sourceRoot":"","sources":["../../../src/risk/strategy-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAOpD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,YAAY,CA2CrF"}
@@ -0,0 +1,40 @@
1
+ import { isCoolingDown } from './cooldown.js';
2
+ import { getOpenPositionCount, getDailyTrades, getTotalPositionUsd, getPositions } from './position-manager.js';
3
+ import { getLogger } from '../core/logger.js';
4
+ const log = () => getLogger();
5
+ export function strategyFilter(intent, config) {
6
+ const risk = config.risk;
7
+ // 1. Max concurrent positions
8
+ if (getOpenPositionCount() >= risk.max_concurrent_positions) {
9
+ return { passed: false, reason: `持仓数已达上限 (${risk.max_concurrent_positions})` };
10
+ }
11
+ // 2. Max daily trades
12
+ if (getDailyTrades() >= risk.max_daily_trades) {
13
+ return { passed: false, reason: `日交易次数已达上限 (${risk.max_daily_trades})` };
14
+ }
15
+ // 3. Max total position
16
+ const intentUsd = intent.entryPrice * (intent.sizePct / 100) * risk.max_total_position_usd;
17
+ if (getTotalPositionUsd() + intentUsd > risk.max_total_position_usd) {
18
+ return { passed: false, reason: `总仓位将超限 ($${risk.max_total_position_usd})` };
19
+ }
20
+ // 4. Cooldown check
21
+ const cd = isCoolingDown(intent.strategy, intent.direction);
22
+ if (cd.cooling) {
23
+ return { passed: false, reason: `冷却中: ${cd.reason} (${cd.remainingSec}s)` };
24
+ }
25
+ // 5. Confidence threshold
26
+ if (intent.confidence < 30) {
27
+ return { passed: false, reason: `置信度过低 (${intent.confidence.toFixed(0)}% < 30%)` };
28
+ }
29
+ // 6. Conflict resolution
30
+ if (risk.conflict_resolution === 'conservative') {
31
+ const positions = getPositions();
32
+ const conflicting = positions.find(p => p.instrument === intent.instrument && p.direction !== intent.direction);
33
+ if (conflicting) {
34
+ return { passed: false, reason: `与现有 ${conflicting.direction} 持仓冲突 (保守模式)` };
35
+ }
36
+ }
37
+ log().debug({ strategy: intent.strategy, direction: intent.direction }, 'Strategy filter passed');
38
+ return { passed: true };
39
+ }
40
+ //# sourceMappingURL=strategy-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy-filter.js","sourceRoot":"","sources":["../../../src/risk/strategy-filter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAC/G,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAE7C,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;AAO7B,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,MAAmB;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;IAExB,8BAA8B;IAC9B,IAAI,oBAAoB,EAAE,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC5D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,IAAI,CAAC,wBAAwB,GAAG,EAAE,CAAA;IAChF,CAAC;IAED,sBAAsB;IACtB,IAAI,cAAc,EAAE,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAA;IAC1E,CAAC;IAED,wBAAwB;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAA;IAC1F,IAAI,mBAAmB,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAA;IAC9E,CAAC;IAED,oBAAoB;IACpB,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;IAC3D,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,YAAY,IAAI,EAAE,CAAA;IAC7E,CAAC;IAED,0BAA0B;IAC1B,IAAI,MAAM,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IACpF,CAAC;IAED,yBAAyB;IACzB,IAAI,IAAI,CAAC,mBAAmB,KAAK,cAAc,EAAE,CAAC;QAChD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;QAChC,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CACrC,CAAC,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,SAAS,CACvE,CAAA;QACD,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,WAAW,CAAC,SAAS,cAAc,EAAE,CAAA;QAC9E,CAAC;IACH,CAAC;IAED,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,EAAE,wBAAwB,CAAC,CAAA;IACjG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;AACzB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare function addReturn(returnPct: number): void;
2
+ export declare function calculateVaR(confidence?: number): number;
3
+ export declare function wouldExceedVaR(additionalUsd: number, maxVarPct: number, totalCapital: number): boolean;
4
+ export declare function getVarStats(): {
5
+ var95: number;
6
+ returnsCount: number;
7
+ worstReturn: number;
8
+ avgReturn: number;
9
+ };
10
+ //# sourceMappingURL=var-calculator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"var-calculator.d.ts","sourceRoot":"","sources":["../../../src/risk/var-calculator.ts"],"names":[],"mappings":"AASA,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,QAG1C;AAED,wBAAgB,YAAY,CAAC,UAAU,GAAE,MAAa,GAAG,MAAM,CAU9D;AAED,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAWtG;AAED,wBAAgB,WAAW,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAM7G"}
@@ -0,0 +1,38 @@
1
+ // Simplified VaR calculator based on historical BTC returns
2
+ // Uses position sizing to estimate portfolio VaR
3
+ import { getTotalPositionUsd } from './position-manager.js';
4
+ // Rolling window of hourly BTC returns
5
+ const returnsHistory = [];
6
+ const MAX_RETURNS = 168; // 7 days of hourly data
7
+ export function addReturn(returnPct) {
8
+ returnsHistory.push(returnPct);
9
+ if (returnsHistory.length > MAX_RETURNS)
10
+ returnsHistory.shift();
11
+ }
12
+ export function calculateVaR(confidence = 0.95) {
13
+ if (returnsHistory.length < 24)
14
+ return 0; // need at least 24h
15
+ const sorted = [...returnsHistory].sort((a, b) => a - b);
16
+ const idx = Math.floor((1 - confidence) * sorted.length);
17
+ const tailReturn = sorted[idx] || sorted[0];
18
+ const totalUsd = getTotalPositionUsd();
19
+ // VaR = position * worst-case return at confidence level
20
+ return Math.abs(tailReturn * totalUsd);
21
+ }
22
+ export function wouldExceedVaR(additionalUsd, maxVarPct, totalCapital) {
23
+ if (returnsHistory.length < 24)
24
+ return false; // not enough data to judge
25
+ const sorted = [...returnsHistory].sort((a, b) => a - b);
26
+ const tailReturn = sorted[Math.floor(0.05 * sorted.length)] || sorted[0];
27
+ const currentUsd = getTotalPositionUsd();
28
+ const projectedVar = Math.abs(tailReturn * (currentUsd + additionalUsd));
29
+ const maxVar = totalCapital * (maxVarPct / 100);
30
+ return projectedVar > maxVar;
31
+ }
32
+ export function getVarStats() {
33
+ const var95 = calculateVaR(0.95);
34
+ const worst = returnsHistory.length > 0 ? Math.min(...returnsHistory) : 0;
35
+ const avg = returnsHistory.length > 0 ? returnsHistory.reduce((a, b) => a + b, 0) / returnsHistory.length : 0;
36
+ return { var95, returnsCount: returnsHistory.length, worstReturn: worst, avgReturn: avg };
37
+ }
38
+ //# sourceMappingURL=var-calculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"var-calculator.js","sourceRoot":"","sources":["../../../src/risk/var-calculator.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,iDAAiD;AAEjD,OAAO,EAAE,mBAAmB,EAAgB,MAAM,uBAAuB,CAAA;AAEzE,uCAAuC;AACvC,MAAM,cAAc,GAAa,EAAE,CAAA;AACnC,MAAM,WAAW,GAAG,GAAG,CAAA,CAAC,wBAAwB;AAEhD,MAAM,UAAU,SAAS,CAAC,SAAiB;IACzC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC9B,IAAI,cAAc,CAAC,MAAM,GAAG,WAAW;QAAE,cAAc,CAAC,KAAK,EAAE,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,aAAqB,IAAI;IACpD,IAAI,cAAc,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,CAAC,CAAA,CAAC,oBAAoB;IAE7D,MAAM,MAAM,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACxD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IAE3C,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAA;IACtC,yDAAyD;IACzD,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,aAAqB,EAAE,SAAiB,EAAE,YAAoB;IAC3F,IAAI,cAAc,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAA,CAAC,2BAA2B;IAExE,MAAM,MAAM,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IAExE,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IACxC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,UAAU,GAAG,aAAa,CAAC,CAAC,CAAA;IACxE,MAAM,MAAM,GAAG,YAAY,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,CAAA;IAE/C,OAAO,YAAY,GAAG,MAAM,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACzE,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAE7G,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;AAC3F,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { MarketSnapshot } from '../collector/types.js';
2
+ import type { Signal } from './types.js';
3
+ export declare function generateFundingSignals(snapshot: MarketSnapshot): Signal[];
4
+ //# sourceMappingURL=funding-radar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funding-radar.d.ts","sourceRoot":"","sources":["../../../src/signal/funding-radar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CA8FzE"}
@@ -0,0 +1,92 @@
1
+ export function generateFundingSignals(snapshot) {
2
+ const { funding, fundingCurrent, deriv } = snapshot;
3
+ const now = snapshot.timestamp;
4
+ const signals = [];
5
+ if (!fundingCurrent || funding.length < 10)
6
+ return signals;
7
+ const frr = fundingCurrent.frr;
8
+ const utilization = fundingCurrent.utilization;
9
+ const spareCapacity = 1 - utilization;
10
+ // Calculate percentiles
11
+ const allFrr = funding.map(f => f.frr).sort((a, b) => a - b);
12
+ const frrPct = percentile(frr, allFrr);
13
+ // 1h rate change
14
+ const prev1h = funding.find(f => f.timestamp <= now - 3600_000);
15
+ const rateChange1h = prev1h && prev1h.frr !== 0 ? (frr - prev1h.frr) / Math.abs(prev1h.frr) : 0;
16
+ // 24h supply delta
17
+ const prev24h = funding.find(f => f.timestamp <= now - 86400_000);
18
+ const supplyDelta24h = prev24h && prev24h.totalAmount > 0
19
+ ? (fundingCurrent.totalAmount - prev24h.totalAmount) / prev24h.totalAmount
20
+ : 0;
21
+ const annualizedRate = frr * 365 * 100;
22
+ const derivAnnualized = deriv ? deriv.fundingRate * 3 * 365 * 100 : 0;
23
+ // S1: 适合放贷
24
+ if (frrPct >= 0.75 && utilization >= 0.80 && spareCapacity < 0.15) {
25
+ const conf = frrPct >= 0.90 ? 85 : 70;
26
+ signals.push({
27
+ id: 'FR-S1',
28
+ module: 'funding',
29
+ direction: 'neutral',
30
+ confidence: conf,
31
+ level: 'yellow',
32
+ title: '适合放贷',
33
+ summary: `FRR P${(frrPct * 100).toFixed(0)}, 利用率 ${(utilization * 100).toFixed(1)}%, 年化 ${annualizedRate.toFixed(1)}%`,
34
+ details: {
35
+ frr, frrPct, utilization, spareCapacity,
36
+ annualizedRate, suggestedPeriod: frrPct >= 0.90 ? 30 : 7,
37
+ },
38
+ timestamp: now,
39
+ });
40
+ }
41
+ // S2: 不适合借杠杆
42
+ if (frrPct >= 0.90 && utilization >= 0.90) {
43
+ signals.push({
44
+ id: 'FR-S2',
45
+ module: 'funding',
46
+ direction: 'neutral',
47
+ confidence: 80,
48
+ level: 'red',
49
+ title: '不适合借杠杆',
50
+ summary: `FRR P${(frrPct * 100).toFixed(0)}, 利用率 ${(utilization * 100).toFixed(1)}%, 费率飙升 ${(rateChange1h * 100).toFixed(1)}%/h`,
51
+ details: { frr, frrPct, utilization, rateChange1h, derivAnnualized },
52
+ timestamp: now,
53
+ });
54
+ }
55
+ // S3: 利率即将回落
56
+ const utilChange1h = prev1h ? utilization - prev1h.utilization : 0;
57
+ if (supplyDelta24h > 0.02 && utilChange1h < 0) {
58
+ signals.push({
59
+ id: 'FR-S3',
60
+ module: 'funding',
61
+ direction: 'neutral',
62
+ confidence: 60,
63
+ level: 'yellow',
64
+ title: '利率即将回落',
65
+ summary: `供给恢复 ${(supplyDelta24h * 100).toFixed(1)}%, 利用率下降中`,
66
+ details: { supplyDelta24h, utilChange1h, frr },
67
+ timestamp: now,
68
+ });
69
+ }
70
+ // S4: 正常 (no special condition)
71
+ if (signals.length === 0) {
72
+ signals.push({
73
+ id: 'FR-S4',
74
+ module: 'funding',
75
+ direction: 'neutral',
76
+ confidence: 30,
77
+ level: 'green',
78
+ title: '融资市场正常',
79
+ summary: `FRR P${(frrPct * 100).toFixed(0)}, 利用率 ${(utilization * 100).toFixed(1)}%`,
80
+ details: { frr, frrPct, utilization, annualizedRate },
81
+ timestamp: now,
82
+ });
83
+ }
84
+ return signals;
85
+ }
86
+ function percentile(value, sorted) {
87
+ if (sorted.length === 0)
88
+ return 0;
89
+ const idx = sorted.findIndex(v => v >= value);
90
+ return idx >= 0 ? idx / sorted.length : 1;
91
+ }
92
+ //# sourceMappingURL=funding-radar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funding-radar.js","sourceRoot":"","sources":["../../../src/signal/funding-radar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { MarketSnapshot } from '../collector/types.js';
2
+ import type { Signal } from './types.js';
3
+ export type { Signal } from './types.js';
4
+ export declare function generateAllSignals(snapshot: MarketSnapshot): Signal[];
5
+ export declare function signalSummary(signals: Signal[]): {
6
+ direction: 'long' | 'short' | 'neutral';
7
+ confidence: number;
8
+ bullish: number;
9
+ bearish: number;
10
+ neutral: number;
11
+ };
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/signal/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAMxC,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CAOrE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IAChD,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,CAwBA"}
@@ -0,0 +1,37 @@
1
+ import { generateSmartMoneySignals } from './smart-money.js';
2
+ import { generateFundingSignals } from './funding-radar.js';
3
+ import { generateLiquidationSignals } from './liquidation.js';
4
+ import { generateOrderbookSignals } from './orderbook.js';
5
+ export function generateAllSignals(snapshot) {
6
+ return [
7
+ ...generateSmartMoneySignals(snapshot),
8
+ ...generateFundingSignals(snapshot),
9
+ ...generateLiquidationSignals(snapshot),
10
+ ...generateOrderbookSignals(snapshot),
11
+ ];
12
+ }
13
+ export function signalSummary(signals) {
14
+ let bullish = 0;
15
+ let bearish = 0;
16
+ let neutral = 0;
17
+ let bullWeight = 0;
18
+ let bearWeight = 0;
19
+ for (const s of signals) {
20
+ if (s.direction === 'long') {
21
+ bullish++;
22
+ bullWeight += s.confidence;
23
+ }
24
+ else if (s.direction === 'short') {
25
+ bearish++;
26
+ bearWeight += s.confidence;
27
+ }
28
+ else {
29
+ neutral++;
30
+ }
31
+ }
32
+ const total = bullWeight + bearWeight;
33
+ const direction = total === 0 ? 'neutral' : bullWeight > bearWeight ? 'long' : bullWeight < bearWeight ? 'short' : 'neutral';
34
+ const confidence = total > 0 ? Math.abs(bullWeight - bearWeight) / total * 100 : 0;
35
+ return { direction, confidence, bullish, bearish, neutral };
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/signal/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAIzD,MAAM,UAAU,kBAAkB,CAAC,QAAwB;IACzD,OAAO;QACL,GAAG,yBAAyB,CAAC,QAAQ,CAAC;QACtC,GAAG,sBAAsB,CAAC,QAAQ,CAAC;QACnC,GAAG,0BAA0B,CAAC,QAAQ,CAAC;QACvC,GAAG,wBAAwB,CAAC,QAAQ,CAAC;KACtC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAiB;IAO7C,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,UAAU,GAAG,CAAC,CAAA;IAElB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAA;YACT,UAAU,IAAI,CAAC,CAAC,UAAU,CAAA;QAC5B,CAAC;aAAM,IAAI,CAAC,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;YACnC,OAAO,EAAE,CAAA;YACT,UAAU,IAAI,CAAC,CAAC,UAAU,CAAA;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAA;IACrC,MAAM,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;IAC5H,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAElF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA;AAC7D,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { MarketSnapshot } from '../collector/types.js';
2
+ import type { Signal } from './types.js';
3
+ export declare function generateLiquidationSignals(snapshot: MarketSnapshot): Signal[];
4
+ //# sourceMappingURL=liquidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liquidation.d.ts","sourceRoot":"","sources":["../../../src/signal/liquidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CAkF7E"}
@@ -0,0 +1,83 @@
1
+ export function generateLiquidationSignals(snapshot) {
2
+ const { liqAgg, liqIntensityPct, trades, ticker } = snapshot;
3
+ const now = snapshot.timestamp;
4
+ const signals = [];
5
+ const { w5m } = liqAgg;
6
+ const liq5mTotal = w5m.longUsd + w5m.shortUsd;
7
+ const dominance = liq5mTotal > 0 ? Math.max(w5m.longUsd, w5m.shortUsd) / liq5mTotal : 0;
8
+ const dominanceSide = w5m.longUsd >= w5m.shortUsd ? 'long' : 'short';
9
+ // Price change in 3 min window
10
+ const recentTrades = trades.filter(t => t.timestamp >= now - 180_000);
11
+ const oldest = recentTrades.length > 0 ? recentTrades[recentTrades.length - 1].price : ticker.lastPrice;
12
+ const priceChange3m = oldest > 0 ? (ticker.lastPrice - oldest) / oldest : 0;
13
+ const pct = liqIntensityPct;
14
+ // LQ1/LQ2: 顺势追击
15
+ if (pct >= 0.85 && dominance > 0.70 && Math.abs(priceChange3m) > 0.003) {
16
+ const isLongLiq = dominanceSide === 'long'; // longs getting liquidated → price dropping → short
17
+ const dir = isLongLiq ? 'short' : 'long';
18
+ const conf = Math.min(85, 55 + (pct - 0.85) * 200);
19
+ signals.push({
20
+ id: isLongLiq ? 'LQ-1' : 'LQ-2',
21
+ module: 'liquidation',
22
+ direction: dir,
23
+ confidence: conf,
24
+ level: 'red',
25
+ title: `顺势追击 ${dir === 'long' ? '做多' : '做空'}`,
26
+ summary: `爆仓强度 P${(pct * 100).toFixed(0)}, ${dominanceSide === 'long' ? '多' : '空'}头主导 ${(dominance * 100).toFixed(0)}%, 价格 ${(priceChange3m * 100).toFixed(2)}%`,
27
+ details: {
28
+ intensity: pct,
29
+ dominance,
30
+ dominanceSide,
31
+ priceChange3m,
32
+ liq5m: { longUsd: w5m.longUsd, shortUsd: w5m.shortUsd },
33
+ },
34
+ timestamp: now,
35
+ });
36
+ }
37
+ // LQ3: 反转博弈
38
+ if (pct >= 0.95 && Math.abs(priceChange3m) < 0.001) {
39
+ const dir = dominanceSide === 'long' ? 'long' : 'short'; // reversal: opposite of liquidation side
40
+ signals.push({
41
+ id: 'LQ-3',
42
+ module: 'liquidation',
43
+ direction: dir,
44
+ confidence: 55,
45
+ level: 'yellow',
46
+ title: '反转博弈',
47
+ summary: `极端爆仓 P${(pct * 100).toFixed(0)} 但价格停滞, 需盘口确认`,
48
+ details: {
49
+ intensity: pct,
50
+ priceChange3m,
51
+ requiresObConfirm: true,
52
+ },
53
+ timestamp: now,
54
+ });
55
+ }
56
+ // LQ4: 观望
57
+ if (signals.length === 0) {
58
+ signals.push({
59
+ id: 'LQ-4',
60
+ module: 'liquidation',
61
+ direction: 'neutral',
62
+ confidence: 25,
63
+ level: 'green',
64
+ title: '爆仓市场平稳',
65
+ summary: `强度 P${(pct * 100).toFixed(0)}, 24h 爆仓 $${fmtUsd(liqAgg.w24h.total)}`,
66
+ details: {
67
+ intensity: pct,
68
+ w24h: liqAgg.w24h,
69
+ w1h: liqAgg.w1h,
70
+ },
71
+ timestamp: now,
72
+ });
73
+ }
74
+ return signals;
75
+ }
76
+ function fmtUsd(n) {
77
+ if (n >= 1e6)
78
+ return `${(n / 1e6).toFixed(1)}M`;
79
+ if (n >= 1e3)
80
+ return `${(n / 1e3).toFixed(0)}K`;
81
+ return n.toFixed(0);
82
+ }
83
+ //# sourceMappingURL=liquidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liquidation.js","sourceRoot":"","sources":["../../../src/signal/liquidation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { MarketSnapshot } from '../collector/types.js';
2
+ import type { Signal } from './types.js';
3
+ export declare function generateOrderbookSignals(snapshot: MarketSnapshot): Signal[];
4
+ //# sourceMappingURL=orderbook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orderbook.d.ts","sourceRoot":"","sources":["../../../src/signal/orderbook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CA0G3E"}