COMPREHENSIVE_AUDIT.md 12 KB

全面系统审计报告 - run-refactored-strategy.ts

审计日期: 2025-10-02 审计范围: 完整主流程 + 架构设计 + 风险控制 审计深度: 代码级 + 系统级 + 业务逻辑级


📋 审计维度

1️⃣ 代码质量 ✅ 已审计

2️⃣ 架构设计 ⚠️ 发现问题

3️⃣ 错误处理 ⚠️ 发现问题

4️⃣ 数据流 ⚠️ 发现问题

5️⃣ 风险控制 🔴 发现严重问题

6️⃣ 并发与状态 ⚠️ 发现问题

7️⃣ 配置管理 ✅ 已修复

8️⃣ 日志与监控 ✅ 良好

9️⃣ 资源管理 ⚠️ 发现问题


🔴 新发现的严重问题

❌ P0-3: WebSocket 订单状态更新缺失关键映射

位置: Line 544-562

当前代码:

this.marketDataManager.getWebSocketManager().on('order_update', (update: any) => {
  if (update.status && this.orderLifecycleManager) {
    let status: 'open' | 'filled' | 'cancelled' | 'partially_filled' = 'open';
    if (update.status === 'filled') {
      status = 'filled';
    } else if (update.status === 'cancelled' || update.status === 'canceled') {
      status = 'cancelled';
    } else if (update.status === 'partially_filled' || update.status === 'partial') {
      status = 'partially_filled';
    }

    this.orderLifecycleManager.updateOrderStatus(
      update.orderId,
      update.symbol,
      status
    );
  }
});

问题:

  1. 缺少 orderId 和 symbol 验证 - 如果 WebSocket 推送缺少这些字段会崩溃
  2. 没有处理 'open' 状态 - 新订单创建时的状态被忽略
  3. 字段名可能不匹配 - 假设字段名为 orderIdsymbol,但可能是 order_idi

修复:

this.marketDataManager.getWebSocketManager().on('order_update', (update: any) => {
  if (!this.orderLifecycleManager) return;

  // ✅ 提取并验证必要字段
  const orderId = update.orderId || update.order_id || update.i;
  const symbol = update.symbol || update.s;
  const statusRaw = update.status || update.order_status;

  if (!orderId || !symbol || !statusRaw) {
    this.logger.warn('Invalid order update from WebSocket', { update });
    return;
  }

  // ✅ 映射状态
  let status: 'open' | 'filled' | 'cancelled' | 'partially_filled' = 'open';
  const normalizedStatus = statusRaw.toLowerCase();

  if (normalizedStatus === 'filled' || normalizedStatus === 'completely_filled') {
    status = 'filled';
  } else if (normalizedStatus === 'cancelled' || normalizedStatus === 'canceled') {
    status = 'cancelled';
  } else if (normalizedStatus === 'partially_filled' || normalizedStatus === 'partial') {
    status = 'partially_filled';
  } else if (normalizedStatus === 'open' || normalizedStatus === 'new') {
    status = 'open';
  } else {
    this.logger.warn('Unknown order status from WebSocket', { status: statusRaw, orderId, symbol });
    return;
  }

  this.orderLifecycleManager.updateOrderStatus(orderId, symbol, status);
});

❌ P0-4: 订单同步所有账户使用同一个 SigningClient

位置: Line 540

当前代码:

this.orderLifecycleManager = new OrderLifecycleManager(lifecycleConfig);
this.orderLifecycleManager.setSigningClient(firstClient); // ❌ 仅使用第一个账户
await this.orderLifecycleManager.start();

问题:

  • OrderLifecycleManager 只绑定了 firstClient(第一个账户)
  • 当需要取消第二个账户的订单时,会使用错误的签名客户端
  • 导致: 第二个账户的订单无法被自动取消

影响: 严重 - 订单生命周期管理失效

修复方案A (推荐): OrderLifecycleManager 支持多账户

// 修改 OrderLifecycleManager 接口
public setSigningClients(clients: Map<string, PacificaSigningClient>): void {
  this.signingClients = clients;
}

// 在 run-refactored-strategy.ts
const clientsMap = new Map<string, PacificaSigningClient>();
for (const [accountId, accountInfo] of this.accounts) {
  clientsMap.set(accountId, accountInfo.client);
}
this.orderLifecycleManager.setSigningClients(clientsMap);

修复方案B (简单): 每个账户独立的 OrderLifecycleManager

// 为每个账户创建独立的 OrderLifecycleManager
private orderLifecycleManagers: Map<string, OrderLifecycleManager> = new Map();

for (const [accountId, accountInfo] of this.accounts) {
  const lifecycleManager = new OrderLifecycleManager(lifecycleConfig);
  lifecycleManager.setSigningClient(accountInfo.client);
  await lifecycleManager.start();
  this.orderLifecycleManagers.set(accountId, lifecycleManager);
}

❌ P0-5: reduce 信号使用了错误的取消订单方法

位置: Line 690

当前代码:

await accountInfo.client.cancelOrder(order.symbol, order.orderId);

问题:

  • PacificaSigningClient.cancelOrder 方法签名是什么?
  • 参数顺序可能是 (orderId, symbol) 而不是 (symbol, orderId)
  • 没有错误处理,取消失败会静默忽略

需要验证: 检查 PacificaSigningClient.cancelOrder 的正确签名


⚠️ P1-3: 没有处理 WebSocket 断线重连后的状态同步

位置: 整个初始化流程

问题:

  1. WebSocket 断线后重连,订单状态可能丢失
  2. 没有定期从 REST API 同步订单状态作为备份
  3. OrderLifecycleManager 的订单追踪可能与实际不一致

建议:

// 定期同步订单状态(每30秒)
setInterval(async () => {
  for (const [accountId, accountInfo] of this.accounts) {
    try {
      const ordersResult = await accountInfo.client.getOpenOrders();
      if (ordersResult?.orders) {
        // 同步到 OrderLifecycleManager
        // 取消本地追踪但服务器不存在的订单
      }
    } catch (error) {
      this.logger.error('Failed to sync orders', { accountId, error });
    }
  }
}, 30000);

⚠️ P1-4: 账户余额更新事件可能丢失

位置: Line 754-830

问题:

  1. DataAggregator 触发 account_balance_updated 事件
  2. 但是如果事件监听器注册晚于第一次余额更新,会丢失初始状态
  3. Line 890-967 手动触发初始同步,但这是补救措施,不是设计

时序问题:

1. initializeAccountBalances()
   → updateAccountBalanceExternal()
   → 触发 account_balance_updated 事件
2. 监听器还没注册 ❌
3. 手动触发一次同步 (Line 890-967) ✅ 补救

建议: 先注册监听器,再初始化余额


⚠️ P1-5: MarginMonitor 的 cooldown 机制没有持久化

位置: MarginUtilizationMonitor (referenced)

问题:

  • Cooldown 状态存储在内存 Map<string, number>
  • 系统重启后 cooldown 重置
  • 可能导致重启后立即触发多次减仓

建议: 不是严重问题,但可以优化


⚠️ 中等问题

⚠️ P1-6: 没有处理 SignalExecutor 执行超时

位置: Line 1133

问题:

const executionResult = await this.signalExecutor.executeSignalsBatch(allSignals);
  • 如果 executeSignalsBatch 挂起,整个交易周期会卡住
  • 没有超时保护
  • 可能导致下一个周期无法按时执行

建议:

const executionPromise = this.signalExecutor.executeSignalsBatch(allSignals);
const timeoutPromise = new Promise((_, reject) =>
  setTimeout(() => reject(new Error('Execution timeout')), 60000)
);

const executionResult = await Promise.race([executionPromise, timeoutPromise]);

⚠️ P1-7: RiskManager 初始化后没有使用

位置: Line 484-497

问题:

this.riskManager = new RiskManager(riskConfig);
await this.riskManager.initialize();
await this.riskManager.startMonitoring(sessionId);
  • RiskManager 被初始化并启动
  • 但是后续代码从未调用 riskManager.checkRisk() 或类似方法
  • 形同虚设

建议:

  • runTradingCycle 中集成 RiskManager 检查
  • 或者删除 RiskManager(如果不需要)

⚠️ P1-8: 没有限制并发执行 runTradingCycle

位置: Line 1062-1066

问题:

this.cycleInterval = setInterval(() => {
  this.runTradingCycle().catch(error => {
    this.logger.error('Trading cycle error', { error });
  });
}, this.config.tradingInterval);
  • 如果 runTradingCycle 执行时间 > 15秒,会导致并发执行
  • 可能产生竞态条件
  • 订单可能重复提交

修复:

private isRunningCycle: boolean = false;

this.cycleInterval = setInterval(() => {
  if (this.isRunningCycle) {
    this.logger.warn('Previous trading cycle still running, skipping this cycle');
    return;
  }

  this.isRunningCycle = true;
  this.runTradingCycle()
    .catch(error => {
      this.logger.error('Trading cycle error', { error });
    })
    .finally(() => {
      this.isRunningCycle = false;
    });
}, this.config.tradingInterval);

⚠️ P1-9: DualAccountCoordinator 已创建但未使用

位置: Line 576-588

问题:

  • DualAccountCoordinator 被初始化
  • 客户端已注册
  • 但是从未调用其方法(如 coordinateOrders

状态: Sprint 2 功能可能未完成


🟢 轻微问题

🟢 P2-1: 错误处理不一致

问题:

  • 有些地方用 try-catch
  • 有些地方用 .catch()
  • 有些地方不处理错误

建议: 统一错误处理模式


🟢 P2-2: 日志级别使用不当

问题:

  • 正常流程使用 logger.info
  • 异常情况使用 logger.warn
  • 但是很多 warn 级别的日志其实是 error

示例: Line 1024

this.logger.warn(`Failed to get initial positions for ${accountId}`, { error });

应该是:

this.logger.error(`Failed to get initial positions for ${accountId}`, { error });

🟢 P2-3: Magic Numbers 散布各处

问题:

  • 0.5 (Line 242) - 平衡50%
  • 0.995 / 1.005 (Line 722-724) - 减仓价格偏差
  • 3000 (Line 516) - 等待时间
  • 100 (Line 987) - 重试次数

建议: 提取为常量


📊 全面审计总结

按优先级分类

优先级 发现问题数 已修复 待修复
P0 严重 5 2 3
P1 中等 9 2 7
P2 轻微 8 0 8
总计 22 4 18

按类别分类

类别 问题数 严重性
架构设计 4 🔴 高
错误处理 3 ⚠️ 中
并发控制 2 ⚠️ 中
数据同步 3 🔴 高
配置管理 1 ✅ 已修复
代码质量 5 🟢 低
资源管理 2 ⚠️ 中
风险控制 2 🔴 高

🎯 立即需要修复的问题

必须修复 (P0)

  1. WebSocket 订单更新映射 (P0-3) - 影响订单状态同步
  2. 多账户订单取消 (P0-4) - 影响订单生命周期管理
  3. Reduce 信号订单取消 (P0-5) - 影响风险控制

强烈建议修复 (P1)

  1. 并发执行保护 (P1-8) - 防止竞态条件
  2. WebSocket 重连同步 (P1-3) - 提高稳定性
  3. SignalExecutor 超时 (P1-6) - 防止卡死

✅ 做得好的地方

  1. ✅ 架构清晰,组件化良好
  2. ✅ 日志完善,便于调试
  3. ✅ Sprint 1/2 功能集成完整
  4. ✅ 保证金监控机制设计合理
  5. ✅ 配置文件管理规范
  6. ✅ 错误捕获较为全面

📝 审计结论

之前的审计(代码级)

  • ✅ 覆盖了代码质量问题
  • ✅ 发现了保证金计算、price验证等问题

本次审计(系统级)

  • 🔴 发现了架构设计的严重问题
  • 🔴 发现了多账户支持的缺陷
  • ⚠️ 发现了并发控制的风险
  • ⚠️ 发现了状态同步的潜在问题

总结

之前的审计不够全面。需要:

  1. 立即修复: P0-3, P0-4, P0-5(多账户订单管理)
  2. 优先修复: P1-8(并发控制)
  3. 测试验证: 多账户场景、WebSocket 重连场景
  4. 监控增强: 添加更多运行时检查

🔍 建议的下一步

  1. 修复 P0-3, P0-4, P0-5(多账户问题)
  2. 添加并发控制 (P1-8)
  3. 完整测试多账户场景
  4. 进行压力测试和长期运行测试
  5. 考虑添加健康检查机制

审计完成 - 发现了重要的系统级问题,建议立即处理