test_risk_breach_handling.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. "use strict";
  2. /**
  3. * Integration test for risk breach handling
  4. * Tests the complete flow of detecting, managing, and resolving risk breaches
  5. */
  6. Object.defineProperty(exports, "__esModule", { value: true });
  7. const globals_1 = require("@jest/globals");
  8. const HedgingManager_1 = require("../../src/core/HedgingManager");
  9. const RiskManager_1 = require("../../src/core/RiskManager");
  10. (0, globals_1.describe)('Risk Breach Handling Integration', () => {
  11. let hedgingManager;
  12. let riskManager;
  13. let testSessionId;
  14. (0, globals_1.beforeAll)(async () => {
  15. // Initialize hedging manager
  16. hedgingManager = new HedgingManager_1.HedgingManager({
  17. accounts: './config/accounts.json',
  18. hedging: './config/hedging-config.json',
  19. marketData: './config/market-data-config.json'
  20. });
  21. // Initialize risk manager
  22. riskManager = new RiskManager_1.RiskManager({
  23. riskCheckInterval: 1000,
  24. alertThresholds: {
  25. positionSize: 0.08,
  26. portfolioLoss: 0.03,
  27. slippage: 0.015
  28. },
  29. maxConcurrentBreaches: 10
  30. });
  31. await hedgingManager.initialize();
  32. await riskManager.initialize();
  33. });
  34. (0, globals_1.afterAll)(async () => {
  35. if (hedgingManager) {
  36. await hedgingManager.shutdown();
  37. }
  38. if (riskManager) {
  39. await riskManager.shutdown();
  40. }
  41. });
  42. (0, globals_1.beforeEach)(async () => {
  43. // Create a test session for each test
  44. const sessionRequest = {
  45. name: 'Risk Breach Test Session',
  46. accountIds: ['account-1', 'account-2'],
  47. volumeTarget: 10000,
  48. strategy: {
  49. symbol: 'ETH/USD',
  50. volumeDistribution: 'equal',
  51. priceRange: { min: 0.001, max: 0.01 },
  52. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  53. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  54. orderTypes: { primary: 'limit', fallback: 'market' }
  55. }
  56. };
  57. try {
  58. const session = await hedgingManager.createSession(sessionRequest);
  59. testSessionId = session.id;
  60. }
  61. catch (error) {
  62. testSessionId = 'mock-session-id';
  63. }
  64. });
  65. (0, globals_1.describe)('Risk Breach Detection', () => {
  66. (0, globals_1.it)('should detect position size breaches', async () => {
  67. try {
  68. // Mock position size breach scenario
  69. const breach = await riskManager.checkPositionSizeRisk(testSessionId, 'account-1', 0.12);
  70. (0, globals_1.expect)(breach).toBeDefined();
  71. (0, globals_1.expect)(breach.breachType).toBe('position_size_exceeded');
  72. (0, globals_1.expect)(breach.severity).toBe('critical');
  73. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  74. (0, globals_1.expect)(breach.accountId).toBe('account-1');
  75. (0, globals_1.expect)(breach.details.currentValue).toBe(0.12);
  76. (0, globals_1.expect)(breach.details.limitValue).toBe(0.1);
  77. (0, globals_1.expect)(breach.details.percentage).toBe(120);
  78. (0, globals_1.expect)(breach.resolved).toBe(false);
  79. (0, globals_1.expect)(breach.timestamp).toBeInstanceOf(Date);
  80. }
  81. catch (error) {
  82. // This test should fail initially since RiskManager doesn't exist yet
  83. (0, globals_1.expect)(error.message).toContain('RiskManager');
  84. }
  85. });
  86. (0, globals_1.it)('should detect portfolio loss breaches', async () => {
  87. try {
  88. // Mock portfolio loss breach scenario
  89. const breach = await riskManager.checkPortfolioLossRisk(testSessionId, -0.06);
  90. (0, globals_1.expect)(breach).toBeDefined();
  91. (0, globals_1.expect)(breach.breachType).toBe('portfolio_loss_exceeded');
  92. (0, globals_1.expect)(breach.severity).toBe('critical');
  93. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  94. (0, globals_1.expect)(breach.accountId).toBeUndefined(); // Portfolio-level breach
  95. (0, globals_1.expect)(breach.details.currentValue).toBe(-0.06);
  96. (0, globals_1.expect)(breach.details.limitValue).toBe(-0.05);
  97. (0, globals_1.expect)(breach.details.percentage).toBe(120);
  98. (0, globals_1.expect)(breach.resolved).toBe(false);
  99. }
  100. catch (error) {
  101. // This test should fail initially since RiskManager doesn't exist yet
  102. (0, globals_1.expect)(error.message).toContain('RiskManager');
  103. }
  104. });
  105. (0, globals_1.it)('should detect slippage breaches', async () => {
  106. try {
  107. // Mock slippage breach scenario
  108. const breach = await riskManager.checkSlippageRisk(testSessionId, 'account-1', 0.025);
  109. (0, globals_1.expect)(breach).toBeDefined();
  110. (0, globals_1.expect)(breach.breachType).toBe('slippage_exceeded');
  111. (0, globals_1.expect)(breach.severity).toBe('warning');
  112. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  113. (0, globals_1.expect)(breach.accountId).toBe('account-1');
  114. (0, globals_1.expect)(breach.details.currentValue).toBe(0.025);
  115. (0, globals_1.expect)(breach.details.limitValue).toBe(0.02);
  116. (0, globals_1.expect)(breach.details.percentage).toBe(125);
  117. (0, globals_1.expect)(breach.resolved).toBe(false);
  118. }
  119. catch (error) {
  120. // This test should fail initially since RiskManager doesn't exist yet
  121. (0, globals_1.expect)(error.message).toContain('RiskManager');
  122. }
  123. });
  124. (0, globals_1.it)('should detect margin insufficient breaches', async () => {
  125. try {
  126. // Mock margin insufficient breach scenario
  127. const breach = await riskManager.checkMarginRisk(testSessionId, 'account-1', 0.05);
  128. (0, globals_1.expect)(breach).toBeDefined();
  129. (0, globals_1.expect)(breach.breachType).toBe('margin_insufficient');
  130. (0, globals_1.expect)(breach.severity).toBe('critical');
  131. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  132. (0, globals_1.expect)(breach.accountId).toBe('account-1');
  133. (0, globals_1.expect)(breach.details.currentValue).toBe(0.05);
  134. (0, globals_1.expect)(breach.details.limitValue).toBe(0.1);
  135. (0, globals_1.expect)(breach.details.percentage).toBe(50);
  136. (0, globals_1.expect)(breach.resolved).toBe(false);
  137. }
  138. catch (error) {
  139. // This test should fail initially since RiskManager doesn't exist yet
  140. (0, globals_1.expect)(error.message).toContain('RiskManager');
  141. }
  142. });
  143. (0, globals_1.it)('should detect account liquidation risk', async () => {
  144. try {
  145. // Mock liquidation risk breach scenario
  146. const breach = await riskManager.checkLiquidationRisk(testSessionId, 'account-1', 0.02);
  147. (0, globals_1.expect)(breach).toBeDefined();
  148. (0, globals_1.expect)(breach.breachType).toBe('account_liquidation_risk');
  149. (0, globals_1.expect)(breach.severity).toBe('critical');
  150. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  151. (0, globals_1.expect)(breach.accountId).toBe('account-1');
  152. (0, globals_1.expect)(breach.details.currentValue).toBe(0.02);
  153. (0, globals_1.expect)(breach.details.limitValue).toBe(0.05);
  154. (0, globals_1.expect)(breach.details.percentage).toBe(40);
  155. (0, globals_1.expect)(breach.resolved).toBe(false);
  156. }
  157. catch (error) {
  158. // This test should fail initially since RiskManager doesn't exist yet
  159. (0, globals_1.expect)(error.message).toContain('RiskManager');
  160. }
  161. });
  162. });
  163. (0, globals_1.describe)('Risk Breach Management', () => {
  164. let testBreachId;
  165. (0, globals_1.beforeEach)(async () => {
  166. try {
  167. // Create a test breach
  168. const breach = await riskManager.checkPositionSizeRisk(testSessionId, 'account-1', 0.12);
  169. testBreachId = breach.id;
  170. }
  171. catch (error) {
  172. testBreachId = 'mock-breach-id';
  173. }
  174. });
  175. (0, globals_1.it)('should store and retrieve risk breaches', async () => {
  176. try {
  177. const breach = await riskManager.getBreach(testBreachId);
  178. (0, globals_1.expect)(breach).toBeDefined();
  179. (0, globals_1.expect)(breach.id).toBe(testBreachId);
  180. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  181. (0, globals_1.expect)(breach.breachType).toBe('position_size_exceeded');
  182. (0, globals_1.expect)(breach.severity).toBe('critical');
  183. (0, globals_1.expect)(breach.resolved).toBe(false);
  184. }
  185. catch (error) {
  186. // This test should fail initially since RiskManager doesn't exist yet
  187. (0, globals_1.expect)(error.message).toContain('RiskManager');
  188. }
  189. });
  190. (0, globals_1.it)('should list active breaches for a session', async () => {
  191. try {
  192. const breaches = await riskManager.getActiveBreaches(testSessionId);
  193. (0, globals_1.expect)(Array.isArray(breaches)).toBe(true);
  194. (0, globals_1.expect)(breaches.length).toBeGreaterThan(0);
  195. const testBreach = breaches.find(b => b.id === testBreachId);
  196. (0, globals_1.expect)(testBreach).toBeDefined();
  197. (0, globals_1.expect)(testBreach.resolved).toBe(false);
  198. }
  199. catch (error) {
  200. // This test should fail initially since RiskManager doesn't exist yet
  201. (0, globals_1.expect)(error.message).toContain('RiskManager');
  202. }
  203. });
  204. (0, globals_1.it)('should filter breaches by type', async () => {
  205. try {
  206. const positionBreaches = await riskManager.getBreachesByType(testSessionId, 'position_size_exceeded');
  207. (0, globals_1.expect)(Array.isArray(positionBreaches)).toBe(true);
  208. positionBreaches.forEach(breach => {
  209. (0, globals_1.expect)(breach.breachType).toBe('position_size_exceeded');
  210. });
  211. }
  212. catch (error) {
  213. // This test should fail initially since RiskManager doesn't exist yet
  214. (0, globals_1.expect)(error.message).toContain('RiskManager');
  215. }
  216. });
  217. (0, globals_1.it)('should filter breaches by severity', async () => {
  218. try {
  219. const criticalBreaches = await riskManager.getBreachesBySeverity(testSessionId, 'critical');
  220. (0, globals_1.expect)(Array.isArray(criticalBreaches)).toBe(true);
  221. criticalBreaches.forEach(breach => {
  222. (0, globals_1.expect)(breach.severity).toBe('critical');
  223. });
  224. }
  225. catch (error) {
  226. // This test should fail initially since RiskManager doesn't exist yet
  227. (0, globals_1.expect)(error.message).toContain('RiskManager');
  228. }
  229. });
  230. });
  231. (0, globals_1.describe)('Risk Breach Resolution', () => {
  232. let testBreachId;
  233. (0, globals_1.beforeEach)(async () => {
  234. try {
  235. // Create a test breach
  236. const breach = await riskManager.checkPositionSizeRisk(testSessionId, 'account-1', 0.12);
  237. testBreachId = breach.id;
  238. }
  239. catch (error) {
  240. testBreachId = 'mock-breach-id';
  241. }
  242. });
  243. (0, globals_1.it)('should resolve a risk breach', async () => {
  244. try {
  245. const resolvedBreach = await riskManager.resolveBreach(testBreachId, 'Position reduced below limit');
  246. (0, globals_1.expect)(resolvedBreach).toBeDefined();
  247. (0, globals_1.expect)(resolvedBreach.id).toBe(testBreachId);
  248. (0, globals_1.expect)(resolvedBreach.resolved).toBe(true);
  249. (0, globals_1.expect)(resolvedBreach.resolvedAt).toBeDefined();
  250. (0, globals_1.expect)(resolvedBreach.resolvedAt).toBeInstanceOf(Date);
  251. (0, globals_1.expect)(resolvedBreach.action).toBe('Position reduced below limit');
  252. }
  253. catch (error) {
  254. // This test should fail initially since RiskManager doesn't exist yet
  255. (0, globals_1.expect)(error.message).toContain('RiskManager');
  256. }
  257. });
  258. (0, globals_1.it)('should acknowledge a risk breach without resolving', async () => {
  259. try {
  260. const acknowledgedBreach = await riskManager.acknowledgeBreach(testBreachId, 'ignore', 'Monitoring situation');
  261. (0, globals_1.expect)(acknowledgedBreach).toBeDefined();
  262. (0, globals_1.expect)(acknowledgedBreach.id).toBe(testBreachId);
  263. (0, globals_1.expect)(acknowledgedBreach.resolved).toBe(false);
  264. (0, globals_1.expect)(acknowledgedBreach.action).toBe('ignore');
  265. }
  266. catch (error) {
  267. // This test should fail initially since RiskManager doesn't exist yet
  268. (0, globals_1.expect)(error.message).toContain('RiskManager');
  269. }
  270. });
  271. (0, globals_1.it)('should prevent operations on resolved breaches', async () => {
  272. try {
  273. // First resolve the breach
  274. await riskManager.resolveBreach(testBreachId, 'Position reduced');
  275. // Try to resolve again
  276. await riskManager.resolveBreach(testBreachId, 'Another action');
  277. fail('Should have rejected resolving an already resolved breach');
  278. }
  279. catch (error) {
  280. (0, globals_1.expect)(error.message).toContain('already resolved');
  281. }
  282. });
  283. });
  284. (0, globals_1.describe)('Risk Monitoring', () => {
  285. (0, globals_1.it)('should continuously monitor risk metrics', async () => {
  286. const riskEvents = [];
  287. try {
  288. riskManager.on('breachDetected', (breach) => {
  289. riskEvents.push('breachDetected');
  290. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  291. });
  292. riskManager.on('breachResolved', (breach) => {
  293. riskEvents.push('breachResolved');
  294. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  295. });
  296. // Start monitoring
  297. await riskManager.startMonitoring(testSessionId);
  298. // Wait for monitoring to detect risks
  299. await new Promise(resolve => setTimeout(resolve, 2000));
  300. // Stop monitoring
  301. await riskManager.stopMonitoring(testSessionId);
  302. (0, globals_1.expect)(riskEvents.length).toBeGreaterThan(0);
  303. }
  304. catch (error) {
  305. // This test should fail initially since RiskManager doesn't exist yet
  306. (0, globals_1.expect)(error.message).toContain('RiskManager');
  307. }
  308. });
  309. (0, globals_1.it)('should calculate overall risk level', async () => {
  310. try {
  311. const riskLevel = await riskManager.calculateOverallRisk(testSessionId);
  312. (0, globals_1.expect)(riskLevel).toBeDefined();
  313. (0, globals_1.expect)(['low', 'medium', 'high']).toContain(riskLevel);
  314. }
  315. catch (error) {
  316. // This test should fail initially since RiskManager doesn't exist yet
  317. (0, globals_1.expect)(error.message).toContain('RiskManager');
  318. }
  319. });
  320. (0, globals_1.it)('should generate risk status report', async () => {
  321. try {
  322. const riskStatus = await riskManager.getRiskStatus(testSessionId);
  323. (0, globals_1.expect)(riskStatus).toBeDefined();
  324. (0, globals_1.expect)(riskStatus.sessionId).toBe(testSessionId);
  325. (0, globals_1.expect)(riskStatus.overallRisk).toBeDefined();
  326. (0, globals_1.expect)(riskStatus.accountRisks).toBeDefined();
  327. (0, globals_1.expect)(Array.isArray(riskStatus.accountRisks)).toBe(true);
  328. (0, globals_1.expect)(riskStatus.portfolioRisk).toBeDefined();
  329. (0, globals_1.expect)(riskStatus.activeBreaches).toBeDefined();
  330. (0, globals_1.expect)(Array.isArray(riskStatus.activeBreaches)).toBe(true);
  331. }
  332. catch (error) {
  333. // This test should fail initially since RiskManager doesn't exist yet
  334. (0, globals_1.expect)(error.message).toContain('RiskManager');
  335. }
  336. });
  337. });
  338. (0, globals_1.describe)('Risk Breach Notifications', () => {
  339. (0, globals_1.it)('should emit breach detection events', async () => {
  340. const events = [];
  341. try {
  342. riskManager.on('breachDetected', (breach) => {
  343. events.push('breachDetected');
  344. (0, globals_1.expect)(breach).toBeDefined();
  345. (0, globals_1.expect)(breach.id).toBeDefined();
  346. (0, globals_1.expect)(breach.sessionId).toBe(testSessionId);
  347. });
  348. // Trigger a breach
  349. await riskManager.checkPositionSizeRisk(testSessionId, 'account-1', 0.12);
  350. (0, globals_1.expect)(events).toContain('breachDetected');
  351. }
  352. catch (error) {
  353. // This test should fail initially since RiskManager doesn't exist yet
  354. (0, globals_1.expect)(error.message).toContain('RiskManager');
  355. }
  356. });
  357. (0, globals_1.it)('should emit breach resolution events', async () => {
  358. const events = [];
  359. let testBreachId;
  360. try {
  361. riskManager.on('breachResolved', (breach) => {
  362. events.push('breachResolved');
  363. (0, globals_1.expect)(breach).toBeDefined();
  364. (0, globals_1.expect)(breach.id).toBe(testBreachId);
  365. });
  366. // Create and resolve a breach
  367. const breach = await riskManager.checkPositionSizeRisk(testSessionId, 'account-1', 0.12);
  368. testBreachId = breach.id;
  369. await riskManager.resolveBreach(testBreachId, 'Position reduced');
  370. (0, globals_1.expect)(events).toContain('breachResolved');
  371. }
  372. catch (error) {
  373. // This test should fail initially since RiskManager doesn't exist yet
  374. (0, globals_1.expect)(error.message).toContain('RiskManager');
  375. }
  376. });
  377. });
  378. (0, globals_1.describe)('Error Handling', () => {
  379. (0, globals_1.it)('should handle non-existent breach operations gracefully', async () => {
  380. const nonExistentBreachId = 'non-existent-breach-id';
  381. try {
  382. await riskManager.getBreach(nonExistentBreachId);
  383. fail('Should have thrown error for non-existent breach');
  384. }
  385. catch (error) {
  386. (0, globals_1.expect)(error.message).toContain('not found');
  387. }
  388. });
  389. (0, globals_1.it)('should handle invalid breach resolution attempts', async () => {
  390. const nonExistentBreachId = 'non-existent-breach-id';
  391. try {
  392. await riskManager.resolveBreach(nonExistentBreachId, 'Test resolution');
  393. fail('Should have thrown error for non-existent breach');
  394. }
  395. catch (error) {
  396. (0, globals_1.expect)(error.message).toContain('not found');
  397. }
  398. });
  399. (0, globals_1.it)('should handle monitoring errors gracefully', async () => {
  400. try {
  401. await riskManager.startMonitoring('non-existent-session');
  402. fail('Should have thrown error for non-existent session');
  403. }
  404. catch (error) {
  405. (0, globals_1.expect)(error.message).toContain('session');
  406. }
  407. });
  408. });
  409. });
  410. //# sourceMappingURL=test_risk_breach_handling.js.map