diagnose-delta.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. #!/usr/bin/env tsx
  2. /**
  3. * Delta 对冲诊断工具
  4. *
  5. * 用途:
  6. * 1. 检查 Delta 检测是否生效
  7. * 2. 验证对冲信号执行情况
  8. * 3. 核对配置与阈值
  9. * 4. 确认镜像减仓有效性
  10. * 5. 实时输出净敞口
  11. */
  12. import Logger from '../src/utils/Logger';
  13. import { ConfigurationManager } from '../src/modules/ConfigurationManager';
  14. import { AccountManager } from '../src/modules/AccountManager';
  15. import { DataAggregator } from '../src/services/DataAggregator';
  16. import { EnhancedDeltaController, PositionData } from '../src/services/EnhancedDeltaController';
  17. import { SignalExecutor } from '../src/services/SignalExecutor';
  18. import { PacificaSigningClient } from '../src/services/PacificaSigningClient';
  19. const logger = Logger.getInstance();
  20. interface DiagnosticResult {
  21. timestamp: string;
  22. deltaDetection: {
  23. enabled: boolean;
  24. threshold: number;
  25. currentDelta: number;
  26. exceeded: boolean;
  27. };
  28. hedgingSignals: {
  29. generated: boolean;
  30. count: number;
  31. details: any[];
  32. };
  33. execution: {
  34. attempted: boolean;
  35. successful: number;
  36. failed: number;
  37. errors: string[];
  38. };
  39. netExposure: {
  40. totalBTC: number;
  41. totalUSDC: number;
  42. byAccount: Record<string, { btc: number; usdc: number }>;
  43. };
  44. recommendations: string[];
  45. }
  46. class DeltaDiagnostic {
  47. private configManager: ConfigurationManager;
  48. private accountManager: AccountManager;
  49. private deltaController: EnhancedDeltaController;
  50. private signalExecutor: SignalExecutor;
  51. constructor() {
  52. this.configManager = ConfigurationManager.getInstance();
  53. this.accountManager = new AccountManager();
  54. this.deltaController = new EnhancedDeltaController();
  55. this.signalExecutor = new SignalExecutor({ enableDryRun: true });
  56. }
  57. async initialize(): Promise<void> {
  58. console.log('🔍 初始化诊断工具...\n');
  59. // Load configurations
  60. this.configManager.loadConfigurations();
  61. const accountsConfig = this.configManager.getAccountsConfig();
  62. const deltaConfig = this.configManager.getDeltaConfig();
  63. // Initialize accounts
  64. this.accountManager.initializeAccounts(accountsConfig);
  65. // Register clients with SignalExecutor
  66. const accounts = this.accountManager.getAccounts();
  67. for (const [accountId, accountInfo] of accounts) {
  68. const client = this.accountManager.getAccountClient(accountId);
  69. if (client) {
  70. this.signalExecutor.registerClient(accountId, client);
  71. }
  72. }
  73. console.log('✅ 诊断工具初始化完成\n');
  74. }
  75. async runDiagnostic(): Promise<DiagnosticResult> {
  76. console.log('📊 开始 Delta 对冲诊断...\n');
  77. const result: DiagnosticResult = {
  78. timestamp: new Date().toISOString(),
  79. deltaDetection: {
  80. enabled: false,
  81. threshold: 0,
  82. currentDelta: 0,
  83. exceeded: false
  84. },
  85. hedgingSignals: {
  86. generated: false,
  87. count: 0,
  88. details: []
  89. },
  90. execution: {
  91. attempted: false,
  92. successful: 0,
  93. failed: 0,
  94. errors: []
  95. },
  96. netExposure: {
  97. totalBTC: 0,
  98. totalUSDC: 0,
  99. byAccount: {}
  100. },
  101. recommendations: []
  102. };
  103. try {
  104. // 1. 检查配置
  105. await this.checkConfiguration(result);
  106. // 2. 获取账户数据
  107. await this.fetchAccountData(result);
  108. // 3. 评估 Delta
  109. await this.assessDelta(result);
  110. // 4. 检查对冲信号
  111. await this.checkHedgingSignals(result);
  112. // 5. 生成建议
  113. this.generateRecommendations(result);
  114. } catch (error) {
  115. logger.error('诊断过程出错', { error });
  116. result.recommendations.push(`❌ 诊断失败: ${error instanceof Error ? error.message : '未知错误'}`);
  117. }
  118. return result;
  119. }
  120. private async checkConfiguration(result: DiagnosticResult): Promise<void> {
  121. console.log('1️⃣ 检查配置...');
  122. const deltaConfig = this.configManager.getDeltaConfig();
  123. const strategyConfig = this.configManager.getStrategyConfig();
  124. // Delta 再平衡配置
  125. const rebalanceEnabled = strategyConfig.deltaRebalancing?.enabled || false;
  126. const rebalanceThreshold = strategyConfig.deltaRebalancing?.rebalanceThreshold || 0.05;
  127. const maxDeltaDeviation = strategyConfig.deltaRebalancing?.maxDeltaDeviation || 0.001;
  128. result.deltaDetection.enabled = rebalanceEnabled;
  129. result.deltaDetection.threshold = rebalanceThreshold;
  130. console.log(` ✓ Delta 再平衡: ${rebalanceEnabled ? '已启用' : '已禁用'}`);
  131. console.log(` ✓ 触发阈值: ${(rebalanceThreshold * 100).toFixed(2)}%`);
  132. console.log(` ✓ 目标偏差: ${(maxDeltaDeviation * 100).toFixed(2)}%`);
  133. // EnhancedDeltaController 配置
  134. const deltaControllerConfig = this.deltaController.getConfig();
  135. console.log(` ✓ 基础容忍度: ${(deltaControllerConfig.baseDeltaTolerance * 100).toFixed(2)}%`);
  136. console.log(` ✓ 平稳容忍度: ${(deltaControllerConfig.stableDeltaTolerance * 100).toFixed(2)}%`);
  137. console.log(` ✓ 波动容忍度: ${(deltaControllerConfig.volatileDeltaTolerance * 100).toFixed(2)}%`);
  138. console.log('');
  139. }
  140. private async fetchAccountData(result: DiagnosticResult): Promise<void> {
  141. console.log('2️⃣ 获取账户数据...');
  142. const accountInfos = await this.accountManager.getAllAccountInfo();
  143. const tradingSymbol = this.configManager.getTradingSymbol();
  144. let totalBTC = 0;
  145. let totalUSDC = 0;
  146. for (const [accountId, info] of accountInfos) {
  147. const positions = info.positions || [];
  148. const btcPosition = positions.find((p: any) => p.symbol === tradingSymbol);
  149. const btcSize = btcPosition ? parseFloat(btcPosition.size) : 0;
  150. const accountEquity = parseFloat(info.account_equity || '0');
  151. totalBTC += btcSize;
  152. totalUSDC += accountEquity;
  153. result.netExposure.byAccount[accountId] = {
  154. btc: btcSize,
  155. usdc: accountEquity
  156. };
  157. console.log(` Account ${accountId}:`);
  158. console.log(` BTC Position: ${btcSize.toFixed(5)} BTC`);
  159. console.log(` Equity: ${accountEquity.toFixed(2)} USDC`);
  160. }
  161. result.netExposure.totalBTC = totalBTC;
  162. result.netExposure.totalUSDC = totalUSDC;
  163. console.log(`\n 📊 总净敞口: ${totalBTC.toFixed(5)} BTC`);
  164. console.log(` 💰 总权益: ${totalUSDC.toFixed(2)} USDC\n`);
  165. }
  166. private async assessDelta(result: DiagnosticResult): Promise<void> {
  167. console.log('3️⃣ 评估 Delta...');
  168. const tradingSymbol = this.configManager.getTradingSymbol();
  169. const totalBTC = result.netExposure.totalBTC;
  170. // Get current price from first account's market data
  171. const accountInfos = await this.accountManager.getAllAccountInfo();
  172. const firstAccount = Array.from(accountInfos.values())[0];
  173. const positions = firstAccount?.positions || [];
  174. const btcPosition = positions.find((p: any) => p.symbol === tradingSymbol);
  175. const currentPrice = btcPosition ? parseFloat(btcPosition.mark_price || '0') : 0;
  176. // Create position data
  177. const positionData: PositionData = {
  178. symbol: tradingSymbol,
  179. size: totalBTC,
  180. value: totalBTC * currentPrice,
  181. timestamp: Date.now()
  182. };
  183. // Record price
  184. this.deltaController.recordPrice(tradingSymbol, currentPrice);
  185. // Assess delta
  186. const assessment = this.deltaController.assessDelta(tradingSymbol, positionData);
  187. result.deltaDetection.currentDelta = assessment.weightedDelta;
  188. result.deltaDetection.exceeded = assessment.exceedsTolerance;
  189. console.log(` 当前价格: ${currentPrice.toFixed(2)} USDC`);
  190. console.log(` 仓位价值: ${positionData.value.toFixed(2)} USDC`);
  191. console.log(` 加权 Delta: ${(assessment.weightedDelta * 100).toFixed(4)}%`);
  192. console.log(` 当前容忍度: ${(assessment.currentTolerance * 100).toFixed(4)}%`);
  193. console.log(` 是否超限: ${assessment.exceedsTolerance ? '是 ⚠️' : '否 ✅'}`);
  194. console.log(` 建议操作: ${assessment.recommendation}`);
  195. if (assessment.predictedDirection) {
  196. console.log(` 预测方向: ${assessment.predictedDirection} (置信度: ${((assessment.confidenceScore || 0) * 100).toFixed(2)}%)`);
  197. }
  198. console.log('');
  199. }
  200. private async checkHedgingSignals(result: DiagnosticResult): Promise<void> {
  201. console.log('4️⃣ 检查对冲信号...');
  202. // 这里需要访问策略引擎生成的信号
  203. // 由于策略引擎是在主循环中运行的,我们无法直接获取
  204. // 建议:在实际运行中监听 SignalExecutor 的事件
  205. console.log(' ℹ️ 对冲信号检查需要在实际运行中通过日志监听');
  206. console.log(' 建议查找日志关键字: "Delta exceeds tolerance", "Hedging signal"\n');
  207. }
  208. private generateRecommendations(result: DiagnosticResult): void {
  209. console.log('5️⃣ 生成建议...\n');
  210. const recommendations: string[] = [];
  211. // 检查配置
  212. if (!result.deltaDetection.enabled) {
  213. recommendations.push('⚠️ Delta 再平衡未启用,建议在配置中启用 deltaRebalancing.enabled');
  214. }
  215. // 检查阈值
  216. if (result.deltaDetection.threshold > 0.1) {
  217. recommendations.push('⚠️ Delta 阈值过高 (>10%),建议降低到 0.01-0.05 之间');
  218. }
  219. // 检查净敞口
  220. const totalBTC = Math.abs(result.netExposure.totalBTC);
  221. if (totalBTC > 0.01) {
  222. const exposurePercent = (totalBTC / 1) * 100; // 假设基准为 1 BTC
  223. recommendations.push(`⚠️ 当前净敞口: ${totalBTC.toFixed(5)} BTC,建议检查对冲机制`);
  224. }
  225. // 检查 Delta 超限
  226. if (result.deltaDetection.exceeded) {
  227. recommendations.push('🚨 Delta 超限!应生成对冲信号,请检查日志中是否有 "Delta exceeds tolerance"');
  228. }
  229. // 配置优化建议
  230. recommendations.push('💡 建议启用详细日志: 在策略引擎中添加 Delta 评估日志');
  231. recommendations.push('💡 建议监控对冲执行: 在 SignalExecutor 中监听执行事件');
  232. result.recommendations = recommendations;
  233. recommendations.forEach(rec => console.log(` ${rec}`));
  234. }
  235. printReport(result: DiagnosticResult): void {
  236. console.log('\n' + '='.repeat(80));
  237. console.log('📋 诊断报告');
  238. console.log('='.repeat(80));
  239. console.log(`时间: ${result.timestamp}\n`);
  240. console.log('【Delta 检测】');
  241. console.log(` 启用状态: ${result.deltaDetection.enabled ? '✅ 已启用' : '❌ 未启用'}`);
  242. console.log(` 触发阈值: ${(result.deltaDetection.threshold * 100).toFixed(2)}%`);
  243. console.log(` 当前 Delta: ${(result.deltaDetection.currentDelta * 100).toFixed(4)}%`);
  244. console.log(` 是否超限: ${result.deltaDetection.exceeded ? '⚠️ 是' : '✅ 否'}\n`);
  245. console.log('【净敞口】');
  246. console.log(` 总 BTC: ${result.netExposure.totalBTC.toFixed(5)} BTC`);
  247. console.log(` 总 USDC: ${result.netExposure.totalUSDC.toFixed(2)} USDC`);
  248. console.log(' 分账户:');
  249. for (const [accountId, exposure] of Object.entries(result.netExposure.byAccount)) {
  250. console.log(` ${accountId}: ${exposure.btc.toFixed(5)} BTC, ${exposure.usdc.toFixed(2)} USDC`);
  251. }
  252. console.log('');
  253. console.log('【建议】');
  254. result.recommendations.forEach(rec => console.log(` ${rec}`));
  255. console.log('\n' + '='.repeat(80));
  256. }
  257. }
  258. // Main execution
  259. async function main() {
  260. const diagnostic = new DeltaDiagnostic();
  261. try {
  262. await diagnostic.initialize();
  263. const result = await diagnostic.runDiagnostic();
  264. diagnostic.printReport(result);
  265. process.exit(0);
  266. } catch (error) {
  267. console.error('❌ 诊断失败:', error);
  268. process.exit(1);
  269. }
  270. }
  271. main();