test_hedging_session_creation.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /**
  2. * Integration test for hedging session creation
  3. * Tests the complete flow of creating and managing hedging sessions
  4. */
  5. import { describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals';
  6. import { HedgingManager } from '../../src/core/HedgingManager';
  7. import { HedgingConfigManager } from '../../src/core/HedgingConfigManager';
  8. import { CreateHedgingSessionRequest } from '../../src/types/hedging';
  9. describe('Hedging Session Creation Integration', () => {
  10. let hedgingManager: HedgingManager;
  11. let configManager: HedgingConfigManager;
  12. beforeAll(async () => {
  13. // Initialize configuration manager
  14. configManager = new HedgingConfigManager({
  15. accounts: './config/accounts.json',
  16. hedging: './config/hedging-config.json',
  17. marketData: './config/market-data-config.json'
  18. });
  19. // Initialize hedging manager
  20. hedgingManager = new HedgingManager({
  21. accounts: './config/accounts.json',
  22. hedging: './config/hedging-config.json',
  23. marketData: './config/market-data-config.json'
  24. });
  25. await hedgingManager.initialize();
  26. });
  27. afterAll(async () => {
  28. if (hedgingManager) {
  29. await hedgingManager.shutdown();
  30. }
  31. });
  32. beforeEach(() => {
  33. // Clean up any existing sessions before each test
  34. hedgingManager.cleanup();
  35. });
  36. describe('Session Creation Flow', () => {
  37. it('should create a new hedging session with valid parameters', async () => {
  38. const sessionRequest: CreateHedgingSessionRequest = {
  39. name: 'Integration Test Session',
  40. accountIds: ['account-1', 'account-2'],
  41. volumeTarget: 10000,
  42. strategy: {
  43. symbol: 'ETH/USD',
  44. volumeDistribution: 'equal',
  45. priceRange: {
  46. min: 0.001,
  47. max: 0.01
  48. },
  49. timing: {
  50. minInterval: 30,
  51. maxInterval: 120,
  52. orderSize: {
  53. min: 100,
  54. max: 500
  55. }
  56. },
  57. riskLimits: {
  58. maxPositionSize: 0.1,
  59. stopLossThreshold: 0.05,
  60. maxSlippage: 0.02
  61. },
  62. orderTypes: {
  63. primary: 'limit',
  64. fallback: 'market'
  65. }
  66. }
  67. };
  68. try {
  69. const session = await hedgingManager.createSession(sessionRequest);
  70. expect(session).toBeDefined();
  71. expect(session.id).toBeDefined();
  72. expect(session.name).toBe(sessionRequest.name);
  73. expect(session.status).toBe('pending');
  74. expect(session.accounts).toEqual(sessionRequest.accountIds);
  75. expect(session.strategy).toEqual(sessionRequest.strategy);
  76. expect(session.volumeTarget).toBe(sessionRequest.volumeTarget);
  77. expect(session.volumeGenerated).toBe(0);
  78. expect(session.riskBreaches).toEqual([]);
  79. expect(session.orders).toEqual([]);
  80. expect(session.createdAt).toBeInstanceOf(Date);
  81. expect(session.updatedAt).toBeInstanceOf(Date);
  82. } catch (error) {
  83. // This test should fail initially since HedgingManager doesn't exist yet
  84. expect(error.message).toContain('HedgingManager');
  85. }
  86. });
  87. it('should validate account availability before creating session', async () => {
  88. const sessionRequest: CreateHedgingSessionRequest = {
  89. name: 'Test Session with Invalid Account',
  90. accountIds: ['account-1', 'non-existent-account'],
  91. volumeTarget: 10000,
  92. strategy: {
  93. symbol: 'ETH/USD',
  94. volumeDistribution: 'equal',
  95. priceRange: { min: 0.001, max: 0.01 },
  96. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  97. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  98. orderTypes: { primary: 'limit', fallback: 'market' }
  99. }
  100. };
  101. try {
  102. await hedgingManager.createSession(sessionRequest);
  103. fail('Should have rejected session with invalid account');
  104. } catch (error) {
  105. expect(error.message).toContain('account');
  106. }
  107. });
  108. it('should validate account balance before creating session', async () => {
  109. const sessionRequest: CreateHedgingSessionRequest = {
  110. name: 'Test Session with Insufficient Balance',
  111. accountIds: ['account-1', 'account-2'],
  112. volumeTarget: 1000000, // Very high volume target
  113. strategy: {
  114. symbol: 'ETH/USD',
  115. volumeDistribution: 'equal',
  116. priceRange: { min: 0.001, max: 0.01 },
  117. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  118. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  119. orderTypes: { primary: 'limit', fallback: 'market' }
  120. }
  121. };
  122. try {
  123. await hedgingManager.createSession(sessionRequest);
  124. fail('Should have rejected session with insufficient balance');
  125. } catch (error) {
  126. expect(error.message).toContain('balance');
  127. }
  128. });
  129. it('should validate strategy parameters before creating session', async () => {
  130. const sessionRequest: CreateHedgingSessionRequest = {
  131. name: 'Test Session with Invalid Strategy',
  132. accountIds: ['account-1', 'account-2'],
  133. volumeTarget: 10000,
  134. strategy: {
  135. symbol: 'ETH/USD',
  136. volumeDistribution: 'equal',
  137. priceRange: {
  138. min: 0.01,
  139. max: 0.001 // Invalid: min > max
  140. },
  141. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  142. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  143. orderTypes: { primary: 'limit', fallback: 'market' }
  144. }
  145. };
  146. try {
  147. await hedgingManager.createSession(sessionRequest);
  148. fail('Should have rejected session with invalid strategy');
  149. } catch (error) {
  150. expect(error.message).toContain('strategy');
  151. }
  152. });
  153. });
  154. describe('Session Management', () => {
  155. let testSessionId: string;
  156. beforeEach(async () => {
  157. const sessionRequest: CreateHedgingSessionRequest = {
  158. name: 'Test Management Session',
  159. accountIds: ['account-1', 'account-2'],
  160. volumeTarget: 10000,
  161. strategy: {
  162. symbol: 'ETH/USD',
  163. volumeDistribution: 'equal',
  164. priceRange: { min: 0.001, max: 0.01 },
  165. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  166. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  167. orderTypes: { primary: 'limit', fallback: 'market' }
  168. }
  169. };
  170. try {
  171. const session = await hedgingManager.createSession(sessionRequest);
  172. testSessionId = session.id;
  173. } catch (error) {
  174. // Session creation will fail initially
  175. testSessionId = 'mock-session-id';
  176. }
  177. });
  178. it('should retrieve session by ID', async () => {
  179. try {
  180. const session = await hedgingManager.getSession(testSessionId);
  181. expect(session).toBeDefined();
  182. expect(session.id).toBe(testSessionId);
  183. expect(session.name).toBe('Test Management Session');
  184. } catch (error) {
  185. // This test should fail initially since HedgingManager doesn't exist yet
  186. expect(error.message).toContain('HedgingManager');
  187. }
  188. });
  189. it('should list all sessions', async () => {
  190. try {
  191. const sessions = await hedgingManager.listSessions();
  192. expect(Array.isArray(sessions)).toBe(true);
  193. expect(sessions.length).toBeGreaterThanOrEqual(1);
  194. const testSession = sessions.find(s => s.id === testSessionId);
  195. expect(testSession).toBeDefined();
  196. expect(testSession.name).toBe('Test Management Session');
  197. } catch (error) {
  198. // This test should fail initially since HedgingManager doesn't exist yet
  199. expect(error.message).toContain('HedgingManager');
  200. }
  201. });
  202. it('should filter sessions by status', async () => {
  203. try {
  204. const pendingSessions = await hedgingManager.listSessions({ status: 'pending' });
  205. expect(Array.isArray(pendingSessions)).toBe(true);
  206. pendingSessions.forEach(session => {
  207. expect(session.status).toBe('pending');
  208. });
  209. } catch (error) {
  210. // This test should fail initially since HedgingManager doesn't exist yet
  211. expect(error.message).toContain('HedgingManager');
  212. }
  213. });
  214. it('should filter sessions by account ID', async () => {
  215. try {
  216. const accountSessions = await hedgingManager.listSessions({ accountId: 'account-1' });
  217. expect(Array.isArray(accountSessions)).toBe(true);
  218. accountSessions.forEach(session => {
  219. expect(session.accounts).toContain('account-1');
  220. });
  221. } catch (error) {
  222. // This test should fail initially since HedgingManager doesn't exist yet
  223. expect(error.message).toContain('HedgingManager');
  224. }
  225. });
  226. });
  227. describe('Session State Transitions', () => {
  228. let testSessionId: string;
  229. beforeEach(async () => {
  230. const sessionRequest: CreateHedgingSessionRequest = {
  231. name: 'Test State Transition Session',
  232. accountIds: ['account-1', 'account-2'],
  233. volumeTarget: 10000,
  234. strategy: {
  235. symbol: 'ETH/USD',
  236. volumeDistribution: 'equal',
  237. priceRange: { min: 0.001, max: 0.01 },
  238. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  239. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  240. orderTypes: { primary: 'limit', fallback: 'market' }
  241. }
  242. };
  243. try {
  244. const session = await hedgingManager.createSession(sessionRequest);
  245. testSessionId = session.id;
  246. } catch (error) {
  247. testSessionId = 'mock-session-id';
  248. }
  249. });
  250. it('should start a pending session', async () => {
  251. try {
  252. const session = await hedgingManager.startSession(testSessionId);
  253. expect(session.status).toBe('active');
  254. expect(session.startTime).toBeDefined();
  255. expect(session.startTime).toBeInstanceOf(Date);
  256. } catch (error) {
  257. // This test should fail initially since HedgingManager doesn't exist yet
  258. expect(error.message).toContain('HedgingManager');
  259. }
  260. });
  261. it('should pause an active session', async () => {
  262. try {
  263. // First start the session
  264. await hedgingManager.startSession(testSessionId);
  265. // Then pause it
  266. const session = await hedgingManager.pauseSession(testSessionId);
  267. expect(session.status).toBe('paused');
  268. } catch (error) {
  269. // This test should fail initially since HedgingManager doesn't exist yet
  270. expect(error.message).toContain('HedgingManager');
  271. }
  272. });
  273. it('should resume a paused session', async () => {
  274. try {
  275. // Start and pause the session
  276. await hedgingManager.startSession(testSessionId);
  277. await hedgingManager.pauseSession(testSessionId);
  278. // Then resume it
  279. const session = await hedgingManager.resumeSession(testSessionId);
  280. expect(session.status).toBe('active');
  281. } catch (error) {
  282. // This test should fail initially since HedgingManager doesn't exist yet
  283. expect(error.message).toContain('HedgingManager');
  284. }
  285. });
  286. it('should stop an active session', async () => {
  287. try {
  288. // Start the session
  289. await hedgingManager.startSession(testSessionId);
  290. // Then stop it
  291. const session = await hedgingManager.stopSession(testSessionId);
  292. expect(session.status).toBe('completed');
  293. expect(session.endTime).toBeDefined();
  294. expect(session.endTime).toBeInstanceOf(Date);
  295. } catch (error) {
  296. // This test should fail initially since HedgingManager doesn't exist yet
  297. expect(error.message).toContain('HedgingManager');
  298. }
  299. });
  300. });
  301. describe('Error Handling', () => {
  302. it('should handle non-existent session operations gracefully', async () => {
  303. const nonExistentSessionId = 'non-existent-session-id';
  304. try {
  305. await hedgingManager.getSession(nonExistentSessionId);
  306. fail('Should have thrown error for non-existent session');
  307. } catch (error) {
  308. expect(error.message).toContain('not found');
  309. }
  310. });
  311. it('should handle invalid session state transitions', async () => {
  312. const sessionRequest: CreateHedgingSessionRequest = {
  313. name: 'Test Invalid Transition Session',
  314. accountIds: ['account-1', 'account-2'],
  315. volumeTarget: 10000,
  316. strategy: {
  317. symbol: 'ETH/USD',
  318. volumeDistribution: 'equal',
  319. priceRange: { min: 0.001, max: 0.01 },
  320. timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
  321. riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
  322. orderTypes: { primary: 'limit', fallback: 'market' }
  323. }
  324. };
  325. try {
  326. const session = await hedgingManager.createSession(sessionRequest);
  327. // Try to pause a pending session (should fail)
  328. await hedgingManager.pauseSession(session.id);
  329. fail('Should have rejected pausing a pending session');
  330. } catch (error) {
  331. expect(error.message).toContain('status');
  332. }
  333. });
  334. });
  335. describe('Configuration Integration', () => {
  336. it('should use default strategy from configuration', async () => {
  337. try {
  338. const defaultStrategy = await configManager.getDefaultStrategy();
  339. expect(defaultStrategy).toBeDefined();
  340. expect(defaultStrategy.symbol).toBeDefined();
  341. expect(defaultStrategy.volumeDistribution).toBeDefined();
  342. expect(defaultStrategy.priceRange).toBeDefined();
  343. expect(defaultStrategy.timing).toBeDefined();
  344. expect(defaultStrategy.riskLimits).toBeDefined();
  345. expect(defaultStrategy.orderTypes).toBeDefined();
  346. } catch (error) {
  347. // This test should fail initially since HedgingConfigManager doesn't exist yet
  348. expect(error.message).toContain('HedgingConfigManager');
  349. }
  350. });
  351. it('should validate configuration parameters', async () => {
  352. try {
  353. const config = await configManager.getConfig();
  354. expect(config).toBeDefined();
  355. expect(config.defaultStrategy).toBeDefined();
  356. expect(config.monitoring).toBeDefined();
  357. expect(config.sessionDefaults).toBeDefined();
  358. expect(config.orderDefaults).toBeDefined();
  359. expect(config.websocket).toBeDefined();
  360. } catch (error) {
  361. // This test should fail initially since HedgingConfigManager doesn't exist yet
  362. expect(error.message).toContain('HedgingConfigManager');
  363. }
  364. });
  365. });
  366. });