Browse Source

🧹 清理项目结构

- 重命名 specs/002- -> specs/002-credential-manager
- 创建对应的feature分支 001-specManager-perp, 002-credential-manager
- 删除src目录中重复的目录结构 (adapters/, api/, app/, config/, constants/, infrastructure/, models/)
- 清理备份文件和无关文档

🎯 结果: 清晰的specs管理、规范的分支对应、简化的src目录结构
helium3@sina.com 1 week ago
parent
commit
5851440636
63 changed files with 0 additions and 13161 deletions
  1. 0 0
      specs/002-credential-manager/contracts/signature-service.md
  2. 0 0
      specs/002-credential-manager/data-model.md
  3. 0 0
      specs/002-credential-manager/plan.md
  4. 0 0
      specs/002-credential-manager/quickstart.md
  5. 0 0
      specs/002-credential-manager/research.md
  6. 0 0
      specs/002-credential-manager/spec.md
  7. 0 0
      specs/002-credential-manager/tasks.md
  8. 0 142
      src/adapters/data/cache/manager.ts
  9. 0 217
      src/adapters/exchanges/AdapterErrorHandler.ts
  10. 0 273
      src/adapters/exchanges/AdapterFactory.ts
  11. 0 70
      src/adapters/exchanges/ExchangeAdapter.ts
  12. 0 253
      src/adapters/exchanges/aster/AsterExchangeAdapter.ts
  13. 0 575
      src/adapters/exchanges/aster/asterAdapter.ts
  14. 0 176
      src/adapters/exchanges/aster/orderBook.ts
  15. 0 125
      src/adapters/exchanges/aster/orderBookManager.ts
  16. 0 80
      src/adapters/exchanges/aster/types.ts
  17. 0 268
      src/adapters/exchanges/aster/wsClient.ts
  18. 0 139
      src/adapters/exchanges/binance/BinanceAdapter.ts
  19. 0 414
      src/adapters/exchanges/binance/FutureConnector.ts
  20. 0 97
      src/adapters/exchanges/pacifica/AccountAdapter.ts
  21. 0 327
      src/adapters/exchanges/pacifica/OrdersAdapter.ts
  22. 0 427
      src/adapters/exchanges/pacifica/PacificaAdapter.ts
  23. 0 355
      src/adapters/exchanges/pacifica/PacificaClient.ts
  24. 0 728
      src/adapters/exchanges/pacifica/PacificaProxyClient.ts
  25. 0 547
      src/adapters/exchanges/pacifica/PacificaWebSocketAdapter.ts
  26. 0 364
      src/adapters/exchanges/pacifica/PacificaWebSocketClient.ts
  27. 0 52
      src/adapters/exchanges/pacifica/RestAdapter.ts
  28. 0 2
      src/adapters/exchanges/pacifica/types.d.ts
  29. 0 147
      src/adapters/exchanges/unifiedEvents.ts
  30. 0 37
      src/adapters/infrastructure/config/configManager.ts
  31. 0 31
      src/adapters/infrastructure/config/default.example.yaml
  32. 0 14
      src/adapters/infrastructure/database/index.ts
  33. 0 239
      src/adapters/infrastructure/health/HealthAPI.ts
  34. 0 321
      src/adapters/infrastructure/health/HealthChecker.ts
  35. 0 4
      src/adapters/infrastructure/health/index.ts
  36. 0 30
      src/adapters/infrastructure/wallet/walletManager.ts
  37. 0 279
      src/api/handlers.ts
  38. 0 79
      src/app/credential-main.ts
  39. 0 346
      src/app/credential-service.ts
  40. 0 520
      src/app/main.ts
  41. 0 97
      src/config/asterConfig.ts
  42. 0 210
      src/config/controlPlaneConfig.ts
  43. 0 277
      src/config/riskTemplates.ts
  44. 0 657
      src/config/simpleEnv.ts
  45. 0 41
      src/constants/index.ts
  46. 0 37
      src/infrastructure/config/configManager.ts
  47. 0 31
      src/infrastructure/config/default.example.yaml
  48. 0 14
      src/infrastructure/database/index.ts
  49. 0 239
      src/infrastructure/health/HealthAPI.ts
  50. 0 321
      src/infrastructure/health/HealthChecker.ts
  51. 0 4
      src/infrastructure/health/index.ts
  52. 0 30
      src/infrastructure/wallet/walletManager.ts
  53. 0 1438
      src/main-complete.ts.backup
  54. 0 30
      src/models/AccountAllocation.ts
  55. 0 237
      src/models/ExchangeAccount.ts
  56. 0 122
      src/models/HedgeExecution.ts
  57. 0 321
      src/models/MarketDataFeed.ts
  58. 0 36
      src/models/MonitoringEvent.ts
  59. 0 404
      src/models/OrderIntent.ts
  60. 0 29
      src/models/ProxySession.ts
  61. 0 490
      src/models/RiskEnvelope.ts
  62. 0 389
      src/models/StrategyModule.ts
  63. 0 29
      src/models/SynthPriceSnapshot.ts

+ 0 - 0
specs/002-/contracts/signature-service.md → specs/002-credential-manager/contracts/signature-service.md


+ 0 - 0
specs/002-/data-model.md → specs/002-credential-manager/data-model.md


+ 0 - 0
specs/002-/plan.md → specs/002-credential-manager/plan.md


+ 0 - 0
specs/002-/quickstart.md → specs/002-credential-manager/quickstart.md


+ 0 - 0
specs/002-/research.md → specs/002-credential-manager/research.md


+ 0 - 0
specs/002-/spec.md → specs/002-credential-manager/spec.md


+ 0 - 0
specs/002-/tasks.md → specs/002-credential-manager/tasks.md


+ 0 - 142
src/adapters/data/cache/manager.ts

@@ -1,142 +0,0 @@
-import { CacheEntry, TradingService, ServiceStatus } from '../../types'
-import { logger } from '../shared/utils/logger'
-
-/**
- * 智能缓存管理器 - 减少API调用频率
- */
-export class CacheManager implements TradingService {
-  private cache = new Map<string, CacheEntry>()
-  private readonly cacheConfig = {
-    priceDataTTL: 2000, // 价格数据缓存2秒
-    balanceDataTTL: 5000, // 余额数据缓存5秒
-    positionDataTTL: 3000, // 仓位数据缓存3秒
-    tickerDataTTL: 1000, // 行情数据缓存1秒
-    accountInfoTTL: 10000, // 账户信息缓存10秒
-    defaultTTL: 3000, // 默认缓存3秒
-  }
-
-  async initialize(): Promise<void> {
-    logger.info('CacheManager初始化')
-  }
-
-  async start(): Promise<void> {
-    logger.info('CacheManager启动')
-    // 启动定期清理过期缓存
-    setInterval(() => this.cleanExpiredCache(), 30000) // 每30秒清理一次
-  }
-
-  async stop(): Promise<void> {
-    logger.info('CacheManager停止')
-    this.cache.clear()
-  }
-
-  getStatus(): ServiceStatus {
-    return {
-      name: 'CacheManager',
-      status: 'running',
-      lastUpdate: Date.now(),
-      details: {
-        cacheSize: this.cache.size,
-        hitRate: this.calculateHitRate(),
-      },
-    }
-  }
-
-  /**
-   * 获取缓存数据
-   */
-  get<T>(key: string, ttl?: number): T | null {
-    const cached = this.cache.get(key)
-    if (cached && Date.now() - cached.timestamp < (ttl || cached.ttl)) {
-      return cached.data as T
-    }
-    return null
-  }
-
-  /**
-   * 设置缓存数据
-   */
-  set<T>(key: string, data: T, ttl: number): void {
-    this.cache.set(key, {
-      data,
-      timestamp: Date.now(),
-      ttl,
-    })
-  }
-
-  /**
-   * 获取配置的TTL
-   */
-  getTTL(type: string): number {
-    switch (type) {
-      case 'price':
-        return this.cacheConfig.priceDataTTL
-      case 'balance':
-        return this.cacheConfig.balanceDataTTL
-      case 'position':
-        return this.cacheConfig.positionDataTTL
-      case 'ticker':
-        return this.cacheConfig.tickerDataTTL
-      case 'account':
-        return this.cacheConfig.accountInfoTTL
-      default:
-        return this.cacheConfig.defaultTTL
-    }
-  }
-
-  /**
-   * 删除匹配的缓存
-   */
-  invalidate(pattern: string): void {
-    const keys = Array.from(this.cache.keys()).filter(key => key.includes(pattern))
-    keys.forEach(key => this.cache.delete(key))
-    logger.debug(`缓存失效: ${keys.length}个条目匹配模式 "${pattern}"`)
-  }
-
-  /**
-   * 清理过期缓存
-   */
-  private cleanExpiredCache(): void {
-    const now = Date.now()
-    let cleanedCount = 0
-
-    for (const [key, entry] of this.cache.entries()) {
-      if (now - entry.timestamp > entry.ttl) {
-        this.cache.delete(key)
-        cleanedCount++
-      }
-    }
-
-    if (cleanedCount > 0) {
-      logger.debug(`清理过期缓存: ${cleanedCount}个条目`)
-    }
-  }
-
-  /**
-   * 计算缓存命中率
-   */
-  private calculateHitRate(): number {
-    // 简化的命中率计算,实际应该跟踪hit/miss统计
-    return 0.939 // 93.9% 基于之前的测试结果
-  }
-
-  /**
-   * 获取缓存统计信息
-   */
-  getStats() {
-    return {
-      totalEntries: this.cache.size,
-      hitRate: this.calculateHitRate(),
-      memoryUsage: this.estimateMemoryUsage(),
-    }
-  }
-
-  /**
-   * 估算内存使用量
-   */
-  private estimateMemoryUsage(): string {
-    const entries = this.cache.size
-    const estimatedKB = entries * 0.5 // 假设每个条目约0.5KB
-    return `${estimatedKB.toFixed(1)}KB`
-  }
-}

+ 0 - 217
src/adapters/exchanges/AdapterErrorHandler.ts

@@ -1,217 +0,0 @@
-/**
- * 统一交易所适配器错误处理工具
- */
-
-export interface AdapterError {
-  code: string
-  message: string
-  exchange: string
-  originalError?: any
-  retryable: boolean
-  severity: 'low' | 'medium' | 'high' | 'critical'
-}
-
-export class AdapterErrorHandler {
-  /**
-   * 标准化错误处理
-   */
-  static handleError(exchange: string, error: any, method: string): AdapterError {
-    const originalMessage = this.extractErrorMessage(error)
-    const code = this.extractErrorCode(error, exchange)
-
-    // 根据错误码判断是否可重试和严重程度
-    const { retryable, severity } = this.analyzeError(code, exchange)
-
-    const adapterError: AdapterError = {
-      code,
-      message: `[${exchange}:${method}] ${originalMessage}`,
-      exchange,
-      originalError: error,
-      retryable,
-      severity,
-    }
-
-    // 记录日志
-    this.logError(adapterError, method)
-
-    return adapterError
-  }
-
-  /**
-   * 提取错误信息
-   */
-  private static extractErrorMessage(error: any): string {
-    if (typeof error === 'string') return error
-    if (error?.message) return error.message
-    if (error?.msg) return error.msg
-    if (error?.reason) return error.reason
-    return '未知错误'
-  }
-
-  /**
-   * 提取错误代码
-   */
-  private static extractErrorCode(error: any, exchange: string): string {
-    // Binance 风格错误码
-    if (error?.code) return String(error.code)
-
-    // HTTP 状态码
-    if (error?.status) return `HTTP_${error.status}`
-    if (error?.response?.status) return `HTTP_${error.response.status}`
-
-    // Pacifica 特殊情况
-    if (exchange === 'pacifica' && error?.message?.includes('403')) return 'HTTP_403'
-
-    // Aster 特殊情况
-    if (exchange === 'aster' && error?.message?.includes('-2019')) return 'INSUFFICIENT_MARGIN'
-
-    return 'UNKNOWN_ERROR'
-  }
-
-  /**
-   * 分析错误属性
-   */
-  private static analyzeError(
-    code: string,
-    exchange: string,
-  ): { retryable: boolean; severity: 'low' | 'medium' | 'high' | 'critical' } {
-    // 通用 HTTP 错误
-    if (code.startsWith('HTTP_')) {
-      const statusCode = parseInt(code.replace('HTTP_', ''))
-      if (statusCode >= 500) return { retryable: true, severity: 'high' }
-      if (statusCode === 429) return { retryable: true, severity: 'medium' }
-      if (statusCode === 403) return { retryable: false, severity: 'medium' }
-      if (statusCode === 401) return { retryable: false, severity: 'high' }
-      return { retryable: false, severity: 'medium' }
-    }
-
-    // 交易所特定错误
-    if (exchange === 'binance') {
-      return this.analyzeBinanceError(code)
-    } else if (exchange === 'aster') {
-      return this.analyzeAsterError(code)
-    } else if (exchange === 'pacifica') {
-      return this.analyzePacificaError(code)
-    }
-
-    return { retryable: false, severity: 'medium' }
-  }
-
-  /**
-   * 分析币安错误
-   */
-  private static analyzeBinanceError(code: string): {
-    retryable: boolean
-    severity: 'low' | 'medium' | 'high' | 'critical'
-  } {
-    const retryableCodes = ['-1001', '-1021', '-2013', '-2015'] // 网络、时间同步等
-    const criticalCodes = ['-1022', '-2010', '-4028'] // API密钥、余额不足等
-    const marginCodes = ['-2019', '-4061'] // 保证金相关
-
-    if (retryableCodes.includes(code)) return { retryable: true, severity: 'medium' }
-    if (criticalCodes.includes(code)) return { retryable: false, severity: 'critical' }
-    if (marginCodes.includes(code)) return { retryable: false, severity: 'high' }
-
-    return { retryable: false, severity: 'medium' }
-  }
-
-  /**
-   * 分析Aster错误
-   */
-  private static analyzeAsterError(code: string): {
-    retryable: boolean
-    severity: 'low' | 'medium' | 'high' | 'critical'
-  } {
-    if (code === 'INSUFFICIENT_MARGIN') return { retryable: false, severity: 'high' }
-    if (code === 'missing_user_signer_privateKey') return { retryable: false, severity: 'critical' }
-    if (code === 'listenKeyExpired') return { retryable: true, severity: 'medium' }
-
-    return { retryable: false, severity: 'medium' }
-  }
-
-  /**
-   * 分析Pacifica错误
-   */
-  private static analyzePacificaError(code: string): {
-    retryable: boolean
-    severity: 'low' | 'medium' | 'high' | 'critical'
-  } {
-    if (code === 'HTTP_403') return { retryable: false, severity: 'medium' } // CDN/白名单
-    if (code === 'orderbook_not_found') return { retryable: true, severity: 'medium' }
-
-    return { retryable: false, severity: 'medium' }
-  }
-
-  /**
-   * 记录错误日志
-   */
-  private static logError(error: AdapterError, method: string) {
-    const level =
-      error.severity === 'critical'
-        ? 'error'
-        : error.severity === 'high'
-        ? 'error'
-        : error.severity === 'medium'
-        ? 'warn'
-        : 'info'
-
-    const logMessage = `${error.message} [代码: ${error.code}, 可重试: ${error.retryable}]`
-
-    // 这里可以集成实际的日志系统
-    if (level === 'error') {
-      console.error(`❌ ${logMessage}`)
-    } else if (level === 'warn') {
-      console.warn(`⚠️ ${logMessage}`)
-    } else {
-      console.info(`ℹ️ ${logMessage}`)
-    }
-  }
-
-  /**
-   * 检查是否应该重试
-   */
-  static shouldRetry(error: AdapterError, attemptCount: number, maxAttempts = 3): boolean {
-    return error.retryable && attemptCount < maxAttempts
-  }
-
-  /**
-   * 计算重试延迟(指数退避)
-   */
-  static getRetryDelay(attemptCount: number, baseDelayMs = 1000, maxDelayMs = 10000): number {
-    const delay = Math.min(baseDelayMs * Math.pow(2, attemptCount - 1), maxDelayMs)
-    // 添加随机抖动避免雷群效应
-    return delay + Math.random() * 1000
-  }
-}
-
-/**
- * 装饰器:为适配器方法添加错误处理和重试逻辑
- */
-export function withErrorHandling(exchange: string, maxRetries = 2) {
-  return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
-    const method = descriptor.value
-
-    descriptor.value = async function (...args: any[]) {
-      let lastError: AdapterError | null = null
-
-      for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
-        try {
-          return await method.apply(this, args)
-        } catch (error) {
-          const adapterError = AdapterErrorHandler.handleError(exchange, error, propertyName)
-          lastError = adapterError
-
-          if (!AdapterErrorHandler.shouldRetry(adapterError, attempt, maxRetries + 1)) {
-            throw adapterError
-          }
-
-          const delay = AdapterErrorHandler.getRetryDelay(attempt)
-          console.info(`🔄 [${exchange}:${propertyName}] 重试第 ${attempt} 次,${delay}ms 后重试`)
-          await new Promise(resolve => setTimeout(resolve, delay))
-        }
-      }
-
-      throw lastError
-    }
-  }
-}

+ 0 - 273
src/adapters/exchanges/AdapterFactory.ts

@@ -1,273 +0,0 @@
-/**
- * 交易所适配器工厂
- * 统一管理适配器的创建、配置和初始化
- */
-
-import { ExchangeAdapter } from './ExchangeAdapter'
-import { BinanceAdapter } from './binance/BinanceAdapter'
-import { FutureConnector } from './binance/FutureConnector'
-import { PacificaAdapter } from './pacifica/PacificaAdapter'
-import { PacificaClient } from './pacifica/PacificaClient'
-import { AsterExchangeAdapter } from './aster/AsterExchangeAdapter'
-import { AsterAdapter } from './aster/asterAdapter'
-
-export type SupportedExchange = 'binance' | 'pacifica' | 'aster'
-
-export interface ExchangeConfig {
-  exchange: SupportedExchange
-  apiKey?: string
-  apiSecret?: string
-  baseUrl?: string
-  wsUrl?: string
-  privateKey?: string
-  accountId?: string
-  [key: string]: any
-}
-
-export interface AdapterFactoryResult {
-  adapter: ExchangeAdapter
-  config: ExchangeConfig
-  initialized: boolean
-}
-
-export class AdapterFactory {
-  private static instances = new Map<string, AdapterFactoryResult>()
-
-  /**
-   * 创建适配器实例
-   */
-  static async create(config: ExchangeConfig): Promise<AdapterFactoryResult> {
-    const key = this.getInstanceKey(config)
-
-    if (this.instances.has(key)) {
-      return this.instances.get(key)!
-    }
-
-    const result = await this.createAdapter(config)
-    this.instances.set(key, result)
-
-    return result
-  }
-
-  /**
-   * 从环境变量创建适配器
-   */
-  static async createFromEnv(exchange: SupportedExchange, accountId?: string): Promise<AdapterFactoryResult> {
-    const config = this.loadConfigFromEnv(exchange, accountId)
-    return this.create(config)
-  }
-
-  /**
-   * 创建具体的适配器实例
-   */
-  private static async createAdapter(config: ExchangeConfig): Promise<AdapterFactoryResult> {
-    let adapter: ExchangeAdapter
-    let initialized = false
-
-    try {
-      switch (config.exchange) {
-        case 'binance':
-          adapter = await this.createBinanceAdapter(config)
-          break
-        case 'pacifica':
-          adapter = await this.createPacificaAdapter(config)
-          break
-        case 'aster':
-          adapter = await this.createAsterAdapter(config)
-          break
-        default:
-          throw new Error(`不支持的交易所: ${config.exchange}`)
-      }
-
-      // 执行初始化测试
-      initialized = await this.testAdapter(adapter, config.exchange)
-
-      if (!initialized && config.exchange === 'pacifica') {
-        // Pacifica 可能有网络问题,但仍然允许创建适配器
-        console.warn(`⚠️ ${config.exchange} 适配器测试失败,但仍然创建实例`)
-        initialized = true
-      }
-
-      return { adapter, config, initialized }
-    } catch (error) {
-      console.error(`❌ 创建 ${config.exchange} 适配器失败:`, error)
-
-      // 对 Pacifica 的特殊处理
-      if (config.exchange === 'pacifica' && error.message.includes('HTTP 500')) {
-        console.warn(`⚠️ Pacifica 可能存在临时网络问题,跳过严格验证`)
-        try {
-          const adapter = await this.createPacificaAdapter(config)
-          return { adapter, config, initialized: true }
-        } catch (retryError) {
-          console.error('❌ Pacifica 重试失败:', retryError)
-        }
-      }
-
-      throw error
-    }
-  }
-
-  /**
-   * 创建币安适配器
-   */
-  private static async createBinanceAdapter(config: ExchangeConfig): Promise<BinanceAdapter> {
-    if (!config.apiKey || !config.apiSecret) {
-      throw new Error('Binance 适配器需要 apiKey 和 apiSecret')
-    }
-
-    const futureConnector = new FutureConnector(config.apiKey, config.apiSecret)
-    return new BinanceAdapter(futureConnector)
-  }
-
-  /**
-   * 创建Pacifica适配器
-   */
-  private static async createPacificaAdapter(config: ExchangeConfig): Promise<PacificaAdapter> {
-    if (!config.privateKey || !config.accountId) {
-      throw new Error('Pacifica 适配器需要 privateKey 和 accountId')
-    }
-
-    const client = new PacificaClient({
-      baseUrl: config.baseUrl || 'https://api.pacifica.fi',
-      wsUrl: config.wsUrl || 'wss://ws.pacifica.fi',
-      account: config.accountId,
-      privateKey: config.privateKey,
-      agentWallet: config.agentWallet,
-      agentPrivateKey: config.agentPrivateKey,
-    })
-
-    return new PacificaAdapter(client)
-  }
-
-  /**
-   * 创建Aster适配器
-   */
-  private static async createAsterAdapter(config: ExchangeConfig): Promise<AsterExchangeAdapter> {
-    if (!config.user || !config.signer || !config.privateKey) {
-      throw new Error('Aster 适配器需要 user、signer 和 privateKey')
-    }
-
-    const asterConfig = {
-      httpBase: config.baseUrl || 'https://fapi.asterdex.com',
-      defaultUser: config.user,
-      defaultSigner: config.signer,
-      apiKey: config.apiKey,
-      apiSecret: config.apiSecret,
-    }
-
-    const asterClient = new AsterAdapter(asterConfig)
-    return new AsterExchangeAdapter(asterClient)
-  }
-
-  /**
-   * 从环境变量加载配置
-   */
-  private static loadConfigFromEnv(exchange: SupportedExchange, accountId?: string): ExchangeConfig {
-    switch (exchange) {
-      case 'binance':
-        return {
-          exchange: 'binance',
-          apiKey: process.env.BINANCE_API_KEY,
-          apiSecret: process.env.BINANCE_SECRET_KEY,
-        }
-
-      case 'pacifica':
-        return {
-          exchange: 'pacifica',
-          accountId: accountId || process.env.PACIFICA_ACCOUNT,
-          privateKey: process.env.PACIFICA_ACCOUNT_PRIVATE_KEY || process.env.PACIFICA_PRIVATE_KEY,
-          baseUrl: process.env.PACIFICA_BASE_URL,
-          wsUrl: process.env.PACIFICA_WS_URL,
-          agentWallet: process.env.PACIFICA_AGENT_WALLET,
-          agentPrivateKey: process.env.PACIFICA_AGENT_PRIVATE_KEY,
-        }
-
-      case 'aster':
-        return {
-          exchange: 'aster',
-          user: process.env.ASTER_ORDER_USER,
-          signer: process.env.ASTER_ORDER_SIGNER || process.env.ASTER_API_KEY,
-          privateKey: process.env.PRIVATE_KEY || process.env.PRIVATE_KEY2 || process.env.ASTER_API_SECRET,
-          apiKey: process.env.ASTER_API_KEY,
-          apiSecret: process.env.ASTER_API_SECRET,
-          baseUrl: process.env.ASTER_HTTP_BASE,
-        }
-
-      default:
-        throw new Error(`不支持的交易所: ${exchange}`)
-    }
-  }
-
-  /**
-   * 测试适配器基本功能
-   */
-  private static async testAdapter(adapter: ExchangeAdapter, exchange: string): Promise<boolean> {
-    try {
-      console.info(`🧪 测试 ${exchange} 适配器连接...`)
-
-      // 基础连接测试
-      const time = await adapter.time()
-      if (!time || time <= 0) {
-        console.warn(`⚠️ ${exchange} 时间同步测试失败`)
-        return false
-      }
-
-      // 符号列表测试
-      const symbols = await adapter.symbols()
-      if (!Array.isArray(symbols)) {
-        console.warn(`⚠️ ${exchange} 符号列表获取失败`)
-        return false
-      }
-
-      console.info(`✅ ${exchange} 适配器测试通过 (获取到 ${symbols.length} 个交易对)`)
-      return true
-    } catch (error) {
-      console.error(`❌ ${exchange} 适配器测试失败:`, error)
-      return false
-    }
-  }
-
-  /**
-   * 生成实例缓存键
-   */
-  private static getInstanceKey(config: ExchangeConfig): string {
-    const keyParts = [config.exchange]
-
-    if (config.accountId) keyParts.push(config.accountId)
-    if (config.user) keyParts.push(config.user)
-
-    return keyParts.join('::')
-  }
-
-  /**
-   * 清理所有适配器实例
-   */
-  static clearInstances(): void {
-    this.instances.clear()
-  }
-
-  /**
-   * 获取所有已创建的适配器
-   */
-  static getAllAdapters(): AdapterFactoryResult[] {
-    return Array.from(this.instances.values())
-  }
-
-  /**
-   * 健康检查所有适配器
-   */
-  static async healthCheck(): Promise<{ [exchange: string]: boolean }> {
-    const results: { [exchange: string]: boolean } = {}
-
-    for (const [key, { adapter, config }] of this.instances) {
-      try {
-        const isHealthy = await this.testAdapter(adapter, config.exchange)
-        results[key] = isHealthy
-      } catch {
-        results[key] = false
-      }
-    }
-
-    return results
-  }
-}

+ 0 - 70
src/adapters/exchanges/ExchangeAdapter.ts

@@ -1,70 +0,0 @@
-import { EventEmitter } from 'events'
-
-export type Side = 'BUY' | 'SELL'
-export type OrderType = 'MARKET' | 'LIMIT' | 'POST_ONLY'
-export type TimeInForce = 'GTC' | 'IOC' | 'FOK'
-export type PositionSide = 'LONG' | 'SHORT'
-
-export interface PlaceOrderReq {
-  symbol: string
-  side: Side
-  type: OrderType
-  quantity: string
-  price?: string
-  tif?: TimeInForce
-  reduceOnly?: boolean
-  clientOrderId?: string
-}
-
-export interface Order {
-  id: string
-  symbol: string
-  status: 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'REJECTED' | 'EXPIRED'
-  side: Side
-  type: OrderType
-  price?: string
-  origQty: string
-  executedQty: string
-  updateTime: number
-}
-
-export interface Position {
-  symbol: string
-  side: PositionSide
-  qty: string
-  entryPrice: string
-  unrealizedPnl: string
-  leverage?: number
-}
-
-export interface Balance {
-  asset: string
-  total: string
-  free: string
-}
-
-export interface DepthLevel {
-  price: string
-  qty: string
-}
-export interface Depth {
-  bids: DepthLevel[]
-  asks: DepthLevel[]
-  ts: number
-}
-
-export interface ExchangeAdapter {
-  name(): string
-  time(): Promise<number>
-  symbols(): Promise<string[]>
-  balances(): Promise<Balance[]>
-  positions(): Promise<Position[]>
-  placeOrder(req: PlaceOrderReq): Promise<Order>
-  cancelOrder(symbol: string, orderId: string): Promise<void>
-  cancelAll(symbol: string): Promise<void>
-  getOrder(symbol: string, orderId: string): Promise<Order>
-  openOrders(symbol: string): Promise<Order[]>
-  leverage?(symbol: string, lev: number): Promise<void>
-  depth(symbol: string, limit?: number): Promise<Depth>
-  ws(): EventEmitter
-}

+ 0 - 253
src/adapters/exchanges/aster/AsterExchangeAdapter.ts

@@ -1,253 +0,0 @@
-import { EventEmitter } from 'events'
-import { ExchangeAdapter, PlaceOrderReq, Order, Position, Balance, Depth } from '../ExchangeAdapter'
-import { AsterAdapter } from './asterAdapter'
-import {
-  normalizeAsterAccountInfoEvent,
-  normalizeAsterBalanceEvent,
-  normalizeAsterOrdersEvent,
-  normalizeAsterPositionsEvent,
-} from '../unifiedEvents'
-import { AsterWsClient } from './wsClient'
-import { httpClient } from '../../utils/httpClient'
-
-export class AsterExchangeAdapter implements ExchangeAdapter {
-  private events = new EventEmitter()
-  private userWs?: AsterWsClient
-  private userKeepAliveTimer?: NodeJS.Timeout
-  constructor(private client: AsterAdapter) {}
-
-  name() {
-    return 'aster'
-  }
-  async time(): Promise<number> {
-    return Date.now()
-  }
-  async symbols(): Promise<string[]> {
-    try {
-      const base = (this.client as any).cfg?.httpBase || process.env.ASTER_HTTP_BASE || ''
-      const res = await httpClient.get(`${String(base).replace(/\/$/, '')}/fapi/v3/exchangeInfo`, {
-        exchange: 'aster',
-        timeout: 10000,
-      })
-
-      if (!res.ok) {
-        return []
-      }
-
-      return (Array.isArray(res.data?.symbols) ? res.data.symbols : [])
-        .map((s: any) => String(s.symbol))
-        .filter(Boolean)
-    } catch {
-      return []
-    }
-  }
-  async balances(): Promise<Balance[]> {
-    try {
-      const arr = await (this.client as any).getBalances()
-      return (Array.isArray(arr) ? arr : []).map((b: any) => ({
-        asset: String(b.asset ?? b.balanceAsset ?? 'USDT'),
-        total: String(b.balance ?? b.balanceTotal ?? b.walletBalance ?? '0'),
-        free: String(b.availableBalance ?? b.free ?? '0'),
-      }))
-    } catch {
-      return []
-    }
-  }
-  async positions(): Promise<Position[]> {
-    try {
-      const arr = await (this.client as any).getPositionRisk()
-      return (Array.isArray(arr) ? arr : [])
-        .map((p: any) => ({
-          symbol: String(p.symbol ?? ''),
-          side: (Number(p.positionAmt ?? p.positionAmtAbs ?? 0) >= 0 ? 'LONG' : 'SHORT') as 'LONG' | 'SHORT',
-          qty: String(p.positionAmt ?? '0'),
-          entryPrice: String(p.entryPrice ?? '0'),
-          unrealizedPnl: String(p.unRealizedProfit ?? p.unrealizedProfit ?? '0'),
-          leverage: Number(p.leverage ?? 0),
-        }))
-        .filter(x => x.symbol)
-    } catch {
-      return []
-    }
-  }
-  async placeOrder(req: PlaceOrderReq): Promise<Order> {
-    const isMarket = req.type === 'MARKET'
-    const side = req.side === 'BUY' ? 'long' : 'short'
-    const price = req.price ? String(req.price) : undefined
-    const res = await this.client.openPerp({
-      symbol: req.symbol,
-      side: side as any,
-      quantity: Number(req.quantity),
-      slippage: 0,
-      deadlineSec: Math.floor(Date.now() / 1000) + 60,
-      positionSide: undefined,
-      ...(isMarket ? {} : { type: 'LIMIT' as any, price }),
-    })
-    return {
-      id: String(
-        res?.txHash
-          ? (() => {
-              try {
-                return JSON.parse(String(res.txHash)).orderId
-              } catch {
-                return Date.now()
-              }
-            })()
-          : Date.now(),
-      ),
-      symbol: req.symbol,
-      status: res.success ? 'NEW' : 'REJECTED',
-      side: req.side,
-      type: req.type,
-      price: price,
-      origQty: String(req.quantity),
-      executedQty: '0',
-      updateTime: Date.now(),
-    }
-  }
-  async cancelOrder(symbol: string, orderId: string): Promise<void> {
-    await this.client.cancelOrderRest({ symbol, side: 'BUY', type: 'LIMIT', orderId: Number(orderId) })
-  }
-  async cancelAll(symbol: string): Promise<void> {
-    // Aster 无单一 cancelAll 端点,这里可拉取 openOrders 后逐个撤单
-    const opens = await this.openOrders(symbol)
-    for (const o of opens) {
-      try {
-        await this.cancelOrder(symbol, o.id)
-      } catch {}
-    }
-  }
-  async getOrder(symbol: string, orderId: string): Promise<Order> {
-    const info = await this.client.getOrderRest({ symbol, side: 'BUY', type: 'LIMIT', orderId: Number(orderId) })
-    return {
-      id: String(orderId),
-      symbol,
-      status: this.mapOrderStatus(info?.status),
-      side: this.mapOrderSide(info?.side),
-      type: this.mapOrderType(info?.type),
-      price: String(info?.price ?? '0'),
-      origQty: String(info?.origQty ?? '0'),
-      executedQty: String(info?.executedQty ?? '0'),
-      updateTime: Number(info?.updateTime ?? Date.now()),
-    }
-  }
-  async openOrders(symbol: string): Promise<Order[]> {
-    try {
-      const arr = await (this.client as any).getOpenOrders(symbol)
-      return (Array.isArray(arr) ? arr : []).map((o: any) => ({
-        id: String(o.orderId ?? o.clientOrderId ?? Date.now()),
-        symbol: String(o.symbol ?? symbol),
-        status: this.mapOrderStatus(o?.status),
-        side: this.mapOrderSide(o?.side),
-        type: this.mapOrderType(o?.type),
-        price: String(o.price ?? '0'),
-        origQty: String(o.origQty ?? o.quantity ?? '0'),
-        executedQty: String(o.executedQty ?? o.cumQty ?? '0'),
-        updateTime: Number(o.updateTime ?? Date.now()),
-      }))
-    } catch {
-      return []
-    }
-  }
-  async leverage(symbol: string, lev: number): Promise<void> {
-    await this.client.updateLeverage(symbol, lev)
-  }
-  async depth(symbol: string, _limit = 50): Promise<Depth> {
-    const base = (this.client as any).cfg?.httpBase || process.env.ASTER_HTTP_BASE || ''
-    const res = await (globalThis.fetch as any)(
-      `${String(base).replace(/\/$/, '')}/fapi/v3/depth?symbol=${encodeURIComponent(symbol)}&limit=20`,
-    )
-    const data = await (res as any).json()
-    const bids = (data?.bids ?? []).map((x: any) => ({ price: String(x[0]), qty: String(x[1]) }))
-    const asks = (data?.asks ?? []).map((x: any) => ({ price: String(x[0]), qty: String(x[1]) }))
-    return { bids, asks, ts: Date.now() }
-  }
-  ws() {
-    return this.events
-  }
-
-  /** 启动账户 WS(listenKey)。需要在 cfg 中提供 apiKey/apiSecret 与 httpBase。*/
-  async startAccountUserStream(wsBase = 'wss://fstream.asterdex.com') {
-    // 1) 创建/续期 listenKey
-    const ensured = await this.client.ensureListenKey()
-    const lk = ensured.listenKey
-    // 2) 连接 user stream
-    const c = new AsterWsClient({ wsUrl: wsBase })
-    c.setUserStream(lk, wsBase)
-    c.on('raw', (m: any) => this.events.emit('raw', m))
-    c.on('balance', (p: any) => this.events.emit('balance', normalizeAsterBalanceEvent(p)))
-    c.on('account_positions', (p: any) => this.events.emit('account_positions', normalizeAsterPositionsEvent(p)))
-    c.on('account_info', (p: any) => this.events.emit('account_info', normalizeAsterAccountInfoEvent(p)))
-    c.on('orders', (p: any) => this.events.emit('orders', normalizeAsterOrdersEvent(p)))
-    c.on('error', (e: any) => this.events.emit('ws_error', e))
-    c.on('ws_error', async (e: any) => {
-      this.events.emit('ws_error', e)
-      const code = e?.code
-      if (code === 'listenKeyExpired' || code === 'INVALID_LISTEN_KEY' || code === -1125) {
-        // 重新创建 listenKey 并重连
-        try {
-          const newState = await this.client.ensureListenKey({ forceNew: true })
-          const newKey = newState.listenKey
-          c.setUserStream(newKey, wsBase)
-          c.connectUserStream()
-        } catch {}
-      }
-    })
-    c.on('close', () => this.events.emit('ws_close', {}))
-    c.connectUserStream()
-    this.userWs = c
-    // 3) 定时 keepAlive(官方 60 分钟;这里 30 分钟)
-    if (this.userKeepAliveTimer) {
-      clearInterval(this.userKeepAliveTimer)
-    }
-    this.userKeepAliveTimer = setInterval(
-      () => {
-        this.client.ensureListenKey({ refreshThresholdMs: 0 }).catch(() => {})
-      },
-      30 * 60 * 1000,
-    )
-  }
-
-  stopAccountUserStream() {
-    if (this.userWs) {
-      try {
-        this.userWs.disconnect()
-      } catch {}
-      this.userWs = undefined
-    }
-    if (this.userKeepAliveTimer) {
-      clearInterval(this.userKeepAliveTimer)
-      this.userKeepAliveTimer = undefined
-    }
-    // 可选:关闭 listenKey
-    this.client.closeListenKey().catch(() => {})
-  }
-
-  // ===== Helpers: type-safe unions for Order fields =====
-  private mapOrderStatus(input: any): Order['status'] {
-    const u = String(input ?? 'NEW').toUpperCase()
-    switch (u) {
-      case 'NEW':
-      case 'PARTIALLY_FILLED':
-      case 'FILLED':
-      case 'CANCELED':
-      case 'REJECTED':
-      case 'EXPIRED':
-        return u as Order['status']
-      default:
-        return 'NEW'
-    }
-  }
-
-  private mapOrderSide(input: any): 'BUY' | 'SELL' {
-    const u = String(input ?? 'BUY').toUpperCase()
-    return u === 'SELL' ? 'SELL' : 'BUY'
-  }
-
-  private mapOrderType(input: any): 'MARKET' | 'LIMIT' | 'POST_ONLY' {
-    const u = String(input ?? 'LIMIT').toUpperCase()
-    if (u === 'MARKET') return 'MARKET'
-    if (u === 'POST_ONLY') return 'POST_ONLY'
-    return 'LIMIT'
-  }
-}

+ 0 - 575
src/adapters/exchanges/aster/asterAdapter.ts

@@ -1,575 +0,0 @@
-import { AbiCoder, Wallet, keccak256, getBytes } from 'ethers'
-import { createHmac } from 'crypto'
-
-export interface AsterConfig {
-  rpcUrl: string
-  chainId: number
-  routerAddress: string // Aster 合约/路由地址(根据文档填写)
-  readerAddress?: string // 读取器合约地址(可选)
-  httpBase?: string // REST API Base,例如 https://fapi.asterdex.com
-  defaultUser?: string // 下单 user 地址(owner)
-  defaultSigner?: string // 下单 signer 地址(与私钥对应)
-  apiKey?: string // (可选)REST HMAC API Key,用于读取账户设置
-  apiSecret?: string // (可选)REST HMAC API Secret
-}
-
-export interface AsterQuoteParams {
-  symbol: string // 交易对(与 Aster 平台定义保持一致)
-  side: 'long' | 'short'
-  quantity: number // 张数或标的数量(依据 Aster 定义)
-  slippage: number // 最大滑点比例
-}
-
-export interface AsterQuoteResult {
-  expectedPrice: number
-  feeUsd?: number
-  fundingRate?: number
-}
-
-export interface AsterOrderParams extends AsterQuoteParams {
-  deadlineSec: number
-  positionSide?: 'BOTH' | 'LONG' | 'SHORT'
-}
-
-export interface AsterOrderResult {
-  success: boolean
-  txHash?: string
-  error?: string
-}
-
-export class AsterAdapter {
-  private provider: any // 懒加载链上需求
-  private signer?: Wallet
-  private cfg: AsterConfig
-  private dualSideCache?: boolean
-  private listenKeyState?: { key: string; updatedAt: number }
-
-  constructor(cfg: AsterConfig, signer?: Wallet) {
-    this.cfg = cfg
-    // 仅在需要链上时使用 provider
-    // @ts-ignore
-    this.provider = undefined
-    this.signer = signer
-  }
-
-  async getFundingRate(symbol: string): Promise<number | null> {
-    // 使用 REST: GET /fapi/v3/fundingRate?symbol=BTCUSDT&limit=1 取最近一条
-    const base = this.cfg.httpBase || process.env.ASTER_HTTP_BASE || ''
-    if (!base) return null
-    const url = `${base.replace(/\/$/, '')}/fapi/v3/fundingRate?symbol=${encodeURIComponent(symbol)}&limit=1`
-    try {
-      const res = await (globalThis.fetch as any)(url, { method: 'GET' } as any)
-      if (!('ok' in res) || !(res as any).ok) return null
-      const data = await (res as any).json()
-      const item = Array.isArray(data) ? data[0] : data
-      const rate = Number(item?.fundingRate ?? item?.funding_rate ?? item?.r)
-      return Number.isFinite(rate) ? rate : null
-    } catch {
-      return null
-    }
-  }
-
-  async quote(params: AsterQuoteParams): Promise<AsterQuoteResult> {
-    // 简化:用标记价格/最新价作为预估成交价,并返回当前资金费率
-    const base = this.cfg.httpBase || process.env.ASTER_HTTP_BASE || ''
-    if (!base) return { expectedPrice: 0 }
-    const url = `${base.replace(/\/$/, '')}/fapi/v3/ticker/price?symbol=${encodeURIComponent(params.symbol)}`
-    try {
-      const res = await (globalThis.fetch as any)(url, { method: 'GET' } as any)
-      const data = await (res as any).json()
-      const px = Number(data?.price ?? data?.p ?? data?.lastPrice)
-      const funding = await this.getFundingRate(params.symbol)
-      return { expectedPrice: Number.isFinite(px) ? px : 0, fundingRate: funding ?? undefined }
-    } catch {
-      return { expectedPrice: 0 }
-    }
-  }
-
-  async openPerp(params: AsterOrderParams): Promise<AsterOrderResult> {
-    // 使用 REST 市价下单(BUY,LONG 或 BOTH 由调用方选择)
-    const side = params.side === 'long' ? 'BUY' : 'SELL'
-    try {
-      const posSide = params.positionSide ?? (await this.choosePositionSide(side as 'BUY' | 'SELL'))
-      const attempt = async (positionSide: 'BOTH' | 'LONG' | 'SHORT') => {
-        const sig = await this.generateOrderSignature({
-          symbol: params.symbol,
-          positionSide,
-          type: 'MARKET',
-          side: side as any,
-          quantity: params.quantity,
-          timeInForce: undefined,
-        })
-        const url = `${this.requireHttpBase()}/fapi/v3/order`
-        const body = new URLSearchParams(sig.formFields).toString()
-        const res = await (globalThis.fetch as any)(url, {
-          method: 'POST',
-          headers: { 'content-type': 'application/x-www-form-urlencoded' } as any,
-          body,
-        } as any)
-        const text = await res.text()
-        return { ok: (res as any).ok, text }
-      }
-      const r1 = await attempt(posSide)
-      if (r1.ok) return { success: true, txHash: r1.text }
-      if (r1.text.includes('position side') || r1.text.includes('positionSide')) {
-        // 切换模式重试:BOTH <-> LONG/SHORT
-        const fallback: 'BOTH' | 'LONG' | 'SHORT' = posSide === 'BOTH' ? (side === 'BUY' ? 'LONG' : 'SHORT') : 'BOTH'
-        const r2 = await attempt(fallback)
-        if (r2.ok) return { success: true, txHash: r2.text }
-        return { success: false, error: r2.text.slice(0, 200) }
-      }
-      return { success: false, error: r1.text.slice(0, 200) }
-    } catch (e: any) {
-      return { success: false, error: e?.message || String(e) }
-    }
-  }
-
-  async closePerp(params: AsterOrderParams): Promise<AsterOrderResult> {
-    const side = params.side === 'long' ? 'SELL' : 'BUY'
-    try {
-      const posSide = params.positionSide ?? (await this.choosePositionSide(side as 'BUY' | 'SELL'))
-      const attempt = async (positionSide: 'BOTH' | 'LONG' | 'SHORT') => {
-        const sig = await this.generateOrderSignature({
-          symbol: params.symbol,
-          positionSide,
-          type: 'MARKET',
-          side: side as any,
-          quantity: params.quantity,
-          timeInForce: undefined,
-        })
-        const url = `${this.requireHttpBase()}/fapi/v3/order`
-        const body = new URLSearchParams(sig.formFields).toString()
-        const res = await (globalThis.fetch as any)(url, {
-          method: 'POST',
-          headers: { 'content-type': 'application/x-www-form-urlencoded' } as any,
-          body,
-        } as any)
-        const text = await res.text()
-        return { ok: (res as any).ok, text }
-      }
-      const r1 = await attempt(posSide)
-      if (r1.ok) return { success: true, txHash: r1.text }
-      if (r1.text.includes('position side') || r1.text.includes('positionSide')) {
-        const fallback: 'BOTH' | 'LONG' | 'SHORT' = posSide === 'BOTH' ? (side === 'BUY' ? 'LONG' : 'SHORT') : 'BOTH'
-        const r2 = await attempt(fallback)
-        if (r2.ok) return { success: true, txHash: r2.text }
-        return { success: false, error: r2.text.slice(0, 200) }
-      }
-      return { success: false, error: r1.text.slice(0, 200) }
-    } catch (e: any) {
-      return { success: false, error: e?.message || String(e) }
-    }
-  }
-
-  // === REST: 查单 / 撤单(使用与下单相同的签名流程) ===
-
-  /** 生成撤单签名 */
-  async generateCancelSignature(
-    req: {
-      symbol: string
-      side: 'BUY' | 'SELL' | 'buy' | 'sell'
-      type: 'LIMIT' | 'MARKET' | 'STOP' | 'STOP_MARKET' | 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET'
-      orderId?: number
-      clientOrderId?: string
-      recvWindow?: number
-      timestamp?: number
-    },
-    creds?: { user?: string; signer?: string; privateKey?: string; nonceMicros?: bigint },
-  ): Promise<{ formFields: Record<string, string> }> {
-    const business: Record<string, any> = {
-      ...req,
-      recvWindow: req.recvWindow ?? 50000,
-      timestamp: req.timestamp ?? Date.now(),
-    }
-    const bizStrDict = this.normalizeBusinessParams(business)
-    const jsonStr = this.stableJSONString(bizStrDict)
-    const user = creds?.user || this.cfg.defaultUser || process.env.ASTER_ORDER_USER || ''
-    const signer = creds?.signer || this.cfg.defaultSigner || process.env.ASTER_ORDER_SIGNER || ''
-    const privateKey = creds?.privateKey || process.env.PRIVATE_KEY || ''
-    if (!user || !signer || !privateKey) throw new Error('缺少用户、签名者或私钥')
-    const nonce = creds?.nonceMicros ?? BigInt(Math.trunc(Date.now() * 1000))
-    const signature = await this.signOrderJSONString(jsonStr, user, signer, nonce, privateKey)
-    const formFields: Record<string, string> = {
-      ...bizStrDict,
-      nonce: String(nonce),
-      user,
-      signer,
-      signature,
-    }
-    return { formFields }
-  }
-
-  /** GET /fapi/v3/order 查单 */
-  async getOrderRest(params: {
-    symbol: string
-    side: 'BUY' | 'SELL'
-    type: string
-    orderId?: number
-    clientOrderId?: string
-  }): Promise<any> {
-    const base = this.requireHttpBase()
-    const { formFields } = await this.generateCancelSignature(params)
-    const qs = new URLSearchParams(formFields).toString()
-    const url = `${base}/fapi/v3/order?${qs}`
-    const res = await (globalThis.fetch as any)(url, { method: 'GET' } as any)
-    const txt = await res.text()
-    if (!('ok' in res) || !(res as any).ok)
-      throw new Error(`HTTP ${(res as any).status} GET /fapi/v3/order - ${txt.slice(0, 200)}`)
-    try {
-      return JSON.parse(txt)
-    } catch {
-      return txt
-    }
-  }
-
-  /** DELETE /fapi/v3/order 撤单 */
-  async cancelOrderRest(params: {
-    symbol: string
-    side: 'BUY' | 'SELL'
-    type: string
-    orderId?: number
-    clientOrderId?: string
-  }): Promise<any> {
-    const base = this.requireHttpBase()
-    const { formFields } = await this.generateCancelSignature(params)
-    const qs = new URLSearchParams(formFields).toString()
-    const url = `${base}/fapi/v3/order?${qs}`
-    const res = await (globalThis.fetch as any)(url, { method: 'DELETE' } as any)
-    const txt = await res.text()
-    if (!('ok' in res) || !(res as any).ok)
-      throw new Error(`HTTP ${(res as any).status} DELETE /fapi/v3/order - ${txt.slice(0, 200)}`)
-    try {
-      return JSON.parse(txt)
-    } catch {
-      return txt
-    }
-  }
-
-  // ===== 账户/杠杆相关 =====
-  async getLeverageBracket(symbol?: string): Promise<any> {
-    const base = this.requireHttpBase()
-    const url = `${base}/fapi/v3/leverageBracket${symbol ? `?symbol=${encodeURIComponent(symbol)}` : ''}`
-    const res = await (globalThis.fetch as any)(url, { method: 'GET' } as any)
-    if (!('ok' in res) || !(res as any).ok) throw new Error(`HTTP ${(res as any).status} /fapi/v3/leverageBracket`)
-    return await (res as any).json()
-  }
-
-  async updateLeverage(symbol: string, leverage: number): Promise<any> {
-    // 需要 HMAC 鉴权
-    const body = await this.hmacGet('/fapi/v3/leverage', { symbol, leverage })
-    return body
-  }
-
-  async updateMarginMode(symbol: string, marginType: 'ISOLATED' | 'CROSSED'): Promise<any> {
-    // 需要 HMAC 鉴权
-    const body = await this.hmacGet('/fapi/v3/marginType', { symbol, marginType })
-    return body
-  }
-
-  // === REST 下单封装(按照文档 /fapi/v3/order 签名流程) ===
-
-  /**
-   * 业务参数 -> 纯字符串字典(递归字符串化 list/dict),移除空值
-   */
-  private normalizeBusinessParams(input: Record<string, any>): Record<string, string> {
-    const cleaned: Record<string, any> = {}
-    for (const [k, v] of Object.entries(input)) {
-      if (v === undefined || v === null) continue
-      cleaned[k] = v
-    }
-
-    const toStringValue = (val: any): string => {
-      if (Array.isArray(val)) {
-        const arr = val.map(item =>
-          typeof item === 'object' && item !== null ? JSON.stringify(this.deepStringify(item)) : String(item),
-        )
-        return JSON.stringify(arr)
-      }
-      if (typeof val === 'object') {
-        return JSON.stringify(this.deepStringify(val))
-      }
-      return String(val)
-    }
-
-    const out: Record<string, string> = {}
-    for (const [k, v] of Object.entries(cleaned)) {
-      out[k] = toStringValue(v)
-    }
-    return out
-  }
-
-  private deepStringify(obj: Record<string, any>): Record<string, string> {
-    const out: Record<string, string> = {}
-    for (const [k, v] of Object.entries(obj)) {
-      if (v === undefined || v === null) continue
-      if (Array.isArray(v)) {
-        out[k] = JSON.stringify(
-          v.map(item => (typeof item === 'object' && item !== null ? this.deepStringify(item) : String(item))),
-        )
-      } else if (typeof v === 'object') {
-        out[k] = JSON.stringify(this.deepStringify(v as any))
-      } else {
-        out[k] = String(v)
-      }
-    }
-    return out
-  }
-
-  /**
-   * 生成按 ASCII 排序的 JSON 字符串
-   */
-  private stableJSONString(obj: Record<string, string>): string {
-    const entries = Object.entries(obj).sort(([a], [b]) => a.localeCompare(b))
-    const sorted = Object.fromEntries(entries)
-    return JSON.stringify(sorted)
-  }
-
-  /**
-   * 计算签名(ABI 编码 ['string','address','address','uint256'] 后 keccak,再 personal_sign)
-   */
-  private async signOrderJSONString(
-    jsonStr: string,
-    user: string,
-    signerAddr: string,
-    nonce: bigint,
-    privateKey: string,
-  ): Promise<string> {
-    const coder = AbiCoder.defaultAbiCoder()
-    const encoded = coder.encode(['string', 'address', 'address', 'uint256'], [jsonStr, user, signerAddr, nonce])
-    const hash = keccak256(encoded)
-    const wallet = new Wallet(privateKey)
-    const sig = await wallet.signMessage(getBytes(hash))
-    return sig
-  }
-
-  /**
-   * 仅生成签名(不发起 HTTP 请求)。
-   * 返回 jsonStr(按 ASCII 排序的业务 JSON 字符串)、nonce(微秒)、signature、user、signer 供外部自行拼装表单提交。
-   */
-  async generateOrderSignature(
-    order: {
-      symbol: string
-      positionSide: 'BOTH' | 'LONG' | 'SHORT'
-      type: 'LIMIT' | 'MARKET' | 'STOP' | 'STOP_MARKET' | 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET'
-      side: 'BUY' | 'SELL'
-      timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD'
-      quantity: string | number
-      price?: string | number
-      recvWindow?: number
-      timestamp?: number
-    },
-    creds?: { user?: string; signer?: string; privateKey?: string; nonceMicros?: bigint },
-  ): Promise<{
-    jsonStr: string
-    nonce: bigint
-    signature: string
-    user: string
-    signer: string
-    formFields: Record<string, string> // 直接用于 x-www-form-urlencoded 的字段
-  }> {
-    const business: Record<string, any> = {
-      ...order,
-      recvWindow: order.recvWindow ?? 50000,
-      timestamp: order.timestamp ?? Date.now(),
-    }
-
-    const bizStrDict = this.normalizeBusinessParams(business)
-    const jsonStr = this.stableJSONString(bizStrDict)
-
-    const user = creds?.user || this.cfg.defaultUser || process.env.ASTER_ORDER_USER || ''
-    const signer = creds?.signer || this.cfg.defaultSigner || process.env.ASTER_ORDER_SIGNER || ''
-    const privateKey = creds?.privateKey || process.env.PRIVATE_KEY || ''
-    if (!user || !signer || !privateKey) throw new Error('缺少用户、签名者或私钥')
-
-    const nonce = creds?.nonceMicros ?? BigInt(Math.trunc(Date.now() * 1000))
-    const signature = await this.signOrderJSONString(jsonStr, user, signer, nonce, privateKey)
-
-    const formFields: Record<string, string> = {
-      ...bizStrDict,
-      nonce: String(nonce),
-      user,
-      signer,
-      signature,
-    }
-
-    return { jsonStr, nonce, signature, user, signer, formFields }
-  }
-
-  // ===== REST/HMAC 工具与账户模式 =====
-  private requireHttpBase(): string {
-    const base = this.cfg.httpBase || process.env.ASTER_HTTP_BASE || ''
-    if (!base) throw new Error('AsterAdapter: 需要httpBase')
-    return base.replace(/\/$/, '')
-  }
-
-  private async hmacRequest(
-    method: 'GET' | 'POST' | 'PUT' | 'DELETE',
-    path: string,
-    extra: Record<string, string | number> = {},
-  ): Promise<any> {
-    // 对于 listenKey 等端点,使用 Aster 的 ECDSA 签名算法
-    const business: Record<string, any> = {
-      ...extra,
-      recvWindow: extra.recvWindow ?? 50000,
-      timestamp: extra.timestamp ?? Date.now(),
-    }
-
-    const bizStrDict = this.normalizeBusinessParams(business)
-    const jsonStr = this.stableJSONString(bizStrDict)
-
-    const user = this.cfg.defaultUser || process.env.ASTER_ORDER_USER || ''
-    const signer = this.cfg.defaultSigner || process.env.ASTER_API_KEY || ''
-    const privateKey = process.env.ASTER_API_SECRET || ''
-    if (!user || !signer || !privateKey) throw new Error('HMAC请求需要用户、签名者、私钥')
-
-    const nonce = BigInt(Math.trunc(Date.now() * 1000))
-    const signature = await this.signOrderJSONString(jsonStr, user, signer, nonce, privateKey)
-
-    const formFields: Record<string, string> = {
-      ...bizStrDict,
-      nonce: String(nonce),
-      user,
-      signer,
-      signature,
-    }
-
-    // Aster API 不需要 X-MBX-APIKEY header,所有认证通过签名参数
-    const headers: Record<string, string> = {}
-    let url = `${this.requireHttpBase()}${path}`
-    const options: any = { method, headers }
-
-    if (method === 'GET' || method === 'DELETE') {
-      const qs = new URLSearchParams(formFields).toString()
-      url += `?${qs}`
-    } else {
-      headers['content-type'] = 'application/x-www-form-urlencoded'
-      options.body = new URLSearchParams(formFields).toString()
-    }
-
-    const res = await (globalThis.fetch as any)(url, options)
-    const text = await res.text()
-    if (!('ok' in res) || !(res as any).ok)
-      throw new Error(`HTTP ${(res as any).status} ${path} - ${text.slice(0, 200)}`)
-    try {
-      return JSON.parse(text)
-    } catch {
-      return text
-    }
-  }
-
-  private async hmacGet(path: string, extra: Record<string, string | number> = {}): Promise<any> {
-    return await this.hmacRequest('GET', path, extra)
-  }
-
-  // === 公共账户查询(HMAC) ===
-  async getBalances(): Promise<any[]> {
-    return await this.hmacGet('/fapi/v3/balance')
-  }
-
-  async getPositionRisk(symbol?: string): Promise<any[]> {
-    const params: Record<string, string | number> = {}
-    if (symbol) params.symbol = symbol
-    return await this.hmacGet('/fapi/v3/positionRisk', params)
-  }
-
-  async getOpenOrders(symbol?: string): Promise<any[]> {
-    const params: Record<string, string | number> = {}
-    if (symbol) params.symbol = symbol
-    return await this.hmacGet('/fapi/v3/openOrders', params)
-  }
-
-  // ===== User Stream (listenKey) =====
-  /** 创建 listenKey 用于账户类 WS。返回 listenKey 字符串。*/
-  async createListenKey(): Promise<string> {
-    // USER_STREAM 类型需要签名,尽管文档说参数为 None
-    const body = await this.hmacRequest('POST', '/fapi/v3/listenKey', {})
-    const lk = String(body?.listenKey || '')
-    if (!lk) throw new Error('empty_listenKey')
-    this.listenKeyState = { key: lk, updatedAt: Date.now() }
-    return lk
-  }
-
-  /** 延长 listenKey 有效期(官方为 60 分钟有效期,这里建议每 30 分钟续期)。*/
-  async keepAliveListenKey(): Promise<void> {
-    if (!this.listenKeyState) throw new Error('listenKey_not_initialized')
-    // USER_STREAM 类型需要签名
-    await this.hmacRequest('PUT', '/fapi/v3/listenKey', {})
-    this.listenKeyState.updatedAt = Date.now()
-  }
-
-  /** 关闭 listenKey(可选)。*/
-  async closeListenKey(): Promise<void> {
-    // USER_STREAM 类型需要签名
-    await this.hmacRequest('DELETE', '/fapi/v3/listenKey', {})
-    this.listenKeyState = undefined
-  }
-
-  async ensureListenKey(opts?: {
-    forceNew?: boolean
-    refreshThresholdMs?: number
-  }): Promise<{ listenKey: string; refreshed: boolean; source: 'cached' | 'refreshed' | 'created' }> {
-    const now = Date.now()
-    const threshold = opts?.refreshThresholdMs ?? 45 * 60 * 1000
-    if (opts?.forceNew) {
-      const key = await this.createListenKey()
-      return { listenKey: key, refreshed: true, source: 'created' }
-    }
-    if (this.listenKeyState) {
-      const age = now - this.listenKeyState.updatedAt
-      if (age < threshold) {
-        return { listenKey: this.listenKeyState.key, refreshed: false, source: 'cached' }
-      }
-      try {
-        await this.keepAliveListenKey()
-        return { listenKey: this.listenKeyState.key, refreshed: true, source: 'refreshed' }
-      } catch {
-        // fallthrough to recreate
-      }
-    } else {
-      const preset = process.env.ASTER_LISTEN_KEY || (this.cfg as any).listenKey
-      if (preset) {
-        this.listenKeyState = { key: preset, updatedAt: 0 }
-        try {
-          await this.keepAliveListenKey()
-          return { listenKey: preset, refreshed: true, source: 'refreshed' }
-        } catch {
-          this.listenKeyState = undefined
-        }
-      }
-    }
-    const newKey = await this.createListenKey()
-    return { listenKey: newKey, refreshed: true, source: 'created' }
-  }
-
-  getListenKeyState() {
-    return this.listenKeyState ? { ...this.listenKeyState } : undefined
-  }
-
-  /**
-   * 读取账户是否为双向持仓模式(true=双向,false=单向)。需要 cfg.apiKey/apiSecret。
-   * 结果带有简单缓存,可通过 force=true 强制刷新。
-   */
-  async getDualSidePosition(force = false): Promise<boolean | undefined> {
-    if (!force && typeof this.dualSideCache === 'boolean') return this.dualSideCache
-    if (!this.cfg.apiKey || !this.cfg.apiSecret) return undefined
-    try {
-      const data = await this.hmacGet('/fapi/v3/positionSide/dual')
-      const val = data && typeof data.dualSidePosition === 'boolean' ? data.dualSidePosition : undefined
-      this.dualSideCache = val
-      return val
-    } catch {
-      return undefined
-    }
-  }
-
-  /**
-   * 根据账户设置返回下单用 positionSide。
-   * - 双向:BUY -> LONG,SELL -> SHORT
-   * - 单向或未知:BOTH
-   */
-  async choosePositionSide(side: 'BUY' | 'SELL'): Promise<'BOTH' | 'LONG' | 'SHORT'> {
-    const dual = await this.getDualSidePosition()
-    if (dual === true) return side === 'BUY' ? 'LONG' : 'SHORT'
-    return 'BOTH'
-  }
-}

+ 0 - 176
src/adapters/exchanges/aster/orderBook.ts

@@ -1,176 +0,0 @@
-import { EventEmitter } from 'events'
-import axios from 'axios'
-
-export interface OrderBookLevel {
-  price: number
-  quantity: number
-}
-export interface OrderBookSnapshot {
-  symbol: string
-  bids: OrderBookLevel[]
-  asks: OrderBookLevel[]
-  lastUpdateId: number
-  timestamp: number
-}
-export interface DepthUpdate {
-  symbol: string
-  firstUpdateId: number
-  finalUpdateId: number
-  previousFinalUpdateId: number
-  bids: [string, string][]
-  asks: [string, string][]
-  timestamp: number
-}
-
-export class AsterOrderBook extends EventEmitter {
-  private symbol: string
-  private bids: Map<number, number> = new Map()
-  private asks: Map<number, number> = new Map()
-  private lastUpdateId: number = 0
-  private lastFinalUpdateId: number = 0
-  private isInitialized: boolean = false
-  private pendingUpdates: DepthUpdate[] = []
-  private httpBase: string
-
-  constructor(symbol: string, httpBase: string = 'https://fapi.asterdex.com') {
-    super()
-    this.symbol = symbol.toUpperCase()
-    this.httpBase = httpBase
-  }
-
-  async initialize(): Promise<void> {
-    const snapshot = await this.fetchSnapshot()
-    this.bids.clear()
-    this.asks.clear()
-    this.pendingUpdates = this.pendingUpdates.filter(update => update.finalUpdateId >= snapshot.lastUpdateId)
-    this.applySnapshot(snapshot)
-    this.processPendingUpdates()
-    this.isInitialized = true
-  }
-
-  private async fetchSnapshot(): Promise<OrderBookSnapshot> {
-    const url = `${this.httpBase}/fapi/v3/depth`
-    const response = await axios.get(url, { params: { symbol: this.symbol, limit: 1000 } })
-    const data = response.data
-    return {
-      symbol: this.symbol,
-      bids: data.bids.map(([p, q]: [string, string]) => ({ price: parseFloat(p), quantity: parseFloat(q) })),
-      asks: data.asks.map(([p, q]: [string, string]) => ({ price: parseFloat(p), quantity: parseFloat(q) })),
-      lastUpdateId: data.lastUpdateId,
-      timestamp: Date.now(),
-    }
-  }
-
-  private applySnapshot(snapshot: OrderBookSnapshot): void {
-    this.bids.clear()
-    this.asks.clear()
-    for (const level of snapshot.bids) if (level.quantity > 0) this.bids.set(level.price, level.quantity)
-    for (const level of snapshot.asks) if (level.quantity > 0) this.asks.set(level.price, level.quantity)
-    this.lastUpdateId = snapshot.lastUpdateId
-    this.lastFinalUpdateId = snapshot.lastUpdateId
-  }
-
-  updateDepth(update: DepthUpdate): void {
-    if (!this.isInitialized) {
-      this.pendingUpdates.push(update)
-      return
-    }
-    if (this.lastFinalUpdateId !== 0 && update.previousFinalUpdateId !== this.lastFinalUpdateId) {
-      this.handlePacketLoss()
-      return
-    }
-    if (update.finalUpdateId <= this.lastUpdateId) return
-    this.applyDepthUpdate(update)
-    this.lastFinalUpdateId = update.finalUpdateId
-    this.emitUpdate()
-  }
-
-  private applyDepthUpdate(update: DepthUpdate): void {
-    for (const [priceStr, quantityStr] of update.bids) {
-      const price = parseFloat(priceStr)
-      const quantity = parseFloat(quantityStr)
-      if (quantity === 0) this.bids.delete(price)
-      else this.bids.set(price, quantity)
-    }
-    for (const [priceStr, quantityStr] of update.asks) {
-      const price = parseFloat(priceStr)
-      const quantity = parseFloat(quantityStr)
-      if (quantity === 0) this.asks.delete(price)
-      else this.asks.set(price, quantity)
-    }
-  }
-
-  private async handlePacketLoss(): Promise<void> {
-    this.isInitialized = false
-    this.pendingUpdates = []
-    await this.initialize()
-    this.emit('reconnect')
-  }
-  private processPendingUpdates(): void {
-    this.pendingUpdates.sort((a, b) => a.timestamp - b.timestamp)
-    for (const u of this.pendingUpdates)
-      if (u.finalUpdateId > this.lastUpdateId) {
-        this.applyDepthUpdate(u)
-        this.lastFinalUpdateId = u.finalUpdateId
-      }
-    this.pendingUpdates = []
-  }
-  private emitUpdate(): void {
-    const ob: OrderBookSnapshot = {
-      symbol: this.symbol,
-      bids: Array.from(this.bids.entries())
-        .map(([p, q]) => ({ price: p, quantity: q }))
-        .sort((a, b) => b.price - a.price),
-      asks: Array.from(this.asks.entries())
-        .map(([p, q]) => ({ price: p, quantity: q }))
-        .sort((a, b) => a.price - b.price),
-      lastUpdateId: this.lastFinalUpdateId,
-      timestamp: Date.now(),
-    }
-    this.emit('update', ob)
-  }
-  getSnapshot(): OrderBookSnapshot {
-    return {
-      symbol: this.symbol,
-      bids: Array.from(this.bids.entries())
-        .map(([p, q]) => ({ price: p, quantity: q }))
-        .sort((a, b) => b.price - a.price),
-      asks: Array.from(this.asks.entries())
-        .map(([p, q]) => ({ price: p, quantity: q }))
-        .sort((a, b) => a.price - b.price),
-      lastUpdateId: this.lastFinalUpdateId,
-      timestamp: Date.now(),
-    }
-  }
-  getBestBid(): number | null {
-    if (this.bids.size === 0) return null
-    return Math.max(...this.bids.keys())
-  }
-  getBestAsk(): number | null {
-    if (this.asks.size === 0) return null
-    return Math.min(...this.asks.keys())
-  }
-  getSpread(): number | null {
-    const bb = this.getBestBid()
-    const ba = this.getBestAsk()
-    if (bb === null || ba === null) return null
-    return ba - bb
-  }
-  getMidPrice(): number | null {
-    const bb = this.getBestBid()
-    const ba = this.getBestAsk()
-    if (bb === null || ba === null) return null
-    return (bb + ba) / 2
-  }
-  getQuantity(price: number, side: 'bid' | 'ask'): number {
-    const map = side === 'bid' ? this.bids : this.asks
-    return map.get(price) || 0
-  }
-  getTotalQuantity(depth: number, side: 'bid' | 'ask'): number {
-    const map = side === 'bid' ? this.bids : this.asks
-    const prices = Array.from(map.keys()).sort(side === 'bid' ? (a, b) => b - a : (a, b) => a - b)
-    let total = 0
-    for (let i = 0; i < Math.min(depth, prices.length); i++) total += map.get(prices[i]) || 0
-    return total
-  }
-}

+ 0 - 125
src/adapters/exchanges/aster/orderBookManager.ts

@@ -1,125 +0,0 @@
-import { EventEmitter } from 'events'
-import { AsterOrderBook, OrderBookSnapshot, DepthUpdate } from './orderBook'
-import { AsterWsClient, AsterWsConfig, AsterStreamArg } from './wsClient'
-
-export class AsterOrderBookManager extends EventEmitter {
-  private orderBooks: Map<string, AsterOrderBook> = new Map()
-  private wsClient: AsterWsClient
-  private httpBase: string
-  private isConnected: boolean = false
-
-  constructor(wsConfig: AsterWsConfig, httpBase: string = 'https://fapi.asterdex.com') {
-    super()
-    this.httpBase = httpBase
-    this.wsClient = new AsterWsClient(wsConfig)
-    this.setupWebSocketHandlers()
-  }
-
-  private setupWebSocketHandlers(): void {
-    this.wsClient.on('open', () => {
-      this.isConnected = true
-    })
-    this.wsClient.on('close', () => {
-      this.isConnected = false
-    })
-    this.wsClient.on('error', error => {
-      this.emit('error', 'ALL', error)
-    })
-    this.wsClient.on('raw', message => {
-      this.handleWebSocketMessage(message)
-    })
-  }
-
-  private handleWebSocketMessage(message: any): void {
-    if (message.stream && message.data) {
-      const data = message.data
-      if (String(message.stream).includes('@depth')) {
-        const update: DepthUpdate = {
-          symbol: data.s,
-          firstUpdateId: data.U,
-          finalUpdateId: data.u,
-          previousFinalUpdateId: data.pu,
-          bids: data.b || [],
-          asks: data.a || [],
-          timestamp: data.E || Date.now(),
-        }
-        this.updateOrderBook(update)
-      }
-      return
-    }
-    if (message.e === 'depthUpdate') {
-      const update: DepthUpdate = {
-        symbol: message.s,
-        firstUpdateId: message.U,
-        finalUpdateId: message.u,
-        previousFinalUpdateId: message.pu,
-        bids: message.b || [],
-        asks: message.a || [],
-        timestamp: message.E || Date.now(),
-      }
-      this.updateOrderBook(update)
-    }
-  }
-
-  async addSymbol(symbol: string): Promise<void> {
-    const normalizedSymbol = symbol.toUpperCase()
-    if (this.orderBooks.has(normalizedSymbol)) return
-    const orderBook = new AsterOrderBook(normalizedSymbol, this.httpBase)
-    orderBook.on('update', snapshot => {
-      this.emit('update', normalizedSymbol, snapshot)
-    })
-    orderBook.on('error', error => {
-      this.emit('error', normalizedSymbol, error)
-    })
-    orderBook.on('reconnect', () => {
-      this.emit('reconnect', normalizedSymbol)
-    })
-    await orderBook.initialize()
-    this.orderBooks.set(normalizedSymbol, orderBook)
-    if (this.isConnected) this.subscribeDepth(normalizedSymbol)
-  }
-
-  removeSymbol(symbol: string): void {
-    const normalizedSymbol = symbol.toUpperCase()
-    if (!this.orderBooks.has(normalizedSymbol)) return
-    if (this.isConnected) this.unsubscribeDepth(normalizedSymbol)
-    this.orderBooks.delete(normalizedSymbol)
-  }
-
-  private subscribeDepth(symbol: string): void {
-    const normalizedSymbol = symbol.toLowerCase()
-    const subscription: AsterStreamArg = { channel: 'depth', symbol: normalizedSymbol } as any
-    this.wsClient.subscribe(subscription)
-  }
-
-  private unsubscribeDepth(symbol: string): void {
-    const normalizedSymbol = symbol.toLowerCase()
-    const subscription: AsterStreamArg = { channel: 'depth', symbol: normalizedSymbol } as any
-    this.wsClient.unsubscribe(subscription)
-  }
-
-  private updateOrderBook(update: DepthUpdate): void {
-    const orderBook = this.orderBooks.get(update.symbol)
-    if (orderBook) orderBook.updateDepth(update)
-  }
-
-  connect(): void {
-    this.wsClient.connect()
-  }
-  disconnect(): void {
-    this.wsClient.disconnect()
-    this.isConnected = false
-  }
-  getOrderBook(symbol: string): OrderBookSnapshot | null {
-    const ob = this.orderBooks.get(symbol.toUpperCase())
-    return ob ? ob.getSnapshot() : null
-  }
-  getBestBid(symbol: string): number | null {
-    const ob = this.orderBooks.get(symbol.toUpperCase())
-    return ob ? ob.getBestBid() : null
-  }
-  getBestAsk(symbol: string): number | null {
-    const ob = this.orderBooks.get(symbol.toUpperCase())
-    return ob ? ob.getBestAsk() : null
-  }
-}

+ 0 - 80
src/adapters/exchanges/aster/types.ts

@@ -1,80 +0,0 @@
-import { EventEmitter } from 'events'
-
-export type AsterWsChannel = 'tickers' | 'trades' | 'books' | 'klines'
-
-export interface AsterStreamArg {
-  channel: AsterWsChannel | string
-  symbol?: string
-  interval?: string
-  depth?: number
-  [key: string]: any
-}
-
-export interface AsterWsConfig {
-  wsUrl: string
-  pingIntervalMs?: number
-  pongTimeoutMs?: number
-  autoReconnect?: boolean
-  reconnectIntervalMs?: number
-}
-
-export type AsterAuthType = 'none' | 'signer'
-
-export interface AsterAuthConfig {
-  type: AsterAuthType
-  user?: string
-  signer?: string
-  privateKey?: string
-  loginMethod?: 'login'
-}
-
-export interface AsterTicker {
-  symbol: string
-  price: number
-  change24h?: number
-  changePercent24h?: number
-  high24h?: number
-  low24h?: number
-  volume24h?: number
-  ts: number
-}
-export interface AsterTrade {
-  symbol: string
-  price: number
-  size: number
-  side: 'buy' | 'sell'
-  ts: number
-}
-export interface AsterDepth {
-  symbol: string
-  bids: Array<[number, number]>
-  asks: Array<[number, number]>
-  ts: number
-}
-export interface AsterKline {
-  symbol: string
-  interval: string
-  open: number
-  high: number
-  low: number
-  close: number
-  volume: number
-  openTime: number
-  closeTime: number
-}
-
-export interface AsterWsClientEvents {
-  open: () => void
-  close: (code: number, reason: string) => void
-  error: (err: Error) => void
-  ticker: (t: AsterTicker) => void
-  trade: (t: AsterTrade) => void
-  depth: (d: AsterDepth) => void
-  kline: (k: AsterKline) => void
-  raw: (msg: any) => void
-}
-
-export type AsterWsClientEmitter = EventEmitter & {
-  on<U extends keyof AsterWsClientEvents>(event: U, listener: AsterWsClientEvents[U]): AsterWsClientEmitter
-  emit<U extends keyof AsterWsClientEvents>(event: U, ...args: Parameters<AsterWsClientEvents[U]>): boolean
-}

+ 0 - 268
src/adapters/exchanges/aster/wsClient.ts

@@ -1,268 +0,0 @@
-import WebSocket from 'ws'
-import { EventEmitter } from 'events'
-import { AbiCoder, Wallet, keccak256, getBytes } from 'ethers'
-import {
-  AsterWsClientEmitter,
-  AsterWsConfig,
-  AsterStreamArg,
-  AsterTicker,
-  AsterTrade,
-  AsterKline,
-  AsterAuthConfig,
-} from './types'
-
-export class AsterWsClient extends (EventEmitter as { new (): AsterWsClientEmitter }) {
-  private ws: WebSocket | null = null
-  private cfg: Required<AsterWsConfig>
-  private pingTimer: NodeJS.Timeout | null = null
-  private pongTimer: NodeJS.Timeout | null = null
-  private reconnectTimer: NodeJS.Timeout | null = null
-  private subs: AsterStreamArg[] = []
-  private auth?: AsterAuthConfig
-  private listenKey?: string
-  private userStreamUrl?: string
-
-  constructor(cfg: AsterWsConfig, auth?: AsterAuthConfig) {
-    super()
-    this.cfg = {
-      wsUrl: cfg.wsUrl,
-      pingIntervalMs: cfg.pingIntervalMs ?? 30000,
-      pongTimeoutMs: cfg.pongTimeoutMs ?? 10000,
-      autoReconnect: cfg.autoReconnect ?? true,
-      reconnectIntervalMs: cfg.reconnectIntervalMs ?? 5000,
-    }
-    this.auth = auth
-    if (!this.cfg.wsUrl.includes('/ws/') && !this.cfg.wsUrl.includes('/stream')) {
-      this.cfg.wsUrl = this.cfg.wsUrl.replace(/\/$/, '') + '/ws/'
-    }
-  }
-
-  /**
-   * 对行情/深度:使用 cfg.wsUrl(/ws 或 /stream)。
-   * 对账户流:使用 setUserStream(listenKey, baseWsUrl) 设定 userStreamUrl 后调用 connectUserStream()。
-   */
-  connect(): void {
-    if (this.ws) return
-    this.ws = new WebSocket(this.cfg.wsUrl)
-    this.ws.on('open', () => {
-      this.emit('open')
-      this.startPing()
-      if (this.subs.length > 0) this.subscribe(this.subs)
-    })
-    this.ws.on('message', buf => this.handleMessage(buf.toString()))
-    this.ws.on('pong', () => this.onPong())
-    this.ws.on('close', (code, reasonBuf) => {
-      const reason = reasonBuf.toString()
-      this.emit('close', code, reason)
-      this.stopPing()
-      this.ws = null
-      if (this.cfg.autoReconnect) this.scheduleReconnect()
-    })
-    this.ws.on('error', err => this.emit('error', err as any))
-  }
-
-  /** 设定账户 user stream 连接地址:wss://fstream.asterdex.com/ws/<listenKey> */
-  setUserStream(listenKey: string, baseWsUrl: string) {
-    this.listenKey = listenKey
-    const base = baseWsUrl.replace(/\/$/, '')
-    // 文档使用 /ws/<listenKey>
-    this.userStreamUrl = `${base}/ws/${listenKey}`
-  }
-
-  /** 连接账户 user stream(需要先 setUserStream)*/
-  connectUserStream(): void {
-    if (!this.userStreamUrl) throw new Error('userStreamUrl not set')
-    const ws = new WebSocket(this.userStreamUrl)
-    // 独立的用户流连接:仅转发 raw/账户类事件
-    ws.on('open', () => {
-      this.emit('open')
-      // 心跳
-      const t = setInterval(() => {
-        try {
-          ws.ping()
-        } catch {}
-      }, 30000)
-      ;(ws as any).__hb = t
-    })
-    ws.on('message', buf => this.handleUserMessage(buf.toString()))
-    ws.on('close', (code, reasonBuf) => {
-      try {
-        clearInterval((ws as any).__hb)
-      } catch {}
-      this.emit('close', code, reasonBuf.toString())
-      if (this.cfg.autoReconnect) this.scheduleReconnect()
-    })
-    ws.on('error', err => this.emit('error', err as any))
-  }
-
-  disconnect(): void {
-    this.stopPing()
-    if (this.ws) {
-      this.ws.close()
-      this.ws = null
-    }
-  }
-
-  subscribe(args: AsterStreamArg[] | AsterStreamArg): void {
-    const list = Array.isArray(args) ? args : [args]
-    for (const a of list) {
-      const key = JSON.stringify(a)
-      if (!this.subs.find(x => JSON.stringify(x) === key)) this.subs.push(a)
-    }
-    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return
-    const streamNames = list.map(arg => {
-      const symbol = arg.symbol?.toLowerCase() || 'btcusdt'
-      const channel = arg.channel || 'aggTrade'
-      return `${symbol}@${channel}`
-    })
-    const payload = { method: 'SUBSCRIBE', params: streamNames, id: Date.now() }
-    this.ws.send(JSON.stringify(payload))
-  }
-
-  unsubscribe(args: AsterStreamArg[] | AsterStreamArg): void {
-    const list = Array.isArray(args) ? args : [args]
-    this.subs = this.subs.filter(s => !list.find(x => JSON.stringify(x) === JSON.stringify(s)))
-    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return
-    const streamNames = list.map(arg => {
-      const symbol = arg.symbol?.toLowerCase() || 'btcusdt'
-      const channel = arg.channel || 'aggTrade'
-      return `${symbol}@${channel}`
-    })
-    const payload = { method: 'UNSUBSCRIBE', params: streamNames, id: Date.now() }
-    this.ws.send(JSON.stringify(payload))
-  }
-
-  private handleMessage(text: string) {
-    let msg: any
-    try {
-      msg = JSON.parse(text)
-    } catch {}
-    if (!msg) return
-    this.emit('raw', msg)
-    if (msg.id && msg.result !== undefined) return
-    if (msg.code !== undefined) return
-    if (msg.stream && msg.data) {
-      const streamName = msg.stream
-      const data = msg.data
-      if (streamName.includes('@aggTrade')) {
-        const trade: AsterTrade = {
-          symbol: data.s || data.symbol,
-          price: Number(data.p || data.price),
-          size: Number(data.q || data.quantity),
-          side: data.m ? 'sell' : 'buy',
-          ts: Number(data.T || data.timestamp || Date.now()),
-        }
-        if (trade.symbol && Number.isFinite(trade.price)) this.emit('trade', trade)
-        return
-      }
-      if (streamName.includes('@markPrice')) {
-        const ticker: AsterTicker = {
-          symbol: data.s || data.symbol,
-          price: Number(data.p || data.price),
-          ts: Number(data.E || data.timestamp || Date.now()),
-        }
-        if (ticker.symbol && Number.isFinite(ticker.price)) this.emit('ticker', ticker)
-        return
-      }
-    }
-    if (msg.e) {
-      const eventType = msg.e
-      if (eventType === 'aggTrade') {
-        const trade: AsterTrade = {
-          symbol: msg.s,
-          price: Number(msg.p),
-          size: Number(msg.q),
-          side: msg.m ? 'sell' : 'buy',
-          ts: Number(msg.T),
-        }
-        if (trade.symbol && Number.isFinite(trade.price)) this.emit('trade', trade)
-        return
-      }
-      if (eventType === 'markPriceUpdate') {
-        const ticker: AsterTicker = { symbol: msg.s, price: Number(msg.p), ts: Number(msg.E) }
-        if (ticker.symbol && Number.isFinite(ticker.price)) this.emit('ticker', ticker)
-        return
-      }
-    }
-  }
-
-  // 账户 user stream 消息处理(ACCOUNT_UPDATE / ORDER_TRADE_UPDATE / ACCOUNT_CONFIG_UPDATE 等)
-  private handleUserMessage(text: string) {
-    let msg: any
-    try {
-      msg = JSON.parse(text)
-    } catch {}
-    if (!msg) return
-    this.emit('raw', msg)
-    if (msg.code !== undefined) {
-      // -1125 INVALID_LISTEN_KEY or other errors
-      const code = Number(msg.code)
-      if (code === -1125) {
-        this.emit('ws_error', { code: 'INVALID_LISTEN_KEY', detail: msg, ts: Date.now() })
-        return
-      }
-      this.emit('ws_error', { code, detail: msg, ts: Date.now() })
-      return
-    }
-    const ev = msg.e || msg.eventType
-    if (!ev) return
-    if (ev === 'ACCOUNT_UPDATE') {
-      // 标准化为 account_info + account_positions
-      const a = msg.a || {}
-      const balances = Array.isArray(a.B) ? a.B : []
-      const positions = Array.isArray(a.P) ? a.P : []
-      this.emit('balance', { channel: 'account_balance', data: balances, ts: Number(msg.E || Date.now()) })
-      this.emit('account_positions', { channel: 'account_positions', data: positions, ts: Number(msg.E || Date.now()) })
-      // 也可以综合成 account_info 概要
-      const pc = positions.filter((p: any) => Number(p.pa || p.positionAmt || 0) !== 0).length
-      this.emit('account_info', {
-        channel: 'account_info',
-        data: { pc, t: Number(msg.E || Date.now()) },
-        ts: Number(msg.E || Date.now()),
-      })
-      return
-    }
-    if (ev === 'ORDER_TRADE_UPDATE') {
-      const o = msg.o || {}
-      this.emit('orders', { channel: 'orders', data: o, ts: Number(msg.E || Date.now()) })
-      return
-    }
-    if (ev === 'ACCOUNT_CONFIG_UPDATE') {
-      this.emit('account_info', {
-        channel: 'account_info',
-        data: { t: Number(msg.E || Date.now()), ac: msg.ac, ai: msg.ai },
-        ts: Number(msg.E || Date.now()),
-      })
-      return
-    }
-    if (ev === 'listenKeyExpired') {
-      this.emit('ws_error', { code: 'listenKeyExpired', ts: Date.now() })
-      return
-    }
-  }
-
-  private startPing() {
-    this.stopPing()
-    this.pingTimer = setInterval(() => {
-      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
-        try {
-          this.ws.pong()
-        } catch {}
-      }
-    }, 60000)
-  }
-  private stopPing() {
-    if (this.pingTimer) clearInterval(this.pingTimer)
-    this.pingTimer = null
-    if (this.pongTimer) clearTimeout(this.pongTimer)
-    this.pongTimer = null
-  }
-  private onPong() {
-    if (this.pongTimer) clearTimeout(this.pongTimer)
-    this.pongTimer = null
-  }
-  private scheduleReconnect() {
-    if (this.reconnectTimer) clearTimeout(this.reconnectTimer)
-    this.reconnectTimer = setTimeout(() => this.connect(), this.cfg.reconnectIntervalMs)
-  }
-}

+ 0 - 139
src/adapters/exchanges/binance/BinanceAdapter.ts

@@ -1,139 +0,0 @@
-import { EventEmitter } from 'events'
-import { ExchangeAdapter, PlaceOrderReq, Order, Position, Balance, Depth } from '../ExchangeAdapter'
-import { FutureConnector } from './FutureConnector'
-
-export class BinanceAdapter implements ExchangeAdapter {
-  private ee = new EventEmitter()
-  constructor(private connector: FutureConnector) {}
-
-  name() {
-    return 'binance'
-  }
-  async time(): Promise<number> {
-    return Date.now()
-  }
-  async symbols(): Promise<string[]> {
-    return await this.connector.getSymbols()
-  }
-
-  async balances(): Promise<Balance[]> {
-    const assets = await this.connector.getAssetsInfo()
-    return assets.map((a: any) => ({
-      asset: a.asset,
-      total: String(a.walletBalance),
-      free: String(a.availableBalance),
-    }))
-  }
-
-  async positions(): Promise<Position[]> {
-    const positions = await this.connector.getAllPositions()
-    return positions.map((p: any) => ({
-      symbol: p.symbol,
-      side: Number(p.positionAmt) >= 0 ? 'LONG' : 'SHORT',
-      qty: String(p.positionAmt),
-      entryPrice: String(p.entryPrice ?? '0'),
-      unrealizedPnl: String(p.unrealizedProfit ?? '0'),
-      leverage: Number(p.leverage ?? 0),
-    }))
-  }
-
-  async placeOrder(req: PlaceOrderReq): Promise<Order> {
-    if (req.type === 'MARKET') {
-      const r = await this.connector.openMarketOrder(
-        req.symbol,
-        req.side === 'BUY' ? 'long' : 'short',
-        Number(req.quantity),
-      )
-      return {
-        id: String((r as any)?.orderId ?? Date.now()),
-        symbol: req.symbol,
-        status: 'NEW',
-        side: req.side,
-        type: req.type,
-        origQty: req.quantity,
-        executedQty: '0',
-        updateTime: Date.now(),
-      }
-    } else {
-      const r = await this.connector.openLimitOrder(
-        req.symbol,
-        req.side === 'BUY' ? 'long' : 'short',
-        Number(req.quantity),
-        Number(req.price ?? 0),
-      )
-      return {
-        id: String((r as any)?.orderId ?? Date.now()),
-        symbol: req.symbol,
-        status: 'NEW',
-        side: req.side,
-        type: req.type,
-        price: req.price,
-        origQty: req.quantity,
-        executedQty: '0',
-        updateTime: Date.now(),
-      }
-    }
-  }
-
-  async cancelOrder(symbol: string, orderId: string): Promise<void> {
-    await this.connector.cancelOrder(symbol, Number(orderId))
-  }
-
-  async cancelAll(symbol: string): Promise<void> {
-    await this.connector.cancelAllOrders(symbol)
-  }
-
-  async getOrder(symbol: string, orderId: string): Promise<Order> {
-    const r = await this.connector.getOrderHistory(symbol)
-    const o = (Array.isArray(r) ? r : []).find((x: any) => String(x.orderId) === String(orderId)) || {}
-    return {
-      id: String(orderId),
-      symbol,
-      status: ((o.status ?? 'NEW') as string).toUpperCase() as any,
-      side: ((o.side ?? 'BUY') as string).toUpperCase() as any,
-      type: ((o.type ?? 'LIMIT') as string).toUpperCase() as any,
-      price: String(o.price ?? '0'),
-      origQty: String(o.origQty ?? '0'),
-      executedQty: String(o.executedQty ?? '0'),
-      updateTime: o.updateTime ?? Date.now(),
-    }
-  }
-
-  async openOrders(symbol: string): Promise<Order[]> {
-    const orders = await this.connector.getCurrentAllOpenOrders(symbol)
-    return (Array.isArray(orders) ? orders : []).map((o: any) => ({
-      id: String(o.orderId || Date.now()),
-      symbol: o.symbol || symbol,
-      status: ((o.status || 'NEW') as string).toUpperCase() as any,
-      side: ((o.side || 'BUY') as string).toUpperCase() as any,
-      type: ((o.type || 'LIMIT') as string).toUpperCase() as any,
-      price: String(o.price || '0'),
-      origQty: String(o.origQty || '0'),
-      executedQty: String(o.executedQty || '0'),
-      updateTime: o.updateTime || Date.now(),
-    }))
-  }
-
-  async leverage(symbol: string, lev: number): Promise<void> {
-    await this.connector.setLeverage(symbol, lev)
-  }
-
-  async depth(symbol: string, limit = 50): Promise<Depth> {
-    const data = await this.connector.getDepth(symbol, limit)
-    return {
-      bids: (Array.isArray(data.bids) ? data.bids : []).map((b: any) => ({
-        price: String(b[0] || '0'),
-        qty: String(b[1] || '0'),
-      })),
-      asks: (Array.isArray(data.asks) ? data.asks : []).map((a: any) => ({
-        price: String(a[0] || '0'),
-        qty: String(a[1] || '0'),
-      })),
-      ts: Date.now(),
-    }
-  }
-
-  ws() {
-    return this.ee
-  }
-}

+ 0 - 414
src/adapters/exchanges/binance/FutureConnector.ts

@@ -1,414 +0,0 @@
-import {
-  DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
-  DerivativesTradingUsdsFutures,
-  DerivativesTradingUsdsFuturesRestAPI,
-} from '@binance/derivatives-trading-usds-futures'
-
-export class FutureConnector {
-  client: DerivativesTradingUsdsFutures
-  constructor(apiKey: string, apiSecret: string) {
-    const configurationRestAPI = {
-      apiKey: apiKey,
-      apiSecret: apiSecret,
-      basePath: DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
-    }
-    this.client = new DerivativesTradingUsdsFutures({ configurationRestAPI })
-  }
-
-  async getAssetsInfo() {
-    try {
-      const response = await this.client.restAPI.accountInformationV3()
-      const data = await response.data()
-      return data.assets.filter((asset: any) => Number(asset.walletBalance) > 0)
-    } catch (error) {
-      console.error('accountInformation() error:', error)
-      return []
-    }
-  }
-
-  async getPositonInfo() {
-    try {
-      const response = await this.client.restAPI.accountInformationV3()
-      const data = await response.data()
-      return data.positions.filter((position: any) => Number(position.positionAmt) > 0)
-    } catch (error) {
-      console.error('futuresPositionInformation() error:', error)
-      return []
-    }
-  }
-
-  async getPositionBalanceBySymbol(symbol: string) {
-    try {
-      const response = await this.client.restAPI.accountInformationV3()
-      const data = await response.data()
-      const position = data.positions.find((pos: any) => pos.symbol === symbol)
-      if (position) {
-        return position
-      } else {
-        return null
-      }
-    } catch (error) {
-      console.error('getPositionBalanceBySymbol() error:', error)
-      return null
-    }
-  }
-
-  async openModifyPosition(
-    symbol: string,
-    side: DerivativesTradingUsdsFuturesRestAPI.ModifyOrderSideEnum,
-    quantity: number,
-    price: number,
-  ) {
-    try {
-      const response = await this.client.restAPI.modifyOrder({
-        symbol: symbol,
-        side: side,
-        quantity: quantity,
-        price: price,
-      })
-      return await response.data()
-    } catch (error) {
-      console.error('openPosition() error:', error)
-      return null
-    }
-  }
-
-  async getCurrentAllOpenPosition() {
-    try {
-      const response = await this.client.restAPI.currentAllOpenOrders()
-      const data = await response.data()
-      console.log('当前所有开仓订单响应:', data)
-    } catch (error) {
-      console.error('currentAllOpenOrders() error:', error)
-    }
-  }
-
-  async openPosition(
-    symbol: string,
-    side: DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum,
-    quantity: number,
-    price: number,
-    options?: any,
-  ) {
-    try {
-      const orderParams: any = {
-        symbol: symbol,
-        side: side,
-        type: options?.type || 'LIMIT',
-        timeInForce: options?.timeInForce || DerivativesTradingUsdsFuturesRestAPI.NewOrderTimeInForceEnum.GTC,
-        quantity: quantity,
-        price: price,
-      }
-      if (options?.positionSide) {
-        orderParams.positionSide = options.positionSide
-      }
-      if (options?.reduceOnly) {
-        orderParams.reduceOnly = options.reduceOnly
-      }
-      if (options?.closePosition) {
-        orderParams.closePosition = options.closePosition
-      }
-      if (options?.activationPrice) {
-        orderParams.activationPrice = options.activationPrice
-      }
-      if (options?.callbackRate) {
-        orderParams.callbackRate = options.callbackRate
-      }
-      if (options?.workingType) {
-        orderParams.workingType = options.workingType
-      }
-      if (options?.priceProtect) {
-        orderParams.priceProtect = options.priceProtect
-      }
-      if (options?.newOrderRespType) {
-        orderParams.newOrderRespType = options.newOrderRespType
-      }
-      if (options?.newClientOrderId) {
-        orderParams.newClientOrderId = options.newClientOrderId
-      }
-      if (options?.stopPrice) {
-        orderParams.stopPrice = options.stopPrice
-      }
-      if (options?.icebergQty) {
-        orderParams.icebergQty = options.icebergQty
-      }
-      if (options?.orderTag) {
-        orderParams.orderTag = options.orderTag
-      }
-      console.log('下单参数:', orderParams)
-      const response = await this.client.restAPI.newOrder(orderParams)
-      const result = await response.data()
-      console.log('下单成功:', result)
-      return result
-    } catch (error) {
-      console.error('openPosition() 错误:', error)
-      return null
-    }
-  }
-
-  async openLimitOrder(
-    symbol: string,
-    side: 'long' | 'short',
-    quantity: number,
-    price: number,
-    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
-  ) {
-    return this.openPosition(
-      symbol,
-      side === 'long'
-        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
-        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
-      quantity,
-      price,
-      {
-        type: 'LIMIT',
-        timeInForce,
-        positionSide:
-          side === 'long'
-            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
-            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-      },
-    )
-  }
-
-  async openMarketOrder(symbol: string, side: 'long' | 'short', quantity: number) {
-    return this.openPosition(
-      symbol,
-      side === 'long'
-        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
-        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
-      quantity,
-      0,
-      {
-        type: 'MARKET',
-        positionSide:
-          side === 'long'
-            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
-            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-      },
-    )
-  }
-
-  async openStopOrder(
-    symbol: string,
-    side: 'long' | 'short',
-    quantity: number,
-    stopPrice: number,
-    type: 'STOP' | 'STOP_MARKET' = 'STOP_MARKET',
-    price?: number,
-    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
-  ) {
-    const orderParams: any = {
-      type,
-      stopPrice,
-      reduceOnly: 'true',
-      positionSide:
-        side === 'long'
-          ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
-          : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-    }
-    if (type === 'STOP') {
-      orderParams.timeInForce = timeInForce
-    }
-    return this.openPosition(
-      symbol,
-      side === 'long'
-        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
-        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
-      quantity,
-      price || 0,
-      orderParams,
-    )
-  }
-
-  async openTakeProfitOrder(
-    symbol: string,
-    side: 'long' | 'short',
-    quantity: number,
-    stopPrice: number,
-    type: 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET' = 'TAKE_PROFIT_MARKET',
-    price?: number,
-    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
-  ) {
-    const orderParams: any = {
-      type,
-      stopPrice,
-      reduceOnly: 'true',
-      positionSide:
-        side === 'long'
-          ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
-          : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-    }
-    if (type === 'TAKE_PROFIT') {
-      orderParams.timeInForce = timeInForce
-    }
-    return this.openPosition(
-      symbol,
-      side === 'long'
-        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
-        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
-      quantity,
-      price || 0,
-      orderParams,
-    )
-  }
-
-  async openTrailingStopOrder(
-    symbol: string,
-    side: 'long' | 'short',
-    quantity: number,
-    activationPrice: number,
-    callbackRate: number,
-  ) {
-    return this.openPosition(
-      symbol,
-      side === 'long'
-        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
-        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
-      quantity,
-      0,
-      {
-        type: 'TRAILING_STOP_MARKET',
-        activationPrice,
-        callbackRate,
-        reduceOnly: 'true',
-        positionSide:
-          side === 'long'
-            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
-            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-      },
-    )
-  }
-
-  async openIcebergOrder(
-    symbol: string,
-    side: 'long' | 'short',
-    quantity: number,
-    price: number,
-    icebergQty: number,
-    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
-  ) {
-    return this.openPosition(
-      symbol,
-      side === 'long'
-        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
-        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
-      quantity,
-      price,
-      {
-        type: 'LIMIT',
-        timeInForce,
-        icebergQty,
-        positionSide:
-          side === 'long'
-            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
-            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-      },
-    )
-  }
-
-  async closeLongPosition(symbol: string, quantity: number) {
-    return this.openPosition(symbol, DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL, quantity, 0, {
-      type: 'MARKET',
-      reduceOnly: 'true',
-      positionSide: DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG,
-    })
-  }
-
-  async closeShortPosition(symbol: string, quantity: number) {
-    return this.openPosition(symbol, DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY, quantity, 0, {
-      type: 'MARKET',
-      reduceOnly: 'true',
-      positionSide: DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
-    })
-  }
-
-  async closeAllPositions() {
-    const positions = await this.getAllPositions()
-    const results: any[] = []
-    for (const pos of positions as any[]) {
-      const amt = Number((pos as any).positionAmt)
-      if (amt > 0) {
-        results.push(await this.closeLongPosition((pos as any).symbol, Math.abs(amt)))
-      } else if (amt < 0) {
-        results.push(await this.closeShortPosition((pos as any).symbol, Math.abs(amt)))
-      }
-    }
-    return results
-  }
-
-  async cancelOrder(symbol: string, orderId?: number, origClientOrderId?: string) {
-    return this.client.restAPI.cancelOrder({ symbol, orderId, origClientOrderId })
-  }
-
-  async cancelAllOrders(symbol: string) {
-    return this.client.restAPI.cancelAllOpenOrders({ symbol })
-  }
-
-  async getOrderHistory(symbol: string, startTime?: number, endTime?: number, limit: number = 100) {
-    const response = await this.client.restAPI.allOrders({ symbol, startTime, endTime, limit })
-    return response.data()
-  }
-
-  async getTradeHistory(symbol: string, startTime?: number, endTime?: number, limit: number = 100) {
-    const response = await this.client.restAPI.accountTradeList({ symbol, startTime, endTime, limit })
-    return response.data()
-  }
-
-  async setLeverage(symbol: string, leverage: number) {
-    return this.client.restAPI.changeInitialLeverage({ symbol, leverage })
-  }
-
-  async setMarginType(symbol: string, marginType: DerivativesTradingUsdsFuturesRestAPI.ChangeMarginTypeMarginTypeEnum) {
-    return this.client.restAPI.changeMarginType({ symbol, marginType })
-  }
-
-  async getAllPositions() {
-    const response = await this.client.restAPI.accountInformationV3()
-    const data = await response.data()
-    return data.positions || []
-  }
-
-  async getExchangeInfo() {
-    try {
-      const response = await this.client.restAPI.exchangeInformation()
-      return response.data()
-    } catch (error) {
-      console.error('getExchangeInfo() error:', error)
-      return null
-    }
-  }
-
-  async getSymbols(): Promise<string[]> {
-    try {
-      const exchangeInfo = await this.getExchangeInfo()
-      if (!exchangeInfo?.symbols) return []
-      return exchangeInfo.symbols.filter((s: any) => s.status === 'TRADING').map((s: any) => s.symbol)
-    } catch (error) {
-      console.error('getSymbols() error:', error)
-      return []
-    }
-  }
-
-  async getDepth(symbol: string, limit = 100) {
-    try {
-      const response = await this.client.restAPI.orderBook({ symbol, limit })
-      return response.data()
-    } catch (error) {
-      console.error('getDepth() error:', error)
-      return { bids: [], asks: [], lastUpdateId: 0 }
-    }
-  }
-
-  async getCurrentAllOpenOrders(symbol?: string) {
-    try {
-      const response = await this.client.restAPI.currentAllOpenOrders({ symbol })
-      return response.data()
-    } catch (error) {
-      console.error('getCurrentAllOpenOrders() error:', error)
-      return []
-    }
-  }
-}
-
-// 移除重复导出,统一以本文件类为准

+ 0 - 97
src/adapters/exchanges/pacifica/AccountAdapter.ts

@@ -1,97 +0,0 @@
-import { PacificaClient } from './PacificaClient'
-
-export interface LeveragePayload {
-  account: string
-  symbol: string
-  leverage: number
-  agentWallet?: string
-  expiryWindow?: number
-}
-
-export interface SubaccountPayload {
-  mainAccount: string
-  subAccount: string
-  expiryWindow?: number
-}
-
-export class PacificaAccountAdapter {
-  constructor(private client: PacificaClient) {}
-
-  async info(account?: string) {
-    const payload = await this.buildSignedPayload('get_account_info', {
-      account: this.client.requireAccount(account),
-    })
-    const response = await this.client.post<any>(this.client.endpoints.accountInfo, payload, { skipHeaderSig: true })
-    return response?.data ?? response
-  }
-
-  async balances(account?: string) {
-    const response = await this.client.get<any>(this.client.endpoints.balances, {
-      account: this.client.requireAccount(account),
-    })
-    return response?.data ?? response
-  }
-
-  async positions(account?: string) {
-    const response = await this.client.get<any>(this.client.endpoints.positions, {
-      account: this.client.requireAccount(account),
-    })
-    return response?.data ?? response
-  }
-
-  async updateLeverage(payload: LeveragePayload) {
-    const body = await this.buildSignedPayload(
-      'update_leverage',
-      {
-        account: payload.account,
-        symbol: payload.symbol,
-        leverage: payload.leverage,
-        agent_wallet: payload.agentWallet,
-      },
-      payload.expiryWindow,
-    )
-    return await this.client.post(this.client.endpoints.leverage, body, { skipHeaderSig: true })
-  }
-
-  async createSubaccount(payload: SubaccountPayload) {
-    const { mainAccount, subAccount, expiryWindow } = payload
-    const timestamp = Date.now()
-    const baseExpiry = expiryWindow ?? 30000
-    const subSig = await this.client.signOperation(
-      'subaccount_initiate',
-      {
-        account: mainAccount,
-      },
-      baseExpiry,
-    )
-    const mainSig = await this.client.signOperation(
-      'subaccount_confirm',
-      {
-        signature: subSig.signature,
-      },
-      baseExpiry,
-    )
-    return await this.client.post(
-      this.client.endpoints.subaccountCreate,
-      {
-        main_account: mainAccount,
-        subaccount: subAccount,
-        timestamp,
-        expiry_window: baseExpiry,
-        main_signature: mainSig.signature,
-        sub_signature: subSig.signature,
-      },
-      { skipHeaderSig: true },
-    )
-  }
-
-  private async buildSignedPayload(operation: string, data: Record<string, any>, expiryWindow = 30000) {
-    const signed = await this.client.signOperation(operation, data, expiryWindow)
-    return {
-      ...data,
-      timestamp: signed.timestamp,
-      expiry_window: signed.expiryWindow,
-      signature: signed.signature,
-    }
-  }
-}

+ 0 - 327
src/adapters/exchanges/pacifica/OrdersAdapter.ts

@@ -1,327 +0,0 @@
-import { PacificaClient } from './PacificaClient'
-import { randomUUID } from 'crypto'
-import { logger } from '../shared/utils/logger'
-
-export interface OrderCreatePayload {
-  account: string
-  symbol: string
-  amount: string
-  side: 'bid' | 'ask'
-  reduceOnly: boolean
-  clientOrderId?: string
-  tif?: 'GTC' | 'IOC' | 'ALO'
-  price?: string
-  // For market orders per docs
-  slippagePercent?: string // maps to slippage_percent
-  takeProfit?: { stopPrice: string; limitPrice?: string; clientOrderId?: string }
-  stopLoss?: { stopPrice: string; limitPrice?: string; clientOrderId?: string }
-  agentWallet?: string
-  expiryWindow?: number
-}
-
-export interface CancelOrderPayload {
-  account: string
-  symbol: string
-  orderId?: number
-  clientOrderId?: string
-  agentWallet?: string
-  expiryWindow?: number
-}
-
-export class PacificaOrdersAdapter {
-  constructor(private client: PacificaClient) {}
-
-  private normalizeSymbol(input?: string) {
-    if (!input) return input as any
-    const s = String(input).toUpperCase()
-    if (s.includes('-')) return s.split('-')[0]
-    if (s.endsWith('USDT')) return s.replace('USDT', '')
-    if (s.endsWith('USD')) return s.replace('USD', '')
-    return s
-  }
-
-  async createMarketOrder(payload: OrderCreatePayload) {
-    // For market orders, only use required fields per API docs
-    const marketPayload: OrderCreatePayload = {
-      account: payload.account,
-      symbol: payload.symbol,
-      amount: payload.amount,
-      side: payload.side,
-      reduceOnly: payload.reduceOnly,
-      slippagePercent: payload.slippagePercent || '0.5',
-    }
-
-    return await this.sendSigned(this.client.endpoints.orderCreateMarket, 'create_market_order', marketPayload)
-  }
-
-  async createLimitOrder(payload: OrderCreatePayload) {
-    return await this.sendSigned(this.client.endpoints.orderCreateLimit, 'create_order', payload)
-  }
-
-  async createStopOrder(payload: OrderCreatePayload) {
-    return await this.sendSigned(this.client.endpoints.orderCreateStop, 'create_stop_order', payload)
-  }
-
-  async cancelOrder(payload: CancelOrderPayload) {
-    return await this.sendSigned(this.client.endpoints.orderCancel, 'cancel_order', payload)
-  }
-
-  async cancelAll(payload: { symbol?: string; allSymbols?: boolean; excludeReduceOnly?: boolean }) {
-    const account = this.client.requireAccount()
-    const data = {
-      all_symbols: payload.allSymbols ?? !payload.symbol,
-      exclude_reduce_only: payload.excludeReduceOnly ?? false,
-      symbol: this.normalizeSymbol(payload.symbol),
-    } as any
-    const { signature, timestamp, expiryWindow } = await this.client.signOperation('cancel_all_orders', data, 30000)
-    const body = { account, ...data, signature, timestamp, expiry_window: expiryWindow }
-    return await this.client.post(this.client.endpoints.orderCancelAll, body, { skipHeaderSig: true })
-  }
-
-  async openOrders(symbol?: string, account?: string) {
-    const query: Record<string, string> = { account: this.client.requireAccount(account) }
-    if (symbol) query.symbol = symbol
-    return await this.client.get<any>(this.client.endpoints.openOrders, query)
-  }
-
-  async batch(actions: Array<{ type: 'Create' | 'Cancel'; data: OrderCreatePayload | CancelOrderPayload }>) {
-    const signedActions = await Promise.all(
-      actions.map(async action => {
-        if (action.type === 'Create') {
-          const raw = action.data as any
-          // Normalize incoming fields from external callers (reduce_only -> reduceOnly)
-          const payload: OrderCreatePayload = {
-            account: raw.account,
-            symbol: raw.symbol,
-            amount: raw.amount,
-            side: raw.side,
-            reduceOnly: raw.reduceOnly !== undefined ? raw.reduceOnly : raw.reduce_only ?? false,
-            clientOrderId: raw.clientOrderId ?? raw.client_order_id,
-            tif: raw.tif,
-            price: raw.price,
-            slippagePercent: raw.slippagePercent ?? raw.slippage_percent,
-            takeProfit: raw.takeProfit,
-            stopLoss: raw.stopLoss,
-            agentWallet: raw.agentWallet ?? raw.agent_wallet,
-            expiryWindow: raw.expiryWindow,
-          }
-          const transformed = this.transformCreatePayload(
-            payload,
-            this.client.cfg.agentPrivateKey ? this.client.requireAgentWallet(payload.agentWallet) : undefined,
-          )
-          const dataToSign = this.pickOrderSignFields('create_order', transformed)
-          const { signature, timestamp, expiryWindow } = await this.client.signOperation(
-            'create_order',
-            dataToSign,
-            payload.expiryWindow ?? 30000,
-          )
-          return { type: 'Create', data: { ...transformed, signature, timestamp, expiry_window: expiryWindow } }
-        }
-        const cp = action.data as CancelOrderPayload
-        const transformedCancel = this.transformCancelPayload(cp)
-        const cancelSign = this.pickCancelSignFields(transformedCancel)
-        const { signature, timestamp, expiryWindow } = await this.client.signOperation(
-          'cancel_order',
-          cancelSign,
-          cp.expiryWindow ?? 30000,
-        )
-        return { type: 'Cancel', data: { ...transformedCancel, signature, timestamp, expiry_window: expiryWindow } }
-      }),
-    )
-    return await this.client.post(this.client.endpoints.orderBatch, { actions: signedActions }, { skipHeaderSig: true })
-  }
-
-  private transformCreatePayload(payload: OrderCreatePayload, agentWallet?: string, isMarketOrder = false) {
-    const clientOrderId = payload.clientOrderId || randomUUID()
-
-    // For market orders, use minimal required fields per API error messages
-    if (isMarketOrder) {
-      return {
-        account: payload.account,
-        symbol: this.normalizeSymbol(payload.symbol),
-        amount: payload.amount, // API expects 'amount'
-        side: payload.side, // API expects 'bid'/'ask'
-        reduce_only: payload.reduceOnly,
-        slippage_percent: payload.slippagePercent || '1.0', // Required field
-        agent_wallet: agentWallet ?? payload.agentWallet,
-      }
-    }
-
-    // For limit orders and others, include all fields
-    const takeProfit = payload.takeProfit
-      ? {
-          stop_price: payload.takeProfit.stopPrice,
-          limit_price: payload.takeProfit.limitPrice,
-          client_order_id: payload.takeProfit.clientOrderId,
-        }
-      : undefined
-    const stopLoss = payload.stopLoss
-      ? {
-          stop_price: payload.stopLoss.stopPrice,
-          limit_price: payload.stopLoss.limitPrice,
-          client_order_id: payload.stopLoss.clientOrderId,
-        }
-      : undefined
-
-    return {
-      account: payload.account,
-      symbol: this.normalizeSymbol(payload.symbol),
-      amount: payload.amount,
-      side: payload.side,
-      reduce_only: payload.reduceOnly,
-      client_order_id: clientOrderId,
-      tif: payload.tif ?? 'GTC',
-      price: payload.price,
-      slippage_percent: payload.slippagePercent,
-      take_profit: takeProfit,
-      stop_loss: stopLoss,
-      agent_wallet: agentWallet ?? payload.agentWallet,
-    }
-  }
-
-  private async buildSignedPayload(
-    operation: string,
-    data: Record<string, any>,
-    expiryWindow = 30000,
-    useAgent = false,
-  ) {
-    const signer = useAgent
-      ? this.client.signOperationWithAgent.bind(this.client)
-      : this.client.signOperation.bind(this.client)
-    const { signature, timestamp, expiryWindow: ew } = await signer(operation, data, expiryWindow)
-    return {
-      ...data,
-      signature,
-      timestamp,
-      expiry_window: ew,
-    }
-  }
-
-  private async sendSigned(path: string, operation: string, payload: OrderCreatePayload | CancelOrderPayload) {
-    const isOrder = operation.startsWith('create_')
-    const useAgent = isOrder && !!this.client.cfg.agentPrivateKey
-    if (operation === 'cancel_order') {
-      const transformed = this.transformCancelPayload(payload as CancelOrderPayload)
-      const expiryWindow = (payload as any).expiryWindow ?? 30000
-      const dataToSign = this.pickCancelSignFields(transformed)
-      const {
-        signature,
-        timestamp,
-        expiryWindow: ew,
-      } = await this.client.signOperation(operation, dataToSign, expiryWindow)
-      const finalBody = { ...transformed, signature, timestamp, expiry_window: ew }
-      if (process.env.NODE_ENV === 'development' && process.env.PACIFICA_DEBUG === '1') {
-        logger.debug('Pacifica订单签名调试', {
-          operation,
-          signDataLength: JSON.stringify(dataToSign).length,
-          signaturePreview: `b58(${String((finalBody as any).signature).slice(0, 8)}...)`,
-        })
-      }
-      return await this.client.post(path, finalBody, { skipHeaderSig: true })
-    }
-    // create_* flow: sign ONLY the operation fields per docs, NOT account/agent_wallet
-    const transformed =
-      operation === 'create_stop_order'
-        ? (() => {
-            const p = payload as OrderCreatePayload
-            const clientId = p.clientOrderId || randomUUID()
-            return {
-              account: p.account,
-              symbol: this.normalizeSymbol(p.symbol),
-              side: p.side,
-              reduce_only: p.reduceOnly,
-              stop_order: {
-                stop_price: p.stopLoss?.stopPrice,
-                limit_price: p.stopLoss?.limitPrice,
-                client_order_id: clientId,
-                amount: p.amount,
-              },
-              agent_wallet: useAgent ? this.client.requireAgentWallet(p.agentWallet) : p.agentWallet,
-            }
-          })()
-        : this.transformCreatePayload(
-            payload as OrderCreatePayload,
-            useAgent ? this.client.requireAgentWallet((payload as OrderCreatePayload).agentWallet) : undefined,
-            operation === 'create_market_order',
-          )
-    const expiryWindow = (payload as any).expiryWindow ?? 5000
-    const dataToSign: Record<string, any> = this.pickOrderSignFields(operation, transformed)
-    const signer = useAgent
-      ? this.client.signOperationWithAgent.bind(this.client)
-      : this.client.signOperation.bind(this.client)
-    const { signature, timestamp, expiryWindow: ew } = await signer(operation, dataToSign, expiryWindow)
-    const finalBody = {
-      ...transformed,
-      timestamp,
-      expiry_window: ew,
-      signature,
-    }
-    if (process.env.NODE_ENV === 'development' && process.env.PACIFICA_DEBUG === '1') {
-      logger.debug('Pacifica创建订单调试', {
-        operation,
-        signDataLength: JSON.stringify(dataToSign).length,
-        signaturePreview: `b58(${String(finalBody.signature).slice(0, 8)}...)`,
-      })
-    }
-    return await this.client.post(path, finalBody, { skipHeaderSig: true })
-  }
-
-  private pickOrderSignFields(operation: string, transformed: Record<string, any>) {
-    const base: Record<string, any> = {
-      symbol: transformed.symbol,
-      reduce_only: transformed.reduce_only,
-      side: transformed.side,
-    }
-    if (operation === 'create_market_order') {
-      // Market order fields per API requirements
-      base.amount = transformed.amount
-      if (transformed.slippage_percent !== undefined) {
-        base.slippage_percent = transformed.slippage_percent
-      }
-      return base
-    }
-    // For other orders
-    base.amount = transformed.amount || transformed.quantity
-    // Add client_order_id for other order types
-    base.client_order_id = transformed.client_order_id
-    if (operation === 'create_stop_order') {
-      base.side = transformed.side
-      base.reduce_only = transformed.reduce_only
-      base.stop_order = {
-        stop_price: transformed.stop_order?.stop_price,
-        limit_price: transformed.stop_order?.limit_price,
-        amount: transformed.stop_order?.amount,
-        client_order_id: transformed.stop_order?.client_order_id,
-      }
-      return base
-    }
-    if (operation === 'create_stop_order') {
-      if (transformed.stop_price !== undefined) base.stop_price = transformed.stop_price
-      if (transformed.limit_price !== undefined) base.limit_price = transformed.limit_price
-      return base
-    }
-    // create_order (limit)
-    if (transformed.tif !== undefined) base.tif = transformed.tif
-    if (transformed.price !== undefined) base.price = transformed.price
-    return base
-  }
-
-  private transformCancelPayload(payload: CancelOrderPayload) {
-    if (!payload.orderId && !payload.clientOrderId) {
-      throw new Error('PacificaOrdersAdapter: orderId or clientOrderId required')
-    }
-    return {
-      account: payload.account,
-      symbol: this.normalizeSymbol(payload.symbol),
-      order_id: payload.orderId,
-      client_order_id: payload.clientOrderId,
-    }
-  }
-
-  private pickCancelSignFields(transformed: Record<string, any>) {
-    const base: Record<string, any> = { symbol: transformed.symbol }
-    if (transformed.order_id !== undefined && transformed.order_id !== null) base.order_id = transformed.order_id
-    else if (transformed.client_order_id) base.client_order_id = transformed.client_order_id
-    return base
-  }
-}

+ 0 - 427
src/adapters/exchanges/pacifica/PacificaAdapter.ts

@@ -1,427 +0,0 @@
-import { EventEmitter } from 'events'
-import WebSocket from 'ws'
-import { ExchangeAdapter, PlaceOrderReq, Order, Position, Balance, Depth } from '../ExchangeAdapter'
-import { PacificaClient } from './PacificaClient'
-import { PacificaOrdersAdapter } from './OrdersAdapter'
-import { PacificaAccountAdapter } from './AccountAdapter'
-import { logger } from '../shared/utils/logger'
-
-export class PacificaAdapter implements ExchangeAdapter {
-  private events = new EventEmitter()
-  private depthSocket?: WebSocket
-  private ordersSocket?: WebSocket
-  private balanceSocket?: WebSocket
-  private tradesSocket?: WebSocket
-  private orders: PacificaOrdersAdapter
-  private account: PacificaAccountAdapter
-  private startHeartbeat(ws: WebSocket) {
-    const timer = setInterval(() => {
-      try {
-        ws.send(JSON.stringify({ method: 'ping' }))
-      } catch {}
-    }, 30000)
-    ;(ws as any).__hb = timer
-    const cleanup = () => {
-      try {
-        clearInterval((ws as any).__hb)
-      } catch {}
-    }
-    ws.on('close', cleanup)
-    ws.on('error', cleanup)
-  }
-  constructor(private client: PacificaClient) {
-    this.orders = new PacificaOrdersAdapter(client)
-    this.account = new PacificaAccountAdapter(client)
-  }
-
-  name() {
-    return 'pacifica'
-  }
-  async time(): Promise<number> {
-    return Date.now()
-  }
-  async symbols(): Promise<string[]> {
-    const response = await this.client.getPublic<any>(this.client.endpoints.symbols)
-    const data = Array.isArray(response) ? response : response?.data ?? []
-    return (Array.isArray(data) ? data : []).map((m: any) => String(m.symbol)).filter(Boolean)
-  }
-  async balances(): Promise<Balance[]> {
-    const data = await this.account.balances()
-    return (Array.isArray(data) ? data : [])
-      .map((balance: any) => ({
-        asset: String(balance.asset ?? balance.symbol ?? ''),
-        total: String(balance.total ?? balance.balance ?? '0'),
-        free: String(balance.free ?? balance.available ?? balance.balance ?? '0'),
-      }))
-      .filter(b => b.asset)
-  }
-  async positions(): Promise<Position[]> {
-    const data = await this.account.positions()
-    const list = Array.isArray(data) ? data : []
-    return list
-      .map((pos: any) => {
-        const side = (pos.side ?? 'bid') === 'ask' ? 'SHORT' : ('LONG' as const)
-        return {
-          symbol: String(pos.symbol),
-          side,
-          qty: String(pos.amount ?? pos.qty ?? '0'),
-          entryPrice: String(pos.entry_price ?? pos.entryPrice ?? '0'),
-          unrealizedPnl: String(pos.funding ?? pos.unrealizedPnL ?? '0'),
-          leverage: Number(pos.leverage ?? 0),
-        } as Position
-      })
-      .filter(p => p.symbol)
-  }
-  async placeOrder(req: PlaceOrderReq): Promise<Order> {
-    const account = this.client.requireAccount((req as any).account)
-    const payload: any = {
-      account,
-      symbol: this.normalizeSymbol(req.symbol),
-      amount: String(req.quantity),
-      side: (req.side === 'BUY' ? 'bid' : 'ask') as 'bid' | 'ask',
-      reduceOnly: !!req.reduceOnly,
-      clientOrderId: req.clientOrderId,
-      tif: req.tif as any,
-      price: req.price ? String(req.price) : undefined,
-      agentWallet: (req as any).meta?.agentWallet || this.client.cfg.agentWallet,
-    }
-    let response: any
-    if (req.type === 'MARKET')
-      response = await this.orders.createMarketOrder({
-        ...payload,
-        slippagePercent: (req as any).meta?.slippagePercent || '0.5',
-        tif: 'IOC' as any,
-      })
-    else if (req.type === 'LIMIT' || req.type === 'POST_ONLY')
-      response = await this.orders.createLimitOrder({
-        ...payload,
-        tif: req.type === 'POST_ONLY' ? 'ALO' : payload.tif,
-        reduceOnly: payload.reduceOnly,
-      })
-    else response = await this.orders.createStopOrder(payload)
-    const data = response?.data ?? response
-    const status = String(data?.status ?? 'NEW').toUpperCase() as Order['status']
-    return {
-      id: String(data?.order_id ?? data?.orderId ?? data?.id ?? ''),
-      symbol: String(data?.symbol ?? req.symbol),
-      status,
-      side: req.side,
-      type: req.type,
-      price: String(data?.price ?? req.price ?? '0'),
-      origQty: String(data?.amount ?? data?.origQty ?? req.quantity),
-      executedQty: String(data?.filled ?? data?.executedQty ?? '0'),
-      updateTime: Number(data?.timestamp ?? Date.now()),
-    }
-  }
-  async cancelOrder(symbol: string, orderId: string): Promise<void> {
-    await this.orders.cancelOrder({ account: this.client.requireAccount(), symbol, orderId: Number(orderId) })
-  }
-  async cancelAll(symbol: string): Promise<void> {
-    await this.orders.cancelAll({ symbol })
-  }
-  async getOrder(symbol: string, orderId: string): Promise<Order> {
-    const account = this.client.requireAccount()
-    const response = await this.client.get<any>(this.client.endpoints.orderGet, { symbol, orderId, account })
-    const data = response?.data ?? response
-    return {
-      id: String(data?.order_id ?? data?.orderId ?? orderId),
-      symbol: String(data?.symbol ?? symbol),
-      status: String(data?.status ?? 'NEW').toUpperCase() as Order['status'],
-      side: String(data?.side ?? 'bid').toUpperCase() === 'BID' ? 'BUY' : 'SELL',
-      type: String(data?.type ?? 'LIMIT').toUpperCase() as any,
-      price: String(data?.price ?? '0'),
-      origQty: String(data?.amount ?? data?.origQty ?? '0'),
-      executedQty: String(data?.filled ?? data?.executedQty ?? '0'),
-      updateTime: Number(data?.timestamp ?? data?.updated_at ?? Date.now()),
-    }
-  }
-  async openOrders(symbol: string): Promise<Order[]> {
-    const account = this.client.requireAccount()
-    let response: any
-    try {
-      response = await this.orders.openOrders(symbol, account)
-    } catch (e: any) {
-      const msg = String(e?.message || '')
-      if (msg.startsWith('HTTP 403')) {
-        // eslint-disable-next-line no-console
-        console.warn('[pacifica.openOrders] 403 forbidden; returning empty list (likely CDN/whitelist).')
-        return []
-      }
-      throw e
-    }
-    const list = response?.data ?? response
-    return (Array.isArray(list) ? list : []).map((o: any) => ({
-      id: String(o.order_id ?? o.orderId ?? o.id),
-      symbol: String(o.symbol ?? symbol),
-      status: String(o.status ?? 'NEW').toUpperCase() as Order['status'],
-      side: String(o.side ?? 'bid').toUpperCase() === 'BID' ? 'BUY' : 'SELL',
-      type: String(o.type ?? 'LIMIT').toUpperCase() as any,
-      price: String(o.price ?? '0'),
-      origQty: String(o.amount ?? o.origQty ?? '0'),
-      executedQty: String(o.filled ?? o.executedQty ?? '0'),
-      updateTime: Number(o.timestamp ?? o.updated_at ?? Date.now()),
-    }))
-  }
-  async depth(symbol: string, limit = 50): Promise<Depth> {
-    const endpoint = this.client.endpoints.depth
-    const baseSymbol = this.normalizeSymbol(symbol)
-    // Try robust combinations: symbol/market keys, public and signed
-    const candidateQueries = [
-      { symbol: baseSymbol },
-      { market: baseSymbol },
-      { market: baseSymbol, limit },
-      { symbol: baseSymbol, limit },
-    ]
-    let response: any | null = null
-    for (const q of candidateQueries) {
-      const qs = `?${new URLSearchParams(q as any).toString()}`
-      try {
-        // debug
-        // eslint-disable-next-line no-console
-        console.log('[pacifica.depth] try public', endpoint + qs)
-        response = await this.client.getPublic<any>(endpoint + qs)
-        if (response) break
-      } catch (e) {
-        // eslint-disable-next-line no-console
-        console.log('[pacifica.depth] public failed', (e as any)?.message || e)
-      }
-      try {
-        // eslint-disable-next-line no-console
-        console.log('[pacifica.depth] try signed', endpoint, q)
-        response = await this.client.get<any>(endpoint, q as any)
-        if (response) break
-      } catch (e) {
-        // eslint-disable-next-line no-console
-        console.log('[pacifica.depth] signed failed', (e as any)?.message || e)
-      }
-    }
-    if (!response) throw new Error('orderbook_not_found')
-    const payload = response?.data ?? response
-    // Doc format: payload.l = [ bids[], asks[] ], where each element is { p: price, a: amount, n: numOrders }
-    if (Array.isArray(payload?.l) && payload.l.length >= 2) {
-      const rawBids = Array.isArray(payload.l[0]) ? payload.l[0] : []
-      const rawAsks = Array.isArray(payload.l[1]) ? payload.l[1] : []
-      const bids = rawBids
-        .map((lvl: any) => ({ price: String(lvl?.p ?? lvl?.price ?? ''), qty: String(lvl?.a ?? lvl?.amount ?? '') }))
-        .filter(x => x.price && x.qty)
-      const asks = rawAsks
-        .map((lvl: any) => ({ price: String(lvl?.p ?? lvl?.price ?? ''), qty: String(lvl?.a ?? lvl?.amount ?? '') }))
-        .filter(x => x.price && x.qty)
-      return { bids, asks, ts: Number(payload?.t ?? Date.now()) }
-    }
-    // Fallback: bids/asks as [price, qty]
-    const bids = (payload?.bids ?? []).map((x: any) => ({ price: String(x[0]), qty: String(x[1]) }))
-    const asks = (payload?.asks ?? []).map((x: any) => ({ price: String(x[0]), qty: String(x[1]) }))
-    return { bids, asks, ts: Number(payload?.ts ?? Date.now()) }
-  }
-  private normalizeSymbol(input: string): string {
-    // Per docs, orderbook expects plain base symbol like 'BTC'
-    if (!input) return input
-    const s = String(input).toUpperCase()
-    if (s.includes('-')) return s.split('-')[0]
-    if (s.endsWith('USDT')) return s.replace('USDT', '')
-    if (s.endsWith('USD')) return s.replace('USD', '')
-    return s
-  }
-  ws() {
-    return this.events
-  }
-
-  subscribeDepth(symbol: string) {
-    if (this.depthSocket) this.depthSocket.close()
-    this.depthSocket = this.client.wsConnect({}, false)
-    this.depthSocket.on('open', () => {
-      this.startHeartbeat(this.depthSocket as WebSocket)
-      // 订阅 orderbook(book)
-      const sub = {
-        method: 'subscribe',
-        params: { source: 'book', symbol: this.normalizeSymbol(symbol), agg_level: 1 },
-      }
-      ;(this.depthSocket as WebSocket).send(JSON.stringify(sub))
-    })
-    this.depthSocket.on('message', (raw: WebSocket.RawData) => {
-      try {
-        const msg = JSON.parse(String(raw))
-        if (msg?.channel === 'book' && msg?.data?.l) {
-          const payload = msg.data
-          const rawBids = Array.isArray(payload.l[0]) ? payload.l[0] : []
-          const rawAsks = Array.isArray(payload.l[1]) ? payload.l[1] : []
-          this.events.emit('depth', {
-            symbol,
-            bids: rawBids.map((lvl: any) => ({ price: String(lvl?.p ?? ''), qty: String(lvl?.a ?? '') })),
-            asks: rawAsks.map((lvl: any) => ({ price: String(lvl?.p ?? ''), qty: String(lvl?.a ?? '') })),
-            ts: Number(payload?.t ?? Date.now()),
-          })
-        }
-      } catch {}
-    })
-    this.depthSocket.on('close', () => this.events.emit('ws_close', { channel: 'depth', symbol }))
-    this.depthSocket.on('error', e => this.events.emit('ws_error', e))
-  }
-
-  // ---- Private WS channels ----
-  private subscribeChannel(
-    topic: 'orders' | 'balance' | 'trades' | 'prices' | 'account_info' | 'account_positions',
-    params: Record<string, any>,
-    onMessage: (msg: any) => void,
-  ) {
-    const sockKey = `${topic}Socket` as const
-    const existing = (this as any)[sockKey] as WebSocket | undefined
-    if (existing) existing.close()
-    const ws = this.client.wsConnect(params, true)
-    ;(this as any)[sockKey] = ws
-    ws.on('open', () => {
-      this.startHeartbeat(ws)
-      const sub = { method: 'subscribe', params: { source: topic, ...params } } as any
-      // map aliases
-      if (topic === 'orders') sub.params.source = 'account_orders'
-      if (topic === 'balance') sub.params.source = 'account_balance'
-      if (topic === 'trades') sub.params.source = 'trades'
-      ws.send(JSON.stringify(sub))
-    })
-    ws.on('message', (raw: WebSocket.RawData) => {
-      try {
-        const msg = JSON.parse(String(raw))
-        onMessage(msg)
-      } catch {}
-    })
-    ws.on('close', () => this.events.emit('ws_close', { channel: topic, params }))
-    ws.on('error', e => this.events.emit('ws_error', e))
-  }
-
-  subscribeOrders() {
-    const account = this.client.requireAccount()
-    this.subscribeChannel('orders', { account }, msg => {
-      // 统一透传,交由上层处理
-      this.events.emit('orders', msg)
-    })
-  }
-
-  subscribeBalance() {
-    const account = this.client.requireAccount()
-    this.subscribeChannel('balance', { account }, msg => {
-      this.events.emit('balance', msg)
-    })
-  }
-
-  subscribeTrades(symbol?: string) {
-    const params: Record<string, any> = {}
-    if (symbol) params.symbol = this.normalizeSymbol(symbol)
-    this.subscribeChannel('trades', params, msg => {
-      this.events.emit('trades', msg)
-    })
-  }
-
-  subscribePrices() {
-    this.subscribeChannel('prices', {}, msg => this.events.emit('prices', msg))
-  }
-
-  subscribeAccountInfo() {
-    const account = this.client.requireAccount()
-    this.subscribeChannel('account_info', { account }, msg => this.events.emit('account_info', msg))
-  }
-
-  subscribeAccountPositions() {
-    const account = this.client.requireAccount()
-    this.subscribeChannel('account_positions', { account }, msg => this.events.emit('account_positions', msg))
-  }
-
-  // --- Extra helpers (not in ExchangeAdapter) ---
-  async createStopOrder(params: {
-    symbol: string
-    side: 'BUY' | 'SELL'
-    quantity: string
-    stopPrice: string
-    limitPrice?: string
-    reduceOnly?: boolean
-  }) {
-    const account = this.client.requireAccount()
-    const side = params.side === 'BUY' ? 'bid' : 'ask'
-    const payload: any = {
-      account,
-      symbol: params.symbol,
-      amount: String(params.quantity),
-      side,
-      reduceOnly: !!params.reduceOnly,
-      clientOrderId: undefined,
-      stopLoss: {
-        stopPrice: String(params.stopPrice),
-        limitPrice: params.limitPrice ? String(params.limitPrice) : undefined,
-      },
-      agentWallet: this.client.cfg.agentWallet,
-    }
-    const res: any = await this.orders.createStopOrder(payload)
-    return res && (res as any).data !== undefined ? (res as any).data : res
-  }
-
-  async setPositionTpSl(params: {
-    symbol: string
-    side: 'BUY' | 'SELL'
-    takeProfit?: { stopPrice: string; limitPrice?: string }
-    stopLoss?: { stopPrice: string; limitPrice?: string }
-  }) {
-    const account = this.client.requireAccount()
-    const side = params.side === 'BUY' ? 'bid' : 'ask'
-    const normSymbol = String(params.symbol).toUpperCase().includes('-')
-      ? String(params.symbol).toUpperCase().split('-')[0]
-      : String(params.symbol).toUpperCase().endsWith('USDT')
-      ? String(params.symbol).toUpperCase().replace('USDT', '')
-      : String(params.symbol).toUpperCase().endsWith('USD')
-      ? String(params.symbol).toUpperCase().replace('USD', '')
-      : String(params.symbol).toUpperCase()
-    const data: any = {
-      symbol: normSymbol,
-      side,
-      take_profit: params.takeProfit
-        ? {
-            stop_price: String(params.takeProfit.stopPrice),
-            limit_price: params.takeProfit.limitPrice ? String(params.takeProfit.limitPrice) : undefined,
-          }
-        : undefined,
-      stop_loss: params.stopLoss
-        ? {
-            stop_price: String(params.stopLoss.stopPrice),
-            limit_price: params.stopLoss.limitPrice ? String(params.stopLoss.limitPrice) : undefined,
-          }
-        : undefined,
-    }
-    const { signature, timestamp, expiryWindow } = await this.client.signOperation('set_position_tpsl', data, 30000)
-    const body = {
-      account,
-      ...data,
-      agent_wallet: this.client.cfg.agentWallet,
-      signature,
-      timestamp,
-      expiry_window: expiryWindow,
-    }
-    if (process.env.NODE_ENV === 'development' && process.env.PACIFICA_DEBUG === '1') {
-      logger.debug('Pacifica设置止盈止损调试', {
-        operation: 'set_position_tpsl',
-        signDataLength: JSON.stringify(data).length,
-        signaturePreview: `b58(${String(signature).slice(0, 8)}...)`,
-      })
-    }
-    const res = await this.client.post(this.client.endpoints.positionTpSl as any, body, { skipHeaderSig: true })
-    return (res as any)?.data ?? res
-  }
-
-  async setPositionTp(params: { symbol: string; side: 'BUY' | 'SELL'; stopPrice: string; limitPrice?: string }) {
-    return await this.setPositionTpSl({
-      symbol: params.symbol,
-      side: params.side,
-      takeProfit: { stopPrice: params.stopPrice, limitPrice: params.limitPrice },
-    })
-  }
-
-  async setPositionSl(params: { symbol: string; side: 'BUY' | 'SELL'; stopPrice: string; limitPrice?: string }) {
-    return await this.setPositionTpSl({
-      symbol: params.symbol,
-      side: params.side,
-      stopLoss: { stopPrice: params.stopPrice, limitPrice: params.limitPrice },
-    })
-  }
-
-  async batch(actions: Array<{ type: 'Create' | 'Cancel'; data: any }>) {
-    return await (this.orders as any).batch(actions)
-  }
-}

+ 0 - 355
src/adapters/exchanges/pacifica/PacificaClient.ts

@@ -1,355 +0,0 @@
-import WebSocket from 'ws'
-import nacl from 'tweetnacl'
-import bs58 from 'bs58'
-import { httpClient } from '../../utils/httpClient'
-
-export interface PacificaEndpoints {
-  time: string // GET
-  symbols: string // GET
-  depth: string // GET  (expects ?symbol=&limit=)
-  balances: string // GET
-  positions: string // GET
-  accountInfo: string // GET
-  leverage: string // POST
-  subaccountCreate: string // POST
-  agentBind: string // POST
-  orderCreateMarket: string // POST
-  orderCreateLimit: string // POST
-  orderCreateStop: string // POST
-  orderCancel: string // POST
-  orderCancelAll: string // POST
-  orderGet: string // GET  (expects ?symbol=&orderId=)
-  openOrders: string // GET  (expects ?symbol=&account=)
-  orderBatch: string // POST
-  positionTpSl: string // POST
-}
-
-export interface PacificaCfg {
-  baseUrl: string
-  wsUrl: string
-  apiKey?: string
-  privateKey?: string
-  timeoutMs?: number
-  account?: string
-  agentWallet?: string
-  agentPrivateKey?: string
-}
-
-export class PacificaClient {
-  public endpoints: PacificaEndpoints
-  public cfg: PacificaCfg
-  private cachedKeys?: { secretKey: Uint8Array; publicKey: Uint8Array }
-  private cachedAgentKeys?: { secretKey: Uint8Array; publicKey: Uint8Array }
-  private defaultAccount?: string
-  private agentWallet?: string
-  constructor(cfg: PacificaCfg) {
-    this.cfg = cfg
-    if (!this.cfg.baseUrl || !this.cfg.wsUrl) {
-      throw new Error('PacificaClient: baseUrl and wsUrl are required')
-    }
-    // 固定为官方文档结构,不再从环境或配置读取
-    this.endpoints = {
-      // Per docs: base is /api/v1; info and orderbook exist
-      time: '/api/v1/info',
-      symbols: '/api/v1/info',
-      depth: '/api/v1/book',
-      prices: '/api/v1/prices',
-      // The rest may differ; keep placeholders under /api/v1 for now
-      balances: '/api/v1/account/balance',
-      positions: '/api/v1/account/positions',
-      accountInfo: '/api/v1/account/info', // POST per docs
-      leverage: '/api/v1/account/update-leverage',
-      subaccountCreate: '/api/v1/subaccounts/create',
-      agentBind: '/api/v1/agent/bind',
-      orderCreateMarket: '/api/v1/orders/create_market',
-      orderCreateLimit: '/api/v1/orders/create',
-      orderCreateStop: '/api/v1/orders/stop/create',
-      orderCancel: '/api/v1/orders/cancel',
-      orderCancelAll: '/api/v1/orders/cancel_all',
-      orderGet: '/api/v1/orders/history', // may be GET by id or requires POST; keep for now
-      openOrders: '/api/v1/orders',
-      orderBatch: '/api/v1/orders/batch',
-      positionTpSl: '/api/v1/positions/tpsl',
-    }
-    this.defaultAccount = cfg.account
-    this.agentWallet = cfg.agentWallet
-  }
-
-  private async sleep(ms: number): Promise<void> {
-    return new Promise(r => setTimeout(r, ms))
-  }
-
-  private shouldRetry(status: number): boolean {
-    if (status === 429) return true
-    if (status >= 500 && status <= 599) return true
-    return false
-  }
-
-  private parseSecretKey(): { secretKey?: Uint8Array; publicKey?: Uint8Array } {
-    if (this.cachedKeys) return this.cachedKeys
-    const pk = this.cfg.privateKey
-    if (!pk) return {}
-    try {
-      let sk: Uint8Array | undefined
-      if (pk.startsWith('[')) {
-        sk = Uint8Array.from(JSON.parse(pk))
-      } else {
-        sk = bs58.decode(pk)
-      }
-      if (sk && (sk.length === 64 || sk.length === 32)) {
-        const kp = sk.length === 64 ? nacl.sign.keyPair.fromSecretKey(sk) : nacl.sign.keyPair.fromSeed(sk)
-        this.cachedKeys = { secretKey: kp.secretKey, publicKey: kp.publicKey }
-        return this.cachedKeys
-      }
-    } catch {}
-    return {}
-  }
-
-  private parseAgentSecretKey(): { secretKey?: Uint8Array; publicKey?: Uint8Array } {
-    if (this.cachedAgentKeys) return this.cachedAgentKeys
-    const pk = this.cfg.agentPrivateKey
-    if (!pk) return {}
-    try {
-      let sk: Uint8Array | undefined
-      if (pk.startsWith('[')) {
-        sk = Uint8Array.from(JSON.parse(pk))
-      } else {
-        sk = bs58.decode(pk)
-      }
-      if (sk && (sk.length === 64 || sk.length === 32)) {
-        const kp = sk.length === 64 ? nacl.sign.keyPair.fromSecretKey(sk) : nacl.sign.keyPair.fromSeed(sk)
-        this.cachedAgentKeys = { secretKey: kp.secretKey, publicKey: kp.publicKey }
-        return this.cachedAgentKeys
-      }
-    } catch {}
-    return {}
-  }
-
-  requireAccount(account?: string): string {
-    const finalAccount = account ?? this.defaultAccount
-    if (!finalAccount) throw new Error('PacificaClient: account is required')
-    return finalAccount
-  }
-
-  requireAgentWallet(wallet?: string): string {
-    const final = wallet ?? this.agentWallet
-    if (!final) throw new Error('PacificaClient: agent wallet is required')
-    return final
-  }
-
-  private sortJson(value: any): any {
-    if (Array.isArray(value)) return value.map(item => this.sortJson(item))
-    if (value && typeof value === 'object') {
-      const sorted: Record<string, any> = {}
-      Object.keys(value)
-        .sort()
-        .forEach(key => {
-          const val = value[key]
-          if (val !== undefined && val !== null) sorted[key] = this.sortJson(val)
-        })
-      return sorted
-    }
-    return value
-  }
-
-  private canonicalJson(input: any): string {
-    if (input == null) return ''
-    const sorted = this.sortJson(input)
-    return JSON.stringify(sorted, (key, value) => value, 0).replace(/\s+/g, '')
-  }
-
-  private signHeaders = async (path: string, body: any, ts: number): Promise<Record<string, string>> => {
-    const headers: Record<string, string> = {}
-    if (this.cfg.apiKey) headers['X-API-KEY'] = this.cfg.apiKey
-    const { secretKey, publicKey } = this.parseSecretKey()
-    if (!secretKey || !publicKey) return headers
-    const payload = `${ts}|${path}|${this.canonicalJson(body)}`
-    const msg = new TextEncoder().encode(payload)
-    const sig = nacl.sign.detached(msg, secretKey)
-    headers['X-PUBKEY'] = bs58.encode(publicKey)
-    headers['X-TS'] = String(ts)
-    headers['X-SIGNATURE'] = bs58.encode(sig)
-    return headers
-  }
-
-  async buildSignedHeaders(path: string, body?: any): Promise<Record<string, string>> {
-    const ts = Date.now()
-    return await this.signHeaders(path, body, ts)
-  }
-
-  private async sign(type: string, data: Record<string, any>, expiryWindow: number, useAgent: boolean) {
-    const keys = useAgent ? this.parseAgentSecretKey() : this.parseSecretKey()
-    if (!keys.secretKey) throw new Error('PacificaClient: private key missing for signing')
-    const timestamp = Date.now()
-    const message = this.sortJson({ timestamp, expiry_window: expiryWindow, type, data })
-    const json = JSON.stringify(message, (k, v) => v, 0).replace(/\s+/g, '')
-    const sig = nacl.sign.detached(new TextEncoder().encode(json), keys.secretKey)
-    return { timestamp, expiryWindow, signature: bs58.encode(sig) }
-  }
-
-  async signOperation(type: string, data: Record<string, any>, expiryWindow = 30000) {
-    return this.sign(type, data, expiryWindow, false)
-  }
-
-  async signOperationWithAgent(type: string, data: Record<string, any>, expiryWindow = 30000) {
-    return this.sign(type, data, expiryWindow, true)
-  }
-
-  async get<T>(path: string, query?: Record<string, string | number | undefined>): Promise<T> {
-    const queryString = query
-      ? `?${new URLSearchParams(Object.entries(query).filter(([, v]) => v !== undefined) as any).toString()}`
-      : ''
-    const url = `${this.cfg.baseUrl}${path}${queryString}`
-    const pathForSig = path.split('?')[0]
-    const maxRetries = 4
-    const baseDelay = 250
-    for (let attempt = 0; attempt <= maxRetries; attempt++) {
-      try {
-        const ts = Date.now()
-        const headers = await this.signHeaders(pathForSig, undefined, ts)
-        const res = await httpClient.get(url, {
-          headers: headers as any,
-          exchange: 'pacifica',
-          timeout: this.cfg.timeoutMs || 30000,
-          retries: 0, // 我们自己处理重试
-        })
-
-        if (!res.ok) {
-          if (this.shouldRetry(res.status) && attempt < maxRetries) {
-            // 对429错误使用更长的等待时间
-            const isRateLimit = res.status === 429
-            const delay = isRateLimit
-              ? 5000 + attempt * 2000 // 429错误: 5s, 7s, 9s, 11s
-              : baseDelay * Math.pow(2, attempt) // 其他错误: 指数退避
-            const jitter = Math.floor(Math.random() * 1000)
-
-            console.log(`HTTP ${res.status}错误,${delay + jitter}ms后重试 (${attempt + 1}/${maxRetries + 1})`)
-            await this.sleep(delay + jitter)
-            continue
-          }
-          const errorMsg = res.data ? (typeof res.data === 'string' ? res.data : JSON.stringify(res.data)) : ''
-          throw new Error(`HTTP ${res.status} ${path}${errorMsg ? ` - ${errorMsg.slice(0, 500)}` : ''}`)
-        }
-        return res.data as T
-      } catch (e: any) {
-        const message = String(e?.message || '')
-        if (message.startsWith('HTTP')) {
-          throw e
-        }
-        if (attempt < maxRetries) {
-          const jitter = Math.floor(Math.random() * 100)
-          await this.sleep(baseDelay * Math.pow(2, attempt) + jitter)
-          continue
-        }
-        throw e
-      }
-    }
-    // Unreachable, to satisfy TS return type
-    throw new Error('unreachable')
-  }
-
-  async getPublic<T>(path: string): Promise<T> {
-    const url = `${this.cfg.baseUrl}${path}`
-    const maxRetries = 4
-    const baseDelay = 250
-    for (let attempt = 0; attempt <= maxRetries; attempt++) {
-      try {
-        const res = await httpClient.get(url, {
-          exchange: 'pacifica',
-          timeout: this.cfg.timeoutMs || 30000,
-          retries: 0, // 我们自己处理重试
-        })
-
-        if (!res.ok) {
-          if (this.shouldRetry(res.status) && attempt < maxRetries) {
-            // 对429错误使用更长的等待时间
-            const isRateLimit = res.status === 429
-            const delay = isRateLimit
-              ? 5000 + attempt * 2000 // 429错误: 5s, 7s, 9s, 11s
-              : baseDelay * Math.pow(2, attempt) // 其他错误: 指数退避
-            const jitter = Math.floor(Math.random() * 1000)
-
-            console.log(`HTTP ${res.status}错误,${delay + jitter}ms后重试 (${attempt + 1}/${maxRetries + 1})`)
-            await this.sleep(delay + jitter)
-            continue
-          }
-          const errorMsg = res.data ? (typeof res.data === 'string' ? res.data : JSON.stringify(res.data)) : ''
-          throw new Error(`HTTP ${res.status} ${path}${errorMsg ? ` - ${errorMsg.slice(0, 500)}` : ''}`)
-        }
-        return res.data as T
-      } catch (e: any) {
-        const message = String(e?.message || '')
-        if (message.startsWith('HTTP')) {
-          throw e
-        }
-        if (attempt < maxRetries) {
-          const jitter = Math.floor(Math.random() * 100)
-          await this.sleep(baseDelay * Math.pow(2, attempt) + jitter)
-          continue
-        }
-        throw e
-      }
-    }
-    throw new Error('unreachable')
-  }
-
-  async post<T>(path: string, body: any, opts?: { skipHeaderSig?: boolean }): Promise<T> {
-    const url = `${this.cfg.baseUrl}${path}`
-    const maxRetries = 4
-    const baseDelay = 250
-    for (let attempt = 0; attempt <= maxRetries; attempt++) {
-      try {
-        const ts = Date.now()
-        const headers = opts?.skipHeaderSig ? {} : await this.signHeaders(path, body, ts)
-        const res = await httpClient.post(url, body, {
-          headers: { 'Content-Type': 'application/json', ...headers } as any,
-          exchange: 'pacifica',
-          timeout: this.cfg.timeoutMs || 30000,
-          retries: 0, // 我们自己处理重试
-        })
-
-        if (!res.ok) {
-          if (this.shouldRetry(res.status) && attempt < maxRetries) {
-            // 对429错误使用更长的等待时间
-            const isRateLimit = res.status === 429
-            const delay = isRateLimit
-              ? 5000 + attempt * 2000 // 429错误: 5s, 7s, 9s, 11s
-              : baseDelay * Math.pow(2, attempt) // 其他错误: 指数退避
-            const jitter = Math.floor(Math.random() * 1000)
-
-            console.log(`HTTP ${res.status}错误,${delay + jitter}ms后重试 (${attempt + 1}/${maxRetries + 1})`)
-            await this.sleep(delay + jitter)
-            continue
-          }
-          const errorMsg = res.data ? (typeof res.data === 'string' ? res.data : JSON.stringify(res.data)) : ''
-          throw new Error(`HTTP ${res.status} ${path}${errorMsg ? ` - ${errorMsg.slice(0, 500)}` : ''}`)
-        }
-        return res.data as T
-      } catch (e: any) {
-        const message = String(e?.message || '')
-        if (message.startsWith('HTTP')) {
-          throw e
-        }
-        if (attempt < maxRetries) {
-          const jitter = Math.floor(Math.random() * 100)
-          await this.sleep(baseDelay * Math.pow(2, attempt) + jitter)
-          continue
-        }
-        throw e
-      }
-    }
-    throw new Error('unreachable')
-  }
-
-  wsConnect(_params: Record<string, any> = {}, _auth = true): WebSocket {
-    // 官方主网:wss://ws.pacifica.fi/ws 测试网:wss://test-ws.pacifica.fi/ws
-    // 若 cfg.wsUrl 已包含 /ws 则直接使用;否则补上 /ws
-    const raw = this.cfg.wsUrl.replace(/\/$/, '')
-    const url = /\/ws(\?|$)/.test(raw) ? raw : `${raw}/ws`
-    return new WebSocket(url)
-  }
-
-  async wsLogin(_ws: WebSocket, _params: Record<string, any> = {}): Promise<void> {
-    return
-  }
-}

+ 0 - 728
src/adapters/exchanges/pacifica/PacificaProxyClient.ts

@@ -1,728 +0,0 @@
-import { httpClient } from '../../utils/httpClient'
-import { Config } from '../../config/simpleEnv'
-import { logger } from '../shared/utils/logger'
-import { PacificaClient } from './PacificaClient'
-import { PacificaOrdersAdapter, OrderCreatePayload, CancelOrderPayload } from './OrdersAdapter'
-import { PacificaWebSocketAdapter } from './PacificaWebSocketAdapter'
-
-/**
- * 使用代理的Pacifica客户端示例
- * 展示如何集成新的HTTP代理系统
- */
-export class PacificaProxyClient {
-  private baseUrl: string
-  private client: PacificaClient
-  private ordersAdapter: PacificaOrdersAdapter
-  private wsAdapter: PacificaWebSocketAdapter
-  private useWebSocket: boolean = false // 默认使用HTTP+代理,WebSocket通过代理连接不稳定
-
-  constructor(accountConfig?: {
-    account?: string
-    privateKey?: string
-    agentWallet?: string
-    agentPrivateKey?: string
-  }) {
-    this.baseUrl = Config.pacifica.baseUrl
-
-    // 创建内部Pacifica客户端
-    this.client = new PacificaClient({
-      baseUrl: Config.pacifica.baseUrl,
-      wsUrl: Config.pacifica.wsUrl,
-      account: accountConfig?.account,
-      privateKey: accountConfig?.privateKey,
-      agentWallet: accountConfig?.agentWallet,
-      agentPrivateKey: accountConfig?.agentPrivateKey,
-      timeoutMs: 30000,
-    })
-
-    // 创建订单适配器
-    this.ordersAdapter = new PacificaOrdersAdapter(this.client)
-
-    // 创建WebSocket适配器(包含私钥用于签名)
-    this.wsAdapter = new PacificaWebSocketAdapter(
-      Config.pacifica.wsUrl || 'wss://ws.pacifica.fi/ws',
-      accountConfig?.account,
-      accountConfig?.privateKey,
-    )
-  }
-
-  /**
-   * 获取服务器时间 (公开接口,不需要认证)
-   */
-  async getServerTime(): Promise<{ time: number }> {
-    try {
-      // Pacifica API doesn't have a separate time endpoint, so we use current timestamp
-      // This aligns with how most DEXs work where client time is acceptable
-      const time = Date.now()
-      return { time }
-    } catch (error: any) {
-      logger.error('获取Pacifica服务器时间失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 获取所有交易对信息 (公开接口)
-   */
-  async getSymbols(): Promise<any> {
-    try {
-      if (this.useWebSocket) {
-        // 优先使用WebSocket
-        logger.debug('使用WebSocket获取交易对信息')
-        const wsResult = await this.wsAdapter.getSymbols()
-
-        if (wsResult.success) {
-          return wsResult.data
-        } else {
-          logger.warn('WebSocket获取交易对信息失败,回退到HTTP', { error: wsResult.error })
-        }
-      }
-
-      // 回退到HTTP请求
-      logger.debug('使用HTTP获取交易对信息')
-      const response = await httpClient.get(`${this.baseUrl}/api/v1/info`, {
-        exchange: 'pacifica',
-        timeout: 15000,
-        retries: 2,
-      })
-
-      if (!response.ok) {
-        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
-      }
-
-      return response.data
-    } catch (error: any) {
-      logger.error('获取Pacifica交易对信息失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 获取订单簿 (公开接口)
-   */
-  async getOrderBook(symbol: string, limit: number = 20): Promise<any> {
-    try {
-      // 优先使用prices接口获取价格数据
-      try {
-        const pricesResult = await this.getPrices()
-        if (pricesResult && Object.keys(pricesResult).length > 0) {
-          // 将prices数据转换为orderbook格式
-          const orderbook = this.convertPricesToOrderbook(pricesResult, symbol)
-          if (orderbook) {
-            return orderbook
-          }
-        }
-      } catch (pricesError: any) {
-        // prices接口失败,继续尝试orderbook
-      }
-
-      // 如果prices接口失败,尝试orderbook接口
-      try {
-        if (this.useWebSocket) {
-          // 优先使用WebSocket获取订单簿
-          logger.debug('使用WebSocket获取订单簿数据', { symbol })
-          const wsResult = await this.wsAdapter.getOrderBook(symbol)
-
-          if (wsResult.success && wsResult.data) {
-            return wsResult.data
-          } else {
-            logger.warn('WebSocket获取订单簿失败,回退到HTTP', { symbol, error: wsResult.error })
-          }
-        }
-
-        // 回退到HTTP请求
-        logger.debug('使用HTTP获取订单簿数据', { symbol })
-        const response = await httpClient.get(`${this.baseUrl}/api/v1/book?symbol=${symbol}`, {
-          exchange: 'pacifica',
-          timeout: 10000,
-          retries: 2,
-        })
-
-        if (response.ok && response.data) {
-          return response.data
-        }
-      } catch (orderbookError: any) {
-        // orderbook接口失败,使用fallback
-        logger.warn('订单簿接口调用失败', { symbol, error: orderbookError.message })
-      }
-
-      // 最后使用市场价格fallback
-      return await this.getPricesAsFallback(symbol)
-    } catch (error: any) {
-      logger.error('获取Pacifica价格数据失败', { symbol, error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 使用外部价格源作为orderbook的fallback
-   */
-  private async getPricesAsFallback(symbol: string): Promise<any> {
-    try {
-      console.log(`💡 [价格fallback] 使用外部价格源获取 ${symbol} 价格`)
-
-      // 使用简单的市场价格映射作为fallback
-      const currentPrice = this.getMarketPrice(symbol)
-      console.log(`✅ [价格fallback] 获取到${symbol}市场价格:`, currentPrice)
-
-      // 将价格转换为orderbook格式
-      const mockOrderbook = this.convertPriceToOrderbook(currentPrice, symbol)
-      console.log(`🔄 [价格fallback] 转换为orderbook格式:`, JSON.stringify(mockOrderbook, null, 2))
-
-      return mockOrderbook
-    } catch (error: any) {
-      console.log(`❌ [价格fallback] 价格fallback失败:`, error.message)
-      throw new Error(`orderbook API失败,fallback也失败: ${error.message}`)
-    }
-  }
-
-  /**
-   * 获取市场价格(基于当前市场估值)
-   */
-  private getMarketPrice(symbol: string): number {
-    const now = Date.now()
-
-    // 根据symbol返回当前市场价格(可以后续接入真实的价格API)
-    const priceMap: Record<string, number> = {
-      'BTC-USD': 65000 + Math.sin(now / 100000) * 1000, // BTC around $65k with small variation
-      BTCUSDT: 65000 + Math.sin(now / 100000) * 1000,
-      BTC: 65000 + Math.sin(now / 100000) * 1000,
-      'ETH-USD': 3450 + Math.sin(now / 80000) * 100, // ETH around $3450 with small variation
-      ETHUSDT: 3450 + Math.sin(now / 80000) * 100,
-      ETH: 3450 + Math.sin(now / 80000) * 100,
-    }
-
-    const price = priceMap[symbol] || priceMap[symbol.replace('-USD', '')] || priceMap[symbol.replace('USDT', '')] || 1
-
-    console.log(`📊 [市场价格] ${symbol}: $${price.toFixed(2)}`)
-    return price
-  }
-
-  /**
-   * 从prices数据中找到对应symbol的价格
-   */
-  private findSymbolPrice(pricesData: any, symbol: string): number | null {
-    // 尝试多种可能的数据结构
-    if (Array.isArray(pricesData)) {
-      for (const item of pricesData) {
-        if (item.symbol === symbol || item.market === symbol) {
-          return parseFloat(item.price || item.mark_price || item.last_price || '0')
-        }
-      }
-    }
-
-    if (pricesData.data && Array.isArray(pricesData.data)) {
-      for (const item of pricesData.data) {
-        if (item.symbol === symbol || item.market === symbol) {
-          return parseFloat(item.price || item.mark_price || item.last_price || '0')
-        }
-      }
-    }
-
-    // 直接通过symbol访问
-    if (pricesData[symbol]) {
-      return parseFloat(pricesData[symbol].price || pricesData[symbol] || '0')
-    }
-
-    return null
-  }
-
-  /**
-   * 将prices接口数据转换为orderbook格式
-   */
-  private convertPricesToOrderbook(pricesData: any, symbol: string): any | null {
-    try {
-      console.log(`🔄 [价格转换] 处理${pricesData?.data?.length || 0}个交易对数据`)
-
-      // 尝试从prices数据中找到指定symbol的价格
-      let price: number | null = null
-      let foundSymbol: string = ''
-
-      // 创建symbol映射表,支持不同的命名规则
-      // Pacifica使用简单的symbol命名:BTC, ETH, SOL等
-      const symbolMappings: Record<string, string[]> = {
-        'BTC-USD': ['BTC'],
-        BTC: ['BTC'],
-        BTCUSDT: ['BTC'],
-        'ETH-USD': ['ETH'],
-        ETH: ['ETH'],
-        ETHUSDT: ['ETH'],
-        'SOL-USD': ['SOL'],
-        SOL: ['SOL'],
-        SOLUSDT: ['SOL'],
-      }
-
-      const searchSymbols = symbolMappings[symbol] || [symbol]
-      console.log(`🔍 [价格转换] 搜索symbol ${symbol},映射为:`, searchSymbols)
-
-      // 多种数据格式兼容处理
-      if (Array.isArray(pricesData)) {
-        // 格式1: 数组格式
-        for (const item of pricesData) {
-          const itemSymbol = item.symbol || item.market || ''
-          if (searchSymbols.some(s => s === itemSymbol || itemSymbol.includes(s.replace('-', '')))) {
-            price = parseFloat(item.mid || item.mark || item.price || item.mark_price || item.last_price || '0')
-            foundSymbol = itemSymbol
-            break
-          }
-        }
-      } else if (pricesData.data && Array.isArray(pricesData.data)) {
-        // 格式2: 包装在data字段中
-        for (const item of pricesData.data) {
-          const itemSymbol = item.symbol || item.market || ''
-          if (searchSymbols.some(s => s === itemSymbol || itemSymbol.includes(s.replace('-', '')))) {
-            price = parseFloat(item.mid || item.mark || item.price || item.mark_price || item.last_price || '0')
-            foundSymbol = itemSymbol
-            break
-          }
-        }
-      } else if (pricesData[symbol]) {
-        // 格式3: 直接通过symbol访问
-        const symbolData = pricesData[symbol]
-        price = parseFloat(
-          symbolData.mid ||
-            symbolData.mark ||
-            symbolData.price ||
-            symbolData.mark_price ||
-            symbolData.last_price ||
-            symbolData ||
-            '0',
-        )
-        foundSymbol = symbol
-      }
-
-      if (!price || price <= 0) {
-        console.log(`⚠️ [价格转换] 无法找到${symbol}的有效价格,搜索的symbols:`, searchSymbols)
-
-        // 显示可用的symbol列表以便调试
-        if (pricesData.data && Array.isArray(pricesData.data)) {
-          const availableSymbols = pricesData.data.map((item: any) => item.symbol).slice(0, 10)
-          console.log(`📋 [价格转换] 可用的symbols (前10个):`, availableSymbols)
-        }
-
-        return null
-      }
-
-      console.log(`✅ [价格转换] 找到${symbol}价格: $${price} (来源symbol: ${foundSymbol})`)
-
-      // 转换为orderbook格式
-      return this.convertPriceToOrderbook(price, symbol)
-    } catch (error: any) {
-      console.log(`❌ [价格转换] 转换失败:`, error.message)
-      return null
-    }
-  }
-
-  /**
-   * 将单一价格转换为orderbook格式
-   */
-  private convertPriceToOrderbook(price: number, symbol: string): any {
-    // 生成虚拟的bid/ask spread (0.1%的价差)
-    const spread = price * 0.001
-    const bid = price - spread / 2
-    const ask = price + spread / 2
-    const midPrice = price
-
-    return {
-      bids: [
-        { price: bid.toString(), qty: '1.0' },
-        { price: (bid - spread).toString(), qty: '2.0' },
-      ],
-      asks: [
-        { price: ask.toString(), qty: '1.0' },
-        { price: (ask + spread).toString(), qty: '2.0' },
-      ],
-      timestamp: Date.now(),
-      symbol: symbol,
-      midPrice: midPrice,
-    }
-  }
-
-  /**
-   * 获取最新价格 (公开接口)
-   */
-  async getPrices(): Promise<any> {
-    try {
-      if (this.useWebSocket) {
-        // 优先使用WebSocket
-        logger.debug('使用WebSocket获取价格信息')
-        const wsResult = await this.wsAdapter.getPrices()
-
-        if (wsResult.success) {
-          return wsResult.data
-        } else {
-          logger.warn('WebSocket获取价格信息失败,回退到HTTP', { error: wsResult.error })
-        }
-      }
-
-      // 回退到HTTP请求
-      logger.debug('使用HTTP获取价格信息')
-      const response = await httpClient.get(`${this.baseUrl}/api/v1/info/prices`, {
-        exchange: 'pacifica',
-        timeout: 10000,
-        retries: 2,
-      })
-
-      if (!response.ok) {
-        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
-      }
-
-      return response.data
-    } catch (error: any) {
-      logger.error('获取Pacifica价格信息失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 创建市价单
-   */
-  async createMarketOrder(payload: OrderCreatePayload): Promise<any> {
-    try {
-      logger.info('创建Pacifica市价单', {
-        symbol: payload.symbol,
-        side: payload.side,
-        amount: payload.amount,
-        account: payload.account.substring(0, 8) + '...',
-      })
-
-      if (this.useWebSocket) {
-        // 优先使用WebSocket
-        logger.debug('使用WebSocket创建市价单')
-
-        // 确保有签名
-        if (!payload.signature) {
-          logger.warn('WebSocket下单需要签名,回退到HTTP')
-        } else {
-          try {
-            const wsResult = await this.wsAdapter.placeMarketOrder({
-              symbol: payload.symbol,
-              side: payload.side,
-              amount: payload.amount,
-              account: payload.account,
-              signature: payload.signature,
-              reduce_only: payload.reduceOnly || false,
-              slippage_percent: '0.5',
-            })
-
-            if (wsResult.success) {
-              logger.info('WebSocket市价单创建成功', {
-                symbol: payload.symbol,
-                side: payload.side,
-                orderId: wsResult.orderId,
-              })
-              return wsResult
-            } else {
-              logger.warn('WebSocket市价单失败,回退到HTTP', { error: wsResult.error })
-            }
-          } catch (wsError: any) {
-            logger.warn('WebSocket市价单异常,回退到HTTP', { error: wsError.message })
-          }
-        }
-      }
-
-      // 回退到HTTP方法
-      logger.debug('使用HTTP创建市价单')
-      const result = await this.ordersAdapter.createMarketOrder(payload)
-
-      logger.info('Pacifica市价单创建成功', {
-        symbol: payload.symbol,
-        side: payload.side,
-        orderId: result.orderId || result.order_id,
-      })
-
-      return result
-    } catch (error: any) {
-      logger.error('创建Pacifica市价单失败', {
-        symbol: payload.symbol,
-        side: payload.side,
-        error: error.message,
-      })
-      throw error
-    }
-  }
-
-  /**
-   * 创建限价单
-   */
-  async createLimitOrder(payload: OrderCreatePayload): Promise<any> {
-    try {
-      logger.info('创建Pacifica限价单', {
-        symbol: payload.symbol,
-        side: payload.side,
-        amount: payload.amount,
-        price: payload.price,
-        account: payload.account.substring(0, 8) + '...',
-      })
-
-      if (this.useWebSocket && payload.signature && payload.price) {
-        // 优先使用WebSocket
-        logger.debug('使用WebSocket创建限价单')
-
-        try {
-          const wsResult = await this.wsAdapter.placeLimitOrder({
-            symbol: payload.symbol,
-            side: payload.side,
-            amount: payload.amount,
-            price: payload.price,
-            account: payload.account,
-            signature: payload.signature,
-            reduce_only: payload.reduceOnly || false,
-          })
-
-          if (wsResult.success) {
-            logger.info('WebSocket限价单创建成功', {
-              symbol: payload.symbol,
-              side: payload.side,
-              orderId: wsResult.orderId,
-            })
-            return wsResult
-          } else {
-            logger.warn('WebSocket限价单失败,回退到HTTP', { error: wsResult.error })
-          }
-        } catch (wsError: any) {
-          logger.warn('WebSocket限价单异常,回退到HTTP', { error: wsError.message })
-        }
-      }
-
-      // 回退到HTTP方法
-      logger.debug('使用HTTP创建限价单')
-      const result = await this.ordersAdapter.createLimitOrder(payload)
-
-      logger.info('Pacifica限价单创建成功', {
-        symbol: payload.symbol,
-        side: payload.side,
-        orderId: result.orderId || result.order_id,
-      })
-
-      return result
-    } catch (error: any) {
-      logger.error('创建Pacifica限价单失败', {
-        symbol: payload.symbol,
-        side: payload.side,
-        amount: payload.amount,
-        price: payload.price,
-        account: payload.account.substring(0, 8) + '...',
-        clientOrderId: payload.clientOrderId,
-        tif: payload.tif,
-        error: error.message,
-        errorStack: error.stack,
-        httpStatus: error.status || 'unknown',
-        responseBody: error.response?.data || error.data || 'No response data',
-        fullError: JSON.stringify(error, Object.getOwnPropertyNames(error)),
-      })
-
-      // 尝试从错误消息中提取更多信息
-      if (error.message && error.message.includes('HTTP')) {
-        console.log('🔍 详细HTTP错误信息:', error.message)
-      }
-
-      throw error
-    }
-  }
-
-  /**
-   * 取消订单
-   */
-  async cancelOrder(payload: CancelOrderPayload): Promise<any> {
-    try {
-      logger.info('取消Pacifica订单', {
-        symbol: payload.symbol,
-        orderId: payload.orderId,
-        clientOrderId: payload.clientOrderId,
-        account: payload.account.substring(0, 8) + '...',
-      })
-
-      const result = await this.ordersAdapter.cancelOrder(payload)
-
-      logger.info('Pacifica订单取消成功', {
-        symbol: payload.symbol,
-        orderId: payload.orderId,
-      })
-
-      return result
-    } catch (error: any) {
-      logger.error('取消Pacifica订单失败', {
-        symbol: payload.symbol,
-        orderId: payload.orderId,
-        error: error.message,
-      })
-      throw error
-    }
-  }
-
-  /**
-   * 获取持仓信息
-   */
-  async getPositions(account?: string): Promise<any> {
-    try {
-      const accountToUse = account || this.client.requireAccount()
-
-      if (this.useWebSocket) {
-        // 优先使用WebSocket
-        logger.debug('使用WebSocket获取持仓信息', { account: accountToUse.substring(0, 8) + '...' })
-        const wsResult = await this.wsAdapter.getPositions(accountToUse)
-
-        if (wsResult.success) {
-          return wsResult
-        } else {
-          logger.warn('WebSocket获取持仓失败,回退到HTTP', { error: wsResult.error })
-        }
-      }
-
-      // 回退到HTTP请求
-      logger.debug('使用HTTP获取持仓信息', { account: accountToUse.substring(0, 8) + '...' })
-      const result = await this.client.get('/api/v1/positions', { account: accountToUse })
-      return result
-    } catch (error: any) {
-      logger.error('获取Pacifica持仓失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 获取余额信息
-   */
-  async getBalances(account?: string): Promise<any> {
-    try {
-      const accountToUse = account || this.client.requireAccount()
-
-      if (this.useWebSocket) {
-        // 优先使用WebSocket
-        logger.debug('使用WebSocket获取余额信息', { account: accountToUse.substring(0, 8) + '...' })
-        const wsResult = await this.wsAdapter.getBalances(accountToUse)
-
-        if (wsResult.success) {
-          return wsResult
-        } else {
-          logger.warn('WebSocket获取余额失败,回退到HTTP', { error: wsResult.error })
-        }
-      }
-
-      // 回退到HTTP请求
-      logger.debug('使用HTTP获取余额信息', { account: accountToUse.substring(0, 8) + '...' })
-      const result = await this.client.get('/api/v1/account', { account: accountToUse })
-      return result
-    } catch (error: any) {
-      logger.error('获取Pacifica余额失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 获取未成交订单
-   */
-  async getOpenOrders(symbol?: string, account?: string): Promise<any> {
-    try {
-      const result = await this.ordersAdapter.openOrders(symbol, account)
-      logger.debug('获取Pacifica未成交订单成功', {
-        count: Array.isArray(result) ? result.length : 'unknown',
-        symbol,
-        account: account?.substring(0, 8) + '...',
-      })
-      return result
-    } catch (error: any) {
-      logger.error('获取Pacifica未成交订单失败', {
-        error: error.message,
-        stack: error.stack,
-        symbol,
-        account: account?.substring(0, 8) + '...',
-        response: error.response?.data || error.response || 'No response data',
-      })
-      throw error
-    }
-  }
-
-  /**
-   * 测试代理连接
-   */
-  async testConnection(): Promise<{
-    success: boolean
-    latency: number
-    proxyUsed: boolean
-    serverTime?: number
-    error?: string
-  }> {
-    const startTime = Date.now()
-
-    try {
-      const result = await this.getServerTime()
-      const latency = Date.now() - startTime
-      const proxyUsed = Config.proxy.isAnyConfigured()
-
-      logger.info('Pacifica连接测试成功', {
-        latency: `${latency}ms`,
-        proxy: proxyUsed ? '启用' : '禁用',
-        serverTime: result.time,
-      })
-
-      return {
-        success: true,
-        latency,
-        proxyUsed,
-        serverTime: result.time,
-      }
-    } catch (error: any) {
-      const latency = Date.now() - startTime
-
-      logger.error('Pacifica连接测试失败', {
-        latency: `${latency}ms`,
-        error: error.message,
-      })
-
-      return {
-        success: false,
-        latency,
-        proxyUsed: Config.proxy.isAnyConfigured(),
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 设置WebSocket模式
-   */
-  setWebSocketEnabled(enabled: boolean): void {
-    this.useWebSocket = enabled
-    logger.info(`WebSocket模式${enabled ? '启用' : '禁用'}`)
-  }
-
-  /**
-   * 获取WebSocket连接状态
-   */
-  isWebSocketConnected(): boolean {
-    return this.wsAdapter.isConnected()
-  }
-
-  /**
-   * 获取WebSocket队列长度
-   */
-  getWebSocketQueueLength(): number {
-    return this.wsAdapter.getQueueLength()
-  }
-
-  /**
-   * 强制初始化WebSocket连接
-   */
-  async initializeWebSocket(): Promise<void> {
-    try {
-      await this.wsAdapter.initialize()
-      logger.info('WebSocket连接初始化成功')
-    } catch (error: any) {
-      logger.error('WebSocket连接初始化失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 关闭所有连接并清理资源
-   */
-  async close(): Promise<void> {
-    try {
-      await this.wsAdapter.close()
-      logger.info('PacificaProxyClient资源清理完成')
-    } catch (error: any) {
-      logger.error('PacificaProxyClient清理失败', { error: error.message })
-    }
-  }
-}

+ 0 - 547
src/adapters/exchanges/pacifica/PacificaWebSocketAdapter.ts

@@ -1,547 +0,0 @@
-import { EventEmitter } from 'events'
-import { PacificaWebSocketClient } from './PacificaWebSocketClient'
-import { logger } from '../shared/utils/logger'
-
-/**
- * 交易响应接口
- */
-interface TradingResponse {
-  success: boolean
-  data?: any
-  error?: string
-  orderId?: string
-  status?: string
-}
-
-/**
- * 市场数据接口
- */
-interface MarketData {
-  symbol: string
-  price: number
-  volume: number
-  timestamp: number
-}
-
-/**
- * 订单簿数据接口
- */
-interface OrderBookData {
-  symbol: string
-  bids: Array<[number, number]>
-  asks: Array<[number, number]>
-  timestamp: number
-}
-
-/**
- * 账户信息接口
- */
-interface AccountInfo {
-  account: string
-  balance: number
-  availableBalance: number
-  positions: any[]
-  marginUsed: number
-}
-
-/**
- * Pacifica WebSocket增强适配器
- * 提供完整的API响应处理和市场数据订阅功能
- */
-export class PacificaWebSocketAdapter extends EventEmitter {
-  private wsClient: PacificaWebSocketClient
-  private subscriptions = new Set<string>()
-  private marketDataCache = new Map<string, MarketData>()
-  private orderBookCache = new Map<string, OrderBookData>()
-  private isInitialized = false
-
-  constructor(
-    wsUrl: string = 'wss://ws.pacifica.fi/ws', // 使用官方WebSocket端点
-    accountId?: string,
-    privateKey?: string,
-  ) {
-    super()
-    this.wsClient = new PacificaWebSocketClient(wsUrl, accountId, privateKey)
-  }
-
-  /**
-   * 初始化WebSocket连接
-   */
-  async initialize(): Promise<void> {
-    try {
-      await this.wsClient.connect()
-      this.setupEventHandlers()
-      this.isInitialized = true
-      logger.info('PacificaWebSocketAdapter初始化成功')
-    } catch (error: any) {
-      logger.error('PacificaWebSocketAdapter初始化失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 设置事件处理器
-   */
-  private setupEventHandlers(): void {
-    // 监听价格数据流
-    this.wsClient.on('prices', (data: any) => {
-      this.handlePricesUpdate(data)
-    })
-
-    // 监听订单簿数据流
-    this.wsClient.on('orderbook', (data: any) => {
-      this.handleOrderBookUpdate(data)
-    })
-
-    // 监听账户余额数据流
-    this.wsClient.on('balance', (data: any) => {
-      this.emit('balance', data)
-    })
-
-    // 监听仓位数据流
-    this.wsClient.on('positions', (data: any) => {
-      this.emit('positions', data)
-    })
-
-    // 监听订单更新数据流
-    this.wsClient.on('orders', (data: any) => {
-      this.emit('orders', data)
-    })
-  }
-
-  /**
-   * 处理价格更新
-   */
-  private handlePricesUpdate(data: any): void {
-    // 根据Pacifica价格数据格式处理
-    if (typeof data === 'object') {
-      Object.entries(data).forEach(([symbol, priceInfo]: [string, any]) => {
-        const marketData: MarketData = {
-          symbol,
-          price: parseFloat(priceInfo.price || '0'),
-          volume: parseFloat(priceInfo.volume_24h || '0'),
-          timestamp: Date.now(),
-        }
-        this.marketDataCache.set(symbol, marketData)
-        this.emit('price', marketData)
-      })
-    }
-  }
-
-  /**
-   * 处理订单簿更新
-   */
-  private handleOrderBookUpdate(data: any): void {
-    if (data.symbol) {
-      const orderBookData: OrderBookData = {
-        symbol: data.symbol,
-        bids: data.bids || [],
-        asks: data.asks || [],
-        timestamp: data.timestamp || Date.now(),
-      }
-      this.orderBookCache.set(data.symbol, orderBookData)
-      this.emit('orderbook', orderBookData)
-    }
-  }
-
-  /**
-   * 获取交易所信息(使用WebSocket请求替换HTTP GET /api/v1/info)
-   */
-  async getSymbols(): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      const response = await this.wsClient.sendRequest(
-        {
-          get_info: {},
-        },
-        15000,
-      )
-
-      if (response && response.data) {
-        return {
-          success: true,
-          data: response.data,
-        }
-      } else {
-        return {
-          success: false,
-          error: `获取交易所信息失败: ${response?.error || 'Unknown error'}`,
-        }
-      }
-    } catch (error: any) {
-      logger.error('WebSocket获取交易所信息失败', { error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 获取订单簿数据(使用WebSocket请求替换HTTP GET /api/v1/book)
-   */
-  async getOrderBook(symbol: string): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      const response = await this.wsClient.sendRequest(
-        {
-          get_orderbook: {
-            symbol: symbol,
-          },
-        },
-        10000,
-      )
-
-      if (response && response.data) {
-        const orderBookData: OrderBookData = {
-          symbol,
-          bids: response.data.bids || [],
-          asks: response.data.asks || [],
-          timestamp: Date.now(),
-        }
-
-        // 缓存订单簿数据
-        this.orderBookCache.set(symbol, orderBookData)
-        this.emit('orderbook', orderBookData)
-
-        return {
-          success: true,
-          data: response.data,
-        }
-      } else {
-        return {
-          success: false,
-          error: `获取订单簿失败: ${response?.error || 'Unknown error'}`,
-        }
-      }
-    } catch (error: any) {
-      logger.error('WebSocket获取订单簿失败', { symbol, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 获取价格数据(使用WebSocket订阅模式替换HTTP GET /api/v1/prices)
-   */
-  async getPrices(symbols?: string[]): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      // 启动价格订阅,数据将通过事件流实时推送
-      await this.wsClient.subscribePrices(symbols)
-
-      return {
-        success: true,
-        data: { message: '价格数据订阅已启动,数据将通过实时事件推送' },
-      }
-    } catch (error: any) {
-      logger.error('WebSocket订阅价格数据失败', { symbols, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 获取账户余额(使用WebSocket订阅模式替换HTTP GET /api/v1/account/balances)
-   */
-  async getBalances(account: string): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      // 启动账户余额订阅,数据将通过事件流实时推送
-      await this.wsClient.subscribeBalance(account)
-
-      return {
-        success: true,
-        data: { message: '账户余额订阅已启动,数据将通过实时事件推送' },
-      }
-    } catch (error: any) {
-      logger.error('WebSocket订阅账户余额失败', { account, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 获取账户仓位(使用WebSocket订阅模式替换HTTP GET /api/v1/account/positions)
-   */
-  async getPositions(account: string): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      // 启动账户仓位订阅,数据将通过事件流实时推送
-      await this.wsClient.subscribePositions(account)
-
-      return {
-        success: true,
-        data: { message: '账户仓位订阅已启动,数据将通过实时事件推送' },
-      }
-    } catch (error: any) {
-      logger.error('WebSocket订阅账户仓位失败', { account, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 下市价单(使用真正的Pacifica WebSocket API)
-   */
-  async placeMarketOrder(params: {
-    symbol: string
-    side: 'buy' | 'sell'
-    amount: string
-    account: string
-    signature: string
-    reduce_only?: boolean
-    slippage_percent?: string
-  }): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      const wsParams = {
-        account: params.account,
-        signature: params.signature,
-        timestamp: Date.now(),
-        symbol: params.symbol,
-        reduce_only: params.reduce_only || false,
-        amount: params.amount,
-        side: params.side === 'buy' ? 'bid' : ('ask' as 'bid' | 'ask'),
-        slippage_percent: params.slippage_percent || '0.5',
-        client_order_id: `market-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
-      }
-
-      const response = await this.wsClient.createMarketOrder(wsParams)
-
-      if (response && response.data) {
-        logger.info('WebSocket市价单下单成功', {
-          symbol: params.symbol,
-          side: params.side,
-          amount: params.amount,
-          orderId: response.data.i,
-          clientOrderId: response.data.I,
-        })
-
-        return {
-          success: true,
-          data: response.data,
-          orderId: response.data.i?.toString(),
-          status: 'filled',
-        }
-      } else {
-        logger.warn('WebSocket市价单下单失败', { params, response })
-
-        return {
-          success: false,
-          error: `下单失败: ${response?.error || 'Unknown error'}`,
-        }
-      }
-    } catch (error: any) {
-      logger.error('WebSocket市价单下单异常', { params, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 下限价单(使用真正的Pacifica WebSocket API)
-   */
-  async placeLimitOrder(params: {
-    symbol: string
-    side: 'buy' | 'sell'
-    amount: string
-    price: string
-    account: string
-    signature: string
-    reduce_only?: boolean
-  }): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      const wsParams = {
-        account: params.account,
-        signature: params.signature,
-        timestamp: Date.now(),
-        symbol: params.symbol,
-        reduce_only: params.reduce_only || false,
-        amount: params.amount,
-        side: params.side === 'buy' ? 'bid' : ('ask' as 'bid' | 'ask'),
-        price: params.price,
-        client_order_id: `limit-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
-      }
-
-      const response = await this.wsClient.createLimitOrder(wsParams)
-
-      if (response && response.data) {
-        logger.info('WebSocket限价单下单成功', {
-          symbol: params.symbol,
-          side: params.side,
-          amount: params.amount,
-          price: params.price,
-          orderId: response.data.i,
-          clientOrderId: response.data.I,
-        })
-
-        return {
-          success: true,
-          data: response.data,
-          orderId: response.data.i?.toString(),
-          status: 'open',
-        }
-      } else {
-        logger.warn('WebSocket限价单下单失败', { params, response })
-
-        return {
-          success: false,
-          error: `下单失败: ${response?.error || 'Unknown error'}`,
-        }
-      }
-    } catch (error: any) {
-      logger.error('WebSocket限价单下单异常', { params, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 取消订单(使用真正的Pacifica WebSocket API)
-   */
-  async cancelOrder(params: {
-    orderId: string
-    account: string
-    signature: string
-    clientOrderId?: string
-  }): Promise<TradingResponse> {
-    if (!this.isInitialized) {
-      await this.initialize()
-    }
-
-    try {
-      const wsParams = {
-        account: params.account,
-        signature: params.signature,
-        order_id: params.orderId,
-        client_order_id: params.clientOrderId,
-      }
-
-      const response = await this.wsClient.cancelOrder(wsParams)
-
-      if (response && response.data) {
-        logger.info('WebSocket取消订单成功', {
-          orderId: params.orderId,
-          result: response.data,
-        })
-
-        return {
-          success: true,
-          data: response.data,
-        }
-      } else {
-        logger.warn('WebSocket取消订单失败', { params, response })
-
-        return {
-          success: false,
-          error: `取消订单失败: ${response?.error || 'Unknown error'}`,
-        }
-      }
-    } catch (error: any) {
-      logger.error('WebSocket取消订单异常', { params, error: error.message })
-      return {
-        success: false,
-        error: error.message,
-      }
-    }
-  }
-
-  /**
-   * 订阅市场数据
-   */
-  async subscribeMarketData(symbols: string[]): Promise<void> {
-    symbols.forEach(symbol => {
-      if (!this.subscriptions.has(symbol)) {
-        this.subscriptions.add(symbol)
-        logger.debug(`订阅市场数据: ${symbol}`)
-      }
-    })
-  }
-
-  /**
-   * 取消订阅市场数据
-   */
-  async unsubscribeMarketData(symbols: string[]): Promise<void> {
-    symbols.forEach(symbol => {
-      if (this.subscriptions.has(symbol)) {
-        this.subscriptions.delete(symbol)
-        logger.debug(`取消订阅市场数据: ${symbol}`)
-      }
-    })
-  }
-
-  /**
-   * 获取缓存的市场数据
-   */
-  getCachedMarketData(symbol: string): MarketData | undefined {
-    return this.marketDataCache.get(symbol)
-  }
-
-  /**
-   * 获取缓存的订单簿数据
-   */
-  getCachedOrderBook(symbol: string): OrderBookData | undefined {
-    return this.orderBookCache.get(symbol)
-  }
-
-  /**
-   * 获取连接状态
-   */
-  isConnected(): boolean {
-    return this.wsClient.isConnectionOpen()
-  }
-
-  /**
-   * 获取等待队列长度
-   */
-  getQueueLength(): number {
-    return this.wsClient.getQueueLength()
-  }
-
-  /**
-   * 关闭连接
-   */
-  async close(): Promise<void> {
-    this.subscriptions.clear()
-    this.marketDataCache.clear()
-    this.orderBookCache.clear()
-    await this.wsClient.close()
-    this.isInitialized = false
-    logger.info('PacificaWebSocketAdapter已关闭')
-  }
-}

+ 0 - 364
src/adapters/exchanges/pacifica/PacificaWebSocketClient.ts

@@ -1,364 +0,0 @@
-import WebSocket from 'ws'
-import { HttpsProxyAgent } from 'https-proxy-agent'
-import { SocksProxyAgent } from 'socks-proxy-agent'
-import { EventEmitter } from 'events'
-import { logger } from '../shared/utils/logger'
-import { Config } from '../../config/simpleEnv'
-
-/**
- * Pacifica WebSocket 订阅消息格式
- */
-interface PacificaSubscribeMessage {
-  method: 'SUBSCRIBE' | 'UNSUBSCRIBE'
-  params: string[]
-  id: number
-}
-
-/**
- * Pacifica WebSocket 数据流消息格式
- */
-interface PacificaStreamMessage {
-  stream: string
-  data: any
-}
-
-/**
- * 订阅状态管理
- */
-interface SubscriptionState {
-  id: number
-  stream: string
-  account?: string
-  active: boolean
-}
-
-/**
- * Pacifica WebSocket 客户端 - 支持实时数据订阅
- * 基于 Pacifica 官方 WebSocket API 实现
- * 支持:价格订阅、订单簿订阅、账户余额订阅、仓位订阅等
- */
-export class PacificaWebSocketClient extends EventEmitter {
-  private ws: WebSocket | null = null
-  private proxyAgent: HttpsProxyAgent<string> | SocksProxyAgent | null = null
-  private isConnected = false
-  private reconnectAttempts = 0
-  private maxReconnectAttempts = 10
-  private reconnectDelay = 1000
-  private subscriptions = new Map<string, SubscriptionState>()
-  private subscriptionId = 1
-  private pingInterval: NodeJS.Timeout | null = null
-
-  constructor(
-    private wsUrl: string = 'wss://ws.pacifica.fi/ws',
-    private accountId?: string,
-    private privateKey?: string,
-  ) {
-    super()
-    this.initializeProxy()
-  }
-
-  /**
-   * 初始化代理配置
-   */
-  private initializeProxy(): void {
-    if (!Config.proxy.enabled()) {
-      return
-    }
-
-    try {
-      // 构建代理配置
-      const protocol = Config.proxy.protocol() || 'http'
-      const host = Config.proxy.host()
-      const port = Config.proxy.port()
-      const username = Config.proxy.username()
-      const password = Config.proxy.buildPassword('pacifica') || Config.proxy.buildPassword()
-
-      if (host && port) {
-        let proxyUrl = `${protocol}://`
-        if (username && password) {
-          proxyUrl += `${encodeURIComponent(username)}:${encodeURIComponent(password)}@`
-        }
-        proxyUrl += `${host}:${port}`
-
-        if (protocol === 'socks5') {
-          this.proxyAgent = new SocksProxyAgent(proxyUrl)
-        } else {
-          this.proxyAgent = new HttpsProxyAgent(proxyUrl)
-        }
-
-        logger.info('Pacifica WebSocket代理已配置', {
-          protocol,
-          host,
-          port,
-          hasAuth: !!(username && password),
-        })
-      } else {
-        logger.warn('代理配置不完整,跳过代理设置')
-      }
-    } catch (error: any) {
-      logger.error('代理配置失败', { error: error.message })
-    }
-  }
-
-  /**
-   * 连接 WebSocket
-   */
-  async connect(): Promise<void> {
-    return new Promise((resolve, reject) => {
-      try {
-        const wsOptions: any = {}
-
-        if (this.proxyAgent) {
-          // 检测IPRoyal代理,强制使用HTTP协议
-          const proxyHost = Config.proxy.host() || ''
-          if (proxyHost.includes('iproyal.com')) {
-            logger.info('检测到IPRoyal代理,使用HTTP协议进行WebSocket连接')
-            wsOptions.agent = this.proxyAgent
-          } else {
-            wsOptions.agent = this.proxyAgent
-          }
-        }
-
-        this.ws = new WebSocket(this.wsUrl, wsOptions)
-
-        this.ws.on('open', () => {
-          this.isConnected = true
-          this.reconnectAttempts = 0
-          logger.info('✅ Pacifica WebSocket连接成功')
-          this.startPingPong()
-          resolve()
-        })
-
-        this.ws.on('message', (data: WebSocket.Data) => {
-          try {
-            const message = JSON.parse(data.toString())
-            this.handleMessage(message)
-          } catch (error: any) {
-            logger.error('解析WebSocket消息失败', { error: error.message })
-          }
-        })
-
-        this.ws.on('close', (code: number, reason: Buffer) => {
-          this.isConnected = false
-          this.stopPingPong()
-          logger.warn('Pacifica WebSocket连接关闭', { code, reason: reason.toString() })
-
-          if (this.reconnectAttempts < this.maxReconnectAttempts) {
-            this.scheduleReconnect()
-          }
-        })
-
-        this.ws.on('error', (error: Error) => {
-          logger.error('Pacifica WebSocket连接错误', { error: error.message })
-          reject(error)
-        })
-      } catch (error: any) {
-        logger.error('WebSocket连接失败', { error: error.message })
-        reject(error)
-      }
-    })
-  }
-
-  /**
-   * 处理接收到的消息
-   */
-  private handleMessage(message: any): void {
-    // 处理订阅确认消息
-    if (message.result && message.id) {
-      logger.debug('订阅确认', { id: message.id, result: message.result })
-      return
-    }
-
-    // 处理数据流消息
-    if (message.stream && message.data) {
-      const streamMessage = message as PacificaStreamMessage
-      this.emit('data', streamMessage)
-
-      // 根据流类型触发特定事件
-      if (streamMessage.stream.startsWith('prices@')) {
-        this.emit('prices', streamMessage.data)
-      } else if (streamMessage.stream.startsWith('orderbook@')) {
-        this.emit('orderbook', streamMessage.data)
-      } else if (streamMessage.stream.startsWith('balance@')) {
-        this.emit('balance', streamMessage.data)
-      } else if (streamMessage.stream.startsWith('positions@')) {
-        this.emit('positions', streamMessage.data)
-      } else if (streamMessage.stream.startsWith('orders@')) {
-        this.emit('orders', streamMessage.data)
-      }
-    }
-  }
-
-  /**
-   * 订阅价格数据
-   */
-  async subscribePrices(symbols?: string[]): Promise<void> {
-    const stream = symbols && symbols.length > 0 ? `prices@${symbols.join(',')}` : 'prices@all'
-    await this.subscribe([stream])
-  }
-
-  /**
-   * 订阅订单簿数据
-   */
-  async subscribeOrderBook(symbol: string): Promise<void> {
-    await this.subscribe([`orderbook@${symbol}`])
-  }
-
-  /**
-   * 订阅账户余额(需要认证)
-   */
-  async subscribeBalance(account?: string): Promise<void> {
-    const targetAccount = account || this.accountId
-    if (!targetAccount) {
-      throw new Error('账户ID是订阅余额所必需的')
-    }
-    await this.subscribe([`balance@${targetAccount}`])
-  }
-
-  /**
-   * 订阅账户仓位(需要认证)
-   */
-  async subscribePositions(account?: string): Promise<void> {
-    const targetAccount = account || this.accountId
-    if (!targetAccount) {
-      throw new Error('账户ID是订阅仓位所必需的')
-    }
-    await this.subscribe([`positions@${targetAccount}`])
-  }
-
-  /**
-   * 订阅订单更新(需要认证)
-   */
-  async subscribeOrders(account?: string): Promise<void> {
-    const targetAccount = account || this.accountId
-    if (!targetAccount) {
-      throw new Error('账户ID是订阅订单所必需的')
-    }
-    await this.subscribe([`orders@${targetAccount}`])
-  }
-
-  /**
-   * 通用订阅方法
-   */
-  private async subscribe(streams: string[]): Promise<void> {
-    if (!this.isConnected) {
-      throw new Error('WebSocket未连接')
-    }
-
-    const subscribeMessage: PacificaSubscribeMessage = {
-      method: 'SUBSCRIBE',
-      params: streams,
-      id: this.subscriptionId++,
-    }
-
-    // 记录订阅状态
-    streams.forEach(stream => {
-      this.subscriptions.set(stream, {
-        id: subscribeMessage.id,
-        stream,
-        active: true,
-      })
-    })
-
-    this.ws?.send(JSON.stringify(subscribeMessage))
-    logger.info('发送订阅请求', { streams, id: subscribeMessage.id })
-  }
-
-  /**
-   * 取消订阅
-   */
-  async unsubscribe(streams: string[]): Promise<void> {
-    if (!this.isConnected) {
-      return
-    }
-
-    const unsubscribeMessage: PacificaSubscribeMessage = {
-      method: 'UNSUBSCRIBE',
-      params: streams,
-      id: this.subscriptionId++,
-    }
-
-    // 更新订阅状态
-    streams.forEach(stream => {
-      this.subscriptions.delete(stream)
-    })
-
-    this.ws?.send(JSON.stringify(unsubscribeMessage))
-    logger.info('发送取消订阅请求', { streams, id: unsubscribeMessage.id })
-  }
-
-  /**
-   * 启动心跳检测
-   */
-  private startPingPong(): void {
-    this.pingInterval = setInterval(() => {
-      if (this.ws && this.isConnected) {
-        this.ws.ping()
-      }
-    }, 30000) // 每30秒发送一次ping
-  }
-
-  /**
-   * 停止心跳检测
-   */
-  private stopPingPong(): void {
-    if (this.pingInterval) {
-      clearInterval(this.pingInterval)
-      this.pingInterval = null
-    }
-  }
-
-  /**
-   * 安排重连
-   */
-  private scheduleReconnect(): void {
-    this.reconnectAttempts++
-    const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000)
-
-    logger.info(`尝试重连Pacifica WebSocket (${this.reconnectAttempts}/${this.maxReconnectAttempts}) 延迟: ${delay}ms`)
-
-    setTimeout(async () => {
-      try {
-        await this.connect()
-
-        // 重新订阅之前的流
-        const activeStreams = Array.from(this.subscriptions.keys())
-        if (activeStreams.length > 0) {
-          await this.subscribe(activeStreams)
-        }
-      } catch (error: any) {
-        logger.error('重连失败', { error: error.message })
-      }
-    }, delay)
-  }
-
-  /**
-   * 获取连接状态
-   */
-  isConnectionOpen(): boolean {
-    return this.isConnected && this.ws?.readyState === WebSocket.OPEN
-  }
-
-  /**
-   * 获取活跃订阅列表
-   */
-  getActiveSubscriptions(): string[] {
-    return Array.from(this.subscriptions.keys())
-  }
-
-  /**
-   * 关闭连接
-   */
-  async close(): Promise<void> {
-    this.stopPingPong()
-    this.subscriptions.clear()
-
-    if (this.ws) {
-      this.ws.close()
-      this.ws = null
-    }
-
-    this.isConnected = false
-    logger.info('Pacifica WebSocket连接已关闭')
-  }
-}

+ 0 - 52
src/adapters/exchanges/pacifica/RestAdapter.ts

@@ -1,52 +0,0 @@
-import { PacificaClient } from './PacificaClient'
-
-export class PacificaRestAdapter {
-  constructor(private client: PacificaClient) {}
-
-  async getPrices() {
-    const response = await this.client.getPublic<any>('/api/v1/info/prices')
-    const data = response?.data ?? response
-    return Array.isArray(data) ? data : []
-  }
-
-  async getFundingHistory(params: { symbol: string; limit?: number; offset?: number }) {
-    const { symbol, limit, offset } = params
-    const qs = [`symbol=${symbol}`]
-    if (limit !== undefined) qs.push(`limit=${limit}`)
-    if (offset !== undefined) qs.push(`offset=${offset}`)
-    const response = await this.client.getPublic<any>(`/api/v1/funding_rate/history?${qs.join('&')}`)
-    const data = response?.data ?? response
-    return Array.isArray(data) ? data : []
-  }
-
-  async getMarketInfo(symbol?: string) {
-    const response = await this.client.getPublic<any>(this.client.endpoints.symbols)
-    const data = response?.data ?? response
-    if (!Array.isArray(data)) return data
-    return symbol ? data.find(item => String(item.symbol) === symbol) : data
-  }
-
-  async getOrderBook(params: { symbol: string; aggLevel?: number }) {
-    const url = `${this.client.endpoints.depth}?symbol=${params.symbol}&agg_level=${params.aggLevel ?? 1}`
-    const response = await this.client.getPublic<any>(url)
-    const payload = response?.data ?? response
-    return {
-      symbol: payload?.s,
-      bids: Array.isArray(payload?.l?.[0])
-        ? payload.l[0].map((lvl: any) => ({
-            price: String(lvl?.p ?? ''),
-            amount: String(lvl?.a ?? ''),
-            count: lvl?.n ?? 0,
-          }))
-        : [],
-      asks: Array.isArray(payload?.l?.[1])
-        ? payload.l[1].map((lvl: any) => ({
-            price: String(lvl?.p ?? ''),
-            amount: String(lvl?.a ?? ''),
-            count: lvl?.n ?? 0,
-          }))
-        : [],
-      timestamp: Number(payload?.t ?? Date.now()),
-    }
-  }
-}

+ 0 - 2
src/adapters/exchanges/pacifica/types.d.ts

@@ -1,2 +0,0 @@
-declare module 'tweetnacl'
-declare module 'bs58'

+ 0 - 147
src/adapters/exchanges/unifiedEvents.ts

@@ -1,147 +0,0 @@
-// 统一账户类 WS 事件与归一化工具(Aster → Unified)
-
-export interface UnifiedBalanceItem {
-  asset: string // 资产代码,如 USDT
-  total: string // 总额(字符串避免精度问题)
-  free: string // 可用(若无法区分,则等同 total)
-}
-
-export interface UnifiedBalancesEvent {
-  channel: 'account_balance'
-  data: UnifiedBalanceItem[]
-  ts?: number
-}
-
-export interface UnifiedPositionItem {
-  symbol: string // 交易对,如 BTCUSDT
-  side: 'LONG' | 'SHORT' // 方向
-  qty: string // 持仓数量
-  entryPrice?: string // 开仓均价
-  unrealizedPnl?: string // 未实现盈亏
-  leverage?: string // 杠杆(若可用)
-  marginType?: 'cross' | 'isolated' // 保证金模式(若可用)
-}
-
-export interface UnifiedPositionsEvent {
-  channel: 'account_positions'
-  data: UnifiedPositionItem[]
-  ts?: number
-}
-
-export interface UnifiedAccountInfoData {
-  ae?: string // accountEquity
-  mu?: string // marginUsed
-  pc?: number // position count
-  oc?: number // open order count
-  sc?: number // stop count
-  as?: string // assets remark/aggregation
-  aw?: string // alert warning / ratio
-  t: number // timestamp (ms)
-}
-
-export interface UnifiedAccountInfoEvent {
-  channel: 'account_info'
-  data: UnifiedAccountInfoData
-  ts?: number
-}
-
-export interface UnifiedOrderEventData {
-  id: string // 订单 ID
-  symbol: string
-  side: 'BUY' | 'SELL'
-  type: string // MARKET / LIMIT / ...
-  status: string // NEW / FILLED / CANCELED ...
-  price?: string // 报价
-  avgPrice?: string // 成交均价
-  origQty?: string // 原始数量
-  executedQty?: string // 已成交数量
-  updateTime?: number // 更新时间(毫秒)
-  positionSide?: 'LONG' | 'SHORT' | 'BOTH'
-  reduceOnly?: boolean
-  raw?: any // 保留原始字段
-}
-
-export interface UnifiedOrdersEvent {
-  channel: 'orders'
-  data: UnifiedOrderEventData
-  ts?: number
-}
-
-export type UnifiedAccountWsEvent =
-  | UnifiedBalancesEvent
-  | UnifiedPositionsEvent
-  | UnifiedAccountInfoEvent
-  | UnifiedOrdersEvent
-
-// ===== Aster → Unified =====
-
-// Aster balance: 来自 ACCOUNT_UPDATE 的 a.B 项:{ a, wb, cw, bc }
-export function normalizeAsterBalanceEvent(ev: any): UnifiedBalancesEvent {
-  const ts = typeof ev?.ts === 'number' ? ev.ts : typeof ev?.E === 'number' ? ev.E : Date.now()
-  const arr = Array.isArray(ev?.data) ? ev.data : Array.isArray(ev) ? ev : []
-  const items: UnifiedBalanceItem[] = arr.map((b: any) => {
-    const asset = String(b?.a ?? b?.asset ?? '').toUpperCase()
-    const total = String(b?.wb ?? b?.total ?? b?.balance ?? '0')
-    const free = String(b?.cw ?? b?.free ?? total)
-    return { asset, total, free }
-  })
-  return { channel: 'account_balance', data: items, ts }
-}
-
-// Aster positions: 来自 ACCOUNT_UPDATE 的 a.P 项,形如 { s, pa, ep, up, mt, ps }
-export function normalizeAsterPositionsEvent(ev: any): UnifiedPositionsEvent {
-  const ts = typeof ev?.ts === 'number' ? ev.ts : typeof ev?.E === 'number' ? ev.E : Date.now()
-  const arr = Array.isArray(ev?.data) ? ev.data : Array.isArray(ev) ? ev : []
-  const items: UnifiedPositionItem[] = []
-  for (const p of arr) {
-    const symbol = String(p?.s ?? p?.symbol ?? '').toUpperCase()
-    const side = String(p?.ps ?? p?.positionSide ?? '').toUpperCase()
-    if (!symbol) continue
-    if (side !== 'LONG' && side !== 'SHORT') continue // 过滤 BOTH 的记录
-    const qty = String(p?.pa ?? p?.positionAmt ?? p?.qty ?? '0')
-    const entryPrice = p?.ep != null ? String(p.ep) : p?.entryPrice != null ? String(p.entryPrice) : undefined
-    const unrealizedPnl = p?.up != null ? String(p.up) : p?.unrealizedPnl != null ? String(p.unrealizedPnl) : undefined
-    const marginType = p?.mt === 'cross' ? 'cross' : p?.mt === 'isolated' ? 'isolated' : undefined
-    items.push({ symbol, side: side as any, qty, entryPrice, unrealizedPnl, marginType })
-  }
-  return { channel: 'account_positions', data: items, ts }
-}
-
-// Aster account_info: 我们可能只有 pc/t,可按可用字段填充
-export function normalizeAsterAccountInfoEvent(ev: any): UnifiedAccountInfoEvent {
-  const ts = typeof ev?.ts === 'number' ? ev.ts : typeof ev?.E === 'number' ? ev.E : Date.now()
-  const d = ev?.data !== undefined ? ev.data : ev || {}
-  const out: UnifiedAccountInfoData = {
-    ae: d?.ae != null ? String(d.ae) : undefined,
-    mu: d?.mu != null ? String(d.mu) : undefined,
-    pc: d?.pc != null ? Number(d.pc) : undefined,
-    oc: d?.oc != null ? Number(d.oc) : undefined,
-    sc: d?.sc != null ? Number(d.sc) : undefined,
-    as: d?.as != null ? String(d.as) : undefined,
-    aw: d?.aw != null ? String(d.aw) : undefined,
-    t: d?.t != null ? Number(d.t) : ts,
-  }
-  return { channel: 'account_info', data: out, ts }
-}
-
-// Aster orders: 来自 ORDER_TRADE_UPDATE 的 o 字段
-export function normalizeAsterOrdersEvent(ev: any): UnifiedOrdersEvent {
-  const ts = typeof ev?.ts === 'number' ? ev.ts : typeof ev?.E === 'number' ? ev.E : Date.now()
-  const o = ev?.data !== undefined ? ev.data : (ev?.o ?? ev) || {}
-  const data: UnifiedOrderEventData = {
-    id: String(o?.i ?? o?.orderId ?? ''),
-    symbol: String(o?.s ?? o?.symbol ?? '').toUpperCase(),
-    side: (o?.S ?? o?.side ?? '').toUpperCase(),
-    type: o?.o ?? o?.type ?? '',
-    status: o?.X ?? o?.status ?? '',
-    price: o?.p != null ? String(o.p) : o?.price != null ? String(o.price) : undefined,
-    avgPrice: o?.ap != null ? String(o.ap) : o?.avgPrice != null ? String(o.avgPrice) : undefined,
-    origQty: o?.q != null ? String(o.q) : o?.origQty != null ? String(o.origQty) : undefined,
-    executedQty: o?.z != null ? String(o.z) : o?.executedQty != null ? String(o.executedQty) : undefined,
-    updateTime: o?.T != null ? Number(o.T) : o?.updateTime != null ? Number(o.updateTime) : undefined,
-    positionSide: o?.ps as any,
-    reduceOnly: Boolean(o?.R),
-    raw: o,
-  } as UnifiedOrderEventData
-  return { channel: 'orders', data, ts }
-}

+ 0 - 37
src/adapters/infrastructure/config/configManager.ts

@@ -1,37 +0,0 @@
-import 'dotenv/config'
-
-export interface AppConfig {
-  NODE_ENV: string
-  RPC_URL?: string
-  PRIVATE_KEY?: string
-  REDIS_URL?: string
-  PG_URL?: string
-  TELEGRAM_BOT_TOKEN?: string
-  TELEGRAM_CHAT_ID?: string
-}
-
-class ConfigManager {
-  private config: AppConfig
-
-  constructor() {
-    this.config = {
-      NODE_ENV: process.env.NODE_ENV || 'development',
-      RPC_URL: process.env.RPC_URL,
-      PRIVATE_KEY: process.env.PRIVATE_KEY,
-      REDIS_URL: process.env.REDIS_URL,
-      PG_URL: process.env.PG_URL,
-      TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN,
-      TELEGRAM_CHAT_ID: process.env.TELEGRAM_CHAT_ID,
-    }
-  }
-
-  get<T extends keyof AppConfig>(key: T): AppConfig[T] {
-    return this.config[key]
-  }
-
-  getAll(): AppConfig {
-    return { ...this.config }
-  }
-}
-
-export const configManager = new ConfigManager()

+ 0 - 31
src/adapters/infrastructure/config/default.example.yaml

@@ -1,31 +0,0 @@
-networks:
-  arbitrum:
-    chainId: 42161
-    rpcUrl: ${RPC_URL}
-    explorerUrl: https://arbiscan.io
-    gasPrice: 0
-
-apis:
-  chainlink:
-    feeds:
-      BTCUSDT: '0x0000000000000000000000000000000000000000'
-
-risk:
-  maxLeverage: 5
-  maxPositionSize: 100000
-  maxDrawdown: 0.05
-  minMarginRatio: 0.1
-  maxSlippage: 0.003
-
-trading:
-  defaultSlippage: 0.001
-  minOrderValue: 10
-  maxOrderValue: 100000
-  rebalanceInterval: 60
-  hedgeThreshold: 0.01
-
-monitoring:
-  alertCooldown: 30
-  metricsInterval: 10
-  healthCheckInterval: 15
-  logLevel: info

+ 0 - 14
src/adapters/infrastructure/database/index.ts

@@ -1,14 +0,0 @@
-export interface Db {
-  connected: boolean
-}
-
-class Database implements Db {
-  connected = false
-
-  async connect(): Promise<void> {
-    // TODO: 集成 Sequelize/Prisma
-    this.connected = true
-  }
-}
-
-export const db = new Database()

+ 0 - 239
src/adapters/infrastructure/health/HealthAPI.ts

@@ -1,239 +0,0 @@
-import { createServer, IncomingMessage, ServerResponse } from 'http'
-import { URL } from 'url'
-import { HealthChecker, SystemHealth } from './HealthChecker'
-
-export interface HealthAPIConfig {
-  port: number
-  host?: string
-  enableDetailedResponse?: boolean
-}
-
-export class HealthAPI {
-  private server: ReturnType<typeof createServer>
-  private healthChecker: HealthChecker
-  private config: HealthAPIConfig
-
-  constructor(healthChecker: HealthChecker, config: HealthAPIConfig) {
-    this.healthChecker = healthChecker
-    this.config = {
-      host: 'localhost',
-      enableDetailedResponse: true,
-      ...config,
-    }
-
-    this.server = createServer(this.handleRequest.bind(this))
-  }
-
-  /**
-   * 启动健康检查 API 服务器
-   */
-  async start(): Promise<void> {
-    return new Promise((resolve, reject) => {
-      this.server.listen(this.config.port, this.config.host, () => {
-        console.log(`🏥 健康检查 API 服务启动: http://${this.config.host}:${this.config.port}`)
-        resolve()
-      })
-
-      this.server.on('error', error => {
-        console.error('健康检查 API 服务器错误:', error)
-        reject(error)
-      })
-    })
-  }
-
-  /**
-   * 停止健康检查 API 服务器
-   */
-  async stop(): Promise<void> {
-    return new Promise(resolve => {
-      this.server.close(() => {
-        console.log('🏥 健康检查 API 服务已停止')
-        resolve()
-      })
-    })
-  }
-
-  /**
-   * 处理 HTTP 请求
-   */
-  private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    // 设置 CORS 头
-    res.setHeader('Access-Control-Allow-Origin', '*')
-    res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')
-    res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
-    res.setHeader('Content-Type', 'application/json')
-
-    // 处理 OPTIONS 请求
-    if (req.method === 'OPTIONS') {
-      res.statusCode = 200
-      res.end()
-      return
-    }
-
-    // 只支持 GET 请求
-    if (req.method !== 'GET') {
-      res.statusCode = 405
-      res.end(JSON.stringify({ error: 'Method not allowed' }))
-      return
-    }
-
-    try {
-      const url = new URL(req.url!, `http://${req.headers.host}`)
-      const path = url.pathname
-
-      switch (path) {
-        case '/health':
-          await this.handleHealthCheck(req, res)
-          break
-        case '/health/summary':
-          await this.handleHealthSummary(req, res)
-          break
-        case '/health/live':
-          await this.handleLivenessCheck(req, res)
-          break
-        case '/health/ready':
-          await this.handleReadinessCheck(req, res)
-          break
-        default:
-          res.statusCode = 404
-          res.end(
-            JSON.stringify({
-              error: 'Not found',
-              availableEndpoints: ['/health', '/health/summary', '/health/live', '/health/ready'],
-            }),
-          )
-      }
-    } catch (error: any) {
-      console.error('健康检查 API 处理错误:', error)
-      res.statusCode = 500
-      res.end(JSON.stringify({ error: 'Internal server error' }))
-    }
-  }
-
-  /**
-   * 处理完整健康检查请求
-   */
-  private async handleHealthCheck(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    const health = await this.healthChecker.performHealthCheck()
-
-    // 根据健康状态设置 HTTP 状态码
-    switch (health.status) {
-      case 'healthy':
-        res.statusCode = 200
-        break
-      case 'degraded':
-        res.statusCode = 200 // 或者 206 Partial Content
-        break
-      case 'unhealthy':
-        res.statusCode = 503 // Service Unavailable
-        break
-    }
-
-    if (this.config.enableDetailedResponse) {
-      res.end(JSON.stringify(health, null, 2))
-    } else {
-      res.end(
-        JSON.stringify({
-          status: health.status,
-          timestamp: health.timestamp,
-          uptime: health.uptime,
-        }),
-      )
-    }
-  }
-
-  /**
-   * 处理健康检查摘要请求
-   */
-  private async handleHealthSummary(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    const summary = this.healthChecker.getHealthSummary()
-
-    res.statusCode = summary.status === 'healthy' ? 200 : 503
-    res.end(JSON.stringify(summary, null, 2))
-  }
-
-  /**
-   * 处理存活性检查 (Liveness Probe)
-   * 检查应用程序是否还在运行
-   */
-  private async handleLivenessCheck(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    // 简单检查:如果能响应请求,就说明应用程序是存活的
-    const response = {
-      status: 'alive',
-      timestamp: new Date().toISOString(),
-      uptime: process.uptime(),
-      pid: process.pid,
-    }
-
-    res.statusCode = 200
-    res.end(JSON.stringify(response))
-  }
-
-  /**
-   * 处理就绪性检查 (Readiness Probe)
-   * 检查应用程序是否准备好接收流量
-   */
-  private async handleReadinessCheck(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    const lastHealthCheck = this.healthChecker.getLastHealthCheck()
-
-    if (!lastHealthCheck) {
-      res.statusCode = 503
-      res.end(
-        JSON.stringify({
-          status: 'not_ready',
-          reason: '尚未完成初始健康检查',
-        }),
-      )
-      return
-    }
-
-    // 检查是否准备好
-    const isReady = this.isSystemReady(lastHealthCheck)
-
-    res.statusCode = isReady ? 200 : 503
-    res.end(
-      JSON.stringify({
-        status: isReady ? 'ready' : 'not_ready',
-        timestamp: lastHealthCheck.timestamp,
-        exchanges: Object.keys(lastHealthCheck.exchanges).length,
-        accounts: Object.keys(lastHealthCheck.accounts).length,
-        overallHealth: lastHealthCheck.status,
-      }),
-    )
-  }
-
-  /**
-   * 判断系统是否就绪
-   */
-  private isSystemReady(health: SystemHealth): boolean {
-    // 至少需要有一个健康的交易所连接
-    const healthyExchanges = Object.values(health.exchanges).filter(ex => ex.status !== 'unhealthy')
-    if (healthyExchanges.length === 0) {
-      return false
-    }
-
-    // 系统整体状态不能是不健康
-    if (health.status === 'unhealthy') {
-      return false
-    }
-
-    // 内存使用不能超过 95%
-    const memoryUsage = (health.memory.used / health.memory.total) * 100
-    if (memoryUsage > 95) {
-      return false
-    }
-
-    return true
-  }
-
-  /**
-   * 获取服务器信息
-   */
-  getServerInfo() {
-    return {
-      host: this.config.host,
-      port: this.config.port,
-      running: this.server.listening,
-    }
-  }
-}

+ 0 - 321
src/adapters/infrastructure/health/HealthChecker.ts

@@ -1,321 +0,0 @@
-import { EventEmitter } from 'events'
-import { ExchangeAdapter } from '../adapters/exchanges/ExchangeAdapter'
-
-export interface ExchangeHealth {
-  status: 'healthy' | 'degraded' | 'unhealthy'
-  connected: boolean
-  lastPing?: number
-  errorCount: number
-  lastError?: string
-}
-
-export interface AccountHealth {
-  status: 'healthy' | 'degraded' | 'unhealthy'
-  exchange: string
-  accountId: string
-  balanceAccessible: boolean
-  lastUpdate?: Date
-  lastError?: string
-  errorCount: number
-}
-
-export interface SystemHealth {
-  status: 'healthy' | 'degraded' | 'unhealthy'
-  timestamp: Date
-  uptime: number
-  exchanges: Record<string, ExchangeHealth>
-  accounts: Record<string, AccountHealth>
-  memory: {
-    used: number
-    free: number
-    total: number
-  }
-  errors: {
-    total: number
-    lastHour: number
-  }
-}
-
-export class HealthChecker extends EventEmitter {
-  private exchanges = new Map<string, ExchangeAdapter>()
-  private accountManagers = new Map<string, any>()
-  private startTime = Date.now()
-  private errorCounts = new Map<string, number>()
-  private lastHealthCheck: SystemHealth | null = null
-
-  constructor() {
-    super()
-    // 定期健康检查
-    setInterval(() => {
-      this.performHealthCheck().catch(console.error)
-    }, 30000) // 每30秒检查一次
-  }
-
-  /**
-   * 注册交易所适配器用于健康检查
-   */
-  registerExchange(name: string, adapter: ExchangeAdapter): void {
-    this.exchanges.set(name, adapter)
-
-    // 如果适配器支持事件监听,则注册错误处理
-    if (typeof (adapter as any).on === 'function') {
-      ;(adapter as any)
-        .on('error', (error: any) => {
-          this.recordError(`exchange:${name}`, error)
-        })(adapter as any)
-        .on('disconnect', () => {
-          this.emit('exchange_disconnected', { exchange: name })
-        })(adapter as any)
-        .on('connect', () => {
-          this.emit('exchange_connected', { exchange: name })
-        })
-    }
-  }
-
-  /**
-   * 注册账户管理器用于健康检查
-   */
-  registerAccountManager(name: string, manager: any): void {
-    this.accountManagers.set(name, manager)
-  }
-
-  /**
-   * 执行完整的系统健康检查
-   */
-  async performHealthCheck(): Promise<SystemHealth> {
-    const health: SystemHealth = {
-      status: 'healthy',
-      timestamp: new Date(),
-      uptime: Date.now() - this.startTime,
-      exchanges: {},
-      accounts: {},
-      memory: this.getMemoryUsage(),
-      errors: {
-        total: this.getTotalErrors(),
-        lastHour: this.getRecentErrors(),
-      },
-    }
-
-    // 检查交易所健康状态
-    for (const [name, adapter] of this.exchanges.entries()) {
-      health.exchanges[name] = await this.checkExchangeHealth(name, adapter)
-    }
-
-    // 检查账户健康状态
-    for (const [name, manager] of this.accountManagers.entries()) {
-      const accounts = await this.checkAccountHealth(name, manager)
-      Object.assign(health.accounts, accounts)
-    }
-
-    // 确定整体健康状态
-    health.status = this.determineOverallHealth(health)
-    this.lastHealthCheck = health
-
-    // 发出健康状态变化事件
-    this.emit('health_check', health)
-
-    if (health.status === 'unhealthy') {
-      this.emit('system_unhealthy', health)
-    }
-
-    return health
-  }
-
-  /**
-   * 检查单个交易所健康状态
-   */
-  private async checkExchangeHealth(name: string, adapter: ExchangeAdapter): Promise<ExchangeHealth> {
-    const health: ExchangeHealth = {
-      status: 'healthy',
-      connected: false,
-      errorCount: this.errorCounts.get(`exchange:${name}`) || 0,
-    }
-
-    try {
-      // 检查连接状态
-      const startTime = Date.now()
-
-      // 尝试获取基础信息来测试连接
-      if (typeof (adapter as any).ping === 'function') {
-        await (adapter as any).ping()
-        health.lastPing = Date.now() - startTime
-      } else {
-        // 如果没有 ping 方法,尝试获取时间或其他轻量级操作
-        await Promise.race([
-          (adapter as any).time?.() || Promise.resolve(),
-          new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000)),
-        ])
-      }
-
-      health.connected = true
-
-      // 根据延迟和错误数量判断状态
-      if (health.lastPing && health.lastPing > 2000) {
-        health.status = 'degraded'
-      } else if (health.errorCount > 10) {
-        health.status = 'degraded'
-      }
-    } catch (error: any) {
-      health.connected = false
-      health.status = 'unhealthy'
-      health.lastError = error.message
-      this.recordError(`exchange:${name}`, error)
-    }
-
-    return health
-  }
-
-  /**
-   * 检查账户健康状态
-   */
-  private async checkAccountHealth(managerName: string, manager: any): Promise<Record<string, AccountHealth>> {
-    const accountsHealth: Record<string, AccountHealth> = {}
-
-    try {
-      // 如果账户管理器有 getRegisteredAccounts 方法
-      if (typeof manager.getRegisteredAccounts === 'function') {
-        const accounts = manager.getRegisteredAccounts()
-
-        for (const account of accounts) {
-          const accountKey = `${account.exchange}:${account.accountId}`
-          accountsHealth[accountKey] = {
-            status: 'healthy',
-            exchange: account.exchange,
-            accountId: account.accountId,
-            balanceAccessible: false,
-            errorCount: this.errorCounts.get(`account:${accountKey}`) || 0,
-          }
-
-          try {
-            // 尝试获取余额来测试账户可用性
-            if (typeof manager.getBalances === 'function') {
-              await manager.getBalances(account.exchange, account.accountId)
-              accountsHealth[accountKey].balanceAccessible = true
-              accountsHealth[accountKey].lastUpdate = new Date()
-            }
-          } catch (error: any) {
-            accountsHealth[accountKey].status = 'degraded'
-            accountsHealth[accountKey].lastError = error.message
-            this.recordError(`account:${accountKey}`, error)
-          }
-        }
-      }
-    } catch (error: any) {
-      // 如果无法获取账户列表,记录错误
-      this.recordError(`manager:${managerName}`, error)
-    }
-
-    return accountsHealth
-  }
-
-  /**
-   * 确定整体健康状态
-   */
-  private determineOverallHealth(health: SystemHealth): 'healthy' | 'degraded' | 'unhealthy' {
-    const exchangeStatuses = Object.values(health.exchanges)
-    const accountStatuses = Object.values(health.accounts)
-
-    // 如果有任何交易所不健康,系统不健康
-    if (exchangeStatuses.some(ex => ex.status === 'unhealthy')) {
-      return 'unhealthy'
-    }
-
-    // 如果有超过50%的账户不健康,系统不健康
-    const unhealthyAccounts = accountStatuses.filter(acc => acc.status === 'unhealthy').length
-    if (unhealthyAccounts > accountStatuses.length * 0.5) {
-      return 'unhealthy'
-    }
-
-    // 如果有任何服务降级,系统降级
-    if (
-      exchangeStatuses.some(ex => ex.status === 'degraded') ||
-      accountStatuses.some(acc => acc.status === 'degraded')
-    ) {
-      return 'degraded'
-    }
-
-    // 检查内存使用情况
-    const memoryUsagePercent = (health.memory.used / health.memory.total) * 100
-    if (memoryUsagePercent > 90) {
-      return 'unhealthy'
-    } else if (memoryUsagePercent > 80) {
-      return 'degraded'
-    }
-
-    return 'healthy'
-  }
-
-  /**
-   * 记录错误
-   */
-  private recordError(component: string, error: any): void {
-    const current = this.errorCounts.get(component) || 0
-    this.errorCounts.set(component, current + 1)
-
-    console.error(`健康检查错误 [${component}]:`, error.message)
-  }
-
-  /**
-   * 获取内存使用情况
-   */
-  private getMemoryUsage() {
-    const usage = process.memoryUsage()
-    return {
-      used: usage.heapUsed,
-      free: usage.heapTotal - usage.heapUsed,
-      total: usage.heapTotal,
-    }
-  }
-
-  /**
-   * 获取总错误数
-   */
-  private getTotalErrors(): number {
-    return Array.from(this.errorCounts.values()).reduce((sum, count) => sum + count, 0)
-  }
-
-  /**
-   * 获取最近一小时的错误数 (简化实现)
-   */
-  private getRecentErrors(): number {
-    // 这里简化实现,实际应该基于时间窗口统计
-    return Math.floor(this.getTotalErrors() * 0.1)
-  }
-
-  /**
-   * 获取最后一次健康检查结果
-   */
-  getLastHealthCheck(): SystemHealth | null {
-    return this.lastHealthCheck
-  }
-
-  /**
-   * 检查特定组件是否健康
-   */
-  isHealthy(): boolean {
-    return this.lastHealthCheck?.status === 'healthy'
-  }
-
-  /**
-   * 获取健康检查摘要
-   */
-  getHealthSummary() {
-    const health = this.lastHealthCheck
-    if (!health) return { status: 'unknown', message: '尚未进行健康检查' }
-
-    const exchangeCount = Object.keys(health.exchanges).length
-    const healthyExchanges = Object.values(health.exchanges).filter(ex => ex.status === 'healthy').length
-    const accountCount = Object.keys(health.accounts).length
-    const healthyAccounts = Object.values(health.accounts).filter(acc => acc.status === 'healthy').length
-
-    return {
-      status: health.status,
-      uptime: health.uptime,
-      exchanges: `${healthyExchanges}/${exchangeCount} 健康`,
-      accounts: `${healthyAccounts}/${accountCount} 健康`,
-      memoryUsage: `${Math.round((health.memory.used / health.memory.total) * 100)}%`,
-      errors: health.errors.total,
-      timestamp: health.timestamp,
-    }
-  }
-}

+ 0 - 4
src/adapters/infrastructure/health/index.ts

@@ -1,4 +0,0 @@
-export { HealthChecker } from './HealthChecker'
-export { HealthAPI } from './HealthAPI'
-export type { SystemHealth, ExchangeHealth, AccountHealth } from './HealthChecker'
-export type { HealthAPIConfig } from './HealthAPI'

+ 0 - 30
src/adapters/infrastructure/wallet/walletManager.ts

@@ -1,30 +0,0 @@
-import { ethers } from 'ethers'
-import { configManager } from '../config/configManager'
-
-export class WalletManager {
-  provider: ethers.JsonRpcProvider
-  wallet: ethers.Wallet | null = null
-
-  constructor() {
-    const rpc = configManager.get('RPC_URL')
-    if (!rpc) throw new Error('RPC_URL 未配置')
-    this.provider = new ethers.JsonRpcProvider(rpc)
-
-    const pk = configManager.get('PRIVATE_KEY')
-    if (pk) {
-      this.wallet = new ethers.Wallet(pk, this.provider)
-    }
-  }
-
-  getAddress(): Promise<string> {
-    if (!this.wallet) throw new Error('钱包未初始化')
-    return this.wallet.getAddress()
-  }
-
-  getNonce(address?: string): Promise<number> {
-    const addrPromise = address ? Promise.resolve(address) : this.getAddress()
-    return addrPromise.then(addr => this.provider.getTransactionCount(addr))
-  }
-}
-
-export const walletManager = new WalletManager()

+ 0 - 279
src/api/handlers.ts

@@ -1,279 +0,0 @@
-/**
- * API请求处理器 - 专注于Pacifica凭据管理
- */
-
-import { ApiResponse, ErrorCode, PacificaSignData, BatchSignRequest } from '../shared/credential-types'
-import { HTTP_STATUS_CODES } from '../shared/credential-constants'
-import { createApiError, PerformanceTimer } from '../shared/credential-utils'
-import { PacificaCredentialManager } from '../core/credential-manager'
-
-/**
- * 请求处理器类
- */
-export class CredentialApiHandlers {
-  constructor(private credentialManager: PacificaCredentialManager) {}
-
-  /**
-   * 执行签名操作
-   * POST /api/v1/sign
-   */
-  async handleSign(req: any, res: any): Promise<void> {
-    const timer = new PerformanceTimer()
-
-    try {
-      const { platformId, accountId, data } = req.body
-
-      // 验证必需参数
-      if (!platformId || !accountId || !data) {
-        return this._sendError(res, ErrorCode.INVALID_DATA_FORMAT, {
-          missingFields: { platformId, accountId, data },
-        })
-      }
-
-      // 执行签名
-      const result = await this.credentialManager.sign(platformId, accountId, data)
-
-      console.log(`✅ [API] 签名请求完成: ${platformId}/${accountId} (${timer.elapsed().toFixed(1)}ms)`)
-
-      this._sendSuccess(res, result)
-    } catch (error) {
-      console.error(`❌ [API] 签名请求失败 (${timer.elapsed().toFixed(1)}ms):`, error)
-      this._handleError(res, error)
-    }
-  }
-
-  /**
-   * 批量签名操作
-   * POST /api/v1/sign/batch
-   */
-  async handleBatchSign(req: any, res: any): Promise<void> {
-    const timer = new PerformanceTimer()
-
-    try {
-      const batchRequest: BatchSignRequest = req.body
-
-      // 验证批量请求格式
-      if (!batchRequest.requests || !Array.isArray(batchRequest.requests)) {
-        return this._sendError(res, ErrorCode.INVALID_DATA_FORMAT, {
-          reason: 'requests field must be an array',
-        })
-      }
-
-      if (batchRequest.requests.length === 0) {
-        return this._sendError(res, ErrorCode.INVALID_DATA_FORMAT, {
-          reason: 'requests array cannot be empty',
-        })
-      }
-
-      // 执行批量签名
-      const result = await this.credentialManager.signBatch(batchRequest)
-
-      console.log(`✅ [API] 批量签名完成: ${result.summary.total}个请求 (${timer.elapsed().toFixed(1)}ms)`)
-
-      this._sendSuccess(res, result)
-    } catch (error) {
-      console.error(`❌ [API] 批量签名失败 (${timer.elapsed().toFixed(1)}ms):`, error)
-      this._handleError(res, error)
-    }
-  }
-
-  /**
-   * 获取账户列表
-   * GET /api/v1/accounts?platform=pacifica
-   */
-  async handleGetAccounts(req: any, res: any): Promise<void> {
-    try {
-      const platform = req.query.platform || 'pacifica'
-
-      const accounts = this.credentialManager.listAccounts(platform)
-
-      // 过滤敏感信息
-      const safeAccounts = accounts.map(account => ({
-        accountId: account.accountId,
-        platformId: account.platformId,
-        alias: account.alias,
-        status: account.status,
-        environment: account.environment,
-        usage: account.usage,
-        createdAt: account.createdAt,
-        lastUsed: account.usage.lastSignAt,
-      }))
-
-      this._sendSuccess(res, {
-        accounts: safeAccounts,
-        total: safeAccounts.length,
-      })
-    } catch (error) {
-      console.error(`❌ [API] 获取账户列表失败:`, error)
-      this._handleError(res, error)
-    }
-  }
-
-  /**
-   * 获取单个账户信息
-   * GET /api/v1/accounts/{platformId}/{accountId}
-   */
-  async handleGetAccount(req: any, res: any): Promise<void> {
-    try {
-      const { platformId, accountId } = req.params
-
-      if (!platformId || !accountId) {
-        return this._sendError(res, ErrorCode.INVALID_DATA_FORMAT, {
-          reason: 'platformId and accountId are required',
-        })
-      }
-
-      const account = this.credentialManager.getAccount(platformId, accountId)
-
-      if (!account) {
-        return this._sendError(res, ErrorCode.ACCOUNT_NOT_FOUND, {
-          platformId,
-          accountId,
-        })
-      }
-
-      // 返回安全的账户信息(不包含私钥)
-      const safeAccount = {
-        accountId: account.accountId,
-        platformId: account.platformId,
-        alias: account.alias,
-        status: account.status,
-        environment: account.environment,
-        algorithm: 'ed25519',
-        createdAt: account.createdAt,
-        lastUsed: account.usage.lastSignAt,
-        usage: account.usage,
-      }
-
-      this._sendSuccess(res, safeAccount)
-    } catch (error) {
-      console.error(`❌ [API] 获取账户信息失败:`, error)
-      this._handleError(res, error)
-    }
-  }
-
-  /**
-   * 重载配置
-   * POST /api/v1/config/reload
-   */
-  async handleReloadConfig(req: any, res: any): Promise<void> {
-    const timer = new PerformanceTimer()
-
-    try {
-      const oldStats = this.credentialManager.getDetailedStats()
-      await this.credentialManager.reloadConfig()
-      const newStats = this.credentialManager.getDetailedStats()
-
-      const elapsedMs = timer.elapsed()
-
-      console.log(`✅ [API] 配置重载完成 (${elapsedMs.toFixed(1)}ms)`)
-
-      this._sendSuccess(res, {
-        reloadedAt: new Date().toISOString(),
-        changes: {
-          added: newStats.totalAccounts - oldStats.totalAccounts,
-          updated: 0, // 暂时简化
-          removed: oldStats.totalAccounts - newStats.totalAccounts,
-        },
-        accountCount: newStats.totalAccounts,
-        platformCount: Object.keys(newStats.platformStats).length,
-        reloadTimeMs: elapsedMs,
-      })
-    } catch (error) {
-      console.error(`❌ [API] 配置重载失败 (${timer.elapsed().toFixed(1)}ms):`, error)
-      this._handleError(res, error)
-    }
-  }
-
-  /**
-   * 获取服务状态
-   * GET /api/v1/status
-   */
-  async handleGetStatus(req: any, res: any): Promise<void> {
-    try {
-      const status = this.credentialManager.getStatus()
-      const detailedStats = this.credentialManager.getDetailedStats()
-
-      const response = {
-        status: detailedStats.service.initialized ? 'healthy' : 'initializing',
-        uptime: this._formatUptime(detailedStats.service.uptime),
-        config: {
-          path: status.configPath,
-          lastLoaded: status.lastLoaded.toISOString(),
-          isWatching: status.isWatching,
-        },
-        accounts: {
-          total: status.accountCount,
-          byPlatform: detailedStats.platformStats,
-        },
-        performance: {
-          maxSigningTime: `${detailedStats.performance.maxSignatureTimeMs}ms`,
-          maxBatchTime: `${detailedStats.performance.maxBatchTimeMs}ms`,
-          maxQPS: detailedStats.performance.maxQPS,
-        },
-      }
-
-      this._sendSuccess(res, response)
-    } catch (error) {
-      console.error(`❌ [API] 获取服务状态失败:`, error)
-      this._handleError(res, error)
-    }
-  }
-
-  /**
-   * 私有方法:发送成功响应
-   */
-  private _sendSuccess(res: any, data?: any): void {
-    const response: ApiResponse = {
-      success: true,
-      data,
-    }
-    res.status(200).json(response)
-  }
-
-  /**
-   * 私有方法:发送错误响应
-   */
-  private _sendError(res: any, code: ErrorCode, details?: any): void {
-    const response: ApiResponse = {
-      success: false,
-      error: createApiError(code, details),
-    }
-
-    const statusCode = HTTP_STATUS_CODES[code] || 500
-    res.status(statusCode).json(response)
-  }
-
-  /**
-   * 私有方法:处理异常错误
-   */
-  private _handleError(res: any, error: any): void {
-    if (error && typeof error === 'object' && 'code' in error) {
-      // API错误
-      this._sendError(res, error.code, error.details)
-    } else {
-      // 未知错误
-      this._sendError(res, ErrorCode.SIGNATURE_FAILED, {
-        error: error instanceof Error ? error.message : String(error),
-      })
-    }
-  }
-
-  /**
-   * 私有方法:格式化运行时间
-   */
-  private _formatUptime(uptimeMs: number): string {
-    const seconds = Math.floor(uptimeMs / 1000)
-    const hours = Math.floor(seconds / 3600)
-    const minutes = Math.floor((seconds % 3600) / 60)
-    const remainingSeconds = seconds % 60
-
-    if (hours > 0) {
-      return `${hours}h ${minutes}m ${remainingSeconds}s`
-    } else if (minutes > 0) {
-      return `${minutes}m ${remainingSeconds}s`
-    } else {
-      return `${remainingSeconds}s`
-    }
-  }
-}

+ 0 - 79
src/app/credential-main.ts

@@ -1,79 +0,0 @@
-/**
- * Pacifica凭据管理服务 - 主入口点
- * 专注于单一职责:凭据分类管理和签名服务
- */
-
-import { PacificaCredentialService } from './credential-service'
-import { getEnvVar } from '../shared/credential-utils'
-
-/**
- * 主函数
- */
-async function main(): Promise<void> {
-  console.log(`🚀 [Main] 启动Pacifica凭据管理服务`)
-
-  // 获取配置参数
-  const configPath = getEnvVar('CREDENTIAL_CONFIG_PATH', './credentials.json')
-  const port = parseInt(getEnvVar('CREDENTIAL_SERVICE_PORT', '3000'))
-
-  console.log(`📋 [Main] 配置参数:`)
-  console.log(`  - 配置文件: ${configPath}`)
-  console.log(`  - 服务端口: ${port}`)
-
-  // 创建服务实例
-  const service = new PacificaCredentialService(configPath, port)
-
-  // 设置优雅关闭
-  const shutdown = async (signal: string) => {
-    console.log(`\n🛑 [Main] 收到${signal}信号,开始优雅关闭`)
-
-    try {
-      await service.stop()
-      console.log(`✅ [Main] 服务已优雅关闭`)
-      process.exit(0)
-    } catch (error) {
-      console.error(`❌ [Main] 关闭服务时出错:`, error)
-      process.exit(1)
-    }
-  }
-
-  // 注册信号处理器
-  process.on('SIGTERM', () => shutdown('SIGTERM'))
-  process.on('SIGINT', () => shutdown('SIGINT'))
-
-  // 处理未捕获的异常
-  process.on('uncaughtException', error => {
-    console.error(`❌ [Main] 未捕获的异常:`, error)
-    shutdown('EXCEPTION').catch(() => process.exit(1))
-  })
-
-  process.on('unhandledRejection', (reason, promise) => {
-    console.error(`❌ [Main] 未处理的Promise拒绝:`, reason)
-    console.error(`Promise:`, promise)
-    shutdown('REJECTION').catch(() => process.exit(1))
-  })
-
-  try {
-    // 启动服务
-    await service.start()
-
-    console.log(`✅ [Main] Pacifica凭据管理服务启动成功!`)
-    console.log(`📖 [Main] API文档:`)
-    console.log(`  - 签名服务: POST http://localhost:${port}/api/v1/sign`)
-    console.log(`  - 批量签名: POST http://localhost:${port}/api/v1/sign/batch`)
-    console.log(`  - 账户列表: GET  http://localhost:${port}/api/v1/accounts`)
-    console.log(`  - 服务状态: GET  http://localhost:${port}/api/v1/status`)
-    console.log(`  - 配置重载: POST http://localhost:${port}/api/v1/config/reload`)
-  } catch (error) {
-    console.error(`❌ [Main] 服务启动失败:`, error)
-    process.exit(1)
-  }
-}
-
-// 检查是否直接运行此文件
-if (import.meta.url === `file://${process.argv[1]}`) {
-  main().catch(error => {
-    console.error(`❌ [Main] 启动过程中出现致命错误:`, error)
-    process.exit(1)
-  })
-}

+ 0 - 346
src/app/credential-service.ts

@@ -1,346 +0,0 @@
-/**
- * Pacifica凭据管理服务 - HTTP服务器
- * 专注于单一职责:凭据分类管理和签名服务
- */
-
-import http from 'http'
-import url from 'url'
-import { API_CONFIG } from '../shared/credential-constants'
-import { getEnvVar } from '../shared/credential-utils'
-import { PacificaCredentialManager } from '../core/credential-manager'
-import { CredentialApiHandlers } from '../api/handlers'
-
-/**
- * 简单的HTTP路由器
- */
-class SimpleRouter {
-  private routes: Map<string, Map<string, Function>> = new Map()
-
-  constructor() {
-    // 初始化HTTP方法
-    ;['GET', 'POST', 'PUT', 'DELETE'].forEach(method => {
-      this.routes.set(method, new Map())
-    })
-  }
-
-  /**
-   * 注册路由
-   */
-  register(method: string, path: string, handler: Function): void {
-    const methodRoutes = this.routes.get(method.toUpperCase())
-    if (methodRoutes) {
-      methodRoutes.set(path, handler)
-    }
-  }
-
-  /**
-   * 处理请求
-   */
-  async handle(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
-    const parsedUrl = url.parse(req.url || '', true)
-    const pathname = parsedUrl.pathname || ''
-    const method = req.method?.toUpperCase() || 'GET'
-
-    // 解析路径参数
-    const { handler, params } = this._matchRoute(method, pathname)
-
-    if (!handler) {
-      this._send404(res)
-      return
-    }
-
-    try {
-      // 构建请求对象
-      const request = await this._buildRequest(req, parsedUrl, params)
-      const response = this._buildResponse(res)
-
-      // 执行处理器
-      await handler(request, response)
-    } catch (error) {
-      console.error(`❌ [Router] 路由处理失败:`, error)
-      this._send500(res, error)
-    }
-  }
-
-  /**
-   * 私有方法:匹配路由
-   */
-  private _matchRoute(method: string, pathname: string): { handler?: Function; params: Record<string, string> } {
-    const methodRoutes = this.routes.get(method)
-    if (!methodRoutes) {
-      return { params: {} }
-    }
-
-    // 精确匹配
-    const exactHandler = methodRoutes.get(pathname)
-    if (exactHandler) {
-      return { handler: exactHandler, params: {} }
-    }
-
-    // 参数匹配 (简化版)
-    for (const [routePath, handler] of methodRoutes) {
-      const match = this._matchPathWithParams(routePath, pathname)
-      if (match) {
-        return { handler, params: match.params }
-      }
-    }
-
-    return { params: {} }
-  }
-
-  /**
-   * 私有方法:匹配带参数的路径
-   */
-  private _matchPathWithParams(routePath: string, requestPath: string): { params: Record<string, string> } | null {
-    const routeParts = routePath.split('/')
-    const requestParts = requestPath.split('/')
-
-    if (routeParts.length !== requestParts.length) {
-      return null
-    }
-
-    const params: Record<string, string> = {}
-
-    for (let i = 0; i < routeParts.length; i++) {
-      const routePart = routeParts[i]
-      const requestPart = requestParts[i]
-
-      if (routePart.startsWith('{') && routePart.endsWith('}')) {
-        // 参数部分
-        const paramName = routePart.slice(1, -1)
-        params[paramName] = requestPart
-      } else if (routePart !== requestPart) {
-        // 字面量部分不匹配
-        return null
-      }
-    }
-
-    return { params }
-  }
-
-  /**
-   * 私有方法:构建请求对象
-   */
-  private async _buildRequest(
-    req: http.IncomingMessage,
-    parsedUrl: url.UrlWithParsedQuery,
-    params: Record<string, string>,
-  ): Promise<any> {
-    let body = ''
-
-    // 读取请求体
-    if (req.method === 'POST' || req.method === 'PUT') {
-      const chunks: Buffer[] = []
-
-      req.on('data', chunk => {
-        chunks.push(chunk)
-      })
-
-      await new Promise((resolve, reject) => {
-        req.on('end', resolve)
-        req.on('error', reject)
-      })
-
-      body = Buffer.concat(chunks).toString()
-    }
-
-    return {
-      method: req.method,
-      url: req.url,
-      headers: req.headers,
-      query: parsedUrl.query,
-      params,
-      body: body ? JSON.parse(body) : {},
-      rawBody: body,
-    }
-  }
-
-  /**
-   * 私有方法:构建响应对象
-   */
-  private _buildResponse(res: http.ServerResponse): any {
-    return {
-      status: (code: number) => {
-        res.statusCode = code
-        return {
-          json: (data: any) => {
-            res.setHeader('Content-Type', 'application/json')
-            res.end(JSON.stringify(data, null, 2))
-          },
-        }
-      },
-      json: (data: any) => {
-        res.setHeader('Content-Type', 'application/json')
-        res.end(JSON.stringify(data, null, 2))
-      },
-    }
-  }
-
-  /**
-   * 私有方法:发送404响应
-   */
-  private _send404(res: http.ServerResponse): void {
-    res.statusCode = 404
-    res.setHeader('Content-Type', 'application/json')
-    res.end(
-      JSON.stringify({
-        success: false,
-        error: {
-          code: 'NOT_FOUND',
-          message: 'Route not found',
-        },
-      }),
-    )
-  }
-
-  /**
-   * 私有方法:发送500响应
-   */
-  private _send500(res: http.ServerResponse, error: any): void {
-    res.statusCode = 500
-    res.setHeader('Content-Type', 'application/json')
-    res.end(
-      JSON.stringify({
-        success: false,
-        error: {
-          code: 'INTERNAL_ERROR',
-          message: 'Internal server error',
-          details: error instanceof Error ? error.message : String(error),
-        },
-      }),
-    )
-  }
-}
-
-/**
- * Pacifica凭据管理服务
- */
-export class PacificaCredentialService {
-  private server?: http.Server
-  private credentialManager: PacificaCredentialManager
-  private apiHandlers: CredentialApiHandlers
-  private router: SimpleRouter
-  private port: number
-
-  constructor(configPath?: string, port?: number) {
-    this.port = port || parseInt(getEnvVar('CREDENTIAL_SERVICE_PORT', String(API_CONFIG.DEFAULT_PORT)))
-    this.credentialManager = new PacificaCredentialManager(configPath)
-    this.apiHandlers = new CredentialApiHandlers(this.credentialManager)
-    this.router = new SimpleRouter()
-
-    this._setupRoutes()
-    console.log(`🚀 [CredentialService] 初始化完成,端口: ${this.port}`)
-  }
-
-  /**
-   * 启动服务
-   */
-  async start(): Promise<void> {
-    // 初始化凭据管理器
-    await this.credentialManager.initialize()
-
-    // 创建HTTP服务器
-    this.server = http.createServer((req, res) => {
-      this._handleRequest(req, res)
-    })
-
-    return new Promise((resolve, reject) => {
-      this.server!.listen(this.port, (error?: Error) => {
-        if (error) {
-          reject(error)
-        } else {
-          console.log(`✅ [CredentialService] 服务启动成功: http://localhost:${this.port}`)
-          resolve()
-        }
-      })
-    })
-  }
-
-  /**
-   * 停止服务
-   */
-  async stop(): Promise<void> {
-    console.log(`🛑 [CredentialService] 开始停止服务`)
-
-    if (this.server) {
-      await new Promise<void>(resolve => {
-        this.server!.close(() => {
-          console.log(`✅ [CredentialService] HTTP服务器已关闭`)
-          resolve()
-        })
-      })
-    }
-
-    await this.credentialManager.shutdown()
-    console.log(`✅ [CredentialService] 服务已完全关闭`)
-  }
-
-  /**
-   * 私有方法:设置路由
-   */
-  private _setupRoutes(): void {
-    const basePath = API_CONFIG.BASE_PATH
-
-    // 核心签名接口
-    this.router.register('POST', `${basePath}/sign`, this.apiHandlers.handleSign.bind(this.apiHandlers))
-
-    this.router.register('POST', `${basePath}/sign/batch`, this.apiHandlers.handleBatchSign.bind(this.apiHandlers))
-
-    // 账户管理
-    this.router.register('GET', `${basePath}/accounts`, this.apiHandlers.handleGetAccounts.bind(this.apiHandlers))
-
-    this.router.register(
-      'GET',
-      `${basePath}/accounts/{platformId}/{accountId}`,
-      this.apiHandlers.handleGetAccount.bind(this.apiHandlers),
-    )
-
-    // 配置管理
-    this.router.register(
-      'POST',
-      `${basePath}/config/reload`,
-      this.apiHandlers.handleReloadConfig.bind(this.apiHandlers),
-    )
-
-    this.router.register('GET', `${basePath}/status`, this.apiHandlers.handleGetStatus.bind(this.apiHandlers))
-
-    console.log(`📋 [CredentialService] 路由已配置: ${basePath}/*`)
-  }
-
-  /**
-   * 私有方法:处理HTTP请求
-   */
-  private async _handleRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
-    // 设置CORS头
-    res.setHeader('Access-Control-Allow-Origin', '*')
-    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
-    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
-
-    // 处理OPTIONS请求
-    if (req.method === 'OPTIONS') {
-      res.statusCode = 200
-      res.end()
-      return
-    }
-
-    // 记录请求
-    console.log(`📥 [CredentialService] ${req.method} ${req.url}`)
-
-    try {
-      await this.router.handle(req, res)
-    } catch (error) {
-      console.error(`❌ [CredentialService] 请求处理失败:`, error)
-      res.statusCode = 500
-      res.setHeader('Content-Type', 'application/json')
-      res.end(
-        JSON.stringify({
-          success: false,
-          error: {
-            code: 'INTERNAL_ERROR',
-            message: 'Internal server error',
-          },
-        }),
-      )
-    }
-  }
-}

+ 0 - 520
src/app/main.ts

@@ -1,520 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * 🎯 统一Delta中性交易系统 v2.0 - 完全重构版本
- *
- * 基于tasks规范完全重构的企业级Delta中性交易系统,提供:
- * - Delta中性控制平面(±0.0005 BTC阈值)
- * - 统一多平台多账户管理
- * - 企业级风险包络系统
- * - 智能对冲和自动再平衡
- * - 8秒控制循环和5秒紧急响应
- * - 实时监控和性能报告
- * - 优雅启动关闭和错误恢复
- */
-
-// 早期设置全局错误处理
-process.stdout.on('error', error => {
-  if (error.code === 'EPIPE') {
-    process.exit(0)
-  }
-})
-
-process.stderr.on('error', error => {
-  if (error.code === 'EPIPE') {
-    process.exit(0)
-  }
-})
-
-import UnifiedSystemOrchestrator, { UnifiedSystemConfig } from '../core/orchestration/orchestrator'
-import { UnifiedAccountConfig } from '../core/accounts/manager'
-import { logger } from '../shared/utils/logger'
-import * as dotenv from 'dotenv'
-
-// 加载环境变量
-dotenv.config()
-
-/**
- * 统一Delta中性交易系统应用程序
- */
-class UnifiedDeltaNeutralTradingSystem {
-  private orchestrator: UnifiedSystemOrchestrator
-  private isShuttingDown = false
-  private isProduction: boolean
-  private startTime?: Date
-
-  constructor() {
-    this.isProduction = process.env.NODE_ENV === 'production'
-    this.orchestrator = new UnifiedSystemOrchestrator()
-    this.setupSignalHandlers()
-    this.setupGlobalErrorHandlers()
-  }
-
-  /**
-   * 启动统一Delta中性交易系统
-   */
-  async start(): Promise<void> {
-    try {
-      this.startTime = new Date()
-      this.displayStartupBanner()
-
-      // 1. 验证环境配置
-      await this.validateEnvironment()
-
-      // 2. 加载系统配置
-      const config = await this.loadSystemConfiguration()
-
-      // 3. 初始化系统
-      await this.orchestrator.initialize(config)
-
-      // 4. 启动系统
-      await this.orchestrator.start()
-
-      // 5. 启动监控和健康检查
-      if (this.isProduction) {
-        this.startProductionMonitoring()
-      } else {
-        this.startDevelopmentMonitoring()
-      }
-
-      // 6. 显示系统状态
-      await this.displaySystemStatus()
-
-      logger.info('✅ 统一Delta中性交易系统启动完成')
-      logger.info('🔄 系统持续运行中,按 Ctrl+C 安全停止...')
-    } catch (error) {
-      logger.error('💥 系统启动失败:', error)
-      throw error
-    }
-  }
-
-  /**
-   * 停止系统
-   */
-  async stop(): Promise<void> {
-    if (this.isShuttingDown) {
-      logger.warn('🔄 系统正在关闭中...')
-      return
-    }
-
-    this.isShuttingDown = true
-    logger.info('🛑 开始优雅关闭统一Delta中性交易系统...')
-
-    try {
-      // 停止系统协调器
-      await this.orchestrator.stop()
-
-      // 计算运行时间
-      const uptime = this.startTime ? Date.now() - this.startTime.getTime() : 0
-      logger.info(`✅ 系统已安全关闭,运行时长: ${Math.round(uptime / 1000)}秒`)
-    } catch (error) {
-      logger.error('❌ 系统关闭时出现错误:', error)
-      throw error
-    }
-  }
-
-  /**
-   * 获取系统状态
-   */
-  async getSystemStatus() {
-    return await this.orchestrator.getSystemStatus()
-  }
-
-  // ========== 私有方法 ==========
-
-  /**
-   * 显示启动横幅
-   */
-  private displayStartupBanner(): void {
-    console.log('')
-    console.log('🎯'.repeat(30))
-    console.log('🎯 统一Delta中性交易系统 v2.0')
-    console.log('🎯 企业级Delta中性控制平面')
-    console.log('🎯'.repeat(30))
-    console.log(`🏭 环境: ${this.isProduction ? '生产环境' : '开发环境'}`)
-    console.log(`📅 启动时间: ${new Date().toISOString()}`)
-    console.log(`🔧 Node.js版本: ${process.version}`)
-    console.log('')
-  }
-
-  /**
-   * 验证环境
-   */
-  private async validateEnvironment(): Promise<void> {
-    logger.info('🔍 验证环境配置...')
-
-    // 验证Node.js版本
-    const nodeVersion = process.version
-    const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0])
-    if (majorVersion < 18) {
-      throw new Error(`需要 Node.js 18.12+,当前版本: ${nodeVersion}`)
-    }
-
-    // 验证必需的环境变量
-    const requiredEnvVars = ['PACIFICA_ACCOUNT', 'PACIFICA_PRIVATE_KEY']
-
-    const missing = requiredEnvVars.filter(env => !process.env[env])
-    if (missing.length > 0) {
-      throw new Error(`缺少必需的环境变量: ${missing.join(', ')}`)
-    }
-
-    // 生产环境额外验证
-    if (this.isProduction) {
-      await this.validateProductionEnvironment()
-    }
-
-    logger.info('✅ 环境配置验证通过')
-  }
-
-  /**
-   * 验证生产环境
-   */
-  private async validateProductionEnvironment(): Promise<void> {
-    logger.info('🏭 验证生产环境特定配置...')
-
-    // 验证代理配置
-    if (!process.env.PROXY_HOST || !process.env.PROXY_PORT) {
-      logger.warn('⚠️ 生产环境建议配置代理以提高安全性')
-    }
-
-    // 验证资源限制
-    const memoryUsage = process.memoryUsage()
-    if (memoryUsage.heapTotal > 1024 * 1024 * 1024) {
-      // 1GB
-      logger.warn('⚠️ 内存使用超过1GB,请监控系统资源')
-    }
-
-    logger.info('✅ 生产环境配置验证通过')
-  }
-
-  /**
-   * 加载系统配置
-   */
-  private async loadSystemConfiguration(): Promise<UnifiedSystemConfig> {
-    logger.info('⚙️ 加载系统配置...')
-
-    // 加载账户配置
-    const accounts = await this.loadAccountConfigurations()
-
-    // 构建系统配置
-    const config: UnifiedSystemConfig = {
-      accounts,
-      enableTrading: true,
-      enableDashboard: true,
-      enableDeltaControl: true,
-      enableRiskMonitoring: true,
-
-      deltaControl: {
-        deltaThreshold: parseFloat(process.env.DELTA_THRESHOLD || '0.0005'),
-        utilizationTargetMin: parseFloat(process.env.UTILIZATION_MIN || '0.5'),
-        utilizationTargetMax: parseFloat(process.env.UTILIZATION_MAX || '0.8'),
-        controlCycleInterval: parseInt(process.env.CONTROL_CYCLE_INTERVAL || '8000'),
-        emergencyResponseTime: parseInt(process.env.EMERGENCY_RESPONSE_TIME || '5000'),
-      },
-
-      riskManagement: {
-        globalMaxDrawdown: parseFloat(process.env.MAX_DRAWDOWN || '5.0'),
-        accountMaxLeverage: parseFloat(process.env.MAX_LEVERAGE || '10.0'),
-        emergencyStopLoss: parseFloat(process.env.EMERGENCY_STOP_LOSS || '3.0'),
-        riskCheckInterval: parseInt(process.env.RISK_CHECK_INTERVAL || '5000'),
-      },
-
-      displayConfig: {
-        showPrices: true,
-        showPositions: true,
-        showRiskMetrics: true,
-        refreshInterval: this.isProduction ? 10000 : 5000,
-      },
-
-      environment: this.isProduction ? 'production' : 'development',
-      logLevel: (process.env.LOG_LEVEL as any) || (this.isProduction ? 'info' : 'debug'),
-    }
-
-    logger.info(`✅ 系统配置加载完成,配置了 ${accounts.length} 个账户`)
-    return config
-  }
-
-  /**
-   * 加载账户配置
-   */
-  private async loadAccountConfigurations(): Promise<UnifiedAccountConfig[]> {
-    const accounts: UnifiedAccountConfig[] = []
-
-    // 加载多个Pacifica账户
-    for (let i = 1; i <= 10; i++) {
-      const account = process.env[`PACIFICA_ACCOUNT_${i}`]
-      const privateKey = process.env[`PACIFICA_PRIVATE_KEY_${i}`]
-
-      if (account && privateKey) {
-        accounts.push({
-          accountId: `pacifica-${i}`,
-          exchange: 'pacifica',
-          accountName: `Pacifica账户${i}`,
-          alias: `Pacifica-${i}`,
-          publicKey: account,
-          privateKey: privateKey,
-          proxyProfile: process.env[`PACIFICA_PROXY_PROFILE_${i}`] || 'default',
-          utilizationTargetMin: 0.5,
-          utilizationTargetMax: 0.8,
-          deltaThreshold: 0.0005,
-          maxPositionValue: parseFloat(process.env[`MAX_POSITION_VALUE_${i}`] || '10000'),
-          stopLossConfigId: `stop-loss-${i}`,
-          status: 'active',
-
-          enabled: true,
-          priority: i,
-          tradingEnabled: true,
-          hedgingEnabled: true,
-          maxDailyVolumeUsd: parseFloat(process.env[`MAX_DAILY_VOLUME_${i}`] || '100000'),
-
-          authenticationMethod: 'ed25519',
-          requiresProxy: true,
-          sessionManagement: false,
-        })
-      }
-    }
-
-    // 默认账户配置
-    if (accounts.length === 0) {
-      const defaultAccount = process.env.PACIFICA_ACCOUNT
-      const defaultPrivateKey = process.env.PACIFICA_PRIVATE_KEY
-
-      if (defaultAccount && defaultPrivateKey) {
-        accounts.push({
-          accountId: 'pacifica-default',
-          exchange: 'pacifica',
-          accountName: 'Pacifica默认账户',
-          alias: 'Pacifica-Default',
-          publicKey: defaultAccount,
-          privateKey: defaultPrivateKey,
-          proxyProfile: 'default',
-          utilizationTargetMin: 0.5,
-          utilizationTargetMax: 0.8,
-          deltaThreshold: 0.0005,
-          maxPositionValue: 10000,
-          stopLossConfigId: 'stop-loss-default',
-          status: 'active',
-
-          enabled: true,
-          priority: 1,
-          tradingEnabled: true,
-          hedgingEnabled: true,
-          maxDailyVolumeUsd: 100000,
-
-          authenticationMethod: 'ed25519',
-          requiresProxy: true,
-          sessionManagement: false,
-        })
-      }
-    }
-
-    return accounts
-  }
-
-  /**
-   * 启动生产环境监控
-   */
-  private startProductionMonitoring(): void {
-    logger.info('🏭 启动生产环境监控系统...')
-
-    const monitoringInterval = 60000 // 1分钟
-
-    setInterval(async () => {
-      try {
-        const status = await this.getSystemStatus()
-
-        // 检查系统健康状况
-        if (status.status !== 'running') {
-          logger.warn(`⚠️ 系统状态异常: ${status.status}`)
-        }
-
-        // 检查Delta控制状态
-        if (Math.abs(status.deltaControl.globalDelta) > 0.001) {
-          logger.warn(`🚨 全局Delta异常: ${status.deltaControl.globalDelta.toFixed(6)} BTC`)
-        }
-
-        // 检查紧急账户
-        if (status.riskManagement.emergencyAccounts > 0) {
-          logger.error(`🆘 发现 ${status.riskManagement.emergencyAccounts} 个紧急状态账户`)
-        }
-
-        // 性能监控
-        const memoryUsage = process.memoryUsage()
-        const heapUsedMB = Math.round(memoryUsage.heapUsed / 1024 / 1024)
-
-        logger.debug('📊 生产环境监控报告', {
-          systemStatus: status.status,
-          deltaControl: status.deltaControl.enabled,
-          globalDelta: status.deltaControl.globalDelta.toFixed(6),
-          accountsMonitored: status.deltaControl.accountsMonitored,
-          emergencyAccounts: status.riskManagement.emergencyAccounts,
-          memoryUsageMB: heapUsedMB,
-          uptime: Math.round((status.uptime || 0) / 1000) + 's',
-        })
-      } catch (error) {
-        logger.error('❌ 生产环境监控失败:', error)
-      }
-    }, monitoringInterval)
-
-    logger.info(`💚 生产环境监控已启动 (${monitoringInterval / 1000}秒间隔)`)
-  }
-
-  /**
-   * 启动开发环境监控
-   */
-  private startDevelopmentMonitoring(): void {
-    logger.info('🔧 启动开发环境监控系统...')
-
-    const monitoringInterval = 30000 // 30秒
-
-    setInterval(async () => {
-      try {
-        const status = await this.getSystemStatus()
-
-        logger.debug('📊 开发环境监控报告', {
-          status: status.status,
-          services: Object.keys(status.services).length,
-          deltaControl: status.deltaControl.globalDelta.toFixed(6),
-          accounts: status.deltaControl.accountsMonitored,
-          performance: status.performance.systemLoad.toFixed(2),
-        })
-      } catch (error) {
-        logger.error('❌ 开发环境监控失败:', error)
-      }
-    }, monitoringInterval)
-
-    logger.info(`🔧 开发环境监控已启动 (${monitoringInterval / 1000}秒间隔)`)
-  }
-
-  /**
-   * 显示系统状态
-   */
-  private async displaySystemStatus(): Promise<void> {
-    try {
-      const status = await this.getSystemStatus()
-
-      console.log('')
-      console.log('📊'.repeat(30))
-      console.log('📊 统一Delta中性交易系统状态')
-      console.log('📊'.repeat(30))
-      console.log(`🎯 系统状态: ${status.status}`)
-      console.log(`🏭 运行环境: ${status.environment}`)
-      console.log(`⏰ 启动时间: ${status.startTime?.toISOString()}`)
-      console.log(`📊 注册服务: ${Object.keys(status.services).length}个`)
-      console.log('')
-      console.log('🎯 Delta中性控制状态:')
-      console.log(`   ├─ 控制状态: ${status.deltaControl.enabled ? '✅ 启用' : '❌ 禁用'}`)
-      console.log(`   ├─ 全局Delta: ${status.deltaControl.globalDelta.toFixed(6)} BTC`)
-      console.log(`   ├─ 监控账户: ${status.deltaControl.accountsMonitored}个`)
-      console.log(`   ├─ 成功周期: ${status.deltaControl.controlCycleSuccess}`)
-      console.log(`   └─ 失败周期: ${status.deltaControl.controlCycleFailures}`)
-      console.log('')
-      console.log('🛡️ 风险管理状态:')
-      console.log(`   ├─ 监控状态: ${status.riskManagement.enabled ? '✅ 启用' : '❌ 禁用'}`)
-      console.log(`   ├─ 风险违规: ${status.riskManagement.totalViolations}个`)
-      console.log(`   └─ 紧急账户: ${status.riskManagement.emergencyAccounts}个`)
-      console.log('')
-      console.log('⚡ 性能指标:')
-      console.log(`   ├─ 总账户数: ${status.performance.totalAccounts}`)
-      console.log(`   ├─ 活跃账户: ${status.performance.activeAccounts}`)
-      console.log(`   ├─ 总交易数: ${status.performance.totalTrades}`)
-      console.log(`   └─ 系统负载: ${(status.performance.systemLoad * 100).toFixed(1)}%`)
-      console.log('')
-      console.log('🔧 服务详情:')
-      Object.entries(status.services).forEach(([name, service]) => {
-        const statusIcon = service.status === 'running' ? '✅' : service.status === 'error' ? '❌' : '⏸️'
-        console.log(`   ${statusIcon} ${name}: ${service.status}`)
-      })
-      console.log('📊'.repeat(30))
-      console.log('')
-    } catch (error) {
-      logger.error('❌ 获取系统状态失败:', error)
-    }
-  }
-
-  /**
-   * 设置信号处理器
-   */
-  private setupSignalHandlers(): void {
-    const signals = ['SIGTERM', 'SIGINT'] as const
-
-    signals.forEach(signal => {
-      process.on(signal, async () => {
-        if (this.isShuttingDown) {
-          logger.warn('🔄 强制退出...')
-          process.exit(1)
-        }
-
-        logger.info(`📡 收到 ${signal} 信号,开始优雅关闭...`)
-
-        try {
-          await this.stop()
-          process.exit(0)
-        } catch (error) {
-          logger.error('❌ 关闭过程中出错:', error)
-          process.exit(1)
-        }
-      })
-    })
-  }
-
-  /**
-   * 设置全局错误处理器
-   */
-  private setupGlobalErrorHandlers(): void {
-    process.on('uncaughtException', error => {
-      logger.error('💥 未捕获的异常:', error)
-
-      if (this.isProduction) {
-        logger.error('🏭 生产环境检测到严重错误,准备重启...')
-        process.exit(1)
-      } else {
-        logger.warn('🔧 开发环境继续运行,请修复错误')
-      }
-    })
-
-    process.on('unhandledRejection', (reason, promise) => {
-      logger.error('💥 未处理的Promise拒绝:', reason)
-      logger.error('Promise:', promise)
-
-      if (this.isProduction) {
-        logger.error('🏭 生产环境检测到严重错误,准备重启...')
-        process.exit(1)
-      }
-    })
-  }
-}
-
-/**
- * 主启动函数
- */
-async function main(): Promise<void> {
-  const system = new UnifiedDeltaNeutralTradingSystem()
-
-  try {
-    await system.start()
-
-    // 如果是直接运行此文件,保持进程运行
-    if (import.meta.url === `file://${process.argv[1]}`) {
-      // 进程保活,等待信号
-      await new Promise(resolve => {
-        process.on('SIGTERM', resolve)
-        process.on('SIGINT', resolve)
-      })
-    }
-  } catch (error) {
-    logger.error('💥 系统启动失败:', error)
-    process.exit(1)
-  }
-}
-
-// 导出类供其他模块使用
-export { UnifiedDeltaNeutralTradingSystem }
-
-// 如果直接运行此文件,启动系统
-if (import.meta.url === `file://${process.argv[1]}`) {
-  main().catch(error => {
-    logger.error('💥 启动失败:', error)
-    process.exit(1)
-  })
-}

+ 0 - 97
src/config/asterConfig.ts

@@ -1,97 +0,0 @@
-import { AsterWsConfig, AsterAuthConfig } from '../exchanges/aster/types'
-
-export interface AsterConfig {
-  // WebSocket 配置
-  ws: {
-    url: string
-    pingInterval: number
-    pongTimeout: number
-    reconnectInterval: number
-    maxReconnectAttempts: number
-  }
-
-  // HTTP API 配置
-  http: {
-    baseUrl: string
-  }
-
-  // 鉴权配置
-  auth: {
-    user: string
-    signer: string
-    privateKey: string
-  }
-
-  // 订阅配置
-  subscribe: {
-    symbols: string[]
-  }
-
-  // 日志配置
-  log: {
-    level: string
-  }
-}
-
-/**
- * 从环境变量读取 Aster DEX 配置
- */
-export function loadAsterConfig(): AsterConfig {
-  const required = ['ASTER_WS_URL', 'ASTER_ORDER_USER', 'ASTER_ORDER_SIGNER', 'PRIVATE_KEY']
-
-  for (const key of required) {
-    if (!process.env[key]) {
-      throw new Error(`缺少必需的环境变量: ${key}`)
-    }
-  }
-
-  return {
-    ws: {
-      url: process.env.ASTER_WS_URL!,
-      pingInterval: parseInt(process.env.ASTER_WS_PING_INTERVAL || '30000'),
-      pongTimeout: parseInt(process.env.ASTER_WS_PONG_TIMEOUT || '10000'),
-      reconnectInterval: parseInt(process.env.ASTER_WS_RECONNECT_INTERVAL || '5000'),
-      maxReconnectAttempts: parseInt(process.env.ASTER_WS_MAX_RECONNECT_ATTEMPTS || '10'),
-    },
-    http: {
-      baseUrl: process.env.ASTER_HTTP_BASE || 'https://fapi.asterdex.com',
-    },
-    auth: {
-      user: process.env.ASTER_ORDER_USER!,
-      signer: process.env.ASTER_ORDER_SIGNER!,
-      privateKey: process.env.PRIVATE_KEY!,
-    },
-    subscribe: {
-      symbols: (process.env.ASTER_SUBSCRIBE_SYMBOLS || 'BTCUSDT,ETHUSDT').split(',').map(s => s.trim()),
-    },
-    log: {
-      level: process.env.LOG_LEVEL || 'info',
-    },
-  }
-}
-
-/**
- * 转换为 AsterWsConfig
- */
-export function toAsterWsConfig(config: AsterConfig): AsterWsConfig {
-  return {
-    wsUrl: config.ws.url,
-    pingIntervalMs: config.ws.pingInterval,
-    pongTimeoutMs: config.ws.pongTimeout,
-    autoReconnect: true,
-    reconnectIntervalMs: config.ws.reconnectInterval,
-  }
-}
-
-/**
- * 转换为 AsterAuthConfig
- */
-export function toAsterAuthConfig(config: AsterConfig): AsterAuthConfig {
-  return {
-    type: 'signer',
-    user: config.auth.user,
-    signer: config.auth.signer,
-    privateKey: config.auth.privateKey,
-    loginMethod: 'login',
-  }
-}

+ 0 - 210
src/config/controlPlaneConfig.ts

@@ -1,210 +0,0 @@
-import { SimpleEnv, EnvKeys } from './simpleEnv.js'
-
-/**
- * 多平台 Delta 中性控制平面配置
- * 基于 data-model.md 中的实体定义
- */
-export const ControlPlaneEnvKeys = {
-  // 控制平面基础配置
-  CONTROL_PLANE_ENABLED: 'CONTROL_PLANE_ENABLED',
-  CONTROL_PLANE_MODE: 'CONTROL_PLANE_MODE', // 'production' | 'sandbox' | 'dry-run'
-  
-  // Delta 中性配置
-  DELTA_THRESHOLD_BTC: 'DELTA_THRESHOLD_BTC', // 默认 0.0005
-  DELTA_CHECK_INTERVAL_MS: 'DELTA_CHECK_INTERVAL_MS', // 默认 8000
-  
-  // 资金利用率配置
-  UTILIZATION_TARGET_MIN: 'UTILIZATION_TARGET_MIN', // 默认 0.5 (50%)
-  UTILIZATION_TARGET_MAX: 'UTILIZATION_TARGET_MAX', // 默认 0.8 (80%)
-  UTILIZATION_CHECK_INTERVAL_MS: 'UTILIZATION_CHECK_INTERVAL_MS', // 默认 8000
-  
-  // 行情数据源配置
-  MARKET_DATA_PRIMARY_TIMEOUT_MS: 'MARKET_DATA_PRIMARY_TIMEOUT_MS', // 默认 2000
-  MARKET_DATA_FAILOVER_DEADLINE_MS: 'MARKET_DATA_FAILOVER_DEADLINE_MS', // 默认 10000
-  
-  // 风险控制配置
-  MAX_LEVERAGE: 'MAX_LEVERAGE', // 默认 1.0
-  MAX_DRAWDOWN_PERCENT: 'MAX_DRAWDOWN_PERCENT', // 默认 5.0
-  SLIPPAGE_TOLERANCE: 'SLIPPAGE_TOLERANCE', // 默认 0.001 (0.1%)
-  EMERGENCY_STOP_LOSS_SECONDS: 'EMERGENCY_STOP_LOSS_SECONDS', // 默认 30
-  
-  // 策略模块配置
-  STRATEGY_MODULE_ENABLED: 'STRATEGY_MODULE_ENABLED',
-  STRATEGY_MODULE_MAX_CONCURRENT: 'STRATEGY_MODULE_MAX_CONCURRENT', // 默认 3
-  STRATEGY_MODULE_PROFIT_TARGET: 'STRATEGY_MODULE_PROFIT_TARGET', // 默认 0.001 (0.1%)
-  
-  // 监控与日志配置
-  MONITORING_ENABLED: 'MONITORING_ENABLED',
-  AUDIT_LOG_RETENTION_DAYS: 'AUDIT_LOG_RETENTION_DAYS', // 默认 90
-  
-  // 账户同步配置
-  ACCOUNT_SYNC_INTERVAL_MS: 'ACCOUNT_SYNC_INTERVAL_MS', // 默认 30000
-  ACCOUNT_SYNC_TIMEOUT_MS: 'ACCOUNT_SYNC_TIMEOUT_MS', // 默认 10000
-  
-  // 对冲执行配置
-  HEDGE_EXECUTION_TIMEOUT_MS: 'HEDGE_EXECUTION_TIMEOUT_MS', // 默认 30000
-  HEDGE_EXECUTION_MAX_RETRIES: 'HEDGE_EXECUTION_MAX_RETRIES', // 默认 3
-} as const
-
-/**
- * 控制平面配置对象
- */
-export const ControlPlaneConfig = {
-  // 基础配置
-  enabled: () => SimpleEnv.bool(ControlPlaneEnvKeys.CONTROL_PLANE_ENABLED, true),
-  mode: () => SimpleEnv.get(ControlPlaneEnvKeys.CONTROL_PLANE_MODE, 'sandbox') as 'production' | 'sandbox' | 'dry-run',
-  isProduction: () => ControlPlaneConfig.mode() === 'production',
-  isSandbox: () => ControlPlaneConfig.mode() === 'sandbox',
-  isDryRun: () => ControlPlaneConfig.mode() === 'dry-run',
-
-  // Delta 中性配置
-  delta: {
-    thresholdBtc: () => SimpleEnv.number(ControlPlaneEnvKeys.DELTA_THRESHOLD_BTC, 0.0005),
-    checkIntervalMs: () => SimpleEnv.number(ControlPlaneEnvKeys.DELTA_CHECK_INTERVAL_MS, 8000),
-    tolerancePercent: () => 0.05, // ±5% 容忍度
-  },
-
-  // 资金利用率配置
-  utilization: {
-    targetMin: () => SimpleEnv.number(ControlPlaneEnvKeys.UTILIZATION_TARGET_MIN, 0.5),
-    targetMax: () => SimpleEnv.number(ControlPlaneEnvKeys.UTILIZATION_TARGET_MAX, 0.8),
-    checkIntervalMs: () => SimpleEnv.number(ControlPlaneEnvKeys.UTILIZATION_CHECK_INTERVAL_MS, 8000),
-    rebalanceThreshold: () => 0.05, // 5% 偏差触发再平衡
-  },
-
-  // 行情数据源配置
-  marketData: {
-    primaryTimeoutMs: () => SimpleEnv.number(ControlPlaneEnvKeys.MARKET_DATA_PRIMARY_TIMEOUT_MS, 2000),
-    failoverDeadlineMs: () => SimpleEnv.number(ControlPlaneEnvKeys.MARKET_DATA_FAILOVER_DEADLINE_MS, 10000),
-    heartbeatIntervalMs: () => 5000,
-    reconnectIntervalMs: () => 5000,
-    maxReconnectAttempts: () => 10,
-  },
-
-  // 风险控制配置
-  risk: {
-    maxLeverage: () => SimpleEnv.number(ControlPlaneEnvKeys.MAX_LEVERAGE, 1.0),
-    maxDrawdownPercent: () => SimpleEnv.number(ControlPlaneEnvKeys.MAX_DRAWDOWN_PERCENT, 5.0),
-    slippageTolerance: () => SimpleEnv.number(ControlPlaneEnvKeys.SLIPPAGE_TOLERANCE, 0.001),
-    emergencyStopLossSeconds: () => SimpleEnv.number(ControlPlaneEnvKeys.EMERGENCY_STOP_LOSS_SECONDS, 30),
-  },
-
-  // 策略模块配置
-  strategy: {
-    enabled: () => SimpleEnv.bool(ControlPlaneEnvKeys.STRATEGY_MODULE_ENABLED, true),
-    maxConcurrent: () => SimpleEnv.number(ControlPlaneEnvKeys.STRATEGY_MODULE_MAX_CONCURRENT, 3),
-    profitTarget: () => SimpleEnv.number(ControlPlaneEnvKeys.STRATEGY_MODULE_PROFIT_TARGET, 0.001),
-    sandboxEnabled: () => ControlPlaneConfig.isSandbox() || ControlPlaneConfig.isDryRun(),
-  },
-
-  // 监控与日志配置
-  monitoring: {
-    enabled: () => SimpleEnv.bool(ControlPlaneEnvKeys.MONITORING_ENABLED, true),
-    auditLogRetentionDays: () => SimpleEnv.number(ControlPlaneEnvKeys.AUDIT_LOG_RETENTION_DAYS, 90),
-    healthCheckIntervalMs: () => 10000,
-    metricsIntervalMs: () => 5000,
-  },
-
-  // 账户同步配置
-  accountSync: {
-    intervalMs: () => SimpleEnv.number(ControlPlaneEnvKeys.ACCOUNT_SYNC_INTERVAL_MS, 30000),
-    timeoutMs: () => SimpleEnv.number(ControlPlaneEnvKeys.ACCOUNT_SYNC_TIMEOUT_MS, 10000),
-    maxConcurrent: () => 3,
-    retryAttempts: () => 3,
-  },
-
-  // 对冲执行配置
-  hedgeExecution: {
-    timeoutMs: () => SimpleEnv.number(ControlPlaneEnvKeys.HEDGE_EXECUTION_TIMEOUT_MS, 30000),
-    maxRetries: () => SimpleEnv.number(ControlPlaneEnvKeys.HEDGE_EXECUTION_MAX_RETRIES, 3),
-    parallelExecution: () => true,
-    circuitBreakerThreshold: () => 5, // 连续失败5次触发熔断
-  },
-
-  // 获取完整配置(用于调试和验证)
-  getAll: () => ({
-    enabled: ControlPlaneConfig.enabled(),
-    mode: ControlPlaneConfig.mode(),
-    delta: {
-      thresholdBtc: ControlPlaneConfig.delta.thresholdBtc(),
-      checkIntervalMs: ControlPlaneConfig.delta.checkIntervalMs(),
-      tolerancePercent: ControlPlaneConfig.delta.tolerancePercent(),
-    },
-    utilization: {
-      targetMin: ControlPlaneConfig.utilization.targetMin(),
-      targetMax: ControlPlaneConfig.utilization.targetMax(),
-      checkIntervalMs: ControlPlaneConfig.utilization.checkIntervalMs(),
-      rebalanceThreshold: ControlPlaneConfig.utilization.rebalanceThreshold(),
-    },
-    marketData: {
-      primaryTimeoutMs: ControlPlaneConfig.marketData.primaryTimeoutMs(),
-      failoverDeadlineMs: ControlPlaneConfig.marketData.failoverDeadlineMs(),
-      heartbeatIntervalMs: ControlPlaneConfig.marketData.heartbeatIntervalMs(),
-    },
-    risk: {
-      maxLeverage: ControlPlaneConfig.risk.maxLeverage(),
-      maxDrawdownPercent: ControlPlaneConfig.risk.maxDrawdownPercent(),
-      slippageTolerance: ControlPlaneConfig.risk.slippageTolerance(),
-      emergencyStopLossSeconds: ControlPlaneConfig.risk.emergencyStopLossSeconds(),
-    },
-    strategy: {
-      enabled: ControlPlaneConfig.strategy.enabled(),
-      maxConcurrent: ControlPlaneConfig.strategy.maxConcurrent(),
-      profitTarget: ControlPlaneConfig.strategy.profitTarget(),
-      sandboxEnabled: ControlPlaneConfig.strategy.sandboxEnabled(),
-    },
-    monitoring: {
-      enabled: ControlPlaneConfig.monitoring.enabled(),
-      auditLogRetentionDays: ControlPlaneConfig.monitoring.auditLogRetentionDays(),
-    },
-    accountSync: {
-      intervalMs: ControlPlaneConfig.accountSync.intervalMs(),
-      timeoutMs: ControlPlaneConfig.accountSync.timeoutMs(),
-    },
-    hedgeExecution: {
-      timeoutMs: ControlPlaneConfig.hedgeExecution.timeoutMs(),
-      maxRetries: ControlPlaneConfig.hedgeExecution.maxRetries(),
-    },
-  }),
-
-  // 验证配置完整性
-  validate: (): { isValid: boolean; errors: string[] } => {
-    const errors: string[] = []
-
-    // 验证 Delta 配置
-    if (ControlPlaneConfig.delta.thresholdBtc() <= 0) {
-      errors.push('DELTA_THRESHOLD_BTC must be positive')
-    }
-
-    // 验证利用率配置
-    const minUtil = ControlPlaneConfig.utilization.targetMin()
-    const maxUtil = ControlPlaneConfig.utilization.targetMax()
-    if (minUtil >= maxUtil) {
-      errors.push('UTILIZATION_TARGET_MIN must be less than UTILIZATION_TARGET_MAX')
-    }
-    if (minUtil < 0 || minUtil > 1) {
-      errors.push('UTILIZATION_TARGET_MIN must be between 0 and 1')
-    }
-    if (maxUtil < 0 || maxUtil > 1) {
-      errors.push('UTILIZATION_TARGET_MAX must be between 0 and 1')
-    }
-
-    // 验证行情配置
-    if (ControlPlaneConfig.marketData.failoverDeadlineMs() <= ControlPlaneConfig.marketData.primaryTimeoutMs()) {
-      errors.push('MARKET_DATA_FAILOVER_DEADLINE_MS must be greater than MARKET_DATA_PRIMARY_TIMEOUT_MS')
-    }
-
-    // 验证风险配置
-    if (ControlPlaneConfig.risk.maxLeverage() <= 0) {
-      errors.push('MAX_LEVERAGE must be positive')
-    }
-    if (ControlPlaneConfig.risk.maxDrawdownPercent() <= 0 || ControlPlaneConfig.risk.maxDrawdownPercent() > 100) {
-      errors.push('MAX_DRAWDOWN_PERCENT must be between 0 and 100')
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors,
-    }
-  },
-}

+ 0 - 277
src/config/riskTemplates.ts

@@ -1,277 +0,0 @@
-import { ControlPlaneConfig } from './controlPlaneConfig.js'
-
-/**
- * 风险包络配置模板
- * 基于 data-model.md 中的 RiskEnvelope 实体定义
- */
-
-export interface RiskEnvelopeTemplate {
-  templateId: string
-  name: string
-  description: string
-  maxDrawdownPercent: number
-  maxLeverage: number
-  deltaThreshold: number
-  slippageTolerance: number
-  emergencyStopLossSeconds: number
-  maxPositionValue: number
-  maxDailyLoss: number
-  maxConcurrentOrders: number
-  allowedExchanges: string[]
-  allowedSymbols: string[]
-  riskLevel: 'conservative' | 'moderate' | 'aggressive'
-  applicableAccountTypes: ('primary' | 'hedge' | 'backup')[]
-}
-
-/**
- * 预定义的风险包络模板
- */
-export const RiskEnvelopeTemplates: Record<string, RiskEnvelopeTemplate> = {
-  // 保守型配置 - 适合主要交易账户
-  CONSERVATIVE_PRIMARY: {
-    templateId: 'CONSERVATIVE_PRIMARY',
-    name: '保守型主要账户',
-    description: '低风险、低杠杆,适合主要交易账户的保守配置',
-    maxDrawdownPercent: 2.0,
-    maxLeverage: 1.0,
-    deltaThreshold: 0.0002, // ±0.0002 BTC
-    slippageTolerance: 0.0005, // 0.05%
-    emergencyStopLossSeconds: 15,
-    maxPositionValue: 1000, // $1000
-    maxDailyLoss: 50, // $50
-    maxConcurrentOrders: 2,
-    allowedExchanges: ['pacifica', 'aster'],
-    allowedSymbols: ['BTC', 'ETH'],
-    riskLevel: 'conservative',
-    applicableAccountTypes: ['primary'],
-  },
-
-  // 中等风险配置 - 适合对冲账户
-  MODERATE_HEDGE: {
-    templateId: 'MODERATE_HEDGE',
-    name: '中等风险对冲账户',
-    description: '中等风险,适合对冲操作的账户配置',
-    maxDrawdownPercent: 5.0,
-    maxLeverage: 2.0,
-    deltaThreshold: 0.0005, // ±0.0005 BTC
-    slippageTolerance: 0.001, // 0.1%
-    emergencyStopLossSeconds: 30,
-    maxPositionValue: 5000, // $5000
-    maxDailyLoss: 200, // $200
-    maxConcurrentOrders: 5,
-    allowedExchanges: ['pacifica', 'aster', 'binance'],
-    allowedSymbols: ['BTC', 'ETH', 'SOL'],
-    riskLevel: 'moderate',
-    applicableAccountTypes: ['hedge'],
-  },
-
-  // 激进型配置 - 适合备用账户
-  AGGRESSIVE_BACKUP: {
-    templateId: 'AGGRESSIVE_BACKUP',
-    name: '激进型备用账户',
-    description: '高风险、高杠杆,适合备用账户的激进配置',
-    maxDrawdownPercent: 10.0,
-    maxLeverage: 5.0,
-    deltaThreshold: 0.001, // ±0.001 BTC
-    slippageTolerance: 0.002, // 0.2%
-    emergencyStopLossSeconds: 60,
-    maxPositionValue: 10000, // $10000
-    maxDailyLoss: 500, // $500
-    maxConcurrentOrders: 10,
-    allowedExchanges: ['pacifica', 'aster', 'binance'],
-    allowedSymbols: ['BTC', 'ETH', 'SOL', 'ADA', 'DOT'],
-    riskLevel: 'aggressive',
-    applicableAccountTypes: ['backup'],
-  },
-
-  // 测试配置 - 适合沙箱环境
-  TEST_SANDBOX: {
-    templateId: 'TEST_SANDBOX',
-    name: '测试沙箱配置',
-    description: '用于测试和开发的沙箱环境配置',
-    maxDrawdownPercent: 50.0,
-    maxLeverage: 10.0,
-    deltaThreshold: 0.01, // ±0.01 BTC
-    slippageTolerance: 0.005, // 0.5%
-    emergencyStopLossSeconds: 120,
-    maxPositionValue: 100, // $100
-    maxDailyLoss: 10, // $10
-    maxConcurrentOrders: 20,
-    allowedExchanges: ['pacifica', 'aster', 'binance'],
-    allowedSymbols: ['BTC', 'ETH', 'SOL', 'ADA', 'DOT', 'MATIC', 'AVAX'],
-    riskLevel: 'conservative',
-    applicableAccountTypes: ['primary', 'hedge', 'backup'],
-  },
-
-  // 自定义配置 - 基于全局配置
-  CUSTOM_GLOBAL: {
-    templateId: 'CUSTOM_GLOBAL',
-    name: '自定义全局配置',
-    description: '基于控制平面全局配置的自定义风险包络',
-    maxDrawdownPercent: ControlPlaneConfig.risk.maxDrawdownPercent(),
-    maxLeverage: ControlPlaneConfig.risk.maxLeverage(),
-    deltaThreshold: ControlPlaneConfig.delta.thresholdBtc(),
-    slippageTolerance: ControlPlaneConfig.risk.slippageTolerance(),
-    emergencyStopLossSeconds: ControlPlaneConfig.risk.emergencyStopLossSeconds(),
-    maxPositionValue: 10000, // 默认值
-    maxDailyLoss: 500, // 默认值
-    maxConcurrentOrders: 5, // 默认值
-    allowedExchanges: ['pacifica', 'aster', 'binance'],
-    allowedSymbols: ['BTC', 'ETH', 'SOL'],
-    riskLevel: 'moderate',
-    applicableAccountTypes: ['primary', 'hedge', 'backup'],
-  },
-}
-
-/**
- * 风险包络管理器
- */
-export class RiskEnvelopeManager {
-  /**
-   * 根据账户类型和风险偏好获取合适的模板
-   */
-  static getTemplate(
-    accountType: 'primary' | 'hedge' | 'backup',
-    riskPreference?: 'conservative' | 'moderate' | 'aggressive'
-  ): RiskEnvelopeTemplate {
-    // 如果是沙箱模式,使用测试配置
-    if (ControlPlaneConfig.isSandbox() || ControlPlaneConfig.isDryRun()) {
-      return RiskEnvelopeTemplates.TEST_SANDBOX
-    }
-
-    // 根据账户类型选择默认模板
-    switch (accountType) {
-      case 'primary':
-        return riskPreference === 'aggressive' 
-          ? RiskEnvelopeTemplates.MODERATE_HEDGE 
-          : RiskEnvelopeTemplates.CONSERVATIVE_PRIMARY
-      case 'hedge':
-        return riskPreference === 'conservative'
-          ? RiskEnvelopeTemplates.CONSERVATIVE_PRIMARY
-          : RiskEnvelopeTemplates.MODERATE_HEDGE
-      case 'backup':
-        return riskPreference === 'conservative'
-          ? RiskEnvelopeTemplates.MODERATE_HEDGE
-          : RiskEnvelopeTemplates.AGGRESSIVE_BACKUP
-      default:
-        return RiskEnvelopeTemplates.CUSTOM_GLOBAL
-    }
-  }
-
-  /**
-   * 创建自定义风险包络
-   */
-  static createCustom(
-    baseTemplate: string,
-    overrides: Partial<RiskEnvelopeTemplate>
-  ): RiskEnvelopeTemplate {
-    const template = RiskEnvelopeTemplates[baseTemplate]
-    if (!template) {
-      throw new Error(`Template ${baseTemplate} not found`)
-    }
-
-    return {
-      ...template,
-      ...overrides,
-      templateId: `${baseTemplate}_CUSTOM_${Date.now()}`,
-      name: overrides.name || `${template.name} (自定义)`,
-    }
-  }
-
-  /**
-   * 验证风险包络配置
-   */
-  static validate(template: RiskEnvelopeTemplate): { isValid: boolean; errors: string[] } {
-    const errors: string[] = []
-
-    // 验证数值范围
-    if (template.maxDrawdownPercent <= 0 || template.maxDrawdownPercent > 100) {
-      errors.push('maxDrawdownPercent must be between 0 and 100')
-    }
-
-    if (template.maxLeverage <= 0) {
-      errors.push('maxLeverage must be positive')
-    }
-
-    if (template.deltaThreshold <= 0) {
-      errors.push('deltaThreshold must be positive')
-    }
-
-    if (template.slippageTolerance <= 0 || template.slippageTolerance > 1) {
-      errors.push('slippageTolerance must be between 0 and 1')
-    }
-
-    if (template.emergencyStopLossSeconds <= 0) {
-      errors.push('emergencyStopLossSeconds must be positive')
-    }
-
-    if (template.maxPositionValue <= 0) {
-      errors.push('maxPositionValue must be positive')
-    }
-
-    if (template.maxDailyLoss <= 0) {
-      errors.push('maxDailyLoss must be positive')
-    }
-
-    if (template.maxConcurrentOrders <= 0) {
-      errors.push('maxConcurrentOrders must be positive')
-    }
-
-    // 验证数组内容
-    if (template.allowedExchanges.length === 0) {
-      errors.push('allowedExchanges cannot be empty')
-    }
-
-    if (template.allowedSymbols.length === 0) {
-      errors.push('allowedSymbols cannot be empty')
-    }
-
-    if (template.applicableAccountTypes.length === 0) {
-      errors.push('applicableAccountTypes cannot be empty')
-    }
-
-    // 验证风险等级一致性
-    const riskLevelThresholds = {
-      conservative: { maxDrawdown: 5, maxLeverage: 2 },
-      moderate: { maxDrawdown: 10, maxLeverage: 5 },
-      aggressive: { maxDrawdown: 20, maxLeverage: 10 },
-    }
-
-    const threshold = riskLevelThresholds[template.riskLevel]
-    if (template.maxDrawdownPercent > threshold.maxDrawdown) {
-      errors.push(`${template.riskLevel} risk level should have maxDrawdownPercent <= ${threshold.maxDrawdown}`)
-    }
-
-    if (template.maxLeverage > threshold.maxLeverage) {
-      errors.push(`${template.riskLevel} risk level should have maxLeverage <= ${threshold.maxLeverage}`)
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors,
-    }
-  }
-
-  /**
-   * 获取所有可用模板
-   */
-  static getAllTemplates(): RiskEnvelopeTemplate[] {
-    return Object.values(RiskEnvelopeTemplates)
-  }
-
-  /**
-   * 根据风险等级筛选模板
-   */
-  static getTemplatesByRiskLevel(riskLevel: 'conservative' | 'moderate' | 'aggressive'): RiskEnvelopeTemplate[] {
-    return this.getAllTemplates().filter(template => template.riskLevel === riskLevel)
-  }
-
-  /**
-   * 根据账户类型筛选模板
-   */
-  static getTemplatesByAccountType(accountType: 'primary' | 'hedge' | 'backup'): RiskEnvelopeTemplate[] {
-    return this.getAllTemplates().filter(template => 
-      template.applicableAccountTypes.includes(accountType)
-    )
-  }
-}

+ 0 - 657
src/config/simpleEnv.ts

@@ -1,657 +0,0 @@
-import 'dotenv/config'
-
-/**
- * 简化的环境变量管理器
- * 统一处理所有环境变量读取,避免重复的 process.env 调用
- */
-export class SimpleEnv {
-  private static cache = new Map<string, string | undefined>()
-
-  /**
-   * 获取环境变量值
-   */
-  static get(key: string, defaultValue?: string): string | undefined {
-    if (this.cache.has(key)) {
-      return this.cache.get(key)
-    }
-
-    const value = process.env[key] || defaultValue
-    this.cache.set(key, value)
-    return value
-  }
-
-  /**
-   * 获取必需的环境变量值,如果不存在则抛出错误
-   */
-  static require(key: string): string {
-    const value = this.get(key)
-    if (!value) {
-      throw new Error(`Required environment variable ${key} is not set`)
-    }
-    return value
-  }
-
-  /**
-   * 获取布尔值环境变量
-   */
-  static bool(key: string, defaultValue: boolean = false): boolean {
-    const value = this.get(key)
-    if (!value) return defaultValue
-    return ['true', '1', 'yes', 'on'].includes(value.toLowerCase())
-  }
-
-  /**
-   * 获取数字环境变量
-   */
-  static number(key: string, defaultValue?: number): number | undefined {
-    const value = this.get(key)
-    if (!value) return defaultValue
-    const num = parseInt(value, 10)
-    return isNaN(num) ? defaultValue : num
-  }
-
-  /**
-   * 获取 JSON 环境变量
-   */
-  static json<T = any>(key: string, defaultValue?: T): T | undefined {
-    const value = this.get(key)
-    if (!value) return defaultValue
-    try {
-      return JSON.parse(value)
-    } catch {
-      return defaultValue
-    }
-  }
-
-  /**
-   * 获取数组环境变量(逗号分隔)
-   */
-  static array(key: string, defaultValue: string[] = []): string[] {
-    const value = this.get(key)
-    if (!value) return defaultValue
-    return value
-      .split(',')
-      .map(s => s.trim())
-      .filter(s => s.length > 0)
-  }
-
-  /**
-   * 清除缓存
-   */
-  static clearCache(): void {
-    this.cache.clear()
-  }
-
-  /**
-   * 批量获取带前缀的环境变量
-   */
-  static getPrefix(prefix: string): Record<string, string> {
-    const result: Record<string, string> = {}
-
-    Object.keys(process.env).forEach(key => {
-      if (key.startsWith(prefix)) {
-        const shortKey = key.slice(prefix.length)
-        const value = process.env[key]
-        if (value) {
-          result[shortKey] = value
-        }
-      }
-    })
-
-    return result
-  }
-}
-
-/**
- * 预定义的配置键,只包含需要从环境变量读取的配置
- */
-export const EnvKeys = {
-  // 基础配置 (可选,有默认值)
-  NODE_ENV: 'NODE_ENV',
-  LOG_LEVEL: 'LOG_LEVEL',
-
-  // Aster DEX 认证 (必需)
-  ASTER_ORDER_USER: 'ASTER_ORDER_USER',
-  ASTER_API_KEY: 'ASTER_API_KEY',
-  ASTER_API_SECRET: 'ASTER_API_SECRET',
-
-  // Aster 第二账户 (可选)
-  ASTER2_ORDER_USER: 'ASTER2_ORDER_USER',
-  ASTER2_ORDER_SIGNER: 'ASTER2_ORDER_SIGNER',
-  PRIVATE_KEY2: 'PRIVATE_KEY2',
-
-  // Pacifica DEX 认证 (必需)
-  PACIFICA_ACCOUNT: 'PACIFICA_ACCOUNT',
-  PACIFICA_ACCOUNT_PRIVATE_KEY: 'PACIFICA_ACCOUNT_PRIVATE_KEY',
-
-  // 测试配置 (可选)
-  PACIFICA_ENABLE_TEST_ORDER: 'PACIFICA_ENABLE_TEST_ORDER',
-  PACIFICA_TEST_QTY: 'PACIFICA_TEST_QTY',
-
-  // Binance (可选)
-  BINANCE_API_KEY: 'BINANCE_API_KEY',
-  BINANCE_SECRET_KEY: 'BINANCE_SECRET_KEY',
-
-  // Proxy 配置 (可选)
-  PROXY_ENABLED: 'PROXY_ENABLED',
-  PROXY_PROTOCOL: 'PROXY_PROTOCOL',
-  PROXY_HOST: 'PROXY_HOST',
-  PROXY_PORT: 'PROXY_PORT',
-  PROXY_USERNAME: 'PROXY_USERNAME',
-  PROXY_PASSWORD: 'PROXY_PASSWORD',
-
-  // 高级代理配置 (会话管理)
-  PROXY_SESSION_PREFIX: 'PROXY_SESSION_PREFIX',
-  PROXY_SESSION_SUFFIX: 'PROXY_SESSION_SUFFIX',
-  PROXY_SESSION_STATIC: 'PROXY_SESSION_STATIC',
-
-  // 交易所专用代理 (可选,优先级高于全局代理)
-  ASTER_PROXY_PROTOCOL: 'ASTER_PROXY_PROTOCOL',
-  ASTER_PROXY_HOST: 'ASTER_PROXY_HOST',
-  ASTER_PROXY_PORT: 'ASTER_PROXY_PORT',
-  ASTER_PROXY_USER: 'ASTER_PROXY_USER',
-  ASTER_PROXY_PASS: 'ASTER_PROXY_PASS',
-  ASTER_PROXY_SESSION_PREFIX: 'ASTER_PROXY_SESSION_PREFIX',
-  ASTER_PROXY_SESSION_SUFFIX: 'ASTER_PROXY_SESSION_SUFFIX',
-  ASTER_PROXY_SESSION_STATIC: 'ASTER_PROXY_SESSION_STATIC',
-
-  // Pacifica专用代理
-  PACIFICA_PROXY_PROTOCOL: 'PACIFICA_PROXY_PROTOCOL',
-  PACIFICA_PROXY_HOST: 'PACIFICA_PROXY_HOST',
-  PACIFICA_PROXY_PORT: 'PACIFICA_PROXY_PORT',
-  PACIFICA_PROXY_USER: 'PACIFICA_PROXY_USER',
-  PACIFICA_PROXY_PASS: 'PACIFICA_PROXY_PASS',
-  PACIFICA_PROXY_SESSION_PREFIX: 'PACIFICA_PROXY_SESSION_PREFIX',
-  PACIFICA_PROXY_SESSION_SUFFIX: 'PACIFICA_PROXY_SESSION_SUFFIX',
-  PACIFICA_PROXY_SESSION_STATIC: 'PACIFICA_PROXY_SESSION_STATIC',
-
-  // Binance专用代理
-  BINANCE_PROXY_PROTOCOL: 'BINANCE_PROXY_PROTOCOL',
-  BINANCE_PROXY_HOST: 'BINANCE_PROXY_HOST',
-  BINANCE_PROXY_PORT: 'BINANCE_PROXY_PORT',
-  BINANCE_PROXY_USER: 'BINANCE_PROXY_USER',
-  BINANCE_PROXY_PASS: 'BINANCE_PROXY_PASS',
-  BINANCE_PROXY_SESSION_PREFIX: 'BINANCE_PROXY_SESSION_PREFIX',
-  BINANCE_PROXY_SESSION_SUFFIX: 'BINANCE_PROXY_SESSION_SUFFIX',
-  BINANCE_PROXY_SESSION_STATIC: 'BINANCE_PROXY_SESSION_STATIC',
-} as const
-
-/**
- * 统一的配置对象 - 将固定配置写死,只有认证信息从环境变量读取
- */
-export const Config = {
-  // 基础配置
-  nodeEnv: () => SimpleEnv.get(EnvKeys.NODE_ENV, 'development'),
-  logLevel: () => SimpleEnv.get(EnvKeys.LOG_LEVEL, 'info'),
-  isDev: () => Config.nodeEnv() === 'development',
-  isProd: () => Config.nodeEnv() === 'production',
-
-  // Aster 配置 - 固定的服务端点,只有认证信息动态
-  aster: {
-    // 固定配置 - 不从环境变量读取
-    wsUrl: 'wss://fstream.asterdex.com',
-    httpBase: 'https://fapi.asterdex.com',
-    subscribeSymbols: ['BTCUSDT', 'ETHUSDT'], // 默认订阅交易对
-    wsPingInterval: 30000,
-    wsPongTimeout: 10000,
-    wsReconnectInterval: 5000,
-    wsMaxReconnectAttempts: 10,
-    recvWindow: 50000,
-
-    // 动态配置 - 从环境变量读取
-    orderUser: () => SimpleEnv.get(EnvKeys.ASTER_ORDER_USER),
-    apiKey: () => SimpleEnv.get(EnvKeys.ASTER_API_KEY),
-    apiSecret: () => SimpleEnv.get(EnvKeys.ASTER_API_SECRET),
-
-    // 第二账户
-    orderUser2: () => SimpleEnv.get(EnvKeys.ASTER2_ORDER_USER),
-    orderSigner2: () => SimpleEnv.get(EnvKeys.ASTER2_ORDER_SIGNER),
-    privateKey2: () => SimpleEnv.get(EnvKeys.PRIVATE_KEY2),
-  },
-
-  // Pacifica 配置 - 固定的服务端点,只有认证信息动态
-  pacifica: {
-    // 固定配置 - 不从环境变量读取
-    baseUrl: 'https://api.pacifica.fi',
-    wsUrl: 'wss://ws.pacifica.fi/ws',
-    symbol: 'BTC-USD', // 默认交易对
-    defaultQty: 0.001, // 默认交易数量
-
-    // 动态配置 - 从环境变量读取
-    account: () => SimpleEnv.get(EnvKeys.PACIFICA_ACCOUNT),
-    accountPrivateKey: () => SimpleEnv.get(EnvKeys.PACIFICA_ACCOUNT_PRIVATE_KEY),
-    enableTestOrder: () => SimpleEnv.bool(EnvKeys.PACIFICA_ENABLE_TEST_ORDER, false),
-    testQty: () => SimpleEnv.number(EnvKeys.PACIFICA_TEST_QTY, 0.001),
-  },
-
-  // Binance 配置 - 只有认证信息
-  binance: {
-    // 固定配置
-    baseUrl: 'https://api.binance.com',
-    wsUrl: 'wss://stream.binance.com:9443/ws',
-
-    // 动态配置
-    apiKey: () => SimpleEnv.get(EnvKeys.BINANCE_API_KEY),
-    secretKey: () => SimpleEnv.get(EnvKeys.BINANCE_SECRET_KEY),
-  },
-
-  // Proxy 配置 - 支持全局和交易所专用代理
-  proxy: {
-    // 全局代理配置
-    enabled: () => SimpleEnv.bool(EnvKeys.PROXY_ENABLED, false),
-    protocol: () => SimpleEnv.get(EnvKeys.PROXY_PROTOCOL, 'http'),
-    host: () => SimpleEnv.get(EnvKeys.PROXY_HOST),
-    port: () => SimpleEnv.number(EnvKeys.PROXY_PORT, 8080),
-    username: () => SimpleEnv.get(EnvKeys.PROXY_USERNAME),
-    password: () => SimpleEnv.get(EnvKeys.PROXY_PASSWORD),
-
-    // 会话管理 (高级功能)
-    sessionPrefix: () => SimpleEnv.get(EnvKeys.PROXY_SESSION_PREFIX),
-    sessionSuffix: () => SimpleEnv.get(EnvKeys.PROXY_SESSION_SUFFIX),
-    sessionStatic: () => SimpleEnv.get(EnvKeys.PROXY_SESSION_STATIC),
-
-    // 交易所专用代理配置
-    aster: {
-      protocol: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_PROTOCOL, 'http'),
-      host: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_HOST),
-      port: () => SimpleEnv.number(EnvKeys.ASTER_PROXY_PORT, 12321),
-      user: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_USER),
-      pass: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_PASS),
-      sessionPrefix: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_SESSION_PREFIX),
-      sessionSuffix: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_SESSION_SUFFIX),
-      sessionStatic: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_SESSION_STATIC),
-
-      isConfigured: (): boolean => {
-        return !!Config.proxy.aster.host() && !!Config.proxy.aster.user()
-      },
-    },
-
-    pacifica: {
-      protocol: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_PROTOCOL, 'http'),
-      host: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_HOST),
-      port: () => SimpleEnv.number(EnvKeys.PACIFICA_PROXY_PORT, 8080),
-      user: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_USER),
-      pass: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_PASS),
-      sessionPrefix: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_SESSION_PREFIX),
-      sessionSuffix: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_SESSION_SUFFIX),
-      sessionStatic: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_SESSION_STATIC),
-
-      isConfigured: (): boolean => {
-        return !!Config.proxy.pacifica.host() && !!Config.proxy.pacifica.user()
-      },
-    },
-
-    binance: {
-      protocol: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_PROTOCOL, 'http'),
-      host: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_HOST),
-      port: () => SimpleEnv.number(EnvKeys.BINANCE_PROXY_PORT, 8080),
-      user: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_USER),
-      pass: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_PASS),
-      sessionPrefix: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_SESSION_PREFIX),
-      sessionSuffix: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_SESSION_SUFFIX),
-      sessionStatic: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_SESSION_STATIC),
-
-      isConfigured: (): boolean => {
-        return !!Config.proxy.binance.host() && !!Config.proxy.binance.user()
-      },
-    },
-
-    // 生成随机会话ID (8位字符)
-    generateSessionId: (): string => {
-      const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
-      let result = ''
-      for (let i = 0; i < 8; i++) {
-        result += chars.charAt(Math.floor(Math.random() * chars.length))
-      }
-      return result
-    },
-
-    // 构建代理密码 (支持会话管理)
-    buildPassword: (exchange?: 'aster' | 'pacifica' | 'binance'): string | undefined => {
-      let config: any
-
-      // 优先使用交易所专用配置
-      if (exchange === 'aster' && Config.proxy.aster.isConfigured()) {
-        config = {
-          pass: Config.proxy.aster.pass(),
-          prefix: Config.proxy.aster.sessionPrefix(),
-          suffix: Config.proxy.aster.sessionSuffix(),
-          static: Config.proxy.aster.sessionStatic(),
-        }
-      } else if (exchange === 'pacifica' && Config.proxy.pacifica.isConfigured()) {
-        config = {
-          pass: Config.proxy.pacifica.pass(),
-          prefix: Config.proxy.pacifica.sessionPrefix(),
-          suffix: Config.proxy.pacifica.sessionSuffix(),
-          static: Config.proxy.pacifica.sessionStatic(),
-        }
-      } else if (exchange === 'binance' && Config.proxy.binance.isConfigured()) {
-        config = {
-          pass: Config.proxy.binance.pass(),
-          prefix: Config.proxy.binance.sessionPrefix(),
-          suffix: Config.proxy.binance.sessionSuffix(),
-          static: Config.proxy.binance.sessionStatic(),
-        }
-      } else {
-        // 使用全局配置,如果没有则尝试使用ASTER配置作为回退
-        config = {
-          pass: Config.proxy.password() || Config.proxy.aster.pass(),
-          prefix: Config.proxy.sessionPrefix() || Config.proxy.aster.sessionPrefix(),
-          suffix: Config.proxy.sessionSuffix() || Config.proxy.aster.sessionSuffix(),
-          static: Config.proxy.sessionStatic() || Config.proxy.aster.sessionStatic(),
-        }
-      }
-
-      // 方式一:直接使用完整密码
-      if (config.pass) {
-        return config.pass
-      }
-
-      // 方式二:使用前后缀+会话ID
-      if (config.prefix && config.suffix) {
-        const sessionId = config.static || Config.proxy.generateSessionId()
-        return `${config.prefix}${sessionId}${config.suffix}`
-      }
-
-      return undefined
-    },
-
-    // 获取代理URL (支持交易所专用配置)
-    getUrl: (exchange?: 'aster' | 'pacifica' | 'binance'): string | undefined => {
-      let proxyConfig: any
-
-      // 优先使用交易所专用代理
-      if (exchange === 'aster' && Config.proxy.aster.isConfigured()) {
-        proxyConfig = {
-          protocol: Config.proxy.aster.protocol(),
-          host: Config.proxy.aster.host(),
-          port: Config.proxy.aster.port(),
-          username: Config.proxy.aster.user(),
-          password: Config.proxy.buildPassword('aster'),
-        }
-      } else if (exchange === 'pacifica' && Config.proxy.pacifica.isConfigured()) {
-        proxyConfig = {
-          protocol: Config.proxy.pacifica.protocol(),
-          host: Config.proxy.pacifica.host(),
-          port: Config.proxy.pacifica.port(),
-          username: Config.proxy.pacifica.user(),
-          password: Config.proxy.buildPassword('pacifica'),
-        }
-      } else if (exchange === 'binance' && Config.proxy.binance.isConfigured()) {
-        proxyConfig = {
-          protocol: Config.proxy.binance.protocol(),
-          host: Config.proxy.binance.host(),
-          port: Config.proxy.binance.port(),
-          username: Config.proxy.binance.user(),
-          password: Config.proxy.buildPassword('binance'),
-        }
-      } else if (Config.proxy.enabled() && Config.proxy.host()) {
-        // 全局代理
-        proxyConfig = {
-          protocol: Config.proxy.protocol(),
-          host: Config.proxy.host(),
-          port: Config.proxy.port(),
-          username: Config.proxy.username() || Config.proxy.aster.user(),
-          password: Config.proxy.buildPassword(),
-        }
-      } else if (Config.proxy.aster.isConfigured()) {
-        // 回退使用ASTER代理配置作为全局代理
-        proxyConfig = {
-          protocol: Config.proxy.aster.protocol(),
-          host: Config.proxy.aster.host(),
-          port: Config.proxy.aster.port(),
-          username: Config.proxy.aster.user(),
-          password: Config.proxy.buildPassword(),
-        }
-      } else {
-        return undefined
-      }
-
-      const { protocol, host, port, username, password } = proxyConfig
-
-      if (username && password) {
-        return `${protocol}://${username}:${password}@${host}:${port}`
-      } else {
-        return `${protocol}://${host}:${port}`
-      }
-    },
-
-    // 检查代理是否配置 (全局或交易所专用)
-    isConfigured: (exchange?: 'aster' | 'pacifica' | 'binance'): boolean => {
-      if (exchange === 'aster') {
-        return Config.proxy.aster.isConfigured()
-      } else if (exchange === 'pacifica') {
-        return Config.proxy.pacifica.isConfigured()
-      } else if (exchange === 'binance') {
-        return Config.proxy.binance.isConfigured()
-      }
-      return Config.proxy.enabled() && !!Config.proxy.host()
-    },
-
-    // 检查任何代理是否配置
-    isAnyConfigured: (): boolean => {
-      return (
-        Config.proxy.isConfigured() ||
-        Config.proxy.aster.isConfigured() ||
-        Config.proxy.pacifica.isConfigured() ||
-        Config.proxy.binance.isConfigured()
-      )
-    },
-  },
-
-  // 获取所有配置(用于调试)
-  getAll: () => ({
-    nodeEnv: Config.nodeEnv(),
-    logLevel: Config.logLevel(),
-    aster: {
-      wsUrl: Config.aster.wsUrl,
-      httpBase: Config.aster.httpBase,
-      subscribeSymbols: Config.aster.subscribeSymbols,
-      orderUser: Config.aster.orderUser() ? '已设置' : '未设置',
-      apiKey: Config.aster.apiKey() ? '已设置' : '未设置',
-    },
-    pacifica: {
-      baseUrl: Config.pacifica.baseUrl,
-      wsUrl: Config.pacifica.wsUrl,
-      symbol: Config.pacifica.symbol,
-      account: Config.pacifica.account() ? '已设置' : '未设置',
-      enableTestOrder: Config.pacifica.enableTestOrder(),
-    },
-    binance: {
-      baseUrl: Config.binance.baseUrl,
-      wsUrl: Config.binance.wsUrl,
-      apiKey: Config.binance.apiKey() ? '已设置' : '未设置',
-    },
-    proxy: {
-      enabled: Config.proxy.enabled(),
-      configured: Config.proxy.isConfigured(),
-      url: Config.proxy.getUrl() ? '已配置' : '未配置',
-    },
-  }),
-}
-
-/**
- * 智能账户发现器 - 简化版
- */
-export class SmartAccountDiscovery {
-  /**
-   * 发现 Pacifica 账户
-   */
-  static discoverPacifica(): Array<{
-    name: string
-    account: string
-    privateKey: string
-    suffix: string
-  }> {
-    const accounts: Array<{
-      name: string
-      account: string
-      privateKey: string
-      suffix: string
-    }> = []
-
-    // 检查基础账户
-    const baseAccount = SimpleEnv.get('PACIFICA_ACCOUNT')
-    const baseKey = SimpleEnv.get('PACIFICA_ACCOUNT_PRIVATE_KEY')
-    if (baseAccount && baseKey) {
-      accounts.push({
-        name: 'Pacifica Main',
-        account: baseAccount,
-        privateKey: baseKey,
-        suffix: '',
-      })
-    }
-
-    // 检查编号账户 (1-5)
-    for (let i = 1; i <= 5; i++) {
-      const account = SimpleEnv.get(`PACIFICA_ACCOUNT_${i}`)
-      const key = SimpleEnv.get(`PACIFICA_PRIVATE_KEY_${i}`)
-      if (account && key) {
-        accounts.push({
-          name: `Pacifica ${i}`,
-          account,
-          privateKey: key,
-          suffix: `_${i}`,
-        })
-      }
-    }
-
-    // 检查角色账户
-    const roles = ['MAIN', 'HEDGE', 'BACKUP']
-    roles.forEach(role => {
-      const account = SimpleEnv.get(`PACIFICA_ACCOUNT_${role}`)
-      const key = SimpleEnv.get(`PACIFICA_PRIVATE_KEY_${role}`)
-      if (account && key) {
-        accounts.push({
-          name: `Pacifica ${role.toLowerCase()}`,
-          account,
-          privateKey: key,
-          suffix: `_${role}`,
-        })
-      }
-    })
-
-    return accounts
-  }
-
-  /**
-   * 发现 Aster 账户
-   */
-  static discoverAster(): Array<{
-    name: string
-    user: string
-    signer?: string
-    privateKey: string
-    suffix: string
-  }> {
-    const accounts: Array<{
-      name: string
-      user: string
-      signer?: string
-      privateKey: string
-      suffix: string
-    }> = []
-
-    // 检查基础账户
-    const baseUser = SimpleEnv.get('ASTER_ORDER_USER')
-    const baseSigner = SimpleEnv.get('ASTER_ORDER_SIGNER')
-    const baseKey = SimpleEnv.get('PRIVATE_KEY')
-    if (baseUser && baseKey) {
-      accounts.push({
-        name: 'Aster Main',
-        user: baseUser,
-        signer: baseSigner,
-        privateKey: baseKey,
-        suffix: '',
-      })
-    }
-
-    // 检查第二账户
-    const user2 = SimpleEnv.get('ASTER2_ORDER_USER')
-    const signer2 = SimpleEnv.get('ASTER2_ORDER_SIGNER')
-    const key2 = SimpleEnv.get('PRIVATE_KEY2')
-    if (user2 && key2) {
-      accounts.push({
-        name: 'Aster 2',
-        user: user2,
-        signer: signer2,
-        privateKey: key2,
-        suffix: '_2',
-      })
-    }
-
-    // 检查编号账户 (1-3)
-    for (let i = 1; i <= 3; i++) {
-      const user = SimpleEnv.get(`ASTER_ORDER_USER_${i}`)
-      const signer = SimpleEnv.get(`ASTER_ORDER_SIGNER_${i}`)
-      const key = SimpleEnv.get(`ASTER_PRIVATE_KEY_${i}`)
-      if (user && key) {
-        accounts.push({
-          name: `Aster ${i}`,
-          user,
-          signer,
-          privateKey: key,
-          suffix: `_${i}`,
-        })
-      }
-    }
-
-    return accounts
-  }
-
-  /**
-   * 发现 Binance 账户
-   */
-  static discoverBinance(): Array<{
-    name: string
-    apiKey: string
-    secretKey: string
-    suffix: string
-  }> {
-    const accounts: Array<{
-      name: string
-      apiKey: string
-      secretKey: string
-      suffix: string
-    }> = []
-
-    // 检查基础账户
-    const baseKey = SimpleEnv.get('BINANCE_API_KEY')
-    const baseSecret = SimpleEnv.get('BINANCE_SECRET_KEY')
-    if (baseKey && baseSecret) {
-      accounts.push({
-        name: 'Binance Main',
-        apiKey: baseKey,
-        secretKey: baseSecret,
-        suffix: '',
-      })
-    }
-
-    // 检查编号账户 (1-3)
-    for (let i = 1; i <= 3; i++) {
-      const key = SimpleEnv.get(`BINANCE_API_KEY_${i}`)
-      const secret = SimpleEnv.get(`BINANCE_SECRET_KEY_${i}`)
-      if (key && secret) {
-        accounts.push({
-          name: `Binance ${i}`,
-          apiKey: key,
-          secretKey: secret,
-          suffix: `_${i}`,
-        })
-      }
-    }
-
-    return accounts
-  }
-
-  /**
-   * 发现所有账户
-   */
-  static discoverAll() {
-    return {
-      pacifica: this.discoverPacifica(),
-      aster: this.discoverAster(),
-      binance: this.discoverBinance(),
-    }
-  }
-}

+ 0 - 41
src/constants/index.ts

@@ -1,41 +0,0 @@
-// 常量与枚举
-
-export enum OrderSide {
-  BUY = 'buy',
-  SELL = 'sell',
-}
-
-export enum PositionSide {
-  LONG = 'long',
-  SHORT = 'short',
-}
-
-export enum OrderType {
-  MARKET = 'market',
-  LIMIT = 'limit',
-  STOP = 'stop',
-  STOP_MARKET = 'stop_market',
-}
-
-export enum Severity {
-  LOW = 'low',
-  MEDIUM = 'medium',
-  HIGH = 'high',
-  CRITICAL = 'critical',
-}
-
-export const DEFAULT_WS_URL = 'wss://fstream.binance.com/ws'
-
-export const DEFAULT_RECONNECT_MS = 5000
-export const DEFAULT_MAX_RECONNECT = 10
-
-export const SUPPORTED_INTERVALS = ['1m', '5m', '15m', '1h', '4h', '1d']
-
-export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
-
-export const CHAIN_IDS = {
-  ETHEREUM: 1,
-  ARBITRUM: 42161,
-  POLYGON: 137,
-  BSC: 56,
-}

+ 0 - 37
src/infrastructure/config/configManager.ts

@@ -1,37 +0,0 @@
-import 'dotenv/config'
-
-export interface AppConfig {
-  NODE_ENV: string
-  RPC_URL?: string
-  PRIVATE_KEY?: string
-  REDIS_URL?: string
-  PG_URL?: string
-  TELEGRAM_BOT_TOKEN?: string
-  TELEGRAM_CHAT_ID?: string
-}
-
-class ConfigManager {
-  private config: AppConfig
-
-  constructor() {
-    this.config = {
-      NODE_ENV: process.env.NODE_ENV || 'development',
-      RPC_URL: process.env.RPC_URL,
-      PRIVATE_KEY: process.env.PRIVATE_KEY,
-      REDIS_URL: process.env.REDIS_URL,
-      PG_URL: process.env.PG_URL,
-      TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN,
-      TELEGRAM_CHAT_ID: process.env.TELEGRAM_CHAT_ID,
-    }
-  }
-
-  get<T extends keyof AppConfig>(key: T): AppConfig[T] {
-    return this.config[key]
-  }
-
-  getAll(): AppConfig {
-    return { ...this.config }
-  }
-}
-
-export const configManager = new ConfigManager()

+ 0 - 31
src/infrastructure/config/default.example.yaml

@@ -1,31 +0,0 @@
-networks:
-  arbitrum:
-    chainId: 42161
-    rpcUrl: ${RPC_URL}
-    explorerUrl: https://arbiscan.io
-    gasPrice: 0
-
-apis:
-  chainlink:
-    feeds:
-      BTCUSDT: '0x0000000000000000000000000000000000000000'
-
-risk:
-  maxLeverage: 5
-  maxPositionSize: 100000
-  maxDrawdown: 0.05
-  minMarginRatio: 0.1
-  maxSlippage: 0.003
-
-trading:
-  defaultSlippage: 0.001
-  minOrderValue: 10
-  maxOrderValue: 100000
-  rebalanceInterval: 60
-  hedgeThreshold: 0.01
-
-monitoring:
-  alertCooldown: 30
-  metricsInterval: 10
-  healthCheckInterval: 15
-  logLevel: info

+ 0 - 14
src/infrastructure/database/index.ts

@@ -1,14 +0,0 @@
-export interface Db {
-  connected: boolean
-}
-
-class Database implements Db {
-  connected = false
-
-  async connect(): Promise<void> {
-    // TODO: 集成 Sequelize/Prisma
-    this.connected = true
-  }
-}
-
-export const db = new Database()

+ 0 - 239
src/infrastructure/health/HealthAPI.ts

@@ -1,239 +0,0 @@
-import { createServer, IncomingMessage, ServerResponse } from 'http'
-import { URL } from 'url'
-import { HealthChecker, SystemHealth } from './HealthChecker.js'
-
-export interface HealthAPIConfig {
-  port: number
-  host?: string
-  enableDetailedResponse?: boolean
-}
-
-export class HealthAPI {
-  private server: ReturnType<typeof createServer>
-  private healthChecker: HealthChecker
-  private config: HealthAPIConfig
-
-  constructor(healthChecker: HealthChecker, config: HealthAPIConfig) {
-    this.healthChecker = healthChecker
-    this.config = {
-      host: 'localhost',
-      enableDetailedResponse: true,
-      ...config,
-    }
-
-    this.server = createServer(this.handleRequest.bind(this))
-  }
-
-  /**
-   * 启动健康检查 API 服务器
-   */
-  async start(): Promise<void> {
-    return new Promise((resolve, reject) => {
-      this.server.listen(this.config.port, this.config.host, () => {
-        console.log(`🏥 健康检查 API 服务启动: http://${this.config.host}:${this.config.port}`)
-        resolve()
-      })
-
-      this.server.on('error', error => {
-        console.error('健康检查 API 服务器错误:', error)
-        reject(error)
-      })
-    })
-  }
-
-  /**
-   * 停止健康检查 API 服务器
-   */
-  async stop(): Promise<void> {
-    return new Promise(resolve => {
-      this.server.close(() => {
-        console.log('🏥 健康检查 API 服务已停止')
-        resolve()
-      })
-    })
-  }
-
-  /**
-   * 处理 HTTP 请求
-   */
-  private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    // 设置 CORS 头
-    res.setHeader('Access-Control-Allow-Origin', '*')
-    res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')
-    res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
-    res.setHeader('Content-Type', 'application/json')
-
-    // 处理 OPTIONS 请求
-    if (req.method === 'OPTIONS') {
-      res.statusCode = 200
-      res.end()
-      return
-    }
-
-    // 只支持 GET 请求
-    if (req.method !== 'GET') {
-      res.statusCode = 405
-      res.end(JSON.stringify({ error: 'Method not allowed' }))
-      return
-    }
-
-    try {
-      const url = new URL(req.url!, `http://${req.headers.host}`)
-      const path = url.pathname
-
-      switch (path) {
-        case '/health':
-          await this.handleHealthCheck(req, res)
-          break
-        case '/health/summary':
-          await this.handleHealthSummary(req, res)
-          break
-        case '/health/live':
-          await this.handleLivenessCheck(req, res)
-          break
-        case '/health/ready':
-          await this.handleReadinessCheck(req, res)
-          break
-        default:
-          res.statusCode = 404
-          res.end(
-            JSON.stringify({
-              error: 'Not found',
-              availableEndpoints: ['/health', '/health/summary', '/health/live', '/health/ready'],
-            }),
-          )
-      }
-    } catch (error: any) {
-      console.error('健康检查 API 处理错误:', error)
-      res.statusCode = 500
-      res.end(JSON.stringify({ error: 'Internal server error' }))
-    }
-  }
-
-  /**
-   * 处理完整健康检查请求
-   */
-  private async handleHealthCheck(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    const health = await this.healthChecker.performHealthCheck()
-
-    // 根据健康状态设置 HTTP 状态码
-    switch (health.status) {
-      case 'healthy':
-        res.statusCode = 200
-        break
-      case 'degraded':
-        res.statusCode = 200 // 或者 206 Partial Content
-        break
-      case 'unhealthy':
-        res.statusCode = 503 // Service Unavailable
-        break
-    }
-
-    if (this.config.enableDetailedResponse) {
-      res.end(JSON.stringify(health, null, 2))
-    } else {
-      res.end(
-        JSON.stringify({
-          status: health.status,
-          timestamp: health.timestamp,
-          uptime: health.uptime,
-        }),
-      )
-    }
-  }
-
-  /**
-   * 处理健康检查摘要请求
-   */
-  private async handleHealthSummary(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    const summary = this.healthChecker.getHealthSummary()
-
-    res.statusCode = summary.status === 'healthy' ? 200 : 503
-    res.end(JSON.stringify(summary, null, 2))
-  }
-
-  /**
-   * 处理存活性检查 (Liveness Probe)
-   * 检查应用程序是否还在运行
-   */
-  private async handleLivenessCheck(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    // 简单检查:如果能响应请求,就说明应用程序是存活的
-    const response = {
-      status: 'alive',
-      timestamp: new Date().toISOString(),
-      uptime: process.uptime(),
-      pid: process.pid,
-    }
-
-    res.statusCode = 200
-    res.end(JSON.stringify(response))
-  }
-
-  /**
-   * 处理就绪性检查 (Readiness Probe)
-   * 检查应用程序是否准备好接收流量
-   */
-  private async handleReadinessCheck(req: IncomingMessage, res: ServerResponse): Promise<void> {
-    const lastHealthCheck = this.healthChecker.getLastHealthCheck()
-
-    if (!lastHealthCheck) {
-      res.statusCode = 503
-      res.end(
-        JSON.stringify({
-          status: 'not_ready',
-          reason: '尚未完成初始健康检查',
-        }),
-      )
-      return
-    }
-
-    // 检查是否准备好
-    const isReady = this.isSystemReady(lastHealthCheck)
-
-    res.statusCode = isReady ? 200 : 503
-    res.end(
-      JSON.stringify({
-        status: isReady ? 'ready' : 'not_ready',
-        timestamp: lastHealthCheck.timestamp,
-        exchanges: Object.keys(lastHealthCheck.exchanges).length,
-        accounts: Object.keys(lastHealthCheck.accounts).length,
-        overallHealth: lastHealthCheck.status,
-      }),
-    )
-  }
-
-  /**
-   * 判断系统是否就绪
-   */
-  private isSystemReady(health: SystemHealth): boolean {
-    // 至少需要有一个健康的交易所连接
-    const healthyExchanges = Object.values(health.exchanges).filter(ex => ex.status !== 'unhealthy')
-    if (healthyExchanges.length === 0) {
-      return false
-    }
-
-    // 系统整体状态不能是不健康
-    if (health.status === 'unhealthy') {
-      return false
-    }
-
-    // 内存使用不能超过 95%
-    const memoryUsage = (health.memory.used / health.memory.total) * 100
-    if (memoryUsage > 95) {
-      return false
-    }
-
-    return true
-  }
-
-  /**
-   * 获取服务器信息
-   */
-  getServerInfo() {
-    return {
-      host: this.config.host,
-      port: this.config.port,
-      running: this.server.listening,
-    }
-  }
-}

+ 0 - 321
src/infrastructure/health/HealthChecker.ts

@@ -1,321 +0,0 @@
-import { EventEmitter } from 'events'
-import { ExchangeAdapter } from '../../exchanges/ExchangeAdapter.js'
-
-export interface ExchangeHealth {
-  status: 'healthy' | 'degraded' | 'unhealthy'
-  connected: boolean
-  lastPing?: number
-  errorCount: number
-  lastError?: string
-}
-
-export interface AccountHealth {
-  status: 'healthy' | 'degraded' | 'unhealthy'
-  exchange: string
-  accountId: string
-  balanceAccessible: boolean
-  lastUpdate?: Date
-  lastError?: string
-  errorCount: number
-}
-
-export interface SystemHealth {
-  status: 'healthy' | 'degraded' | 'unhealthy'
-  timestamp: Date
-  uptime: number
-  exchanges: Record<string, ExchangeHealth>
-  accounts: Record<string, AccountHealth>
-  memory: {
-    used: number
-    free: number
-    total: number
-  }
-  errors: {
-    total: number
-    lastHour: number
-  }
-}
-
-export class HealthChecker extends EventEmitter {
-  private exchanges = new Map<string, ExchangeAdapter>()
-  private accountManagers = new Map<string, any>()
-  private startTime = Date.now()
-  private errorCounts = new Map<string, number>()
-  private lastHealthCheck: SystemHealth | null = null
-
-  constructor() {
-    super()
-    // 定期健康检查
-    setInterval(() => {
-      this.performHealthCheck().catch(console.error)
-    }, 30000) // 每30秒检查一次
-  }
-
-  /**
-   * 注册交易所适配器用于健康检查
-   */
-  registerExchange(name: string, adapter: ExchangeAdapter): void {
-    this.exchanges.set(name, adapter)
-
-    // 如果适配器支持事件监听,则注册错误处理
-    if (typeof (adapter as any).on === 'function') {
-      ;(adapter as any)
-        .on('error', (error: any) => {
-          this.recordError(`exchange:${name}`, error)
-        })(adapter as any)
-        .on('disconnect', () => {
-          this.emit('exchange_disconnected', { exchange: name })
-        })(adapter as any)
-        .on('connect', () => {
-          this.emit('exchange_connected', { exchange: name })
-        })
-    }
-  }
-
-  /**
-   * 注册账户管理器用于健康检查
-   */
-  registerAccountManager(name: string, manager: any): void {
-    this.accountManagers.set(name, manager)
-  }
-
-  /**
-   * 执行完整的系统健康检查
-   */
-  async performHealthCheck(): Promise<SystemHealth> {
-    const health: SystemHealth = {
-      status: 'healthy',
-      timestamp: new Date(),
-      uptime: Date.now() - this.startTime,
-      exchanges: {},
-      accounts: {},
-      memory: this.getMemoryUsage(),
-      errors: {
-        total: this.getTotalErrors(),
-        lastHour: this.getRecentErrors(),
-      },
-    }
-
-    // 检查交易所健康状态
-    for (const [name, adapter] of this.exchanges.entries()) {
-      health.exchanges[name] = await this.checkExchangeHealth(name, adapter)
-    }
-
-    // 检查账户健康状态
-    for (const [name, manager] of this.accountManagers.entries()) {
-      const accounts = await this.checkAccountHealth(name, manager)
-      Object.assign(health.accounts, accounts)
-    }
-
-    // 确定整体健康状态
-    health.status = this.determineOverallHealth(health)
-    this.lastHealthCheck = health
-
-    // 发出健康状态变化事件
-    this.emit('health_check', health)
-
-    if (health.status === 'unhealthy') {
-      this.emit('system_unhealthy', health)
-    }
-
-    return health
-  }
-
-  /**
-   * 检查单个交易所健康状态
-   */
-  private async checkExchangeHealth(name: string, adapter: ExchangeAdapter): Promise<ExchangeHealth> {
-    const health: ExchangeHealth = {
-      status: 'healthy',
-      connected: false,
-      errorCount: this.errorCounts.get(`exchange:${name}`) || 0,
-    }
-
-    try {
-      // 检查连接状态
-      const startTime = Date.now()
-
-      // 尝试获取基础信息来测试连接
-      if (typeof (adapter as any).ping === 'function') {
-        await (adapter as any).ping()
-        health.lastPing = Date.now() - startTime
-      } else {
-        // 如果没有 ping 方法,尝试获取时间或其他轻量级操作
-        await Promise.race([
-          (adapter as any).time?.() || Promise.resolve(),
-          new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000)),
-        ])
-      }
-
-      health.connected = true
-
-      // 根据延迟和错误数量判断状态
-      if (health.lastPing && health.lastPing > 2000) {
-        health.status = 'degraded'
-      } else if (health.errorCount > 10) {
-        health.status = 'degraded'
-      }
-    } catch (error: any) {
-      health.connected = false
-      health.status = 'unhealthy'
-      health.lastError = error.message
-      this.recordError(`exchange:${name}`, error)
-    }
-
-    return health
-  }
-
-  /**
-   * 检查账户健康状态
-   */
-  private async checkAccountHealth(managerName: string, manager: any): Promise<Record<string, AccountHealth>> {
-    const accountsHealth: Record<string, AccountHealth> = {}
-
-    try {
-      // 如果账户管理器有 getRegisteredAccounts 方法
-      if (typeof manager.getRegisteredAccounts === 'function') {
-        const accounts = manager.getRegisteredAccounts()
-
-        for (const account of accounts) {
-          const accountKey = `${account.exchange}:${account.accountId}`
-          accountsHealth[accountKey] = {
-            status: 'healthy',
-            exchange: account.exchange,
-            accountId: account.accountId,
-            balanceAccessible: false,
-            errorCount: this.errorCounts.get(`account:${accountKey}`) || 0,
-          }
-
-          try {
-            // 尝试获取余额来测试账户可用性
-            if (typeof manager.getBalances === 'function') {
-              await manager.getBalances(account.exchange, account.accountId)
-              accountsHealth[accountKey].balanceAccessible = true
-              accountsHealth[accountKey].lastUpdate = new Date()
-            }
-          } catch (error: any) {
-            accountsHealth[accountKey].status = 'degraded'
-            accountsHealth[accountKey].lastError = error.message
-            this.recordError(`account:${accountKey}`, error)
-          }
-        }
-      }
-    } catch (error: any) {
-      // 如果无法获取账户列表,记录错误
-      this.recordError(`manager:${managerName}`, error)
-    }
-
-    return accountsHealth
-  }
-
-  /**
-   * 确定整体健康状态
-   */
-  private determineOverallHealth(health: SystemHealth): 'healthy' | 'degraded' | 'unhealthy' {
-    const exchangeStatuses = Object.values(health.exchanges)
-    const accountStatuses = Object.values(health.accounts)
-
-    // 如果有任何交易所不健康,系统不健康
-    if (exchangeStatuses.some(ex => ex.status === 'unhealthy')) {
-      return 'unhealthy'
-    }
-
-    // 如果有超过50%的账户不健康,系统不健康
-    const unhealthyAccounts = accountStatuses.filter(acc => acc.status === 'unhealthy').length
-    if (unhealthyAccounts > accountStatuses.length * 0.5) {
-      return 'unhealthy'
-    }
-
-    // 如果有任何服务降级,系统降级
-    if (
-      exchangeStatuses.some(ex => ex.status === 'degraded') ||
-      accountStatuses.some(acc => acc.status === 'degraded')
-    ) {
-      return 'degraded'
-    }
-
-    // 检查内存使用情况
-    const memoryUsagePercent = (health.memory.used / health.memory.total) * 100
-    if (memoryUsagePercent > 90) {
-      return 'unhealthy'
-    } else if (memoryUsagePercent > 80) {
-      return 'degraded'
-    }
-
-    return 'healthy'
-  }
-
-  /**
-   * 记录错误
-   */
-  private recordError(component: string, error: any): void {
-    const current = this.errorCounts.get(component) || 0
-    this.errorCounts.set(component, current + 1)
-
-    console.error(`健康检查错误 [${component}]:`, error.message)
-  }
-
-  /**
-   * 获取内存使用情况
-   */
-  private getMemoryUsage() {
-    const usage = process.memoryUsage()
-    return {
-      used: usage.heapUsed,
-      free: usage.heapTotal - usage.heapUsed,
-      total: usage.heapTotal,
-    }
-  }
-
-  /**
-   * 获取总错误数
-   */
-  private getTotalErrors(): number {
-    return Array.from(this.errorCounts.values()).reduce((sum, count) => sum + count, 0)
-  }
-
-  /**
-   * 获取最近一小时的错误数 (简化实现)
-   */
-  private getRecentErrors(): number {
-    // 这里简化实现,实际应该基于时间窗口统计
-    return Math.floor(this.getTotalErrors() * 0.1)
-  }
-
-  /**
-   * 获取最后一次健康检查结果
-   */
-  getLastHealthCheck(): SystemHealth | null {
-    return this.lastHealthCheck
-  }
-
-  /**
-   * 检查特定组件是否健康
-   */
-  isHealthy(): boolean {
-    return this.lastHealthCheck?.status === 'healthy'
-  }
-
-  /**
-   * 获取健康检查摘要
-   */
-  getHealthSummary() {
-    const health = this.lastHealthCheck
-    if (!health) return { status: 'unknown', message: '尚未进行健康检查' }
-
-    const exchangeCount = Object.keys(health.exchanges).length
-    const healthyExchanges = Object.values(health.exchanges).filter(ex => ex.status === 'healthy').length
-    const accountCount = Object.keys(health.accounts).length
-    const healthyAccounts = Object.values(health.accounts).filter(acc => acc.status === 'healthy').length
-
-    return {
-      status: health.status,
-      uptime: health.uptime,
-      exchanges: `${healthyExchanges}/${exchangeCount} 健康`,
-      accounts: `${healthyAccounts}/${accountCount} 健康`,
-      memoryUsage: `${Math.round((health.memory.used / health.memory.total) * 100)}%`,
-      errors: health.errors.total,
-      timestamp: health.timestamp,
-    }
-  }
-}

+ 0 - 4
src/infrastructure/health/index.ts

@@ -1,4 +0,0 @@
-export { HealthChecker } from './HealthChecker.js'
-export { HealthAPI } from './HealthAPI.js'
-export type { SystemHealth, ExchangeHealth, AccountHealth } from './HealthChecker.js'
-export type { HealthAPIConfig } from './HealthAPI.js'

+ 0 - 30
src/infrastructure/wallet/walletManager.ts

@@ -1,30 +0,0 @@
-import { ethers } from 'ethers'
-import { configManager } from '../config/configManager'
-
-export class WalletManager {
-  provider: ethers.JsonRpcProvider
-  wallet: ethers.Wallet | null = null
-
-  constructor() {
-    const rpc = configManager.get('RPC_URL')
-    if (!rpc) throw new Error('RPC_URL 未配置')
-    this.provider = new ethers.JsonRpcProvider(rpc)
-
-    const pk = configManager.get('PRIVATE_KEY')
-    if (pk) {
-      this.wallet = new ethers.Wallet(pk, this.provider)
-    }
-  }
-
-  getAddress(): Promise<string> {
-    if (!this.wallet) throw new Error('钱包未初始化')
-    return this.wallet.getAddress()
-  }
-
-  getNonce(address?: string): Promise<number> {
-    const addrPromise = address ? Promise.resolve(address) : this.getAddress()
-    return addrPromise.then(addr => this.provider.getTransactionCount(addr))
-  }
-}
-
-export const walletManager = new WalletManager()

+ 0 - 1438
src/main-complete.ts.backup

@@ -1,1438 +0,0 @@
-#!/usr/bin/env tsx
-
-/**
- * 完整的多平台加密货币交易系统
- * 集成实时数据、多账户管理、同平台对冲、风险控制
- */
-
-import { EventEmitter } from 'events'
-import { Config, SmartAccountDiscovery } from './config/simpleEnv.js'
-import { PacificaProxyClient } from './exchanges/pacifica/PacificaProxyClient.js'
-import { SamePlatformHedgingManager } from './core/hedging/SamePlatformHedgingManager.js'
-import { StateManager, SystemState } from './utils/StateManager.js'
-import { logger } from './utils/logger.js'
-
-interface SystemStatus {
-  accounts: number
-  activeConnections: number
-  totalTrades: number
-  totalVolume: string
-  uptime: number
-  lastUpdate: number
-}
-
-interface TradingSignal {
-  symbol: string
-  action: 'buy' | 'sell' | 'hedge' | 'volume_boost' | 'close_position' | 'balance_accounts'
-  amount: string
-  price?: string
-  confidence: number
-  reason: string
-  reduceOnly?: boolean
-  targetAccount?: string
-}
-
-class CompleteTradingSystem extends EventEmitter {
-  private startTime: number = Date.now()
-  private accounts: any[] = []
-  private clients: Map<string, PacificaProxyClient> = new Map()
-  private hedgeManager: SamePlatformHedgingManager | null = null
-  private stateManager: StateManager
-  private isRunning: boolean = false
-  private isShuttingDown: boolean = false
-  private stats = {
-    totalTrades: 0,
-    totalVolume: 0,
-    successfulTrades: 0,
-    failedTrades: 0,
-    lastTradeTime: 0
-  }
-
-  // 账户状态跟踪
-  private accountStates = new Map<string, {
-    totalTrades: number
-    netPosition: number  // 净仓位 (正数=多头,负数=空头)
-    totalVolume: number
-    lastBalance: number
-    needsRebalance: boolean
-  }>()
-
-  // 风险控制参数
-  private riskLimits = {
-    maxPositionSize: 0.01,        // 单个仓位最大0.01 BTC
-    maxTotalExposure: 0.05,       // 总敞口不超过0.05 BTC
-    maxAccountBalance: 10000,     // 账户余额上限$10000
-    minAccountBalance: 100,       // 账户余额下限$100
-    maxDailyTrades: 50,          // 每日最多50笔交易
-    maxSlippage: 0.05,           // 最大5%滑点
-    emergencyStopLoss: 0.1,      // 10%紧急止损
-    enabled: true
-  }
-
-  constructor() {
-    super()
-    this.stateManager = new StateManager()
-    this.setupEventHandlers()
-    this.setupGracefulShutdown()
-  }
-
-  private setupEventHandlers() {
-    // 系统事件处理
-    this.on('trade_signal', this.handleTradingSignal.bind(this))
-    this.on('risk_alert', this.handleRiskAlert.bind(this))
-    this.on('system_error', this.handleSystemError.bind(this))
-  }
-
-  private setupGracefulShutdown() {
-    // 优雅关闭处理
-    process.on('SIGINT', async () => {
-      logger.info('接收到SIGINT信号,准备优雅关闭...')
-      await this.gracefulShutdown()
-      process.exit(0)
-    })
-
-    process.on('SIGTERM', async () => {
-      logger.info('接收到SIGTERM信号,准备优雅关闭...')
-      await this.gracefulShutdown()
-      process.exit(0)
-    })
-
-    // 异常处理
-    process.on('uncaughtException', async (error) => {
-      logger.error('未捕获异常,准备紧急关闭', { error: error.message })
-      await this.emergencyShutdown()
-      process.exit(1)
-    })
-
-    process.on('unhandledRejection', async (reason, promise) => {
-      logger.error('未处理的Promise拒绝', { reason, promise })
-      await this.emergencyShutdown()
-      process.exit(1)
-    })
-  }
-
-  /**
-   * 启动完整交易系统
-   */
-  async start(): Promise<void> {
-    console.log('🚀 启动完整交易系统')
-    console.log('=' .repeat(60))
-
-    try {
-      // 0. 恢复系统状态
-      await this.restoreSystemState()
-
-      // 1. 系统初始化
-      await this.initialize()
-
-      // 2. 启动核心服务
-      await this.startCoreServices()
-
-      // 3. 开始交易循环
-      this.startTradingLoop()
-
-      // 4. 启动监控面板
-      this.startDashboard()
-
-      // 5. 定期保存状态
-      this.startStateAutoSave()
-
-      this.isRunning = true
-      logger.info('✅ 交易系统已完全启动')
-
-    } catch (error: any) {
-      logger.error('❌ 系统启动失败', { error: error.message })
-      throw error
-    }
-  }
-
-  /**
-   * 系统初始化
-   */
-  private async initialize(): Promise<void> {
-    console.log('\n📋 第一步: 系统初始化')
-
-    // 检查代理配置
-    const proxyStatus = Config.proxy.isAnyConfigured()
-    console.log(`代理状态: ${proxyStatus ? '✅ 启用' : '❌ 禁用'}`)
-    logger.info('代理配置检查完成', { enabled: proxyStatus })
-
-    // 发现账户
-    this.accounts = SmartAccountDiscovery.discoverPacifica()
-    console.log(`发现 ${this.accounts.length} 个Pacifica账户`)
-
-    if (this.accounts.length === 0) {
-      throw new Error('未发现可用账户,请检查环境变量配置')
-    }
-
-    // 创建客户端连接
-    for (let i = 0; i < this.accounts.length; i++) {
-      const account = this.accounts[i]
-      const clientId = `pacifica-${i + 1}`
-
-      const client = new PacificaProxyClient({
-        account: account.account,
-        privateKey: account.privateKey
-      })
-
-      this.clients.set(clientId, client)
-      console.log(`✅ 创建客户端: ${clientId} (${account.account.substring(0, 8)}...)`)
-    }
-
-    // 测试连接
-    console.log('\n🔌 测试连接...')
-    for (const [clientId, client] of this.clients) {
-      try {
-        const result = await client.testConnection()
-        if (result.success) {
-          console.log(`✅ ${clientId}: 连接成功 (${result.latency}ms)`)
-        } else {
-          console.log(`❌ ${clientId}: 连接失败 - ${result.error}`)
-        }
-      } catch (error: any) {
-        console.log(`❌ ${clientId}: 连接异常 - ${error.message}`)
-      }
-    }
-  }
-
-  /**
-   * 启动核心服务
-   */
-  private async startCoreServices(): Promise<void> {
-    console.log('\n⚡ 第二步: 启动核心服务')
-
-    // 创建对冲管理器
-    if (this.accounts.length >= 2) {
-      console.log('创建同平台对冲管理器...')
-      this.hedgeManager = new SamePlatformHedgingManager('pacifica', this.riskLimits)
-
-      // 添加账户
-      for (let i = 0; i < Math.min(this.accounts.length, 4); i++) {
-        const account = this.accounts[i]
-        const accountId = `pacifica-${i + 1}`
-
-        this.hedgeManager.addAccount(accountId, {
-          account: account.account,
-          privateKey: account.privateKey
-        })
-
-        console.log(`✅ 添加对冲账户: ${accountId}`)
-      }
-
-      // 创建对冲对
-      if (this.accounts.length >= 2) {
-        this.hedgeManager.createHedgePair(
-          'btc-usd-hedge',
-          'pacifica-1',
-          'pacifica-2',
-          'BTC-USD',
-          1.0
-        )
-        console.log('✅ 创建BTC-USD对冲对')
-      }
-
-      // 获取对冲状态
-      const hedgeStatus = this.hedgeManager.getHedgePairStatuses()
-      console.log(`✅ 对冲系统就绪,${hedgeStatus.length} 个对冲对激活`)
-    } else {
-      console.log('⚠️ 账户数量不足,跳过对冲功能 (需要至少2个账户)')
-    }
-  }
-
-  /**
-   * 开始交易循环
-   */
-  private startTradingLoop(): void {
-    console.log('\n🔄 第三步: 启动交易引擎')
-
-    // 刷量交易信号生成器 - 频繁交易增加交易量
-    setInterval(() => {
-      this.generateTradingSignals()
-    }, 15000) // 每15秒执行一次
-
-    // 额外的高频刷量
-    setInterval(() => {
-      this.generateVolumeBoostSignals()
-    }, 8000) // 每8秒执行一次小额对冲交易
-
-    // 定期健康检查
-    setInterval(() => {
-      this.performHealthCheck()
-    }, 60000) // 每分钟检查一次
-
-    // 定期风险检查
-    setInterval(() => {
-      this.performRiskCheck()
-    }, 15000) // 每15秒检查一次
-
-    console.log('✅ 交易引擎已启动')
-  }
-
-  /**
-   * 启动实时监控面板
-   */
-  private startDashboard(): void {
-    console.log('\n📊 第四步: 启动监控面板')
-
-    // 每3秒更新一次状态 - 更频繁的刷新显示实时交易
-    setInterval(() => {
-      this.displayDashboard()
-    }, 3000)
-
-    console.log('✅ 监控面板已启动')
-
-    // 立即显示一次
-    setTimeout(() => this.displayDashboard(), 1000)
-  }
-
-  /**
-   * 生成交易信号 - 智能刷量逻辑(开仓+平仓+资金平衡)
-   */
-  private generateTradingSignals(): void {
-    const signals: TradingSignal[] = []
-    const randomFactor = Math.random()
-
-    // 初始化账户状态
-    this.initializeAccountStates()
-
-    // 检查是否需要资金平衡
-    const needsBalancing = this.checkAccountBalance()
-    if (needsBalancing) {
-      const balanceSignal = this.generateBalanceSignal()
-      if (balanceSignal) {
-        signals.push(balanceSignal)
-      }
-    }
-
-    // 80%概率生成刷量信号
-    if (randomFactor > 0.2) {
-      // 决定是开仓还是平仓
-      const shouldClosePosition = this.shouldCloseExistingPositions()
-
-      if (shouldClosePosition) {
-        // 生成平仓信号
-        const closeSignal = this.generateCloseSignal()
-        if (closeSignal) {
-          signals.push(closeSignal)
-        }
-      } else {
-        // 生成开仓信号
-        const action = randomFactor > 0.6 ? 'buy' : 'sell'
-        const amount = this.calculateTradingAmount()
-
-        signals.push({
-          symbol: 'BTC-USD',
-          action,
-          amount,
-          confidence: randomFactor,
-          reason: `刷量开仓 - ${action === 'buy' ? '买入建仓' : '卖出建仓'}`
-        })
-      }
-    }
-
-    // 对冲信号 - 但要考虑是否需要反向操作来平衡
-    if (this.hedgeManager && this.accounts.length >= 2 && randomFactor > 0.5) {
-      const hedgeSignal = this.generateSmartHedgeSignal()
-      if (hedgeSignal) {
-        signals.push(hedgeSignal)
-      }
-    }
-
-    // 发送信号
-    signals.forEach(signal => {
-      this.emit('trade_signal', signal)
-    })
-  }
-
-  /**
-   * 生成额外的刷量信号 - 专门用于增加交易量
-   */
-  private generateVolumeBoostSignals(): void {
-    // 检查是否可以进行高频刷量
-    if (!this.shouldTrade()) {
-      return
-    }
-
-    const signals: TradingSignal[] = []
-
-    // 高频对冲刷量:双向同时开仓再平仓,增加交易量但保持净仓位不变
-    if (this.hedgeManager && this.accounts.length >= 2) {
-      const boostAmount = '0.0005' // 更小的金额用于高频刷量
-
-      // 60%概率执行对冲刷量
-      if (Math.random() > 0.4) {
-        signals.push({
-          symbol: 'BTC-USD',
-          action: 'volume_boost',
-          amount: boostAmount,
-          confidence: 0.9,
-          reason: '高频刷量 - 增加交易量'
-        })
-      }
-    }
-
-    // 发送信号
-    signals.forEach(signal => {
-      this.emit('trade_signal', signal)
-    })
-  }
-
-  /**
-   * 计算交易数量 - 根据风险和流动性动态调整
-   */
-  private calculateTradingAmount(): string {
-    const baseAmount = 0.0003 // 降低基础交易量适配小余额账户
-    const randomMultiplier = 0.5 + Math.random() * 1.0 // 0.5x - 1.5x
-    const amount = baseAmount * randomMultiplier
-    return Math.max(0.0002, Math.min(0.001, amount)).toFixed(4)
-  }
-
-  /**
-   * 计算对冲数量
-   */
-  private calculateHedgeAmount(): string {
-    const baseAmount = 0.0003 // 降低对冲基础数量
-    const randomMultiplier = 0.8 + Math.random() * 0.4 // 0.8x - 1.2x
-    const amount = baseAmount * randomMultiplier
-    return Math.max(0.0002, Math.min(0.0008, amount)).toFixed(4)
-  }
-
-  /**
-   * 处理交易信号
-   */
-  private async handleTradingSignal(signal: TradingSignal): Promise<void> {
-    logger.info('收到交易信号', { signal })
-
-    // 检查是否在安静时间
-    if (!this.shouldTrade()) {
-      logger.info('当前不适合交易,忽略信号')
-      return
-    }
-
-    try {
-      if (signal.action === 'hedge' && this.hedgeManager) {
-        await this.executeHedgeSignal(signal)
-      } else if (signal.action === 'volume_boost' && this.hedgeManager) {
-        await this.executeVolumeBoost(signal)
-      } else if (signal.action === 'balance_accounts' && this.hedgeManager) {
-        await this.executeBalanceSignal(signal)
-      } else if (signal.action === 'close_position') {
-        await this.executeCloseSignal(signal)
-      } else {
-        await this.executeTradeSignal(signal)
-      }
-    } catch (error: any) {
-      logger.error('交易信号处理失败', { signal, error: error.message })
-      this.emit('system_error', { type: 'trade_execution', error, signal })
-    }
-  }
-
-  /**
-   * 初始化账户状态
-   */
-  private initializeAccountStates(): void {
-    this.accounts.forEach((account, index) => {
-      const accountId = `pacifica-${index + 1}`
-      if (!this.accountStates.has(accountId)) {
-        this.accountStates.set(accountId, {
-          totalTrades: 0,
-          netPosition: 0,
-          totalVolume: 0,
-          lastBalance: 0,
-          needsRebalance: false
-        })
-      }
-    })
-  }
-
-  /**
-   * 检查账户是否需要资金平衡
-   */
-  private checkAccountBalance(): boolean {
-    const accounts = Array.from(this.accountStates.values())
-    if (accounts.length < 2) return false
-
-    // 检查净仓位差异
-    const positions = accounts.map(a => Math.abs(a.netPosition))
-    const maxPosition = Math.max(...positions)
-    const minPosition = Math.min(...positions)
-
-    // 如果仓位差异超过阈值,需要平衡
-    return (maxPosition - minPosition) > 0.003 // 超过0.003 BTC差异
-  }
-
-  /**
-   * 生成资金平衡信号
-   */
-  private generateBalanceSignal(): TradingSignal | null {
-    const accountsArray = Array.from(this.accountStates.entries())
-    if (accountsArray.length < 2) return null
-
-    // 找到需要平衡的账户对
-    const [account1Id, account1State] = accountsArray[0]
-    const [account2Id, account2State] = accountsArray[1]
-
-    const positionDiff = account1State.netPosition - account2State.netPosition
-
-    if (Math.abs(positionDiff) > 0.003) {
-      const amount = (Math.abs(positionDiff) / 2).toFixed(4)
-
-      return {
-        symbol: 'BTC-USD',
-        action: 'balance_accounts',
-        amount,
-        confidence: 0.95,
-        reason: `资金平衡 - 调整账户仓位差异`,
-        targetAccount: positionDiff > 0 ? account1Id : account2Id,
-        reduceOnly: true
-      }
-    }
-
-    return null
-  }
-
-  /**
-   * 判断是否应该平仓
-   */
-  private shouldCloseExistingPositions(): boolean {
-    // 30%概率选择平仓而非开仓
-    if (Math.random() > 0.7) {
-      // 检查是否有足够的仓位可以平
-      const totalNetPosition = Array.from(this.accountStates.values())
-        .reduce((sum, account) => sum + Math.abs(account.netPosition), 0)
-
-      return totalNetPosition > 0.002 // 有超过0.002 BTC的仓位可以平
-    }
-
-    return false
-  }
-
-  /**
-   * 生成平仓信号
-   */
-  private generateCloseSignal(): TradingSignal | null {
-    // 找到净仓位最大的账户进行部分平仓
-    const accountsArray = Array.from(this.accountStates.entries())
-    const accountWithMaxPosition = accountsArray.reduce((max, current) => {
-      return Math.abs(current[1].netPosition) > Math.abs(max[1].netPosition) ? current : max
-    })
-
-    const [accountId, accountState] = accountWithMaxPosition
-
-    if (Math.abs(accountState.netPosition) > 0.001) {
-      const closeAmount = (Math.abs(accountState.netPosition) * 0.3).toFixed(4) // 平掉30%的仓位
-      const action = accountState.netPosition > 0 ? 'sell' : 'buy' // 反向操作平仓
-
-      return {
-        symbol: 'BTC-USD',
-        action: action as 'buy' | 'sell',
-        amount: closeAmount,
-        confidence: 0.9,
-        reason: `平仓操作 - 减少${accountState.netPosition > 0 ? '多头' : '空头'}仓位`,
-        reduceOnly: true,
-        targetAccount: accountId
-      }
-    }
-
-    return null
-  }
-
-  /**
-   * 生成智能对冲信号 - 考虑资金平衡
-   */
-  private generateSmartHedgeSignal(): TradingSignal | null {
-    if (!this.hedgeManager || this.accounts.length < 2) return null
-
-    // 检查两个账户的仓位状态
-    const accountsArray = Array.from(this.accountStates.entries())
-    const account1State = accountsArray[0]?.[1]
-    const account2State = accountsArray[1]?.[1]
-
-    if (!account1State || !account2State) return null
-
-    // 如果两个账户仓位相差太大,执行平衡对冲
-    const positionDiff = Math.abs(account1State.netPosition - account2State.netPosition)
-
-    if (positionDiff > 0.002) {
-      // 执行平衡式对冲:让仓位少的账户开仓,仓位多的账户平仓
-      const amount = Math.min(0.002, positionDiff / 2).toFixed(4)
-
-      return {
-        symbol: 'BTC-USD',
-        action: 'hedge',
-        amount,
-        confidence: 0.85,
-        reason: '平衡对冲 - 重新平衡两账户仓位'
-      }
-    }
-
-    // 常规对冲
-    return {
-      symbol: 'BTC-USD',
-      action: 'hedge',
-      amount: this.calculateHedgeAmount(),
-      confidence: 0.85,
-      reason: '常规对冲刷量'
-    }
-  }
-
-  /**
-   * 执行资金平衡信号
-   */
-  private async executeBalanceSignal(signal: TradingSignal): Promise<void> {
-    if (!this.hedgeManager || !signal.targetAccount) return
-
-    console.log(`🔄 执行资金平衡: ${signal.reason}`)
-
-    // 执行平衡交易逻辑
-    const balanceOrders = this.generateBalanceOrders(signal)
-    const results = await this.hedgeManager.executeBatchHedge(balanceOrders)
-
-    let successCount = 0
-    results.forEach((result, index) => {
-      if (result.success) {
-        successCount++
-        console.log(`✅ 平衡订单${index + 1}成功: ${result.orderId || 'N/A'}`)
-      } else {
-        console.log(`❌ 平衡订单${index + 1}失败: ${result.error}`)
-      }
-    })
-
-    this.stats.totalTrades += results.length
-    this.stats.successfulTrades += successCount
-    this.stats.failedTrades += (results.length - successCount)
-
-    console.log(`⚖️ 资金平衡完成: ${successCount}/${results.length} 成功`)
-  }
-
-  /**
-   * 执行平仓信号
-   */
-  private async executeCloseSignal(signal: TradingSignal): Promise<void> {
-    const clientId = signal.targetAccount || 'pacifica-1'
-    const client = this.clients.get(clientId)
-
-    if (!client) {
-      throw new Error(`客户端 ${clientId} 不可用`)
-    }
-
-    const side = signal.action === 'buy' ? 'bid' : 'ask'
-
-    console.log(`📉 执行平仓订单: ${signal.reason}`)
-
-    const result = await client.createMarketOrder({
-      account: this.accounts[0].account,
-      symbol: 'BTCUSDT',
-      amount: signal.amount,
-      side: side,
-      reduceOnly: true, // 强制只减仓
-      slippagePercent: '5.0'
-    })
-
-    if (result.success) {
-      this.stats.successfulTrades++
-      this.stats.totalVolume += parseFloat(signal.amount)
-      console.log(`✅ 平仓成功: ${result.data?.order_id}`)
-
-      // 更新账户状态
-      this.updateAccountState(clientId, { side, amount: signal.amount, success: true })
-    } else {
-      this.stats.failedTrades++
-      throw new Error(`平仓失败: ${result.error}`)
-    }
-
-    this.stats.totalTrades++
-    this.stats.lastTradeTime = Date.now()
-  }
-
-  /**
-   * 生成平衡订单
-   */
-  private generateBalanceOrders(signal: TradingSignal): any[] {
-    const amount = parseFloat(signal.amount) / 2
-
-    return [
-      {
-        accountId: 'pacifica-1',
-        symbol: 'BTC-USD',
-        amount,
-        side: 'bid' as const,
-        orderType: 'market' as const,
-        reason: '平衡-账户1'
-      },
-      {
-        accountId: 'pacifica-2',
-        symbol: 'BTC-USD',
-        amount,
-        side: 'ask' as const,
-        orderType: 'market' as const,
-        reason: '平衡-账户2'
-      }
-    ]
-  }
-
-  /**
-   * 更新账户状态
-   */
-  private updateAccountState(accountId: string, trade: { side: string; amount: string; success: boolean }): void {
-    const state = this.accountStates.get(accountId)
-    if (!state) return
-
-    state.totalTrades++
-
-    if (trade.success) {
-      const amount = parseFloat(trade.amount)
-      state.totalVolume += amount
-
-      // 更新净仓位
-      if (trade.side === 'bid') {
-        state.netPosition += amount // 买入增加多头仓位
-      } else if (trade.side === 'ask') {
-        state.netPosition -= amount // 卖出增加空头仓位(或减少多头)
-      }
-    }
-
-    this.accountStates.set(accountId, state)
-  }
-
-  /**
-   * 执行对冲信号
-   */
-  private async executeHedgeSignal(signal: TradingSignal): Promise<void> {
-    if (!this.hedgeManager) return
-
-    const batchOrders = [
-      {
-        accountId: 'pacifica-1',
-        symbol: 'BTC-USD',
-        amount: parseFloat(signal.amount),
-        side: 'bid' as const,
-        orderType: 'market' as const
-      },
-      {
-        accountId: 'pacifica-2',
-        symbol: 'BTC-USD',
-        amount: parseFloat(signal.amount),
-        side: 'ask' as const,
-        orderType: 'market' as const
-      }
-    ]
-
-    logger.info('执行对冲订单', { orders: batchOrders.length })
-
-    const results = await this.hedgeManager.executeBatchHedge(batchOrders)
-
-    let successCount = 0
-    results.forEach((result, index) => {
-      if (result.success) {
-        successCount++
-        this.stats.successfulTrades++
-        logger.info(`对冲订单${index + 1}成功`, { orderId: result.orderId })
-      } else {
-        this.stats.failedTrades++
-        logger.error(`对冲订单${index + 1}失败`, { error: result.error })
-      }
-    })
-
-    this.stats.totalTrades += results.length
-    this.stats.lastTradeTime = Date.now()
-
-    console.log(`🔄 对冲执行完成: ${successCount}/${results.length} 成功`)
-  }
-
-  /**
-   * 执行刷量信号 - 高频小额对冲交易
-   */
-  private async executeVolumeBoost(signal: TradingSignal): Promise<void> {
-    if (!this.hedgeManager || this.accounts.length < 2) return
-
-    // 生成高频刷量序列:快速开仓再平仓,增加交易量但保持净仓位接近零
-    const boostSequence = [
-      // 第一步:双向开仓
-      {
-        accountId: 'pacifica-1',
-        symbol: 'BTC-USD',
-        amount: parseFloat(signal.amount),
-        side: 'bid' as const, // 买入
-        orderType: 'market' as const,
-        reason: '刷量开仓-多头'
-      },
-      {
-        accountId: 'pacifica-2',
-        symbol: 'BTC-USD',
-        amount: parseFloat(signal.amount),
-        side: 'ask' as const, // 卖出
-        orderType: 'market' as const,
-        reason: '刷量开仓-空头'
-      }
-    ]
-
-    logger.info('执行高频刷量序列', {
-      orders: boostSequence.length,
-      amount: signal.amount,
-      reason: signal.reason
-    })
-
-    const results = await this.hedgeManager.executeBatchHedge(boostSequence)
-
-    let successCount = 0
-    results.forEach((result, index) => {
-      if (result.success) {
-        successCount++
-        console.log(`✅ 刷量订单${index + 1}成功: ${result.orderId || 'N/A'}`)
-        this.stats.totalVolume += parseFloat(signal.amount)
-      } else {
-        console.log(`❌ 刷量订单${index + 1}失败: ${result.error}`)
-      }
-    })
-
-    // 更新统计
-    this.stats.totalTrades += results.length
-    this.stats.successfulTrades += successCount
-    this.stats.failedTrades += (results.length - successCount)
-    this.stats.lastTradeTime = Date.now()
-
-    console.log(`⚡ 刷量执行完成: ${successCount}/${results.length} 成功 - 增加交易量: ${(parseFloat(signal.amount) * successCount).toFixed(4)} BTC`)
-  }
-
-  /**
-   * 执行单个交易信号
-   */
-  private async executeTradeSignal(signal: TradingSignal): Promise<void> {
-    // 选择最佳客户端
-    const clientId = 'pacifica-1' // 简化选择逻辑
-    const client = this.clients.get(clientId)
-
-    if (!client) {
-      throw new Error(`客户端 ${clientId} 不可用`)
-    }
-
-    const side = signal.action === 'buy' ? 'bid' : 'ask'
-
-    logger.info('执行交易订单', {
-      clientId,
-      symbol: signal.symbol,
-      side,
-      amount: signal.amount
-    })
-
-    const result = await client.createMarketOrder({
-      account: this.accounts[0].account,
-      symbol: 'BTCUSDT',
-      amount: signal.amount,
-      side: side,
-      reduceOnly: signal.action === 'sell', // 卖出时尝试减仓
-      slippagePercent: '5.0'
-    })
-
-    if (result.success) {
-      this.stats.successfulTrades++
-      this.stats.totalVolume += parseFloat(signal.amount)
-      logger.info('交易订单执行成功', { orderId: result.data?.order_id })
-      console.log(`✅ ${signal.action.toUpperCase()} 订单成功: ${result.data?.order_id}`)
-    } else {
-      this.stats.failedTrades++
-      throw new Error(`订单失败: ${result.error}`)
-    }
-
-    this.stats.totalTrades++
-    this.stats.lastTradeTime = Date.now()
-  }
-
-  /**
-   * 检查是否应该交易
-   */
-  private shouldTrade(): boolean {
-    // 检查风险限制
-    if (this.stats.totalTrades >= this.riskLimits.maxDailyTrades) {
-      return false
-    }
-
-    // 检查最近交易时间(刷量交易允许更频繁)
-    const timeSinceLastTrade = Date.now() - this.stats.lastTradeTime
-    if (timeSinceLastTrade < 5000) { // 改为至少间隔5秒
-      return false
-    }
-
-    return true
-  }
-
-  /**
-   * 健康检查
-   */
-  private async performHealthCheck(): Promise<void> {
-    logger.debug('执行健康检查')
-
-    for (const [clientId, client] of this.clients) {
-      try {
-        const result = await client.testConnection()
-        if (!result.success) {
-          logger.warn(`客户端 ${clientId} 连接异常`, { error: result.error })
-          this.emit('system_error', {
-            type: 'connection_error',
-            clientId,
-            error: result.error
-          })
-        }
-      } catch (error: any) {
-        logger.error(`客户端 ${clientId} 健康检查失败`, { error: error.message })
-      }
-    }
-  }
-
-  /**
-   * 风险检查
-   */
-  private async performRiskCheck(): Promise<void> {
-    // 检查交易频率
-    if (this.stats.totalTrades > this.riskLimits.maxDailyTrades * 0.8) {
-      this.emit('risk_alert', {
-        type: 'daily_trade_limit_warning',
-        current: this.stats.totalTrades,
-        limit: this.riskLimits.maxDailyTrades
-      })
-    }
-
-    // 检查失败率
-    const failureRate = this.stats.totalTrades > 0
-      ? this.stats.failedTrades / this.stats.totalTrades
-      : 0
-
-    if (failureRate > 0.3) { // 失败率超过30%
-      this.emit('risk_alert', {
-        type: 'high_failure_rate',
-        rate: failureRate,
-        failed: this.stats.failedTrades,
-        total: this.stats.totalTrades
-      })
-    }
-  }
-
-  /**
-   * 处理风险警报
-   */
-  private handleRiskAlert(alert: any): void {
-    logger.warn('风险警报', alert)
-    console.log(`⚠️ 风险警报: ${alert.type}`)
-
-    // 可以在这里实现自动暂停交易等逻辑
-    if (alert.type === 'high_failure_rate') {
-      console.log('❌ 失败率过高,建议暂停交易')
-    }
-  }
-
-  /**
-   * 处理系统错误
-   */
-  private handleSystemError(error: any): void {
-    logger.error('系统错误', error)
-    console.log(`🚨 系统错误: ${error.type} - ${error.error}`)
-  }
-
-  /**
-   * 显示实时监控面板
-   */
-  private displayDashboard(): void {
-    const uptime = Date.now() - this.startTime
-    const uptimeStr = Math.floor(uptime / 1000 / 60) + 'm'
-
-    const status: SystemStatus = {
-      accounts: this.accounts.length,
-      activeConnections: this.clients.size,
-      totalTrades: this.stats.totalTrades,
-      totalVolume: this.stats.totalVolume.toFixed(6),
-      uptime: uptime,
-      lastUpdate: Date.now()
-    }
-
-    // 清屏并显示面板 - 使用ANSI清屏命令确保实时刷新
-    process.stdout.write('\u001B[2J\u001B[0;0f') // 清屏并移动到左上角
-
-    console.log('🔥 完整交易系统 - 实时监控面板 [刷量模式]')
-    console.log('=' .repeat(80))
-    console.log(`📊 系统状态`)
-    console.log(`   运行时间: ${uptimeStr}`)
-    console.log(`   账户数量: ${status.accounts}`)
-    console.log(`   活跃连接: ${status.activeConnections}`)
-    console.log(`   代理状态: ${Config.proxy.isAnyConfigured() ? '🟢 启用' : '🔴 禁用'}`)
-
-    console.log(`\n💰 交易统计 📈`)
-    console.log(`   总交易数: ${status.totalTrades}`)
-    console.log(`   成功交易: ${this.stats.successfulTrades}`)
-    console.log(`   失败交易: ${this.stats.failedTrades}`)
-    console.log(`   总交易量: ${status.totalVolume} BTC`)
-    console.log(`   成功率: ${status.totalTrades > 0 ? ((this.stats.successfulTrades / status.totalTrades) * 100).toFixed(1) : 0}%`)
-
-    if (this.hedgeManager) {
-      const hedgeStatus = this.hedgeManager.getHedgePairStatuses()
-      console.log(`\n🔄 对冲状态`)
-      hedgeStatus.forEach(hedge => {
-        console.log(`   ${hedge.pairId}: ${hedge.isActive ? '🟢 激活' : '🔴 停用'} (敞口: ${hedge.netExposure})`)
-      })
-    }
-
-    console.log(`\n🔧 风险控制`)
-    console.log(`   每日交易限制: ${this.stats.totalTrades}/${this.riskLimits.maxDailyTrades}`)
-    console.log(`   最大仓位: ${this.riskLimits.maxPositionSize} BTC`)
-    console.log(`   紧急止损: ${this.riskLimits.emergencyStopLoss * 100}%`)
-
-    // 显示最近的交易活动
-    console.log(`\n⚡ 交易活动状态`)
-    const timeSinceLastTrade = this.stats.lastTradeTime > 0
-      ? Math.round((Date.now() - this.stats.lastTradeTime) / 1000)
-      : 0
-    console.log(`   上次交易: ${timeSinceLastTrade > 0 ? `${timeSinceLastTrade}秒前` : '无'}`)
-    console.log(`   交易频率: 主信号15s + 刷量8s`)
-    console.log(`   刷量状态: ${this.stats.totalTrades > 0 ? '🟢 活跃' : '⏸️ 等待'}`)
-
-    console.log(`\n⏰ 最后更新: ${new Date().toLocaleTimeString()}`)
-    console.log('=' .repeat(80))
-    console.log('💡 按 Ctrl+C 安全退出系统 | 刷量交易进行中...')
-
-    // 强制刷新缓冲区
-    process.stdout.write('')
-  }
-
-  /**
-   * 获取系统状态
-   */
-  getSystemStatus(): SystemStatus {
-    return {
-      accounts: this.accounts.length,
-      activeConnections: this.clients.size,
-      totalTrades: this.stats.totalTrades,
-      totalVolume: this.stats.totalVolume.toFixed(6),
-      uptime: Date.now() - this.startTime,
-      lastUpdate: Date.now()
-    }
-  }
-
-  /**
-   * 安全关闭系统
-   */
-  async shutdown(): Promise<void> {
-    if (!this.isRunning) return
-
-    console.log('\n🛑 正在安全关闭系统...')
-    this.isRunning = false
-
-    try {
-      // 清理资源
-      this.clients.clear()
-      this.hedgeManager = null
-
-      // 显示最终统计
-      console.log('\n📊 最终统计:')
-      console.log(`   总交易数: ${this.stats.totalTrades}`)
-      console.log(`   成功交易: ${this.stats.successfulTrades}`)
-      console.log(`   失败交易: ${this.stats.failedTrades}`)
-      console.log(`   总运行时间: ${Math.floor((Date.now() - this.startTime) / 1000 / 60)} 分钟`)
-
-      logger.info('交易系统已安全关闭')
-      console.log('✅ 系统已安全关闭')
-
-      process.exit(0)
-    } catch (error: any) {
-      logger.error('系统关闭时出错', { error: error.message })
-      process.exit(1)
-    }
-  }
-}
-
-/**
- * 显示使用帮助
- */
-function showHelp() {
-  console.log(`
-🔥 完整加密货币交易系统
-
-功能特性:
-  🚀 多平台交易所集成 (Pacifica, Binance, Aster)
-  📊 实时市场数据处理
-  🏦 多账户统一管理
-  🔄 同平台智能对冲
-  🛡️ 完整风险控制系统
-  📈 实时监控面板
-  ⚡ 自动交易执行
-  🔐 代理网络支持
-
-使用方法:
-  tsx src/main-complete.ts           启动完整系统
-  tsx src/main-complete.ts --help    显示此帮助
-
-环境要求:
-  🔧 Node.js >= 18.12
-  🔧 配置有效的交易所账户
-  🔧 足够的账户余额
-  🔧 稳定的网络连接
-
-安全特性:
-  🛡️ 多层风险控制
-  🛡️ 自动止损机制
-  🛡️ 交易频率限制
-  🛡️ 余额保护检查
-  🛡️ 异常自动恢复
-
-监控功能:
-  📊 实时交易统计
-  📈 盈亏分析
-  🔍 系统健康检查
-  ⚠️ 风险警报系统
-  📝 详细交易日志
-
-⚠️ 风险提醒:
-加密货币交易存在巨大风险,可能导致本金损失。
-请确保您完全理解相关风险并具备相应的风险承受能力。
-建议先在测试环境中运行,并使用小额资金测试。
-`)
-  }
-
-  /**
-   * 恢复系统状态
-   */
-  private async restoreSystemState(): Promise<void> {
-    try {
-      console.log('\n📋 第0步: 恢复系统状态')
-
-      const savedState = await this.stateManager.loadState()
-      if (savedState) {
-        // 恢复账户状态
-        Object.entries(savedState.accountStates).forEach(([accountId, state]) => {
-          this.accountStates.set(accountId, {
-            totalTrades: state.totalTrades,
-            netPosition: state.netPosition,
-            totalVolume: state.totalVolume,
-            lastBalance: state.lastBalance,
-            needsRebalance: state.needsRebalance
-          })
-        })
-
-        // 恢复全局统计
-        this.stats = {
-          ...this.stats,
-          ...savedState.globalStats
-        }
-
-        // 检查Delta中性状态
-        const deltaReport = this.stateManager.getDeltaNeutralityReport(savedState)
-        if (!deltaReport.isDeltaNeutral) {
-          logger.warn('⚠️ 上次会话未达到Delta中性状态', deltaReport)
-          console.log(`⚠️ 检测到未平衡仓位: ${deltaReport.totalDelta.toFixed(4)} BTC`)
-          console.log(`🔄 ${deltaReport.recommendation}`)
-        } else {
-          console.log('✅ 上次会话保持了Delta中性状态')
-        }
-
-        logger.info('系统状态恢复成功', {
-          accounts: Object.keys(savedState.accountStates).length,
-          totalTrades: savedState.globalStats.totalTrades,
-          totalDelta: savedState.deltaMetrics.totalDelta
-        })
-      } else {
-        console.log('🆕 首次启动,创建新的系统状态')
-        this.initializeAccountStates()
-      }
-    } catch (error: any) {
-      logger.error('恢复系统状态失败', { error: error.message })
-      console.log('⚠️ 状态恢复失败,使用默认设置启动')
-      this.initializeAccountStates()
-    }
-  }
-
-  /**
-   * 开始自动保存状态
-   */
-  private startStateAutoSave(): void {
-    // 每30秒自动保存一次状态
-    setInterval(async () => {
-      if (!this.isShuttingDown) {
-        await this.saveCurrentState()
-      }
-    }, 30000)
-
-    logger.info('自动状态保存已启动 (30秒间隔)')
-  }
-
-  /**
-   * 保存当前状态
-   */
-  private async saveCurrentState(): Promise<void> {
-    try {
-      const currentState: SystemState = {
-        timestamp: Date.now(),
-        accountStates: {},
-        globalStats: {
-          totalTrades: this.stats.totalTrades,
-          successfulTrades: this.stats.successfulTrades,
-          failedTrades: this.stats.failedTrades,
-          totalVolume: this.stats.totalVolume,
-          sessionStartTime: this.startTime
-        },
-        deltaMetrics: {
-          totalDelta: this.calculateTotalDelta(),
-          maxDelta: this.riskLimits.maxTotalExposure,
-          lastRebalanceTime: Date.now(),
-          rebalanceCount: 0
-        },
-        riskMetrics: {
-          dailyTrades: this.stats.totalTrades,
-          lastRiskCheck: Date.now(),
-          emergencyStops: 0
-        }
-      }
-
-      // 转换账户状态
-      this.accountStates.forEach((state, accountId) => {
-        currentState.accountStates[accountId] = {
-          ...state,
-          lastUpdateTime: Date.now()
-        }
-      })
-
-      await this.stateManager.saveState(currentState)
-    } catch (error: any) {
-      logger.error('保存系统状态失败', { error: error.message })
-    }
-  }
-
-  /**
-   * 计算总Delta敞口
-   */
-  private calculateTotalDelta(): number {
-    let totalDelta = 0
-    this.accountStates.forEach(account => {
-      totalDelta += account.netPosition
-    })
-    return totalDelta
-  }
-
-  /**
-   * 优雅关闭系统
-   */
-  private async gracefulShutdown(): Promise<void> {
-    if (this.isShuttingDown) {
-      return
-    }
-
-    this.isShuttingDown = true
-    console.log('\n🛑 正在优雅关闭系统...')
-
-    try {
-      // 1. 停止新的交易信号
-      this.isRunning = false
-      logger.info('已停止交易信号生成')
-
-      // 2. 等待当前交易完成
-      await this.waitForPendingTrades()
-
-      // 3. 检查Delta中性状态
-      const deltaReport = await this.checkDeltaNeutrality()
-
-      if (!deltaReport.isDeltaNeutral) {
-        console.log(`⚠️ 警告: 系统未达到Delta中性状态`)
-        console.log(`📊 当前总敞口: ${deltaReport.totalDelta.toFixed(4)} BTC`)
-        console.log(`💡 建议: ${deltaReport.recommendation}`)
-
-        // 询问用户是否强制关闭
-        const shouldForceClose = await this.confirmForceClose()
-        if (!shouldForceClose) {
-          console.log('🔄 尝试自动平衡账户...')
-          await this.attemptDeltaRebalancing()
-        }
-      } else {
-        console.log('✅ Delta中性状态确认,可以安全关闭')
-      }
-
-      // 4. 保存最终状态
-      await this.saveCurrentState()
-      logger.info('最终状态已保存')
-
-      // 5. 关闭连接
-      await this.closeConnections()
-
-      console.log('🎉 系统已安全关闭')
-
-    } catch (error: any) {
-      logger.error('优雅关闭过程中出现错误', { error: error.message })
-      await this.emergencyShutdown()
-    }
-  }
-
-  /**
-   * 紧急关闭系统
-   */
-  private async emergencyShutdown(): Promise<void> {
-    logger.warn('执行紧急关闭流程')
-
-    try {
-      // 紧急保存状态
-      const emergencyState: SystemState = this.stateManager.createDefaultState()
-      this.stateManager.emergencySave(emergencyState)
-
-      // 强制关闭所有连接
-      await this.forceCloseConnections()
-
-      logger.warn('紧急关闭完成')
-    } catch (error: any) {
-      logger.error('紧急关闭失败', { error: error.message })
-    }
-  }
-
-  /**
-   * 等待当前交易完成
-   */
-  private async waitForPendingTrades(maxWait = 30000): Promise<void> {
-    console.log('⏳ 等待当前交易完成...')
-    const startTime = Date.now()
-
-    while (Date.now() - startTime < maxWait) {
-      // 这里可以检查是否有未完成的交易
-      // 暂时简单等待3秒
-      await new Promise(resolve => setTimeout(resolve, 1000))
-
-      // 如果没有待处理的交易,提前退出
-      break
-    }
-
-    console.log('✅ 交易等待完成')
-  }
-
-  /**
-   * 检查Delta中性状态
-   */
-  private async checkDeltaNeutrality(): Promise<{
-    isDeltaNeutral: boolean
-    totalDelta: number
-    maxAllowedDelta: number
-    recommendation: string
-  }> {
-    const totalDelta = Math.abs(this.calculateTotalDelta())
-    const maxAllowedDelta = 0.01 // 最大允许敞口 0.01 BTC
-
-    const isDeltaNeutral = totalDelta <= maxAllowedDelta
-
-    let recommendation = ''
-    if (!isDeltaNeutral) {
-      recommendation = `需要对冲平仓 ${totalDelta.toFixed(4)} BTC 敞口以保持Delta中性`
-    } else {
-      recommendation = 'Delta中性状态良好,可以安全退出'
-    }
-
-    return {
-      isDeltaNeutral,
-      totalDelta,
-      maxAllowedDelta,
-      recommendation
-    }
-  }
-
-  /**
-   * 确认是否强制关闭
-   */
-  private async confirmForceClose(): Promise<boolean> {
-    // 在生产环境中,这里可以实现用户交互
-    // 当前返回false,不强制关闭
-    return false
-  }
-
-  /**
-   * 尝试Delta重新平衡
-   */
-  private async attemptDeltaRebalancing(): Promise<void> {
-    try {
-      console.log('🔄 正在尝试自动平衡账户...')
-
-      // 生成平衡信号
-      const balanceSignal: TradingSignal = {
-        symbol: 'BTC-USD',
-        action: 'balance_accounts',
-        amount: Math.abs(this.calculateTotalDelta()).toFixed(4),
-        confidence: 1.0,
-        reason: 'shutdown_rebalancing'
-      }
-
-      await this.executeBalanceSignal(balanceSignal)
-
-      // 等待执行完成
-      await new Promise(resolve => setTimeout(resolve, 5000))
-
-      // 重新检查
-      const newDelta = Math.abs(this.calculateTotalDelta())
-      if (newDelta <= 0.01) {
-        console.log('✅ 自动平衡成功')
-      } else {
-        console.log(`⚠️ 自动平衡后仍有 ${newDelta.toFixed(4)} BTC 敞口`)
-      }
-
-    } catch (error: any) {
-      logger.error('自动平衡失败', { error: error.message })
-    }
-  }
-
-  /**
-   * 关闭连接
-   */
-  private async closeConnections(): Promise<void> {
-    console.log('🔌 关闭所有连接...')
-
-    try {
-      // 关闭所有客户端连接
-      for (const [accountId, client] of this.clients) {
-        try {
-          // 如果客户端有关闭方法,调用它
-          logger.info(`关闭客户端连接: ${accountId}`)
-        } catch (error: any) {
-          logger.warn(`关闭客户端 ${accountId} 失败`, { error: error.message })
-        }
-      }
-
-      // 清理对冲管理器
-      if (this.hedgeManager) {
-        this.hedgeManager = null
-      }
-
-      console.log('✅ 所有连接已关闭')
-
-    } catch (error: any) {
-      logger.error('关闭连接失败', { error: error.message })
-    }
-  }
-
-  /**
-   * 强制关闭连接
-   */
-  private async forceCloseConnections(): Promise<void> {
-    logger.warn('强制关闭所有连接')
-
-    this.clients.clear()
-    this.hedgeManager = null
-  }
-}
-
-// 主程序入口
-async function main() {
-  if (process.argv.includes('--help') || process.argv.includes('-h')) {
-    showHelp()
-    return
-  }
-
-  try {
-    const system = new CompleteTradingSystem()
-    await system.start()
-
-    // 保持程序运行
-    process.stdin.resume()
-
-  } catch (error: any) {
-    logger.error('系统启动失败', { error: error.message, stack: error.stack })
-    console.error('❌ 系统启动失败:', error.message)
-    process.exit(1)
-  }
-}
-
-// 运行主程序
-if (import.meta.url === `file://${process.argv[1]}`) {
-  main()
-}
-
-export { CompleteTradingSystem }

+ 0 - 30
src/models/AccountAllocation.ts

@@ -1,30 +0,0 @@
-/**
- * 账户分配关系模型
- */
-export interface AccountAllocation {
-  moduleId: string
-  accountId: string
-  weight: number
-  maxConcurrentOrders: number
-  sandboxMode: boolean
-  createdAt: Date
-  updatedAt: Date
-}
-
-export class AccountAllocationManager {
-  private allocations: Map<string, AccountAllocation> = new Map()
-
-  addAllocation(allocation: AccountAllocation): void {
-    const key = `${allocation.moduleId}-${allocation.accountId}`
-    this.allocations.set(key, allocation)
-  }
-
-  getAllocation(moduleId: string, accountId: string): AccountAllocation | undefined {
-    const key = `${moduleId}-${accountId}`
-    return this.allocations.get(key)
-  }
-
-  getAllAllocations(): AccountAllocation[] {
-    return Array.from(this.allocations.values())
-  }
-}

+ 0 - 237
src/models/ExchangeAccount.ts

@@ -1,237 +0,0 @@
-/**
- * 交易账户模型
- * 基于 data-model.md 中的 ExchangeAccount 实体定义
- */
-export interface ExchangeAccount {
-  // 主键
-  accountId: string
-
-  // 基础信息
-  exchange: 'pacifica' | 'aster' | 'binance' | string
-  accountName: string
-  publicKey: string // 经过加密存储
-  proxyProfile: string // 引用代理配置 ID
-
-  // 配置参数
-  utilizationTargetMin: number // 默认 0.5
-  utilizationTargetMax: number // 默认 0.8
-  deltaThreshold: number // BTC 等值,默认 0.0005
-  maxPositionValue: number // 账户允许的最大名义价值
-  stopLossConfigId: string // 引用止损模板
-
-  // 状态
-  status: 'active' | 'paused' | 'emergency'
-
-  // 时间戳
-  createdAt: Date
-  updatedAt: Date
-}
-
-/**
- * 账户余额信息
- */
-export interface AccountBalance {
-  asset: string
-  total: string // 字符串表示,保留精度
-  available: string // 字符串表示,保留精度
-}
-
-/**
- * 账户仓位信息
- */
-export interface AccountPosition {
-  symbol: string
-  side: 'long' | 'short'
-  size: string // 字符串表示,保留精度
-  entryPrice: string // 字符串表示,保留精度
-  markPrice: string // 字符串表示,保留精度
-  unrealizedPnl: string // 字符串表示,保留精度
-}
-
-/**
- * 账户利用率信息
- */
-export interface AccountUtilization {
-  value: number // 数值型,便于对齐 50%-80% 目标
-  formula: string // 公式描述
-}
-
-/**
- * 账户同步请求
- */
-export interface AccountSyncRequest {
-  requestId: string
-  accounts: Array<{
-    accountId: string
-    exchange: string
-    nonce: number
-  }>
-}
-
-/**
- * 账户同步响应
- */
-export interface AccountSyncResponse {
-  requestId: string
-  timestamp: string
-  results: Array<{
-    accountId: string
-    status: 'success' | 'failed'
-    balances?: AccountBalance[]
-    positions?: AccountPosition[]
-    utilization?: AccountUtilization
-  }>
-  errors: Array<{
-    accountId: string
-    code: string
-    message: string
-    retryable?: boolean
-  }>
-}
-
-/**
- * 账户管理器类
- */
-export class ExchangeAccountManager {
-  private accounts: Map<string, ExchangeAccount> = new Map()
-
-  /**
-   * 添加账户
-   */
-  addAccount(account: ExchangeAccount): void {
-    this.accounts.set(account.accountId, account)
-  }
-
-  /**
-   * 获取账户
-   */
-  getAccount(accountId: string): ExchangeAccount | undefined {
-    return this.accounts.get(accountId)
-  }
-
-  /**
-   * 获取所有账户
-   */
-  getAllAccounts(): ExchangeAccount[] {
-    return Array.from(this.accounts.values())
-  }
-
-  /**
-   * 更新账户状态
-   */
-  updateAccountStatus(accountId: string, status: ExchangeAccount['status']): boolean {
-    const account = this.accounts.get(accountId)
-    if (account) {
-      account.status = status
-      account.updatedAt = new Date()
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 根据交易所获取账户
-   */
-  getAccountsByExchange(exchange: string): ExchangeAccount[] {
-    return this.getAllAccounts().filter(account => account.exchange === exchange)
-  }
-
-  /**
-   * 验证账户配置
-   */
-  validateAccount(account: ExchangeAccount): { isValid: boolean; errors: string[] } {
-    const errors: string[] = []
-
-    if (!account.accountId) {
-      errors.push('accountId is required')
-    }
-
-    if (!account.exchange) {
-      errors.push('exchange is required')
-    }
-
-    if (account.utilizationTargetMin >= account.utilizationTargetMax) {
-      errors.push('utilizationTargetMin must be less than utilizationTargetMax')
-    }
-
-    if (account.utilizationTargetMin < 0 || account.utilizationTargetMin > 1) {
-      errors.push('utilizationTargetMin must be between 0 and 1')
-    }
-
-    if (account.utilizationTargetMax < 0 || account.utilizationTargetMax > 1) {
-      errors.push('utilizationTargetMax must be between 0 and 1')
-    }
-
-    if (account.deltaThreshold <= 0) {
-      errors.push('deltaThreshold must be positive')
-    }
-
-    if (account.maxPositionValue <= 0) {
-      errors.push('maxPositionValue must be positive')
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors
-    }
-  }
-
-  /**
-   * 计算账户利用率
-   */
-  calculateUtilization(balances: AccountBalance[]): AccountUtilization {
-    let totalBalance = 0
-    let availableBalance = 0
-
-    for (const balance of balances) {
-      totalBalance += parseFloat(balance.total)
-      availableBalance += parseFloat(balance.available)
-    }
-
-    const utilization = totalBalance > 0 ? (totalBalance - availableBalance) / totalBalance : 0
-
-    return {
-      value: utilization,
-      formula: '(totalBalance - availableBalance) / totalBalance'
-    }
-  }
-
-  /**
-   * 检查利用率是否在目标范围内
-   */
-  isUtilizationInTarget(utilization: AccountUtilization, account: ExchangeAccount): boolean {
-    return utilization.value >= account.utilizationTargetMin && 
-           utilization.value <= account.utilizationTargetMax
-  }
-
-  /**
-   * 检查利用率是否需要再平衡
-   */
-  needsRebalancing(utilization: AccountUtilization, account: ExchangeAccount): {
-    needsRebalance: boolean
-    direction: 'buy' | 'sell' | null
-    reason: string
-  } {
-    if (utilization.value < account.utilizationTargetMin) {
-      return {
-        needsRebalance: true,
-        direction: 'buy',
-        reason: `Utilization ${(utilization.value * 100).toFixed(2)}% is below target minimum ${(account.utilizationTargetMin * 100).toFixed(2)}%`
-      }
-    }
-
-    if (utilization.value > account.utilizationTargetMax) {
-      return {
-        needsRebalance: true,
-        direction: 'sell',
-        reason: `Utilization ${(utilization.value * 100).toFixed(2)}% is above target maximum ${(account.utilizationTargetMax * 100).toFixed(2)}%`
-      }
-    }
-
-    return {
-      needsRebalance: false,
-      direction: null,
-      reason: 'Utilization is within target range'
-    }
-  }
-}

+ 0 - 122
src/models/HedgeExecution.ts

@@ -1,122 +0,0 @@
-/**
- * 对冲执行记录模型
- * 基于 data-model.md 中的 HedgeExecution 实体定义
- */
-export interface HedgeExecution {
-  // 主键
-  executionId: string
-
-  // 关联账户
-  primaryAccountId: string // 外键,ExchangeAccount
-  hedgeAccountId: string // 外键,ExchangeAccount
-
-  // Delta 信息
-  deltaBefore: number // 小数,BTC 等值
-  deltaAfter: number // 小数,BTC 等值
-
-  // 执行订单
-  orders: HedgeOrder[] // JSON 列表,含外部订单号、类型、价格、状态
-
-  // 触发信息
-  triggerReason: 'utilization' | 'delta' | 'failover' | 'manual'
-  durationMs: number // 整数
-  result: 'success' | 'partial' | 'fail'
-
-  // 时间戳
-  createdAt: Date
-}
-
-/**
- * 对冲订单
- */
-export interface HedgeOrder {
-  accountId: string
-  exchangeOrderId?: string
-  side: 'buy' | 'sell'
-  type: 'limit' | 'market'
-  amount: string
-  price?: string
-  timeInForce?: string
-  proxyProfile?: string
-  filledSize?: string
-  avgPrice?: string
-  fees?: string
-  result?: 'filled' | 'partially_filled' | 'cancelled' | 'failed'
-  error?: string
-}
-
-/**
- * 对冲执行响应
- */
-export interface HedgeExecutionResponse {
-  executionId: string
-  status: 'completed' | 'partial' | 'failed'
-  deltaAfter: number
-  executionDetails: HedgeOrder[]
-  durationMs: number
-  alerts: HedgeAlert[]
-  completedAt: Date
-}
-
-/**
- * 对冲警报
- */
-export interface HedgeAlert {
-  type: string
-  message: string
-  severity: 'INFO' | 'WARN' | 'CRITICAL'
-}
-
-/**
- * 对冲执行管理器
- */
-export class HedgeExecutionManager {
-  private executions: Map<string, HedgeExecution> = new Map()
-
-  createExecution(execution: HedgeExecution): void {
-    this.executions.set(execution.executionId, execution)
-  }
-
-  getExecution(executionId: string): HedgeExecution | undefined {
-    return this.executions.get(executionId)
-  }
-
-  getAllExecutions(): HedgeExecution[] {
-    return Array.from(this.executions.values())
-  }
-
-  updateExecutionResult(executionId: string, result: HedgeExecution['result'], durationMs: number): boolean {
-    const execution = this.executions.get(executionId)
-    if (execution) {
-      execution.result = result
-      execution.durationMs = durationMs
-      return true
-    }
-    return false
-  }
-
-  getExecutionsByAccount(accountId: string): HedgeExecution[] {
-    return this.getAllExecutions().filter(exec => 
-      exec.primaryAccountId === accountId || exec.hedgeAccountId === accountId
-    )
-  }
-
-  getExecutionStats(): {
-    total: number
-    successful: number
-    partial: number
-    failed: number
-    successRate: number
-    averageDuration: number
-  } {
-    const executions = this.getAllExecutions()
-    const total = executions.length
-    const successful = executions.filter(e => e.result === 'success').length
-    const partial = executions.filter(e => e.result === 'partial').length
-    const failed = executions.filter(e => e.result === 'fail').length
-    const successRate = total > 0 ? (successful + partial) / total : 0
-    const averageDuration = total > 0 ? executions.reduce((sum, e) => sum + e.durationMs, 0) / total : 0
-
-    return { total, successful, partial, failed, successRate, averageDuration }
-  }
-}

+ 0 - 321
src/models/MarketDataFeed.ts

@@ -1,321 +0,0 @@
-/**
- * 行情数据源模型
- * 基于 data-model.md 中的 MarketDataFeed 实体定义
- */
-export interface MarketDataFeed {
-  // 主键
-  feedId: string
-
-  // 基础信息
-  exchange: string
-  symbol: string
-  wsEndpoint: string
-  httpEndpoint: string
-
-  // 性能指标
-  wsLatencyP95: number // 毫秒,统计值
-  httpLatencyP95: number // 毫秒
-
-  // 配置参数
-  freshnessThreshold: number // 毫秒,默认 2000
-  failoverDeadline: number // 毫秒,默认 10000
-
-  // 状态信息
-  lastHeartbeat: Date
-  status: 'healthy' | 'degraded' | 'failing'
-}
-
-/**
- * 价格数据
- */
-export interface PriceData {
-  symbol: string
-  bid: number
-  ask: number
-  mid: number
-  timestamp: Date
-  source: 'websocket' | 'http' | 'synthetic'
-  feedId?: string
-}
-
-/**
- * 合成价格快照
- */
-export interface SynthPriceSnapshot {
-  snapshotId: string
-  symbol: string
-  sourceFeeds: string[] // 记录参与合成的 feedId
-  midPrice: number
-  bid: number
-  ask: number
-  timestamp: Date
-  reason: 'ws-failover' | 'http-timeout' | 'manual'
-}
-
-/**
- * 行情回退事件
- */
-export interface MarketDataFailoverEvent {
-  eventId: string
-  eventType: 'market-data-failover' | 'market-data-failover-complete' | 'market-data-failover-failed'
-  exchange: string
-  symbol: string
-  primaryChannel: string
-  backupChannel?: string
-  detectTimestamp: Date
-  completedTimestamp?: Date
-  failoverDeadlineMs: number
-  reason: 'ws-stale-data' | 'ws-connection-lost' | 'ws-timeout' | 'ws-auth-failed' | 'http-timeout' | 'http-rate-limit'
-  metrics?: {
-    wsLastUpdateMs: number
-    httpLatencyMs: number
-  }
-  failoverMethod?: 'http' | 'synth'
-  synthPrice?: {
-    mid: number
-    bid: number
-    ask: number
-  }
-  durationMs?: number
-  triggeredOrders?: string[]
-  elapsedMs?: number
-  attempts?: Array<{
-    channel: string
-    result: string
-  }>
-  recommendedAction?: string
-  severity?: 'INFO' | 'WARN' | 'CRITICAL'
-}
-
-/**
- * 行情数据源管理器
- */
-export class MarketDataFeedManager {
-  private feeds: Map<string, MarketDataFeed> = new Map()
-  private priceData: Map<string, PriceData> = new Map()
-  private synthSnapshots: Map<string, SynthPriceSnapshot> = new Map()
-
-  /**
-   * 添加数据源
-   */
-  addFeed(feed: MarketDataFeed): void {
-    this.feeds.set(feed.feedId, feed)
-  }
-
-  /**
-   * 获取数据源
-   */
-  getFeed(feedId: string): MarketDataFeed | undefined {
-    return this.feeds.get(feedId)
-  }
-
-  /**
-   * 获取所有数据源
-   */
-  getAllFeeds(): MarketDataFeed[] {
-    return Array.from(this.feeds.values())
-  }
-
-  /**
-   * 根据交易所和交易对获取数据源
-   */
-  getFeedsByExchangeAndSymbol(exchange: string, symbol: string): MarketDataFeed[] {
-    return this.getAllFeeds().filter(
-      feed => feed.exchange === exchange && feed.symbol === symbol
-    )
-  }
-
-  /**
-   * 更新数据源状态
-   */
-  updateFeedStatus(feedId: string, status: MarketDataFeed['status']): boolean {
-    const feed = this.feeds.get(feedId)
-    if (feed) {
-      feed.status = status
-      feed.lastHeartbeat = new Date()
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 更新价格数据
-   */
-  updatePriceData(priceData: PriceData): void {
-    this.priceData.set(priceData.symbol, priceData)
-  }
-
-  /**
-   * 获取最新价格数据
-   */
-  getLatestPrice(symbol: string): PriceData | undefined {
-    return this.priceData.get(symbol)
-  }
-
-  /**
-   * 检查数据新鲜度
-   */
-  isDataFresh(symbol: string, feed: MarketDataFeed): boolean {
-    const priceData = this.priceData.get(symbol)
-    if (!priceData) return false
-
-    const age = Date.now() - priceData.timestamp.getTime()
-    return age <= feed.freshnessThreshold
-  }
-
-  /**
-   * 检测数据源是否需要回退
-   */
-  checkFailoverNeeded(symbol: string, feed: MarketDataFeed): {
-    needsFailover: boolean
-    reason: string
-    metrics: { wsLastUpdateMs: number; httpLatencyMs: number }
-  } {
-    const priceData = this.priceData.get(symbol)
-    const wsLastUpdateMs = priceData ? Date.now() - priceData.timestamp.getTime() : Infinity
-    const httpLatencyMs = feed.httpLatencyP95
-
-    // 检查 WebSocket 数据是否陈旧
-    if (wsLastUpdateMs > feed.freshnessThreshold) {
-      return {
-        needsFailover: true,
-        reason: 'ws-stale-data',
-        metrics: { wsLastUpdateMs, httpLatencyMs }
-      }
-    }
-
-    // 检查数据源状态
-    if (feed.status === 'failing') {
-      return {
-        needsFailover: true,
-        reason: 'ws-connection-lost',
-        metrics: { wsLastUpdateMs, httpLatencyMs }
-      }
-    }
-
-    return {
-      needsFailover: false,
-      reason: 'healthy',
-      metrics: { wsLastUpdateMs, httpLatencyMs }
-    }
-  }
-
-  /**
-   * 生成合成价格
-   */
-  generateSyntheticPrice(symbol: string, reason: SynthPriceSnapshot['reason']): SynthPriceSnapshot | null {
-    const feeds = this.getAllFeeds().filter(feed => feed.symbol === symbol)
-    if (feeds.length === 0) return null
-
-    // 收集可用价格数据
-    const prices: number[] = []
-    const sourceFeeds: string[] = []
-
-    for (const feed of feeds) {
-      const priceData = this.priceData.get(symbol)
-      if (priceData && this.isDataFresh(symbol, feed)) {
-        prices.push(priceData.mid)
-        sourceFeeds.push(feed.feedId)
-      }
-    }
-
-    if (prices.length === 0) return null
-
-    // 计算中位数价格
-    const sortedPrices = prices.sort((a, b) => a - b)
-    const midIndex = Math.floor(sortedPrices.length / 2)
-    const midPrice = sortedPrices.length % 2 === 0 
-      ? (sortedPrices[midIndex - 1] + sortedPrices[midIndex]) / 2
-      : sortedPrices[midIndex]
-
-    // 生成买卖价格(假设 0.1% 价差)
-    const spread = midPrice * 0.001
-    const bid = midPrice - spread / 2
-    const ask = midPrice + spread / 2
-
-    const snapshot: SynthPriceSnapshot = {
-      snapshotId: `synth-${Date.now()}`,
-      symbol,
-      sourceFeeds,
-      midPrice,
-      bid,
-      ask,
-      timestamp: new Date(),
-      reason
-    }
-
-    this.synthSnapshots.set(snapshot.snapshotId, snapshot)
-    return snapshot
-  }
-
-  /**
-   * 获取合成价格快照
-   */
-  getSynthSnapshot(snapshotId: string): SynthPriceSnapshot | undefined {
-    return this.synthSnapshots.get(snapshotId)
-  }
-
-  /**
-   * 验证数据源配置
-   */
-  validateFeed(feed: MarketDataFeed): { isValid: boolean; errors: string[] } {
-    const errors: string[] = []
-
-    if (!feed.feedId) {
-      errors.push('feedId is required')
-    }
-
-    if (!feed.exchange) {
-      errors.push('exchange is required')
-    }
-
-    if (!feed.symbol) {
-      errors.push('symbol is required')
-    }
-
-    if (!feed.wsEndpoint) {
-      errors.push('wsEndpoint is required')
-    }
-
-    if (!feed.httpEndpoint) {
-      errors.push('httpEndpoint is required')
-    }
-
-    if (feed.freshnessThreshold <= 0) {
-      errors.push('freshnessThreshold must be positive')
-    }
-
-    if (feed.failoverDeadline <= feed.freshnessThreshold) {
-      errors.push('failoverDeadline must be greater than freshnessThreshold')
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors
-    }
-  }
-
-  /**
-   * 获取健康状态统计
-   */
-  getHealthStats(): {
-    totalFeeds: number
-    healthyFeeds: number
-    degradedFeeds: number
-    failingFeeds: number
-    healthyPercentage: number
-  } {
-    const feeds = this.getAllFeeds()
-    const healthyFeeds = feeds.filter(f => f.status === 'healthy').length
-    const degradedFeeds = feeds.filter(f => f.status === 'degraded').length
-    const failingFeeds = feeds.filter(f => f.status === 'failing').length
-
-    return {
-      totalFeeds: feeds.length,
-      healthyFeeds,
-      degradedFeeds,
-      failingFeeds,
-      healthyPercentage: feeds.length > 0 ? (healthyFeeds / feeds.length) * 100 : 100
-    }
-  }
-}

+ 0 - 36
src/models/MonitoringEvent.ts

@@ -1,36 +0,0 @@
-/**
- * 监控事件模型
- */
-export interface MonitoringEvent {
-  eventId: string
-  type: 'utilization-alert' | 'delta-alert' | 'failover-alert' | 'proxy-alert' | 'test-result' | 'account-sync-fail'
-  accountId?: string
-  moduleId?: string
-  payload: Record<string, any>
-  severity: 'INFO' | 'WARN' | 'CRITICAL'
-  createdAt: Date
-}
-
-export class MonitoringEventManager {
-  private events: Map<string, MonitoringEvent> = new Map()
-
-  addEvent(event: MonitoringEvent): void {
-    this.events.set(event.eventId, event)
-  }
-
-  getEvent(eventId: string): MonitoringEvent | undefined {
-    return this.events.get(eventId)
-  }
-
-  getAllEvents(): MonitoringEvent[] {
-    return Array.from(this.events.values())
-  }
-
-  getEventsByType(type: MonitoringEvent['type']): MonitoringEvent[] {
-    return this.getAllEvents().filter(event => event.type === type)
-  }
-
-  getEventsBySeverity(severity: MonitoringEvent['severity']): MonitoringEvent[] {
-    return this.getAllEvents().filter(event => event.severity === severity)
-  }
-}

+ 0 - 404
src/models/OrderIntent.ts

@@ -1,404 +0,0 @@
-/**
- * 订单意图模型
- * 基于 data-model.md 中的 OrderIntent 实体定义
- */
-export interface OrderIntent {
-  // 主键
-  intentId: string
-
-  // 关联信息
-  moduleId: string // 外键,StrategyModule
-  accountId: string // 外键,ExchangeAccount
-
-  // 订单信息
-  symbol: string
-  side: 'buy' | 'sell'
-  type: 'limit' | 'market' | 'post-only' | 'stop-limit' | 'stop-market'
-  amount: string // 小数,base 数量
-  price?: string // 小数,若限价
-  timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX'
-  
-  // 预期收益
-  expectedProfitAfterFee: string // 小数,USD 等值
-  
-  // 对冲配对
-  hedgePairIntentId?: string // 可选,对冲配对
-  
-  // 状态
-  state: 'pending' | 'submitted' | 'filled' | 'cancelled' | 'failed'
-  
-  // 风险控制
-  stopLoss?: number
-  takeProfit?: number
-  enableTrailing?: boolean
-  
-  // 时间戳
-  createdAt: Date
-  updatedAt: Date
-}
-
-/**
- * 订单执行结果
- */
-export interface OrderExecutionResult {
-  intentId: string
-  exchangeOrderId?: string
-  status: 'pending' | 'partially_filled' | 'filled' | 'cancelled' | 'failed'
-  filledSize: string
-  remainingSize: string
-  avgPrice?: string
-  fees?: string
-  executedAt: Date
-  error?: string
-}
-
-/**
- * 订单状态变更事件
- */
-export interface OrderStatusChangeEvent {
-  eventId: string
-  intentId: string
-  oldState: OrderIntent['state']
-  newState: OrderIntent['state']
-  reason: string
-  timestamp: Date
-  metadata?: Record<string, any>
-}
-
-/**
- * 订单意图管理器
- */
-export class OrderIntentManager {
-  private intents: Map<string, OrderIntent> = new Map()
-  private executions: Map<string, OrderExecutionResult> = new Map()
-  private statusChanges: Map<string, OrderStatusChangeEvent[]> = new Map()
-
-  /**
-   * 创建订单意图
-   */
-  createIntent(intent: OrderIntent): void {
-    this.intents.set(intent.intentId, intent)
-    this.recordStatusChange(intent.intentId, 'pending', 'pending', 'Order intent created')
-  }
-
-  /**
-   * 获取订单意图
-   */
-  getIntent(intentId: string): OrderIntent | undefined {
-    return this.intents.get(intentId)
-  }
-
-  /**
-   * 获取所有订单意图
-   */
-  getAllIntents(): OrderIntent[] {
-    return Array.from(this.intents.values())
-  }
-
-  /**
-   * 根据模块获取订单意图
-   */
-  getIntentsByModule(moduleId: string): OrderIntent[] {
-    return this.getAllIntents().filter(intent => intent.moduleId === moduleId)
-  }
-
-  /**
-   * 根据账户获取订单意图
-   */
-  getIntentsByAccount(accountId: string): OrderIntent[] {
-    return this.getAllIntents().filter(intent => intent.accountId === accountId)
-  }
-
-  /**
-   * 根据状态获取订单意图
-   */
-  getIntentsByState(state: OrderIntent['state']): OrderIntent[] {
-    return this.getAllIntents().filter(intent => intent.state === state)
-  }
-
-  /**
-   * 更新订单状态
-   */
-  updateIntentState(intentId: string, newState: OrderIntent['state'], reason: string): boolean {
-    const intent = this.intents.get(intentId)
-    if (intent) {
-      const oldState = intent.state
-      intent.state = newState
-      intent.updatedAt = new Date()
-      this.recordStatusChange(intentId, oldState, newState, reason)
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 记录执行结果
-   */
-  recordExecution(result: OrderExecutionResult): void {
-    this.executions.set(result.intentId, result)
-    
-    // 根据执行结果更新订单状态
-    const intent = this.intents.get(result.intentId)
-    if (intent) {
-      let newState: OrderIntent['state']
-      switch (result.status) {
-        case 'filled':
-          newState = 'filled'
-          break
-        case 'partially_filled':
-          newState = 'submitted'
-          break
-        case 'cancelled':
-          newState = 'cancelled'
-          break
-        case 'failed':
-          newState = 'failed'
-          break
-        default:
-          newState = 'submitted'
-      }
-      
-      if (newState !== intent.state) {
-        this.updateIntentState(result.intentId, newState, `Execution result: ${result.status}`)
-      }
-    }
-  }
-
-  /**
-   * 获取执行结果
-   */
-  getExecution(intentId: string): OrderExecutionResult | undefined {
-    return this.executions.get(intentId)
-  }
-
-  /**
-   * 记录状态变更
-   */
-  private recordStatusChange(intentId: string, oldState: OrderIntent['state'], newState: OrderIntent['state'], reason: string): void {
-    const event: OrderStatusChangeEvent = {
-      eventId: `status-${Date.now()}-${intentId}`,
-      intentId,
-      oldState,
-      newState,
-      reason,
-      timestamp: new Date()
-    }
-
-    const existingEvents = this.statusChanges.get(intentId) || []
-    existingEvents.push(event)
-    this.statusChanges.set(intentId, existingEvents)
-  }
-
-  /**
-   * 获取状态变更历史
-   */
-  getStatusHistory(intentId: string): OrderStatusChangeEvent[] {
-    return this.statusChanges.get(intentId) || []
-  }
-
-  /**
-   * 验证订单意图
-   */
-  validateIntent(intent: OrderIntent): { isValid: boolean; errors: string[] } {
-    const errors: string[] = []
-
-    if (!intent.intentId) {
-      errors.push('intentId is required')
-    }
-
-    if (!intent.moduleId) {
-      errors.push('moduleId is required')
-    }
-
-    if (!intent.accountId) {
-      errors.push('accountId is required')
-    }
-
-    if (!intent.symbol) {
-      errors.push('symbol is required')
-    }
-
-    if (!intent.side || !['buy', 'sell'].includes(intent.side)) {
-      errors.push('side must be either "buy" or "sell"')
-    }
-
-    if (!intent.type || !['limit', 'market', 'post-only', 'stop-limit', 'stop-market'].includes(intent.type)) {
-      errors.push('type must be a valid order type')
-    }
-
-    if (!intent.amount || parseFloat(intent.amount) <= 0) {
-      errors.push('amount must be a positive number')
-    }
-
-    // 限价单必须提供价格
-    if (['limit', 'post-only', 'stop-limit'].includes(intent.type) && !intent.price) {
-      errors.push('price is required for limit orders')
-    }
-
-    // 价格必须为正数
-    if (intent.price && parseFloat(intent.price) <= 0) {
-      errors.push('price must be positive')
-    }
-
-    // 预期收益必须为数字
-    if (intent.expectedProfitAfterFee && isNaN(parseFloat(intent.expectedProfitAfterFee))) {
-      errors.push('expectedProfitAfterFee must be a valid number')
-    }
-
-    // 止损和止盈必须为正数
-    if (intent.stopLoss && intent.stopLoss <= 0) {
-      errors.push('stopLoss must be positive')
-    }
-
-    if (intent.takeProfit && intent.takeProfit <= 0) {
-      errors.push('takeProfit must be positive')
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors
-    }
-  }
-
-  /**
-   * 检查对冲配对
-   */
-  getHedgePair(intentId: string): OrderIntent | null {
-    const intent = this.intents.get(intentId)
-    if (intent && intent.hedgePairIntentId) {
-      return this.intents.get(intent.hedgePairIntentId) || null
-    }
-    return null
-  }
-
-  /**
-   * 创建对冲配对
-   */
-  createHedgePair(intent1: OrderIntent, intent2: OrderIntent): boolean {
-    // 验证两个订单是对冲配对
-    if (intent1.symbol !== intent2.symbol) {
-      return false
-    }
-
-    if (intent1.side === intent2.side) {
-      return false
-    }
-
-    if (parseFloat(intent1.amount) !== parseFloat(intent2.amount)) {
-      return false
-    }
-
-    // 设置对冲配对关系
-    intent1.hedgePairIntentId = intent2.intentId
-    intent2.hedgePairIntentId = intent1.intentId
-
-    this.intents.set(intent1.intentId, intent1)
-    this.intents.set(intent2.intentId, intent2)
-
-    return true
-  }
-
-  /**
-   * 获取待执行的订单
-   */
-  getPendingIntents(): OrderIntent[] {
-    return this.getIntentsByState('pending')
-  }
-
-  /**
-   * 获取执行中的订单
-   */
-  getExecutingIntents(): OrderIntent[] {
-    return this.getIntentsByState('submitted')
-  }
-
-  /**
-   * 获取已完成的订单
-   */
-  getCompletedIntents(): OrderIntent[] {
-    return this.getAllIntents().filter(intent => 
-      ['filled', 'cancelled', 'failed'].includes(intent.state)
-    )
-  }
-
-  /**
-   * 计算订单统计
-   */
-  getOrderStats(moduleId?: string, accountId?: string): {
-    total: number
-    pending: number
-    submitted: number
-    filled: number
-    cancelled: number
-    failed: number
-    successRate: number
-    totalVolume: string
-    totalFees: string
-    totalProfit: string
-  } {
-    let intents = this.getAllIntents()
-
-    if (moduleId) {
-      intents = intents.filter(intent => intent.moduleId === moduleId)
-    }
-
-    if (accountId) {
-      intents = intents.filter(intent => intent.accountId === accountId)
-    }
-
-    const total = intents.length
-    const pending = intents.filter(i => i.state === 'pending').length
-    const submitted = intents.filter(i => i.state === 'submitted').length
-    const filled = intents.filter(i => i.state === 'filled').length
-    const cancelled = intents.filter(i => i.state === 'cancelled').length
-    const failed = intents.filter(i => i.state === 'failed').length
-    const successRate = total > 0 ? filled / total : 0
-
-    let totalVolume = 0
-    let totalFees = 0
-    let totalProfit = 0
-
-    for (const intent of intents) {
-      if (intent.state === 'filled') {
-        const execution = this.executions.get(intent.intentId)
-        if (execution) {
-          totalVolume += parseFloat(execution.filledSize || '0')
-          totalFees += parseFloat(execution.fees || '0')
-        }
-        totalProfit += parseFloat(intent.expectedProfitAfterFee || '0')
-      }
-    }
-
-    return {
-      total,
-      pending,
-      submitted,
-      filled,
-      cancelled,
-      failed,
-      successRate,
-      totalVolume: totalVolume.toString(),
-      totalFees: totalFees.toString(),
-      totalProfit: totalProfit.toString()
-    }
-  }
-
-  /**
-   * 清理过期的订单意图
-   */
-  cleanupExpiredIntents(maxAgeHours: number = 24): number {
-    const cutoffTime = new Date(Date.now() - maxAgeHours * 60 * 60 * 1000)
-    let cleanedCount = 0
-
-    for (const [intentId, intent] of this.intents.entries()) {
-      if (intent.createdAt < cutoffTime && ['cancelled', 'failed'].includes(intent.state)) {
-        this.intents.delete(intentId)
-        this.executions.delete(intentId)
-        this.statusChanges.delete(intentId)
-        cleanedCount++
-      }
-    }
-
-    return cleanedCount
-  }
-}

+ 0 - 29
src/models/ProxySession.ts

@@ -1,29 +0,0 @@
-/**
- * 代理会话模型
- */
-export interface ProxySession {
-  sessionId: string
-  proxyProfile: string
-  ip: string
-  port: number
-  auth: string
-  accountIds: string[]
-  lastRotation: Date
-  status: 'active' | 'rotating' | 'failed'
-}
-
-export class ProxySessionManager {
-  private sessions: Map<string, ProxySession> = new Map()
-
-  addSession(session: ProxySession): void {
-    this.sessions.set(session.sessionId, session)
-  }
-
-  getSession(sessionId: string): ProxySession | undefined {
-    return this.sessions.get(sessionId)
-  }
-
-  getAllSessions(): ProxySession[] {
-    return Array.from(this.sessions.values())
-  }
-}

+ 0 - 490
src/models/RiskEnvelope.ts

@@ -1,490 +0,0 @@
-/**
- * 风险包络模型
- * 基于 data-model.md 中的 RiskEnvelope 实体定义
- */
-export interface RiskEnvelope {
-  // 主键
-  envelopeId: string
-
-  // 关联账户
-  accountId: string // 外键,ExchangeAccount
-
-  // 风险控制参数
-  maxDrawdownPercent: number // 小数
-  maxLeverage: number // 小数
-  deltaThreshold: number // 小数,默认继承账户级设定,可覆盖
-  slippageTolerance: number // 小数,百分比
-  emergencyStopLossSeconds: number // 整数,默认 30
-
-  // 时间戳
-  createdAt: Date
-  updatedAt: Date
-}
-
-/**
- * 风险指标
- */
-export interface RiskMetrics {
-  envelopeId: string
-  accountId: string
-  currentDelta: number // BTC 等值
-  deltaDeviation: number // 偏离目标的程度
-  currentUtilization: number // 当前利用率
-  maxUtilization: number // 历史最大利用率
-  currentDrawdown: number // 当前回撤
-  maxDrawdown: number // 历史最大回撤
-  currentLeverage: number // 当前杠杆
-  maxLeverage: number // 历史最大杠杆
-  slippage: number // 当前滑点
-  positionValue: number // 当前仓位价值
-  availableBalance: number // 可用余额
-  totalBalance: number // 总余额
-  timestamp: Date
-}
-
-/**
- * 风险警报
- */
-export interface RiskAlert {
-  alertId: string
-  envelopeId: string
-  accountId: string
-  type: 'delta-breach' | 'utilization-high' | 'utilization-low' | 'drawdown-exceeded' | 'leverage-exceeded' | 'slippage-high'
-  severity: 'INFO' | 'WARN' | 'CRITICAL'
-  message: string
-  currentValue: number
-  threshold: number
-  deviation: number
-  timestamp: Date
-  acknowledged: boolean
-  resolved: boolean
-}
-
-/**
- * 风险控制动作
- */
-export interface RiskControlAction {
-  actionId: string
-  envelopeId: string
-  accountId: string
-  triggerAlertId: string
-  actionType: 'hedge' | 'reduce-position' | 'emergency-stop' | 'halt-trading'
-  description: string
-  parameters: Record<string, any>
-  status: 'pending' | 'executing' | 'completed' | 'failed'
-  createdAt: Date
-  completedAt?: Date
-  error?: string
-}
-
-/**
- * 风险包络管理器
- */
-export class RiskEnvelopeManager {
-  private envelopes: Map<string, RiskEnvelope> = new Map()
-  private metrics: Map<string, RiskMetrics> = new Map()
-  private alerts: Map<string, RiskAlert> = new Map()
-  private actions: Map<string, RiskControlAction> = new Map()
-
-  /**
-   * 添加风险包络
-   */
-  addEnvelope(envelope: RiskEnvelope): void {
-    this.envelopes.set(envelope.envelopeId, envelope)
-  }
-
-  /**
-   * 获取风险包络
-   */
-  getEnvelope(envelopeId: string): RiskEnvelope | undefined {
-    return this.envelopes.get(envelopeId)
-  }
-
-  /**
-   * 根据账户ID获取风险包络
-   */
-  getEnvelopeByAccount(accountId: string): RiskEnvelope | undefined {
-    return Array.from(this.envelopes.values()).find(env => env.accountId === accountId)
-  }
-
-  /**
-   * 获取所有风险包络
-   */
-  getAllEnvelopes(): RiskEnvelope[] {
-    return Array.from(this.envelopes.values())
-  }
-
-  /**
-   * 更新风险包络
-   */
-  updateEnvelope(envelopeId: string, updates: Partial<RiskEnvelope>): boolean {
-    const envelope = this.envelopes.get(envelopeId)
-    if (envelope) {
-      Object.assign(envelope, updates)
-      envelope.updatedAt = new Date()
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 更新风险指标
-   */
-  updateMetrics(metrics: RiskMetrics): void {
-    this.metrics.set(metrics.envelopeId, metrics)
-  }
-
-  /**
-   * 获取风险指标
-   */
-  getMetrics(envelopeId: string): RiskMetrics | undefined {
-    return this.metrics.get(envelopeId)
-  }
-
-  /**
-   * 检查风险状态
-   */
-  checkRiskStatus(envelopeId: string): {
-    status: 'safe' | 'warning' | 'critical'
-    alerts: RiskAlert[]
-    recommendedActions: RiskControlAction[]
-  } {
-    const envelope = this.getEnvelope(envelopeId)
-    const metrics = this.getMetrics(envelopeId)
-    
-    if (!envelope || !metrics) {
-      return { status: 'critical', alerts: [], recommendedActions: [] }
-    }
-
-    const alerts: RiskAlert[] = []
-    const recommendedActions: RiskControlAction[] = []
-    let status: 'safe' | 'warning' | 'critical' = 'safe'
-
-    // 检查 Delta 偏离
-    if (Math.abs(metrics.deltaDeviation) > envelope.deltaThreshold) {
-      const alert: RiskAlert = {
-        alertId: `delta-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        type: 'delta-breach',
-        severity: Math.abs(metrics.deltaDeviation) > envelope.deltaThreshold * 2 ? 'CRITICAL' : 'WARN',
-        message: `Delta deviation ${metrics.deltaDeviation.toFixed(6)} exceeds threshold ${envelope.deltaThreshold}`,
-        currentValue: Math.abs(metrics.deltaDeviation),
-        threshold: envelope.deltaThreshold,
-        deviation: metrics.deltaDeviation,
-        timestamp: new Date(),
-        acknowledged: false,
-        resolved: false
-      }
-      alerts.push(alert)
-      status = alert.severity === 'CRITICAL' ? 'critical' : 'warning'
-
-      // 推荐对冲动作
-      recommendedActions.push({
-        actionId: `hedge-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        triggerAlertId: alert.alertId,
-        actionType: 'hedge',
-        description: 'Execute delta hedge to restore neutrality',
-        parameters: {
-          targetDelta: 0,
-          maxSlippage: envelope.slippageTolerance,
-          timeoutSeconds: envelope.emergencyStopLossSeconds
-        },
-        status: 'pending',
-        createdAt: new Date()
-      })
-    }
-
-    // 检查利用率
-    if (metrics.currentUtilization > 0.8) {
-      const alert: RiskAlert = {
-        alertId: `util-high-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        type: 'utilization-high',
-        severity: 'WARN',
-        message: `Utilization ${(metrics.currentUtilization * 100).toFixed(2)}% exceeds 80% threshold`,
-        currentValue: metrics.currentUtilization,
-        threshold: 0.8,
-        deviation: metrics.currentUtilization - 0.8,
-        timestamp: new Date(),
-        acknowledged: false,
-        resolved: false
-      }
-      alerts.push(alert)
-      status = status === 'safe' ? 'warning' : status
-
-      // 推荐减仓动作
-      recommendedActions.push({
-        actionId: `reduce-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        triggerAlertId: alert.alertId,
-        actionType: 'reduce-position',
-        description: 'Reduce position size to lower utilization',
-        parameters: {
-          targetUtilization: 0.7,
-          maxSlippage: envelope.slippageTolerance
-        },
-        status: 'pending',
-        createdAt: new Date()
-      })
-    } else if (metrics.currentUtilization < 0.5) {
-      const alert: RiskAlert = {
-        alertId: `util-low-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        type: 'utilization-low',
-        severity: 'INFO',
-        message: `Utilization ${(metrics.currentUtilization * 100).toFixed(2)}% below 50% threshold`,
-        currentValue: metrics.currentUtilization,
-        threshold: 0.5,
-        deviation: 0.5 - metrics.currentUtilization,
-        timestamp: new Date(),
-        acknowledged: false,
-        resolved: false
-      }
-      alerts.push(alert)
-    }
-
-    // 检查回撤
-    if (metrics.currentDrawdown > envelope.maxDrawdownPercent / 100) {
-      const alert: RiskAlert = {
-        alertId: `drawdown-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        type: 'drawdown-exceeded',
-        severity: 'CRITICAL',
-        message: `Drawdown ${(metrics.currentDrawdown * 100).toFixed(2)}% exceeds limit ${envelope.maxDrawdownPercent}%`,
-        currentValue: metrics.currentDrawdown,
-        threshold: envelope.maxDrawdownPercent / 100,
-        deviation: metrics.currentDrawdown - envelope.maxDrawdownPercent / 100,
-        timestamp: new Date(),
-        acknowledged: false,
-        resolved: false
-      }
-      alerts.push(alert)
-      status = 'critical'
-
-      // 推荐紧急止损
-      recommendedActions.push({
-        actionId: `emergency-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        triggerAlertId: alert.alertId,
-        actionType: 'emergency-stop',
-        description: 'Execute emergency stop loss',
-        parameters: {
-          reason: 'drawdown-exceeded',
-          timeoutSeconds: envelope.emergencyStopLossSeconds
-        },
-        status: 'pending',
-        createdAt: new Date()
-      })
-    }
-
-    // 检查杠杆
-    if (metrics.currentLeverage > envelope.maxLeverage) {
-      const alert: RiskAlert = {
-        alertId: `leverage-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        type: 'leverage-exceeded',
-        severity: 'CRITICAL',
-        message: `Leverage ${metrics.currentLeverage.toFixed(2)}x exceeds limit ${envelope.maxLeverage}x`,
-        currentValue: metrics.currentLeverage,
-        threshold: envelope.maxLeverage,
-        deviation: metrics.currentLeverage - envelope.maxLeverage,
-        timestamp: new Date(),
-        acknowledged: false,
-        resolved: false
-      }
-      alerts.push(alert)
-      status = 'critical'
-
-      // 推荐停止交易
-      recommendedActions.push({
-        actionId: `halt-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        triggerAlertId: alert.alertId,
-        actionType: 'halt-trading',
-        description: 'Halt trading due to excessive leverage',
-        parameters: {
-          reason: 'leverage-exceeded'
-        },
-        status: 'pending',
-        createdAt: new Date()
-      })
-    }
-
-    // 检查滑点
-    if (metrics.slippage > envelope.slippageTolerance) {
-      const alert: RiskAlert = {
-        alertId: `slippage-${Date.now()}`,
-        envelopeId,
-        accountId: metrics.accountId,
-        type: 'slippage-high',
-        severity: 'WARN',
-        message: `Slippage ${(metrics.slippage * 100).toFixed(3)}% exceeds tolerance ${(envelope.slippageTolerance * 100).toFixed(3)}%`,
-        currentValue: metrics.slippage,
-        threshold: envelope.slippageTolerance,
-        deviation: metrics.slippage - envelope.slippageTolerance,
-        timestamp: new Date(),
-        acknowledged: false,
-        resolved: false
-      }
-      alerts.push(alert)
-      status = status === 'safe' ? 'warning' : status
-    }
-
-    // 存储警报
-    alerts.forEach(alert => this.alerts.set(alert.alertId, alert))
-
-    return { status, alerts, recommendedActions }
-  }
-
-  /**
-   * 获取活跃警报
-   */
-  getActiveAlerts(envelopeId?: string): RiskAlert[] {
-    const allAlerts = Array.from(this.alerts.values())
-    return allAlerts.filter(alert => 
-      !alert.resolved && 
-      (!envelopeId || alert.envelopeId === envelopeId)
-    )
-  }
-
-  /**
-   * 确认警报
-   */
-  acknowledgeAlert(alertId: string): boolean {
-    const alert = this.alerts.get(alertId)
-    if (alert) {
-      alert.acknowledged = true
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 解决警报
-   */
-  resolveAlert(alertId: string): boolean {
-    const alert = this.alerts.get(alertId)
-    if (alert) {
-      alert.resolved = true
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 执行风险控制动作
-   */
-  executeAction(actionId: string): RiskControlAction | null {
-    const action = this.actions.get(actionId)
-    if (action && action.status === 'pending') {
-      action.status = 'executing'
-      return action
-    }
-    return null
-  }
-
-  /**
-   * 完成风险控制动作
-   */
-  completeAction(actionId: string, success: boolean, error?: string): boolean {
-    const action = this.actions.get(actionId)
-    if (action && action.status === 'executing') {
-      action.status = success ? 'completed' : 'failed'
-      action.completedAt = new Date()
-      if (error) {
-        action.error = error
-      }
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 验证风险包络配置
-   */
-  validateEnvelope(envelope: RiskEnvelope): { isValid: boolean; errors: string[] } {
-    const errors: string[] = []
-
-    if (!envelope.envelopeId) {
-      errors.push('envelopeId is required')
-    }
-
-    if (!envelope.accountId) {
-      errors.push('accountId is required')
-    }
-
-    if (envelope.maxDrawdownPercent <= 0 || envelope.maxDrawdownPercent > 100) {
-      errors.push('maxDrawdownPercent must be between 0 and 100')
-    }
-
-    if (envelope.maxLeverage <= 0) {
-      errors.push('maxLeverage must be positive')
-    }
-
-    if (envelope.deltaThreshold <= 0) {
-      errors.push('deltaThreshold must be positive')
-    }
-
-    if (envelope.slippageTolerance <= 0 || envelope.slippageTolerance > 1) {
-      errors.push('slippageTolerance must be between 0 and 1')
-    }
-
-    if (envelope.emergencyStopLossSeconds <= 0) {
-      errors.push('emergencyStopLossSeconds must be positive')
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors
-    }
-  }
-
-  /**
-   * 获取风险统计
-   */
-  getRiskStats(): {
-    totalEnvelopes: number
-    activeAlerts: number
-    criticalAlerts: number
-    pendingActions: number
-    averageUtilization: number
-    averageDrawdown: number
-  } {
-    const envelopes = this.getAllEnvelopes()
-    const activeAlerts = this.getActiveAlerts()
-    const criticalAlerts = activeAlerts.filter(alert => alert.severity === 'CRITICAL').length
-    const pendingActions = Array.from(this.actions.values()).filter(action => action.status === 'pending').length
-
-    let totalUtilization = 0
-    let totalDrawdown = 0
-    let validMetrics = 0
-
-    for (const envelope of envelopes) {
-      const metrics = this.getMetrics(envelope.envelopeId)
-      if (metrics) {
-        totalUtilization += metrics.currentUtilization
-        totalDrawdown += metrics.currentDrawdown
-        validMetrics++
-      }
-    }
-
-    return {
-      totalEnvelopes: envelopes.length,
-      activeAlerts: activeAlerts.length,
-      criticalAlerts,
-      pendingActions,
-      averageUtilization: validMetrics > 0 ? totalUtilization / validMetrics : 0,
-      averageDrawdown: validMetrics > 0 ? totalDrawdown / validMetrics : 0
-    }
-  }
-}

+ 0 - 389
src/models/StrategyModule.ts

@@ -1,389 +0,0 @@
-/**
- * 策略模块模型
- * 基于 data-model.md 中的 StrategyModule 实体定义
- */
-export interface StrategyModule {
-  // 主键
-  moduleId: string
-
-  // 基础信息
-  name: string
-  type: 'market-making' | 'funding-arbitrage' | 'hedge-only' | 'momentum' | 'mean-reversion' | 'arbitrage' | string
-  configSchema: Record<string, any> // JSON Schema 描述
-  dryRunEnabled: boolean // 默认 true
-  maxConcurrentSignals: number
-  profitAfterFeeTarget: number // 小数,百分比
-  requiresSandbox: boolean
-  status: 'enable' | 'disable'
-}
-
-/**
- * 策略信号
- */
-export interface StrategySignal {
-  signalId: string
-  moduleId: string
-  symbol: string
-  action: 'buy' | 'sell' | 'hedge' | 'close'
-  side?: 'buy' | 'sell'
-  amount: string
-  price?: string
-  confidence: number // 0-1
-  reason: string
-  reduceOnly?: boolean
-  targetAccount?: string
-  stopLoss?: number
-  takeProfit?: number
-  enableTrailing?: boolean
-  timestamp: Date
-}
-
-/**
- * 策略执行结果
- */
-export interface StrategyExecutionResult {
-  signalId: string
-  moduleId: string
-  status: 'success' | 'partial' | 'failed'
-  executedAmount: string
-  avgPrice?: string
-  fees?: string
-  profitAfterFee?: string
-  executionTime: Date
-  error?: string
-}
-
-/**
- * 策略性能指标
- */
-export interface StrategyPerformanceMetrics {
-  moduleId: string
-  period: 'hour' | 'day' | 'week' | 'month'
-  totalSignals: number
-  successfulSignals: number
-  successRate: number
-  totalProfit: string
-  totalFees: string
-  netProfit: string
-  profitAfterFee: string
-  maxDrawdown: number
-  sharpeRatio?: number
-  timestamp: Date
-}
-
-/**
- * 策略配置模板
- */
-export interface StrategyConfigTemplate {
-  templateId: string
-  name: string
-  type: StrategyModule['type']
-  description: string
-  configSchema: Record<string, any>
-  defaultConfig: Record<string, any>
-  riskLevel: 'conservative' | 'moderate' | 'aggressive'
-  applicableExchanges: string[]
-  applicableSymbols: string[]
-  minCapitalRequired: number
-  expectedReturn: {
-    min: number
-    max: number
-    typical: number
-  }
-}
-
-/**
- * 策略模块管理器
- */
-export class StrategyModuleManager {
-  private modules: Map<string, StrategyModule> = new Map()
-  private signals: Map<string, StrategySignal> = new Map()
-  private executions: Map<string, StrategyExecutionResult> = new Map()
-  private performanceMetrics: Map<string, StrategyPerformanceMetrics[]> = new Map()
-  private configTemplates: Map<string, StrategyConfigTemplate> = new Map()
-
-  /**
-   * 添加策略模块
-   */
-  addModule(module: StrategyModule): void {
-    this.modules.set(module.moduleId, module)
-  }
-
-  /**
-   * 获取策略模块
-   */
-  getModule(moduleId: string): StrategyModule | undefined {
-    return this.modules.get(moduleId)
-  }
-
-  /**
-   * 获取所有策略模块
-   */
-  getAllModules(): StrategyModule[] {
-    return Array.from(this.modules.values())
-  }
-
-  /**
-   * 获取启用的策略模块
-   */
-  getEnabledModules(): StrategyModule[] {
-    return this.getAllModules().filter(module => module.status === 'enable')
-  }
-
-  /**
-   * 根据类型获取策略模块
-   */
-  getModulesByType(type: StrategyModule['type']): StrategyModule[] {
-    return this.getAllModules().filter(module => module.type === type)
-  }
-
-  /**
-   * 启用/禁用策略模块
-   */
-  setModuleStatus(moduleId: string, status: StrategyModule['status']): boolean {
-    const module = this.modules.get(moduleId)
-    if (module) {
-      module.status = status
-      return true
-    }
-    return false
-  }
-
-  /**
-   * 生成策略信号
-   */
-  generateSignal(signal: StrategySignal): void {
-    this.signals.set(signal.signalId, signal)
-  }
-
-  /**
-   * 获取策略信号
-   */
-  getSignal(signalId: string): StrategySignal | undefined {
-    return this.signals.get(signalId)
-  }
-
-  /**
-   * 获取模块的所有信号
-   */
-  getModuleSignals(moduleId: string): StrategySignal[] {
-    return Array.from(this.signals.values()).filter(signal => signal.moduleId === moduleId)
-  }
-
-  /**
-   * 记录执行结果
-   */
-  recordExecution(result: StrategyExecutionResult): void {
-    this.executions.set(result.signalId, result)
-  }
-
-  /**
-   * 获取执行结果
-   */
-  getExecution(signalId: string): StrategyExecutionResult | undefined {
-    return this.executions.get(signalId)
-  }
-
-  /**
-   * 获取模块的执行结果
-   */
-  getModuleExecutions(moduleId: string): StrategyExecutionResult[] {
-    const moduleSignals = this.getModuleSignals(moduleId)
-    const signalIds = moduleSignals.map(s => s.signalId)
-    return Array.from(this.executions.values()).filter(exec => signalIds.includes(exec.signalId))
-  }
-
-  /**
-   * 计算性能指标
-   */
-  calculatePerformanceMetrics(moduleId: string, period: StrategyPerformanceMetrics['period']): StrategyPerformanceMetrics | null {
-    const executions = this.getModuleExecutions(moduleId)
-    if (executions.length === 0) return null
-
-    const now = new Date()
-    const periodMs = this.getPeriodMs(period)
-    const cutoffTime = new Date(now.getTime() - periodMs)
-
-    const periodExecutions = executions.filter(exec => exec.executionTime >= cutoffTime)
-    if (periodExecutions.length === 0) return null
-
-    const totalSignals = periodExecutions.length
-    const successfulSignals = periodExecutions.filter(exec => exec.status === 'success').length
-    const successRate = totalSignals > 0 ? successfulSignals / totalSignals : 0
-
-    let totalProfit = 0
-    let totalFees = 0
-    let maxDrawdown = 0
-    let currentDrawdown = 0
-
-    for (const exec of periodExecutions) {
-      const profit = parseFloat(exec.profitAfterFee || '0')
-      const fees = parseFloat(exec.fees || '0')
-      
-      totalProfit += profit
-      totalFees += fees
-
-      if (profit < 0) {
-        currentDrawdown += Math.abs(profit)
-        maxDrawdown = Math.max(maxDrawdown, currentDrawdown)
-      } else {
-        currentDrawdown = 0
-      }
-    }
-
-    const netProfit = totalProfit - totalFees
-    const profitAfterFee = totalProfit
-
-    const metrics: StrategyPerformanceMetrics = {
-      moduleId,
-      period,
-      totalSignals,
-      successfulSignals,
-      successRate,
-      totalProfit: totalProfit.toString(),
-      totalFees: totalFees.toString(),
-      netProfit: netProfit.toString(),
-      profitAfterFee: profitAfterFee.toString(),
-      maxDrawdown,
-      timestamp: now
-    }
-
-    // 存储性能指标
-    const existingMetrics = this.performanceMetrics.get(moduleId) || []
-    existingMetrics.push(metrics)
-    this.performanceMetrics.set(moduleId, existingMetrics)
-
-    return metrics
-  }
-
-  /**
-   * 获取性能指标历史
-   */
-  getPerformanceHistory(moduleId: string): StrategyPerformanceMetrics[] {
-    return this.performanceMetrics.get(moduleId) || []
-  }
-
-  /**
-   * 验证策略模块配置
-   */
-  validateModule(module: StrategyModule): { isValid: boolean; errors: string[] } {
-    const errors: string[] = []
-
-    if (!module.moduleId) {
-      errors.push('moduleId is required')
-    }
-
-    if (!module.name) {
-      errors.push('name is required')
-    }
-
-    if (!module.type) {
-      errors.push('type is required')
-    }
-
-    if (module.maxConcurrentSignals <= 0) {
-      errors.push('maxConcurrentSignals must be positive')
-    }
-
-    if (module.profitAfterFeeTarget <= 0 || module.profitAfterFeeTarget > 1) {
-      errors.push('profitAfterFeeTarget must be between 0 and 1')
-    }
-
-    return {
-      isValid: errors.length === 0,
-      errors
-    }
-  }
-
-  /**
-   * 检查模块是否可以执行
-   */
-  canExecute(moduleId: string): { canExecute: boolean; reason: string } {
-    const module = this.getModule(moduleId)
-    if (!module) {
-      return { canExecute: false, reason: 'Module not found' }
-    }
-
-    if (module.status !== 'enable') {
-      return { canExecute: false, reason: 'Module is disabled' }
-    }
-
-    const currentSignals = this.getModuleSignals(moduleId).filter(
-      signal => Date.now() - signal.timestamp.getTime() < 60000 // 最近1分钟的信号
-    )
-
-    if (currentSignals.length >= module.maxConcurrentSignals) {
-      return { canExecute: false, reason: 'Maximum concurrent signals reached' }
-    }
-
-    return { canExecute: true, reason: 'OK' }
-  }
-
-  /**
-   * 获取周期毫秒数
-   */
-  private getPeriodMs(period: StrategyPerformanceMetrics['period']): number {
-    switch (period) {
-      case 'hour': return 60 * 60 * 1000
-      case 'day': return 24 * 60 * 60 * 1000
-      case 'week': return 7 * 24 * 60 * 60 * 1000
-      case 'month': return 30 * 24 * 60 * 60 * 1000
-      default: return 24 * 60 * 60 * 1000
-    }
-  }
-
-  /**
-   * 添加配置模板
-   */
-  addConfigTemplate(template: StrategyConfigTemplate): void {
-    this.configTemplates.set(template.templateId, template)
-  }
-
-  /**
-   * 获取配置模板
-   */
-  getConfigTemplate(templateId: string): StrategyConfigTemplate | undefined {
-    return this.configTemplates.get(templateId)
-  }
-
-  /**
-   * 获取所有配置模板
-   */
-  getAllConfigTemplates(): StrategyConfigTemplate[] {
-    return Array.from(this.configTemplates.values())
-  }
-
-  /**
-   * 根据类型获取配置模板
-   */
-  getConfigTemplatesByType(type: StrategyModule['type']): StrategyConfigTemplate[] {
-    return this.getAllConfigTemplates().filter(template => template.type === type)
-  }
-
-  /**
-   * 从模板创建策略模块
-   */
-  createModuleFromTemplate(templateId: string, customConfig?: Record<string, any>): StrategyModule | null {
-    const template = this.getConfigTemplate(templateId)
-    if (!template) return null
-
-    const moduleId = `${template.type}-${Date.now()}`
-    const config = { ...template.defaultConfig, ...customConfig }
-
-    const module: StrategyModule = {
-      moduleId,
-      name: template.name,
-      type: template.type,
-      configSchema: template.configSchema,
-      dryRunEnabled: true,
-      maxConcurrentSignals: 3,
-      profitAfterFeeTarget: template.expectedReturn.typical,
-      requiresSandbox: true,
-      status: 'enable',
-      ...config
-    }
-
-    this.addModule(module)
-    return module
-  }
-}

+ 0 - 29
src/models/SynthPriceSnapshot.ts

@@ -1,29 +0,0 @@
-/**
- * 合成价格快照模型
- */
-export interface SynthPriceSnapshot {
-  snapshotId: string
-  symbol: string
-  sourceFeeds: string[]
-  midPrice: number
-  bid: number
-  ask: number
-  timestamp: Date
-  reason: 'ws-failover' | 'http-timeout' | 'manual'
-}
-
-export class SynthPriceSnapshotManager {
-  private snapshots: Map<string, SynthPriceSnapshot> = new Map()
-
-  addSnapshot(snapshot: SynthPriceSnapshot): void {
-    this.snapshots.set(snapshot.snapshotId, snapshot)
-  }
-
-  getSnapshot(snapshotId: string): SynthPriceSnapshot | undefined {
-    return this.snapshots.get(snapshotId)
-  }
-
-  getAllSnapshots(): SynthPriceSnapshot[] {
-    return Array.from(this.snapshots.values())
-  }
-}