test_control_loop_latency.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'
  2. import { performance } from 'perf_hooks'
  3. import { DeltaNeutralController } from '../../src/controllers/DeltaNeutralController.js'
  4. import { AccountManager } from '../../src/modules/account/AccountManager.js'
  5. import { HedgeExecutionService } from '../../src/services/HedgeExecutionService.js'
  6. import { RiskMonitoringService } from '../../src/services/RiskMonitoringService.js'
  7. /**
  8. * 控制循环延迟性能测试
  9. * 验证 8 秒控制循环延迟要求 (T043)
  10. * 验证 10 秒故障转移 SLA 要求 (T044)
  11. */
  12. describe('Control Loop Latency Performance Tests', () => {
  13. let controller: DeltaNeutralController
  14. let mockAccountManager: jest.Mocked<AccountManager>
  15. let mockHedgeService: jest.Mocked<HedgeExecutionService>
  16. let mockRiskService: jest.Mocked<RiskMonitoringService>
  17. beforeEach(() => {
  18. // 创建快速响应的模拟服务
  19. mockAccountManager = {
  20. getAccounts: jest.fn().mockReturnValue(new Map([
  21. ['account-1', { netPosition: 0.5, unrealizedPnl: 100 }],
  22. ['account-2', { netPosition: -0.3, unrealizedPnl: -50 }],
  23. ['account-3', { netPosition: 0.2, unrealizedPnl: 25 }]
  24. ])),
  25. getAccountState: jest.fn().mockResolvedValue({ netPosition: 0.1, unrealizedPnl: 10 }),
  26. updateAccountState: jest.fn().mockResolvedValue(undefined),
  27. } as any
  28. mockHedgeService = {
  29. executeHedge: jest.fn().mockImplementation(async () => {
  30. // 模拟实际执行时间 (100-500ms)
  31. await new Promise(resolve => setTimeout(resolve, Math.random() * 400 + 100))
  32. return {
  33. success: true,
  34. executedOrders: [
  35. { accountId: 'account-1', symbol: 'BTC-USD', amount: 0.2, side: 'sell' }
  36. ],
  37. totalCost: 1000,
  38. executionTime: 150,
  39. netDeltaChange: -0.2
  40. }
  41. }),
  42. getStatus: jest.fn().mockReturnValue('running'),
  43. } as any
  44. mockRiskService = {
  45. getRiskMetrics: jest.fn().mockImplementation(async () => {
  46. // 模拟风险评估时间 (50-200ms)
  47. await new Promise(resolve => setTimeout(resolve, Math.random() * 150 + 50))
  48. return {
  49. accountId: 'test-account',
  50. deltaDeviation: 0.5,
  51. utilizationRate: 0.7,
  52. leverageRatio: 2,
  53. unrealizedPnl: 100,
  54. maxDrawdown: 200,
  55. timestamp: Date.now()
  56. }
  57. }),
  58. updateAccountRisk: jest.fn().mockResolvedValue(undefined),
  59. getActiveAlerts: jest.fn().mockReturnValue([]),
  60. getStatus: jest.fn().mockReturnValue('running'),
  61. } as any
  62. controller = new DeltaNeutralController(
  63. mockAccountManager,
  64. mockHedgeService,
  65. mockRiskService
  66. )
  67. })
  68. afterEach(async () => {
  69. await controller.stop()
  70. })
  71. describe('8-Second Control Loop Latency (T043)', () => {
  72. beforeEach(async () => {
  73. await controller.start()
  74. })
  75. it('should complete delta control within 8 seconds - single account', async () => {
  76. const startTime = performance.now()
  77. const request = {
  78. targetDelta: 0.0,
  79. accounts: ['account-1'],
  80. maxDeviation: 0.1,
  81. symbol: 'BTC-USD'
  82. }
  83. const response = await controller.executeDeltaControl(request)
  84. const endTime = performance.now()
  85. const executionTime = endTime - startTime
  86. expect(response.success).toBe(true)
  87. expect(executionTime).toBeLessThan(8000) // 8秒要求
  88. console.log(`Delta控制执行时间 (单账户): ${executionTime.toFixed(2)}ms`)
  89. })
  90. it('should complete delta control within 8 seconds - multiple accounts', async () => {
  91. const startTime = performance.now()
  92. const request = {
  93. targetDelta: 0.0,
  94. accounts: ['account-1', 'account-2', 'account-3'],
  95. maxDeviation: 0.1,
  96. symbol: 'BTC-USD'
  97. }
  98. const response = await controller.executeDeltaControl(request)
  99. const endTime = performance.now()
  100. const executionTime = endTime - startTime
  101. expect(response.success).toBe(true)
  102. expect(executionTime).toBeLessThan(8000) // 8秒要求
  103. console.log(`Delta控制执行时间 (多账户): ${executionTime.toFixed(2)}ms`)
  104. })
  105. it('should complete utilization rebalancing within 8 seconds', async () => {
  106. const startTime = performance.now()
  107. const request = {
  108. targetUtilization: 0.75,
  109. accounts: ['account-1', 'account-2', 'account-3'],
  110. symbol: 'BTC-USD'
  111. }
  112. const response = await controller.executeUtilizationRebalance(request)
  113. const endTime = performance.now()
  114. const executionTime = endTime - startTime
  115. expect(response.success).toBe(true)
  116. expect(executionTime).toBeLessThan(8000) // 8秒要求
  117. console.log(`利用率再平衡执行时间: ${executionTime.toFixed(2)}ms`)
  118. })
  119. it('should maintain consistent performance under load', async () => {
  120. const iterations = 10
  121. const executionTimes: number[] = []
  122. for (let i = 0; i < iterations; i++) {
  123. const startTime = performance.now()
  124. const request = {
  125. targetDelta: 0.0,
  126. accounts: ['account-1', 'account-2'],
  127. maxDeviation: 0.1,
  128. symbol: 'BTC-USD'
  129. }
  130. const response = await controller.executeDeltaControl(request)
  131. const endTime = performance.now()
  132. const executionTime = endTime - startTime
  133. expect(response.success).toBe(true)
  134. expect(executionTime).toBeLessThan(8000)
  135. executionTimes.push(executionTime)
  136. // 短暂间隔避免资源争用
  137. await new Promise(resolve => setTimeout(resolve, 100))
  138. }
  139. const avgExecutionTime = executionTimes.reduce((a, b) => a + b) / iterations
  140. const maxExecutionTime = Math.max(...executionTimes)
  141. const minExecutionTime = Math.min(...executionTimes)
  142. console.log(`性能统计 (${iterations}次迭代):`)
  143. console.log(` 平均执行时间: ${avgExecutionTime.toFixed(2)}ms`)
  144. console.log(` 最大执行时间: ${maxExecutionTime.toFixed(2)}ms`)
  145. console.log(` 最小执行时间: ${minExecutionTime.toFixed(2)}ms`)
  146. expect(avgExecutionTime).toBeLessThan(5000) // 平均应该更快
  147. expect(maxExecutionTime).toBeLessThan(8000) // 最大也要符合要求
  148. })
  149. })
  150. describe('10-Second Failover SLA (T044)', () => {
  151. beforeEach(async () => {
  152. await controller.start()
  153. })
  154. it('should handle hedge service failure within 10 seconds', async () => {
  155. // 模拟对冲服务失败
  156. mockHedgeService.executeHedge.mockImplementation(async () => {
  157. await new Promise(resolve => setTimeout(resolve, 2000)) // 2秒延迟
  158. throw new Error('Hedge service temporarily unavailable')
  159. })
  160. const startTime = performance.now()
  161. const request = {
  162. targetDelta: 0.0,
  163. accounts: ['account-1'],
  164. maxDeviation: 0.1,
  165. symbol: 'BTC-USD'
  166. }
  167. const response = await controller.executeDeltaControl(request)
  168. const endTime = performance.now()
  169. const failoverTime = endTime - startTime
  170. expect(response.success).toBe(false)
  171. expect(failoverTime).toBeLessThan(10000) // 10秒故障转移SLA
  172. console.log(`故障检测和处理时间: ${failoverTime.toFixed(2)}ms`)
  173. })
  174. it('should handle risk service timeout within 10 seconds', async () => {
  175. // 模拟风险服务超时
  176. mockRiskService.getRiskMetrics.mockImplementation(async () => {
  177. await new Promise(resolve => setTimeout(resolve, 8000)) // 8秒超时
  178. throw new Error('Risk service timeout')
  179. })
  180. const startTime = performance.now()
  181. const request = {
  182. targetUtilization: 0.75,
  183. accounts: ['account-1'],
  184. symbol: 'BTC-USD'
  185. }
  186. const response = await controller.executeUtilizationRebalance(request)
  187. const endTime = performance.now()
  188. const failoverTime = endTime - startTime
  189. expect(response.success).toBe(false)
  190. expect(failoverTime).toBeLessThan(10000) // 10秒故障转移SLA
  191. console.log(`服务超时处理时间: ${failoverTime.toFixed(2)}ms`)
  192. })
  193. it('should gracefully degrade when account manager is slow', async () => {
  194. // 模拟账户管理器响应缓慢
  195. mockAccountManager.getAccounts.mockImplementation(() => {
  196. const slowResponse = new Promise(resolve => {
  197. setTimeout(() => {
  198. resolve(new Map([
  199. ['account-1', { netPosition: 0.5, unrealizedPnl: 100 }]
  200. ]))
  201. }, 5000) // 5秒延迟
  202. })
  203. return slowResponse as any
  204. })
  205. const startTime = performance.now()
  206. const request = {
  207. targetDelta: 0.0,
  208. accounts: ['account-1'],
  209. maxDeviation: 0.1,
  210. symbol: 'BTC-USD'
  211. }
  212. const response = await controller.executeDeltaControl(request)
  213. const endTime = performance.now()
  214. const responseTime = endTime - startTime
  215. // 应该在合理时间内响应,即使依赖服务慢
  216. expect(responseTime).toBeLessThan(10000) // 10秒SLA
  217. console.log(`慢速服务降级处理时间: ${responseTime.toFixed(2)}ms`)
  218. })
  219. it('should maintain system stability during partial failures', async () => {
  220. // 模拟部分账户故障
  221. let callCount = 0
  222. mockRiskService.getRiskMetrics.mockImplementation(async (accountId) => {
  223. callCount++
  224. if (accountId === 'account-2' && callCount <= 2) {
  225. throw new Error('Account 2 temporarily unavailable')
  226. }
  227. await new Promise(resolve => setTimeout(resolve, 100))
  228. return {
  229. accountId,
  230. deltaDeviation: 0.3,
  231. utilizationRate: 0.7,
  232. leverageRatio: 2,
  233. unrealizedPnl: 50,
  234. maxDrawdown: 100,
  235. timestamp: Date.now()
  236. }
  237. })
  238. const startTime = performance.now()
  239. const request = {
  240. targetUtilization: 0.75,
  241. accounts: ['account-1', 'account-2', 'account-3'],
  242. symbol: 'BTC-USD'
  243. }
  244. const response = await controller.executeUtilizationRebalance(request)
  245. const endTime = performance.now()
  246. const recoveryTime = endTime - startTime
  247. expect(recoveryTime).toBeLessThan(10000) // 10秒SLA
  248. console.log(`部分故障恢复时间: ${recoveryTime.toFixed(2)}ms`)
  249. // 系统应该能够处理部分成功的情况
  250. expect(response.success).toBeDefined()
  251. })
  252. })
  253. describe('Stress Testing and Performance Benchmarks', () => {
  254. beforeEach(async () => {
  255. await controller.start()
  256. })
  257. it('should handle high-frequency requests efficiently', async () => {
  258. const concurrentRequests = 5
  259. const requests = []
  260. const startTime = performance.now()
  261. for (let i = 0; i < concurrentRequests; i++) {
  262. requests.push(
  263. controller.executeDeltaControl({
  264. targetDelta: 0.0,
  265. accounts: [`account-${i % 3 + 1}`],
  266. maxDeviation: 0.1,
  267. symbol: 'BTC-USD'
  268. })
  269. )
  270. }
  271. const responses = await Promise.all(requests)
  272. const endTime = performance.now()
  273. const totalTime = endTime - startTime
  274. expect(totalTime).toBeLessThan(15000) // 并发请求应在15秒内完成
  275. console.log(`${concurrentRequests}个并发请求总时间: ${totalTime.toFixed(2)}ms`)
  276. // 验证所有请求都有响应
  277. expect(responses).toHaveLength(concurrentRequests)
  278. responses.forEach(response => {
  279. expect(response).toBeDefined()
  280. })
  281. })
  282. it('should demonstrate target performance benchmarks', async () => {
  283. const benchmarks = {
  284. singleAccountDelta: 0,
  285. multiAccountDelta: 0,
  286. utilizationRebalance: 0,
  287. riskAssessment: 0
  288. }
  289. // 单账户Delta控制基准
  290. let startTime = performance.now()
  291. await controller.executeDeltaControl({
  292. targetDelta: 0.0,
  293. accounts: ['account-1'],
  294. maxDeviation: 0.1,
  295. symbol: 'BTC-USD'
  296. })
  297. benchmarks.singleAccountDelta = performance.now() - startTime
  298. // 多账户Delta控制基准
  299. startTime = performance.now()
  300. await controller.executeDeltaControl({
  301. targetDelta: 0.0,
  302. accounts: ['account-1', 'account-2', 'account-3'],
  303. maxDeviation: 0.1,
  304. symbol: 'BTC-USD'
  305. })
  306. benchmarks.multiAccountDelta = performance.now() - startTime
  307. // 利用率再平衡基准
  308. startTime = performance.now()
  309. await controller.executeUtilizationRebalance({
  310. targetUtilization: 0.75,
  311. accounts: ['account-1', 'account-2'],
  312. symbol: 'BTC-USD'
  313. })
  314. benchmarks.utilizationRebalance = performance.now() - startTime
  315. console.log('性能基准测试结果:')
  316. console.log(` 单账户Delta控制: ${benchmarks.singleAccountDelta.toFixed(2)}ms`)
  317. console.log(` 多账户Delta控制: ${benchmarks.multiAccountDelta.toFixed(2)}ms`)
  318. console.log(` 利用率再平衡: ${benchmarks.utilizationRebalance.toFixed(2)}ms`)
  319. // 验证性能基准
  320. expect(benchmarks.singleAccountDelta).toBeLessThan(2000) // 2秒目标
  321. expect(benchmarks.multiAccountDelta).toBeLessThan(5000) // 5秒目标
  322. expect(benchmarks.utilizationRebalance).toBeLessThan(3000) // 3秒目标
  323. })
  324. it('should measure memory usage and cleanup efficiency', async () => {
  325. const initialMemory = process.memoryUsage()
  326. // 执行多次操作以测试内存泄漏
  327. for (let i = 0; i < 50; i++) {
  328. await controller.executeDeltaControl({
  329. targetDelta: 0.0,
  330. accounts: ['account-1'],
  331. maxDeviation: 0.1,
  332. symbol: 'BTC-USD'
  333. })
  334. if (i % 10 === 0) {
  335. // 强制垃圾回收测试
  336. if (global.gc) {
  337. global.gc()
  338. }
  339. }
  340. }
  341. const finalMemory = process.memoryUsage()
  342. const memoryIncrease = finalMemory.heapUsed - initialMemory.heapUsed
  343. console.log('内存使用情况:')
  344. console.log(` 初始堆内存: ${(initialMemory.heapUsed / 1024 / 1024).toFixed(2)} MB`)
  345. console.log(` 最终堆内存: ${(finalMemory.heapUsed / 1024 / 1024).toFixed(2)} MB`)
  346. console.log(` 内存增长: ${(memoryIncrease / 1024 / 1024).toFixed(2)} MB`)
  347. // 内存增长应该在合理范围内 (< 50MB for 50 operations)
  348. expect(memoryIncrease).toBeLessThan(50 * 1024 * 1024)
  349. })
  350. })
  351. })