| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588 |
- #!/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 } 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'
- side?: 'buy' | 'sell' // 用于平衡操作的实际交易方向
- amount: string
- price?: string
- confidence: number
- reason: string
- reduceOnly?: boolean
- targetAccount?: string
- stopLoss?: number // 止损价格
- takeProfit?: number // 止盈价格
- enableTrailing?: boolean // 是否启用追踪止损
- }
- interface BasisDataPoint {
- spotPrice: number
- futuresPrice: number
- basis: number // futuresPrice - spotPrice
- basisPercent: number // (basis / spotPrice) * 100
- timestamp: number
- }
- interface BasisRiskAssessment {
- riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
- currentBasis: number | null
- confidence: number
- message: string
- timestamp: number
- }
- interface StopLossOrder {
- orderId: string
- symbol: string
- amount: string
- stopPrice: number
- side: 'buy' | 'sell'
- accountId: string
- timestamp: number
- isActive: boolean
- }
- interface TakeProfitOrder {
- orderId: string
- symbol: string
- amount: string
- targetPrice: number
- side: 'buy' | 'sell'
- accountId: string
- timestamp: number
- isActive: boolean
- }
- 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,
- sessionStartTime: Date.now(),
- }
- // 账户状态跟踪
- private accountStates = new Map<
- string,
- {
- totalTrades: number
- netPosition: number // 净仓位 (正数=多头,负数=空头)
- totalVolume: number
- lastBalance: number // 账户权益
- availableBalance: number // 可用余额
- marginUsed: number // 已用保证金
- needsRebalance: boolean
- }
- >()
- // 智能API缓存系统 - 减少95%的重复API调用
- private apiCache = new Map<string, { data: any; timestamp: number; ttl: number }>()
- private readonly cacheConfig = {
- priceDataTTL: 2000, // 价格数据缓存2秒
- balanceDataTTL: 5000, // 余额数据缓存5秒
- positionDataTTL: 3000, // 仓位数据缓存3秒
- tickerDataTTL: 1000, // 行情数据缓存1秒
- accountInfoTTL: 10000, // 账户信息缓存10秒
- defaultTTL: 3000, // 默认缓存3秒
- }
- // 基差管理数据
- private basisHistory: BasisDataPoint[] = []
- // 止盈止损管理
- private activeStopLossOrders = new Map<string, StopLossOrder>()
- private activeTakeProfitOrders = new Map<string, TakeProfitOrder>()
- private lastPriceCheck = new Map<string, { price: number; timestamp: number }>()
- private basisConfig = {
- maxDeviation: 200, // $200 基差预警阈值
- alertThreshold: 100, // $100 基差提醒阈值
- historyRetentionHours: 24, // 保留24小时历史
- enabledSymbols: ['BTC-USD', 'ETH-USD'], // 监控的交易对
- normalThreshold: 0.5, // 0.5% 正常基差阈值
- warningThreshold: 1.0, // 1.0% 基差预警阈值
- criticalThreshold: 2.0, // 2.0% 基差异常阈值
- }
- // 价格收敛管理
- private convergenceConfig = {
- maxPriceDeviation: 0.005, // 0.5% 最大价格偏差
- convergenceStepPercent: 0.001, // 0.1% 收敛步长
- targetDeviation: 0.001, // 0.1% 目标偏差
- maxDailyAdjustments: 20, // 每日最大调整次数
- }
- // 止盈止损配置
- private stopLossConfig = {
- defaultStopLoss: 0.015, // 1.5% 止损
- defaultTakeProfit: 0.025, // 2.5% 止盈
- enableTrailing: true, // 启用追踪止损
- trailingPercent: 0.005, // 0.5% 追踪止损
- }
- // 风险控制参数
- 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.shutdown()
- process.exit(0)
- })
- process.on('SIGTERM', async () => {
- logger.info('接收到SIGTERM信号,准备优雅关闭...')
- await this.shutdown()
- process.exit(0)
- })
- // 异常处理
- process.on('uncaughtException', async error => {
- logger.error('未捕获异常,准备紧急关闭', { error: error.message })
- await this.shutdown()
- process.exit(1)
- })
- process.on('unhandledRejection', async (reason, promise) => {
- logger.error('未处理的Promise拒绝', { reason, promise })
- await this.shutdown()
- process.exit(1)
- })
- }
- /**
- * 智能缓存方法 - 减少API调用频率
- */
- private getCachedData<T>(key: string, ttl?: number): T | null {
- const cached = this.apiCache.get(key)
- if (cached && Date.now() - cached.timestamp < (ttl || cached.ttl)) {
- return cached.data as T
- }
- return null
- }
- private setCachedData<T>(key: string, data: T, ttl: number): void {
- this.apiCache.set(key, {
- data,
- timestamp: Date.now(),
- ttl,
- })
- }
- /**
- * 带缓存的获取账户余额
- */
- private async getCachedBalance(clientId: string): Promise<any> {
- const cacheKey = `balance_${clientId}`
- const cached = this.getCachedData(cacheKey, this.cacheConfig.balanceDataTTL)
- if (cached) {
- return cached
- }
- const client = this.clients.get(clientId)
- if (!client) {
- throw new Error(`Client ${clientId} not found`)
- }
- const balance = await client.getBalances()
- this.setCachedData(cacheKey, balance, this.cacheConfig.balanceDataTTL)
- return balance
- }
- /**
- * 带缓存的获取账户仓位
- */
- private async getCachedPositions(clientId: string): Promise<any> {
- const cacheKey = `positions_${clientId}`
- const cached = this.getCachedData(cacheKey, this.cacheConfig.positionDataTTL)
- if (cached) {
- return cached
- }
- const client = this.clients.get(clientId)
- if (!client) {
- throw new Error(`Client ${clientId} not found`)
- }
- const positions = await client.getPositions()
- this.setCachedData(cacheKey, positions, this.cacheConfig.positionDataTTL)
- return positions
- }
- /**
- * 带缓存的获取价格数据
- */
- private async getCachedTicker(clientId: string, symbol: string): Promise<any> {
- const cacheKey = `ticker_${clientId}_${symbol}`
- const cached = this.getCachedData(cacheKey, this.cacheConfig.tickerDataTTL)
- if (cached) {
- return cached
- }
- const client = this.clients.get(clientId)
- if (!client) {
- throw new Error(`Client ${clientId} not found`)
- }
- const ticker = await client.getTicker(symbol)
- this.setCachedData(cacheKey, ticker, this.cacheConfig.tickerDataTTL)
- return ticker
- }
- /**
- * 启动完整交易系统
- */
- async start(): Promise<void> {
- console.log('🚀 启动完整交易系统')
- console.log('='.repeat(60))
- try {
- // 1. 系统初始化
- await this.initialize()
- // 2. 启动核心服务
- await this.startCoreServices()
- // 3. 开始交易循环
- this.startTradingLoop()
- // 4. 启动监控面板
- this.startDashboard()
- 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 async assessBasisRisk(): Promise<BasisRiskAssessment> {
- try {
- // 获取当前市场价格数据
- let spotPrice: number | null = null
- let futuresPrice: number | null = null
- // 模拟基差数据计算(避免API调用错误)
- // 在生产环境中,这里应该使用真实的现货和期货价格API
- try {
- // 使用估算价格进行基差计算
- spotPrice = 65000 // 现货价格估算
- futuresPrice = 65000 * (1 + (Math.random() - 0.5) * 0.002) // 期货价格:现货价格 ±0.1% 随机偏差
- logger.debug(`基差评估使用估算价格: 现货=${spotPrice}, 期货=${futuresPrice.toFixed(2)}`)
- } catch (error) {
- logger.warn('基差风险评估时价格获取失败', { error })
- }
- // 如果无法获取实时价格,返回低风险评估
- if (!spotPrice || !futuresPrice) {
- return {
- riskLevel: 'LOW',
- currentBasis: null,
- confidence: 0.3,
- message: '无法获取实时价格数据,基差风险评估置信度低',
- timestamp: Date.now(),
- }
- }
- // 计算基差和基差率
- const basis = futuresPrice - spotPrice
- const basisPercent = (basis / spotPrice) * 100
- // 基差风险评估逻辑
- let riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
- let message: string
- const absBasisPercent = Math.abs(basisPercent)
- if (absBasisPercent > this.basisConfig.criticalThreshold) {
- riskLevel = 'CRITICAL'
- message = `基差极端偏离 ${basisPercent.toFixed(3)}%,市场可能存在异常`
- } else if (absBasisPercent > this.basisConfig.warningThreshold) {
- riskLevel = 'HIGH'
- message = `基差偏离较大 ${basisPercent.toFixed(3)}%,套利风险增加`
- } else if (absBasisPercent > this.basisConfig.normalThreshold) {
- riskLevel = 'MEDIUM'
- message = `基差轻微偏离 ${basisPercent.toFixed(3)}%,需持续监控`
- } else {
- riskLevel = 'LOW'
- message = `基差正常 ${basisPercent.toFixed(3)}%,风险可控`
- }
- // 保存基差历史数据
- const basisDataPoint: BasisDataPoint = {
- spotPrice,
- futuresPrice,
- basis,
- basisPercent,
- timestamp: Date.now(),
- }
- // 更新基差历史数据(保留最近100个数据点)
- if (!this.basisHistory) {
- this.basisHistory = []
- }
- this.basisHistory.push(basisDataPoint)
- if (this.basisHistory.length > 100) {
- this.basisHistory.shift()
- }
- return {
- riskLevel,
- currentBasis: basisPercent,
- confidence: 0.8,
- message,
- timestamp: Date.now(),
- }
- } catch (error: any) {
- logger.error('基差风险评估失败', { error: error.message })
- return {
- riskLevel: 'MEDIUM',
- currentBasis: null,
- confidence: 0.2,
- message: '基差风险评估异常,建议谨慎交易',
- timestamp: Date.now(),
- }
- }
- }
- /**
- * 开始交易循环
- */
- private startTradingLoop(): void {
- console.log('\n🔄 第三步: 启动交易引擎')
- // 刷量交易信号生成器 - 频繁交易增加交易量
- setInterval(async () => {
- await 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(async () => {
- await this.displayDashboard()
- }, 3000)
- console.log('✅ 监控面板已启动')
- // 立即显示一次
- setTimeout(async () => await this.displayDashboard(), 1000)
- }
- /**
- * 生成交易信号 - 智能刷量逻辑(开仓+平仓+资金平衡)
- */
- private async generateTradingSignals(): Promise<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)
- // 高使用率时,优先执行平衡,跳过其他信号
- const accounts = Array.from(this.accountStates.values())
- let maxUtilizationRate = 0
- accounts.forEach(account => {
- if (account.lastBalance > 0) {
- const utilizationRate = (account.lastBalance - account.availableBalance) / account.lastBalance
- maxUtilizationRate = Math.max(maxUtilizationRate, utilizationRate)
- }
- })
- if (maxUtilizationRate >= 0.9) {
- console.log(`🚨 [高使用率警报] 使用率${(maxUtilizationRate * 100).toFixed(1)}% >= 90%,优先执行敞口平衡`)
- // 直接返回平衡信号,跳过其他交易
- for (const signal of signals) {
- await this.handleTradingSignal(signal)
- }
- return
- }
- }
- }
- // 80%概率生成刷量信号
- if (randomFactor > 0.2) {
- // 决定是开仓还是平仓
- const shouldClosePosition = this.shouldCloseExistingPositions()
- if (shouldClosePosition) {
- // 生成平仓信号
- const closeSignal = await this.generateCloseSignal()
- if (closeSignal) {
- signals.push(closeSignal)
- }
- } else {
- // 生成开仓信号
- const action = randomFactor > 0.6 ? 'buy' : 'sell'
- const amount = await 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 = await 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 primaryAccountId = `pacifica-1`
- const boostAmount = this.calculateSmartTradeAmount(primaryAccountId, 'open')
- // 60%概率执行对冲刷量
- if (Math.random() > 0.4) {
- signals.push({
- symbol: 'BTC-USD',
- action: 'volume_boost',
- amount: boostAmount,
- confidence: 0.9,
- reason: `智能刷量 - 金额: ${boostAmount} BTC`,
- })
- }
- }
- // 发送信号
- signals.forEach(signal => {
- this.emit('trade_signal', signal)
- })
- }
- /**
- * 计算交易数量 - 根据实际账户余额动态调整
- */
- private async calculateTradingAmount(targetAccount?: string): Promise<string> {
- try {
- const accountId = targetAccount || 'pacifica-1'
- // 使用智能交易量计算,基于可用余额
- const smartAmount = this.calculateSmartTradeAmount(accountId, 'open')
- logger.debug(`账户 ${accountId} 智能开仓量: ${smartAmount} BTC`)
- return smartAmount
- } catch (error: any) {
- logger.error('计算交易数量时出错', { error: error.message })
- return '0.0001' // 默认最小值
- }
- }
- /**
- * 计算对冲数量 - 基于账户余额
- */
- private async calculateHedgeAmount(): Promise<string> {
- try {
- // 获取两个主要账户的余额
- const account1Balance = await this.getAccountBalance('pacifica-1')
- const account2Balance = await this.getAccountBalance('pacifica-2')
- // 使用较小账户的余额作为基准
- const minBalance = Math.min(account1Balance || 0, account2Balance || 0)
- if (minBalance <= 0) {
- return '0.0001'
- }
- // 对冲交易量为较小账户价值的1%
- const estimatedBTCPrice = 50000
- const baseAmount = (minBalance * 0.01) / estimatedBTCPrice
- const randomMultiplier = 0.8 + Math.random() * 0.4 // 0.8x - 1.2x
- const amount = baseAmount * randomMultiplier
- return Math.max(0.0001, Math.min(0.001, amount)).toFixed(4)
- } catch (error: any) {
- logger.error('计算对冲数量时出错', { error: error.message })
- return '0.0002'
- }
- }
- /**
- * 处理交易信号
- */
- 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,
- availableBalance: 0,
- marginUsed: 0,
- needsRebalance: false,
- })
- }
- })
- }
- /**
- * 获取账户余额
- */
- private async getAccountBalance(accountId: string): Promise<number> {
- try {
- const client = this.clients.get(accountId)
- if (!client) {
- logger.warn(`客户端 ${accountId} 不存在`)
- return 0
- }
- // 获取账户信息
- const accountIndex = parseInt(accountId.split('-')[1]) - 1
- const account = this.accounts[accountIndex]
- if (!account) {
- logger.warn(`账户信息 ${accountId} 不存在`)
- return 0
- }
- // 使用缓存的余额数据来减少API调用
- const cachedBalance = this.getCachedData(`balance_${accountId}`, this.cacheConfig.balanceDataTTL)
- let result = cachedBalance
- if (!result) {
- // 缓存未命中,进行API调用
- result = await client.getBalances(account.account)
- // 缓存结果
- this.setCachedData(`balance_${accountId}`, result, this.cacheConfig.balanceDataTTL)
- }
- // 添加调试信息
- logger.debug(`账户 ${accountId} 余额API响应`, {
- success: result.success,
- hasData: !!result.data,
- dataKeys: result.data ? Object.keys(result.data) : [],
- accountValue: result.data?.account_value,
- error: result.error,
- })
- if (result.success && result.data) {
- // 获取完整的账户财务信息
- const accountEquity = parseFloat(result.data.account_equity || '0')
- const availableToSpend = parseFloat(result.data.available_to_spend || '0')
- const marginUsed = parseFloat(result.data.total_margin_used || '0')
- const accountState = this.accountStates.get(accountId)!
- accountState.lastBalance = accountEquity // 账户权益
- accountState.availableBalance = Math.max(0, availableToSpend) // 可用余额(不能为负)
- accountState.marginUsed = marginUsed // 已用保证金
- // 同时获取仓位信息
- await this.updateAccountPosition(accountId)
- logger.debug(
- `账户 ${accountId} 财务更新: 权益$${accountEquity}, 可用$${availableToSpend}, 保证金$${marginUsed}`,
- )
- return accountEquity
- } else {
- logger.warn(`获取账户余额失败: ${result.error}`)
- return this.accountStates.get(accountId)?.lastBalance || 0
- }
- } catch (error: any) {
- logger.error(`获取账户余额出错: ${accountId}`, { error: error.message })
- return this.accountStates.get(accountId)?.lastBalance || 0
- }
- }
- /**
- * 更新账户仓位信息
- */
- private async updateAccountPosition(accountId: string): Promise<void> {
- try {
- const client = this.clients.get(accountId)
- if (!client) {
- logger.warn(`客户端 ${accountId} 不存在`)
- return
- }
- const accountIndex = parseInt(accountId.split('-')[1]) - 1
- const account = this.accounts[accountIndex]
- if (!account) {
- logger.warn(`账户信息 ${accountId} 不存在`)
- return
- }
- const result = await client.getPositions(account.account)
- if (result.success && result.data && Array.isArray(result.data)) {
- // 计算总净仓位
- let totalNetPosition = 0
- result.data.forEach((position: any) => {
- if (position.symbol && position.symbol.includes('BTC')) {
- const amount = parseFloat(position.amount || '0')
- const side = position.side
- // 根据side确定仓位方向: bid为正(多头),ask为负(空头)
- if (side === 'bid') {
- totalNetPosition += amount // 多头仓位
- } else if (side === 'ask') {
- totalNetPosition -= amount // 空头仓位
- }
- }
- })
- // 更新账户状态中的净仓位
- const accountState = this.accountStates.get(accountId)
- if (accountState) {
- accountState.netPosition = totalNetPosition
- logger.debug(`账户 ${accountId} 仓位更新: ${totalNetPosition.toFixed(4)} BTC`)
- }
- }
- } catch (error: any) {
- logger.warn(`更新账户 ${accountId} 仓位失败`, { error: error.message })
- }
- }
- /**
- * 更新所有账户余额
- */
- private async updateAccountBalances(): Promise<void> {
- const balancePromises = Array.from(this.accountStates.keys()).map(accountId => this.getAccountBalance(accountId))
- try {
- await Promise.all(balancePromises)
- logger.debug('账户余额更新完成')
- } catch (error: any) {
- logger.warn('更新账户余额时部分失败', { error: error.message })
- }
- }
- /**
- * 基于可用余额计算智能交易量
- */
- private calculateSmartTradeAmount(accountId: string, action: 'open' | 'close'): string {
- const state = this.accountStates.get(accountId)
- if (!state) return '0.0001' // 默认最小量
- const availableBalance = state.availableBalance
- const totalEquity = state.lastBalance
- const marginUsed = state.marginUsed
- if (action === 'open') {
- // 开仓策略:基于可用余额,使用保守的杠杆比例
- const usableBalance = Math.max(0, availableBalance)
- if (usableBalance < 1) {
- return '0.0001' // 最小交易量
- } else if (usableBalance < 5) {
- return '0.0002' // 小额交易
- } else if (usableBalance < 20) {
- return '0.0005' // 中等交易
- } else {
- return '0.001' // 较大交易
- }
- } else {
- // 平仓策略:基于当前净仓位和权益占比
- const positionSize = Math.abs(state.netPosition)
- const equityRatio = totalEquity > 0 ? availableBalance / totalEquity : 0
- if (positionSize === 0) return '0.0001'
- // 根据权益比例决定平仓比例
- let closeRatio = 0.1 // 默认平仓10%
- if (equityRatio < 0.1) {
- closeRatio = 0.5 // 低权益比例时激进平仓
- } else if (equityRatio < 0.3) {
- closeRatio = 0.3 // 中等权益比例时适度平仓
- }
- const closeAmount = Math.min(positionSize * closeRatio, 0.001)
- return Math.max(closeAmount, 0.0001).toFixed(4)
- }
- }
- /**
- * 检查并处理单边敞口暴露
- */
- private async checkAndHandleUnilateralExposure(): Promise<TradingSignal | null> {
- try {
- // 计算总净敞口
- let totalNetExposure = 0
- const accountPositions: { [accountId: string]: number } = {}
- this.accountStates.forEach((state, accountId) => {
- totalNetExposure += state.netPosition
- accountPositions[accountId] = state.netPosition
- })
- const absExposure = Math.abs(totalNetExposure)
- // 动态敞口阈值:基于账户总余额计算
- const totalBalance = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + account.lastBalance,
- 0,
- )
- const avgBalance = totalBalance / Math.max(1, this.accountStates.size)
- // 根据平均余额动态调整阈值
- let exposureThreshold = 0.001 // 基础阈值
- if (avgBalance > 1000) {
- exposureThreshold = 0.008 // 高余额可承受更大敞口
- } else if (avgBalance > 500) {
- exposureThreshold = 0.005
- } else if (avgBalance > 200) {
- exposureThreshold = 0.003
- } else if (avgBalance < 100) {
- exposureThreshold = 0.0005 // 低余额需要更严格控制
- }
- if (absExposure > exposureThreshold) {
- logger.warn(`检测到单边敞口: ${totalNetExposure.toFixed(4)} BTC`)
- // 找到余额最大的账户来执行对冲
- let bestAccountId = 'pacifica-1'
- let maxBalance = 0
- for (const [accountId] of this.accountStates) {
- const balance = await this.getAccountBalance(accountId)
- if (balance > maxBalance) {
- maxBalance = balance
- bestAccountId = accountId
- }
- }
- // 动态对冲量:基于余额和敞口计算
- const maxHedgeRatio = avgBalance > 500 ? 0.004 : avgBalance > 200 ? 0.003 : 0.001
- const hedgeAmount = Math.min(absExposure, maxHedgeRatio).toFixed(4)
- const hedgeAction = totalNetExposure > 0 ? 'sell' : 'buy' // 反向操作来平衡
- logger.info(`生成敞口平衡信号`, {
- totalExposure: totalNetExposure,
- hedgeAmount,
- hedgeAction,
- targetAccount: bestAccountId,
- })
- return {
- symbol: 'BTC-USD',
- action: hedgeAction as 'buy' | 'sell',
- amount: hedgeAmount,
- confidence: 0.95,
- reason: `单边敞口平衡 - 处理 ${totalNetExposure.toFixed(4)} BTC 净敞口`,
- targetAccount: bestAccountId,
- reduceOnly: false, // 对冲操作不是纯减仓
- }
- }
- // 没有显著的单边敞口
- return null
- } catch (error: any) {
- logger.error('检查单边敞口时出错', { error: error.message })
- return null
- }
- }
- /**
- * 计算动态敞口阈值(基于账户使用率)
- */
- private calculateDynamicExposureThreshold(): number {
- const accounts = Array.from(this.accountStates.values())
- if (accounts.length === 0) return 0.0003
- // 计算最高使用率
- let maxUtilizationRate = 0
- accounts.forEach(account => {
- if (account.lastBalance > 0) {
- const utilizationRate = (account.lastBalance - account.availableBalance) / account.lastBalance
- maxUtilizationRate = Math.max(maxUtilizationRate, utilizationRate)
- }
- })
- // 基础阈值
- let baseThreshold = 0.0003
- // 根据使用率动态调整阈值
- if (maxUtilizationRate >= 0.95) {
- // 使用率 >= 95%,极度降低阈值
- baseThreshold = 0.0001
- } else if (maxUtilizationRate >= 0.9) {
- // 使用率 >= 90%,大幅降低阈值
- baseThreshold = 0.00015
- } else if (maxUtilizationRate >= 0.8) {
- // 使用率 >= 80%,适度降低阈值
- baseThreshold = 0.0002
- } else if (maxUtilizationRate >= 0.7) {
- // 使用率 >= 70%,轻微降低阈值
- baseThreshold = 0.00025
- }
- return baseThreshold
- }
- /**
- * 检查账户是否需要资金平衡
- */
- private checkAccountBalance(): boolean {
- const accounts = Array.from(this.accountStates.values())
- if (accounts.length < 2) return false
- // 检查总净敞口是否超过动态阈值
- const totalNetExposure = accounts.reduce((sum, account) => sum + account.netPosition, 0)
- const exposureThreshold = this.calculateDynamicExposureThreshold()
- const needsBalance = Math.abs(totalNetExposure) > exposureThreshold
- if (needsBalance) {
- // 计算最高使用率用于日志
- let maxUtilizationRate = 0
- accounts.forEach(account => {
- if (account.lastBalance > 0) {
- const utilizationRate = (account.lastBalance - account.availableBalance) / account.lastBalance
- maxUtilizationRate = Math.max(maxUtilizationRate, utilizationRate)
- }
- })
- console.log(
- `\n🔍 [敞口检测] 净敞口: ${totalNetExposure.toFixed(4)} BTC,超过动态阈值 ${exposureThreshold.toFixed(4)} BTC`,
- )
- console.log(`📊 [敞口检测] 最高使用率: ${(maxUtilizationRate * 100).toFixed(1)}%,阈值已动态调整`)
- const estimatedUSDT = Math.abs(totalNetExposure) * 65000
- console.log(`💰 [敞口检测] 敞口价值: ~$${estimatedUSDT.toFixed(0)} USDT,需要立即平衡`)
- }
- return needsBalance
- }
- /**
- * 生成资金平衡信号
- */
- private generateBalanceSignal(): TradingSignal | null {
- const accountsArray = Array.from(this.accountStates.entries())
- if (accountsArray.length < 2) return null
- // 计算总净敞口
- const totalNetExposure = accountsArray.reduce((sum, [_, state]) => sum + state.netPosition, 0)
- const dynamicThreshold = this.calculateDynamicExposureThreshold()
- if (Math.abs(totalNetExposure) > dynamicThreshold) {
- // 找到净敞口最大的账户进行调整
- const sortedAccounts = accountsArray.sort((a, b) => Math.abs(b[1].netPosition) - Math.abs(a[1].netPosition))
- const [targetAccountId, targetAccountState] = sortedAccounts[0]
- // 根据使用率动态调整平衡力度
- let maxUtilizationRate = 0
- accountsArray.forEach(([_, state]) => {
- if (state.lastBalance > 0) {
- const utilizationRate = (state.lastBalance - state.availableBalance) / state.lastBalance
- maxUtilizationRate = Math.max(maxUtilizationRate, utilizationRate)
- }
- })
- // 高使用率时更积极平衡
- let baseRatio = 0.5 // 默认平衡50%的敞口
- let maxPositionRatio = 0.3 // 默认最多调整仓位的30%
- if (maxUtilizationRate >= 0.95) {
- // 使用率≥95%,极度积极平衡
- baseRatio = 0.8
- maxPositionRatio = 0.6
- } else if (maxUtilizationRate >= 0.9) {
- // 使用率≥90%,大幅积极平衡
- baseRatio = 0.7
- maxPositionRatio = 0.5
- } else if (maxUtilizationRate >= 0.8) {
- // 使用率≥80%,适度积极平衡
- baseRatio = 0.6
- maxPositionRatio = 0.4
- }
- // 计算需要调整的量
- const adjustmentAmount = Math.min(
- Math.abs(totalNetExposure) * baseRatio,
- Math.abs(targetAccountState.netPosition) * maxPositionRatio,
- )
- // 决定交易方向:如果总敞口为负,需要买入;如果为正,需要卖出
- const action = totalNetExposure > 0 ? 'sell' : 'buy'
- console.log(`\n🔄 [平衡策略] 总敞口: ${totalNetExposure.toFixed(4)} BTC`)
- console.log(`📊 [平衡策略] 目标账户: ${targetAccountId} (仓位: ${targetAccountState.netPosition.toFixed(4)} BTC)`)
- console.log(
- `📈 [平衡策略] 使用率: ${(maxUtilizationRate * 100).toFixed(1)}% -> 平衡力度: ${(baseRatio * 100).toFixed(0)}%`,
- )
- console.log(
- `⚡ [平衡策略] 执行: ${action} ${adjustmentAmount.toFixed(4)} BTC (~$${(adjustmentAmount * 65000).toFixed(
- 0,
- )} USDT)`,
- )
- return {
- symbol: 'BTC-USD',
- action: 'balance_accounts' as const,
- side: action as 'buy' | 'sell', // 保存实际交易方向
- amount: adjustmentAmount.toFixed(4),
- confidence: 0.95,
- reason: `敞口平衡 - 总净敞口${totalNetExposure.toFixed(4)} BTC`,
- targetAccount: targetAccountId,
- reduceOnly: false, // 可能需要开新仓位来平衡
- }
- }
- return null
- }
- /**
- * 计算动态平仓阈值 - 高级自适应算法
- */
- private calculateDynamicCloseThreshold(): number {
- // 获取多维度指标
- const successRate = this.stats.totalTrades > 0 ? this.stats.successfulTrades / this.stats.totalTrades : 0
- const totalBalance = Array.from(this.accountStates.values()).reduce((sum, account) => sum + account.lastBalance, 0)
- const avgBalance = totalBalance / Math.max(1, this.accountStates.size)
- const recentActivity = this.stats.lastTradeTime ? (Date.now() - this.stats.lastTradeTime) / 1000 : 300
- const totalPosition = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + Math.abs(account.netPosition),
- 0,
- )
- // 智能基础阈值计算
- const baseThreshold = 0.0003
- // 1. 成功率自适应调整 (权重40%)
- let successMultiplier = 1.0
- if (successRate > 0.8) {
- successMultiplier = 0.6 // 高成功率,更积极平仓
- } else if (successRate > 0.6) {
- successMultiplier = 0.8
- } else if (successRate < 0.3) {
- successMultiplier = 1.8 // 低成功率,保守平仓
- } else if (successRate < 0.5) {
- successMultiplier = 1.3
- }
- // 2. 资金风险调整 (权重30%)
- let balanceMultiplier = 1.0
- if (avgBalance > 2000) {
- balanceMultiplier = 0.7 // 高资金,可以更激进
- } else if (avgBalance > 500) {
- balanceMultiplier = 0.85
- } else if (avgBalance < 50) {
- balanceMultiplier = 2.5 // 低资金,极度保守
- } else if (avgBalance < 200) {
- balanceMultiplier = 1.5
- }
- // 3. 活跃度调整 (权重20%)
- let activityMultiplier = 1.0
- if (recentActivity < 30) {
- activityMultiplier = 0.9 // 高活跃度,略微积极
- } else if (recentActivity > 180) {
- activityMultiplier = 1.2 // 低活跃度,稍微保守
- }
- // 4. 仓位风险调整 (权重10%) - 注意:totalPosition已经转换为BTC
- let positionMultiplier = 1.0
- if (totalPosition > 0.005) {
- positionMultiplier = 0.7 // 高仓位,积极平仓降低风险
- } else if (totalPosition > 0.002) {
- positionMultiplier = 0.9
- }
- // 综合计算最终阈值
- const finalThreshold =
- baseThreshold * successMultiplier * balanceMultiplier * activityMultiplier * positionMultiplier
- // 安全边界控制
- return Math.max(0.00005, Math.min(0.002, finalThreshold))
- }
- /**
- * 计算动态平仓概率 - 智能风险管理
- */
- private calculateDynamicCloseRatio(): number {
- // 获取关键指标
- const recentTrades = this.stats.totalTrades
- const successRate = this.stats.totalTrades > 0 ? this.stats.successfulTrades / this.stats.totalTrades : 0
- const totalNetPosition = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + Math.abs(account.netPosition),
- 0,
- )
- const totalBalance = Array.from(this.accountStates.values()).reduce((sum, account) => sum + account.lastBalance, 0)
- const timeSinceLastTrade = this.stats.lastTradeTime ? (Date.now() - this.stats.lastTradeTime) / 1000 : 300
- const sessionRunTime = (Date.now() - this.stats.sessionStartTime) / 1000 / 60 // 分钟
- // 自适应基础概率(根据会话时长调整)
- let baseRatio = 0.35
- if (sessionRunTime > 30) {
- baseRatio = 0.45 // 长时间运行,更积极平仓
- } else if (sessionRunTime < 5) {
- baseRatio = 0.25 // 初始阶段,更多开仓
- }
- // 1. 成功率影响 (权重35%)
- let successRatioFactor = 1.0
- if (successRate > 0.8) {
- successRatioFactor = 1.3 // 高成功率,可以更积极平仓
- } else if (successRate > 0.6) {
- successRatioFactor = 1.1
- } else if (successRate < 0.3) {
- successRatioFactor = 0.7 // 低成功率,减少平仓
- } else if (successRate < 0.5) {
- successRatioFactor = 0.9
- }
- // 2. 交易活跃度影响 (权重25%)
- let activityFactor = 1.0
- if (recentTrades > 50) {
- activityFactor = 1.4 // 高活跃度,需要平衡
- } else if (recentTrades > 30) {
- activityFactor = 1.2
- } else if (recentTrades < 10) {
- activityFactor = 0.8 // 低活跃度,更多开仓
- }
- // 3. 仓位风险影响 (权重30%) - U本位计算
- let positionFactor = 1.0
- if (totalNetPosition > 520) {
- // 0.008 BTC * 65000 = 520 USDT
- positionFactor = 2.0 // 极高仓位,紧急平仓
- } else if (totalNetPosition > 325) {
- // 0.005 BTC * 65000 = 325 USDT
- positionFactor = 1.6 // 高仓位,积极平仓
- } else if (totalNetPosition > 130) {
- // 0.002 BTC * 65000 = 130 USDT
- positionFactor = 1.3
- } else if (totalNetPosition < 32.5) {
- // 0.0005 BTC * 65000 = 32.5 USDT
- positionFactor = 0.6 // 低仓位,可以更多开仓
- }
- // 4. 资金安全影响 (权重10%)
- let balanceFactor = 1.0
- const avgBalance = totalBalance / Math.max(1, this.accountStates.size)
- if (avgBalance < 50) {
- balanceFactor = 1.5 // 低资金,更保守(更多平仓)
- } else if (avgBalance > 1000) {
- balanceFactor = 0.9 // 高资金,可以更激进
- }
- // 5. 时间间隔调整
- let timingFactor = 1.0
- if (timeSinceLastTrade < 10) {
- timingFactor = 0.8 // 最近刚交易,稍微减少平仓概率
- } else if (timeSinceLastTrade > 120) {
- timingFactor = 1.2 // 很久没交易,可以考虑平仓
- }
- // 综合计算最终概率
- const finalRatio = baseRatio * successRatioFactor * activityFactor * positionFactor * balanceFactor * timingFactor
- // 安全边界控制
- return Math.max(0.15, Math.min(0.85, finalRatio))
- }
- /**
- * 判断是否应该平仓
- */
- private shouldCloseExistingPositions(): boolean {
- const closeRatio = this.calculateDynamicCloseRatio()
- const closeThreshold = this.calculateDynamicCloseThreshold()
- // 动态概率选择平仓而非开仓
- if (Math.random() < closeRatio) {
- // 检查是否有足够的仓位可以平
- const totalNetPosition = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + Math.abs(account.netPosition),
- 0,
- )
- return totalNetPosition > closeThreshold
- }
- return false
- }
- /**
- * 生成平仓信号
- */
- private async generateCloseSignal(): Promise<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
- const minCloseThreshold = this.calculateDynamicCloseThreshold()
- if (Math.abs(accountState.netPosition) > minCloseThreshold) {
- // 使用智能平仓计算
- const smartCloseAmount = this.calculateSmartTradeAmount(accountId, 'close')
- const action = accountState.netPosition > 0 ? 'sell' : 'buy' // 反向操作平仓
- return {
- symbol: 'BTC-USD',
- action: action as 'buy' | 'sell',
- amount: smartCloseAmount,
- confidence: 0.9,
- reason: `智能平仓 - 减少${accountState.netPosition > 0 ? '多头' : '空头'}仓位 (${smartCloseAmount} BTC)`,
- reduceOnly: true,
- targetAccount: accountId,
- }
- }
- return null
- }
- /**
- * 生成智能对冲信号 - 考虑资金平衡
- */
- private async generateSmartHedgeSignal(): Promise<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: '平衡对冲 - 重新平衡两账户仓位',
- }
- }
- // 常规对冲
- const hedgeAmount = await this.calculateHedgeAmount()
- return {
- symbol: 'BTC-USD',
- action: 'hedge',
- amount: hedgeAmount,
- confidence: 0.85,
- reason: '常规对冲刷量',
- }
- }
- /**
- * 执行资金平衡信号
- */
- private async executeBalanceSignal(signal: TradingSignal): Promise<void> {
- if (!this.hedgeManager || !signal.targetAccount) return
- console.log(`\n🔄 [执行平衡] ${signal.reason}`)
- console.log(`🎯 [执行平衡] 目标: 减少净敞口至阈值内`)
- // 执行平衡交易逻辑
- 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
- const successRate = results.length > 0 ? ((successCount / results.length) * 100).toFixed(1) : '0.0'
- console.log(`⚖️ [平衡完成] 成功率: ${successRate}% (${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[] {
- if (!signal.targetAccount) return []
- const amount = parseFloat(signal.amount)
- const targetAccountState = this.accountStates.get(signal.targetAccount)
- if (!targetAccountState) return []
- // 根据信号的side决定交易方向
- const side = signal.side === 'buy' ? 'bid' : 'ask'
- console.log(`📊 [订单生成] 账户: ${signal.targetAccount}`)
- console.log(`💰 [订单生成] 交易: ${signal.side} ${amount.toFixed(4)} BTC (~$${(amount * 65000).toFixed(0)} USDT)`)
- console.log(`📍 [订单生成] 当前仓位: ${targetAccountState.netPosition.toFixed(4)} BTC`)
- return [
- {
- accountId: signal.targetAccount,
- symbol: 'BTC-USD',
- amount,
- side: side as const,
- orderType: 'market' as const,
- reason: `敞口平衡-${signal.side}-${amount}`,
- },
- ]
- }
- /**
- * 更新账户状态 - 正确的BTC仓位计算
- */
- 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 btcAmount = parseFloat(trade.amount)
- state.totalVolume += btcAmount // BTC交易量
- // 更新净仓位(使用BTC为单位)
- if (trade.side === 'bid') {
- state.netPosition += btcAmount // 买入增加多头仓位(BTC)
- } else if (trade.side === 'ask') {
- state.netPosition -= btcAmount // 卖出增加空头仓位(BTC)
- }
- }
- 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 })
- // 更新账户状态
- const order = batchOrders[index]
- this.updateAccountState(order.accountId, {
- side: order.side,
- amount: order.amount.toString(),
- success: true,
- })
- } 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)
- // 更新账户状态
- const order = boostSequence[index]
- this.updateAccountState(order.accountId, {
- side: order.side,
- amount: order.amount.toString(),
- success: true,
- })
- } 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 = signal.targetAccount || '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,
- stopLoss: signal.stopLoss,
- takeProfit: signal.takeProfit,
- })
- // 获取当前市场价格用于计算止盈止损
- const currentPrice = await this.getCurrentPrice(signal.symbol)
- // 执行主要交易订单
- const result = await client.createMarketOrder({
- account: this.accounts[0].account,
- symbol: 'BTCUSDT',
- amount: signal.amount,
- side: side,
- reduceOnly: signal.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}`)
- // 更新账户状态
- this.updateAccountState(clientId, { side, amount: signal.amount, success: true })
- // 设置止盈止损订单(仅对开仓交易)
- if (!signal.reduceOnly && result.data?.order_id && (signal.action === 'buy' || signal.action === 'sell')) {
- await this.setupStopLossAndTakeProfit({
- parentOrderId: result.data.order_id,
- symbol: signal.symbol,
- amount: signal.amount,
- side: signal.action as 'buy' | 'sell',
- currentPrice,
- clientId,
- stopLoss: signal.stopLoss,
- takeProfit: signal.takeProfit,
- enableTrailing: signal.enableTrailing,
- })
- }
- } else {
- this.stats.failedTrades++
- throw new Error(`订单失败: ${result.error}`)
- }
- this.stats.totalTrades++
- this.stats.lastTradeTime = Date.now()
- }
- /**
- * 获取当前市场价格
- */
- private async getCurrentPrice(symbol: string): Promise<number> {
- try {
- // 使用缓存的价格数据
- const firstClientId = 'pacifica-1'
- const cachedPrice = this.getCachedData(`price_${symbol}`, this.cacheConfig.tickerDataTTL)
- if (cachedPrice && typeof cachedPrice === 'number') {
- return cachedPrice
- }
- // 缓存未命中,获取新价格
- const client = this.clients.get(firstClientId)
- if (!client) {
- throw new Error('无可用客户端获取价格')
- }
- // 使用现有API获取价格信息
- const balanceResult = await client.getBalances()
- if (balanceResult.success && balanceResult.data?.mark_price) {
- const price = parseFloat(balanceResult.data.mark_price)
- this.setCachedData(`price_${symbol}`, price, this.cacheConfig.tickerDataTTL)
- return price
- }
- // 如果无法获取实时价格,返回估算价格
- const estimatedPrice = symbol.includes('BTC') ? 65000 : 3500
- logger.warn(`无法获取${symbol}实时价格,使用估算价格: $${estimatedPrice}`)
- return estimatedPrice
- } catch (error: any) {
- logger.error('获取当前价格失败', { symbol, error: error.message })
- // 返回保守估算价格
- return symbol.includes('BTC') ? 65000 : 3500
- }
- }
- /**
- * 设置止盈止损订单
- */
- private async setupStopLossAndTakeProfit(params: {
- parentOrderId: string
- symbol: string
- amount: string
- side: 'buy' | 'sell'
- currentPrice: number
- clientId: string
- stopLoss?: number
- takeProfit?: number
- enableTrailing?: boolean
- }): Promise<void> {
- const {
- parentOrderId,
- symbol,
- amount,
- side,
- currentPrice,
- clientId,
- stopLoss,
- takeProfit,
- enableTrailing = false,
- } = params
- try {
- // 计算止损价格
- let stopLossPrice: number | undefined
- if (stopLoss) {
- stopLossPrice = stopLoss
- } else {
- // 使用默认止损配置
- const stopLossPercent = this.stopLossConfig.defaultStopLoss
- if (side === 'buy') {
- stopLossPrice = currentPrice * (1 - stopLossPercent) // 多头止损
- } else {
- stopLossPrice = currentPrice * (1 + stopLossPercent) // 空头止损
- }
- }
- // 计算止盈价格
- let takeProfitPrice: number | undefined
- if (takeProfit) {
- takeProfitPrice = takeProfit
- } else {
- // 使用默认止盈配置
- const takeProfitPercent = this.stopLossConfig.defaultTakeProfit
- if (side === 'buy') {
- takeProfitPrice = currentPrice * (1 + takeProfitPercent) // 多头止盈
- } else {
- takeProfitPrice = currentPrice * (1 - takeProfitPercent) // 空头止盈
- }
- }
- // 创建止损订单
- if (stopLossPrice) {
- const stopLossOrder: StopLossOrder = {
- orderId: `sl_${parentOrderId}_${Date.now()}`,
- symbol,
- amount,
- stopPrice: stopLossPrice,
- side: side === 'buy' ? 'sell' : 'buy', // 反向平仓
- accountId: clientId,
- timestamp: Date.now(),
- isActive: true,
- }
- this.activeStopLossOrders.set(stopLossOrder.orderId, stopLossOrder)
- logger.info('止损订单已设置', {
- orderId: stopLossOrder.orderId,
- stopPrice: stopLossPrice,
- enableTrailing,
- })
- }
- // 创建止盈订单
- if (takeProfitPrice) {
- const takeProfitOrder: TakeProfitOrder = {
- orderId: `tp_${parentOrderId}_${Date.now()}`,
- symbol,
- amount,
- targetPrice: takeProfitPrice,
- side: side === 'buy' ? 'sell' : 'buy', // 反向平仓
- accountId: clientId,
- timestamp: Date.now(),
- isActive: true,
- }
- this.activeTakeProfitOrders.set(takeProfitOrder.orderId, takeProfitOrder)
- logger.info('止盈订单已设置', {
- orderId: takeProfitOrder.orderId,
- targetPrice: takeProfitPrice,
- })
- }
- // 启动价格监控(如果有止盈止损订单)
- if (stopLossPrice || takeProfitPrice) {
- this.startPriceMonitoring(symbol)
- }
- console.log(
- `🎯 止盈止损已设置: ${stopLossPrice ? `止损@$${stopLossPrice.toFixed(2)}` : ''} ${
- takeProfitPrice ? `止盈@$${takeProfitPrice.toFixed(2)}` : ''
- }`,
- )
- } catch (error: any) {
- logger.error('设置止盈止损失败', { error: error.message, params })
- }
- }
- /**
- * 启动价格监控
- */
- private startPriceMonitoring(symbol: string): void {
- // 避免重复启动监控
- if (this.lastPriceCheck.has(symbol)) {
- return
- }
- this.lastPriceCheck.set(symbol, { price: 0, timestamp: Date.now() })
- // 每5秒检查一次价格触发
- const monitoringInterval = setInterval(async () => {
- try {
- await this.checkStopLossAndTakeProfitTriggers(symbol)
- // 如果没有活跃的止盈止损订单,停止监控
- const hasActiveOrders =
- Array.from(this.activeStopLossOrders.values()).some(order => order.symbol === symbol && order.isActive) ||
- Array.from(this.activeTakeProfitOrders.values()).some(order => order.symbol === symbol && order.isActive)
- if (!hasActiveOrders) {
- clearInterval(monitoringInterval)
- this.lastPriceCheck.delete(symbol)
- logger.info(`价格监控已停止: ${symbol}`)
- }
- } catch (error: any) {
- logger.error('价格监控检查失败', { symbol, error: error.message })
- }
- }, 5000)
- logger.info(`价格监控已启动: ${symbol}`)
- }
- /**
- * 检查止盈止损触发条件
- */
- private async checkStopLossAndTakeProfitTriggers(symbol: string): Promise<void> {
- try {
- const currentPrice = await this.getCurrentPrice(symbol)
- // 检查止损触发
- for (const [orderId, stopLossOrder] of this.activeStopLossOrders) {
- if (!stopLossOrder.isActive || stopLossOrder.symbol !== symbol) continue
- const shouldTrigger =
- stopLossOrder.side === 'sell'
- ? currentPrice <= stopLossOrder.stopPrice // 多头止损: 价格跌破止损价
- : currentPrice >= stopLossOrder.stopPrice // 空头止损: 价格涨破止损价
- if (shouldTrigger) {
- await this.executeTrigger('stop_loss', stopLossOrder, currentPrice)
- }
- }
- // 检查止盈触发
- for (const [orderId, takeProfitOrder] of this.activeTakeProfitOrders) {
- if (!takeProfitOrder.isActive || takeProfitOrder.symbol !== symbol) continue
- const shouldTrigger =
- takeProfitOrder.side === 'sell'
- ? currentPrice >= takeProfitOrder.targetPrice // 多头止盈: 价格涨过目标价
- : currentPrice <= takeProfitOrder.targetPrice // 空头止盈: 价格跌过目标价
- if (shouldTrigger) {
- await this.executeTrigger('take_profit', takeProfitOrder, currentPrice)
- }
- }
- // 更新价格检查记录
- this.lastPriceCheck.set(symbol, { price: currentPrice, timestamp: Date.now() })
- } catch (error: any) {
- logger.error('检查止盈止损触发失败', { symbol, error: error.message })
- }
- }
- /**
- * 执行止盈止损触发
- */
- private async executeTrigger(
- type: 'stop_loss' | 'take_profit',
- order: StopLossOrder | TakeProfitOrder,
- currentPrice: number,
- ): Promise<void> {
- try {
- const client = this.clients.get(order.accountId)
- if (!client) {
- logger.error(`客户端 ${order.accountId} 不可用,无法执行${type}`)
- return
- }
- const side = order.side === 'sell' ? 'ask' : 'bid'
- const triggerPrice = 'stopPrice' in order ? order.stopPrice : order.targetPrice
- logger.info(`执行${type}触发`, {
- orderId: order.orderId,
- symbol: order.symbol,
- triggerPrice,
- currentPrice,
- side: order.side,
- })
- // 执行平仓订单
- const result = await client.createMarketOrder({
- account: this.accounts[0].account,
- symbol: 'BTCUSDT',
- amount: order.amount,
- side: side,
- reduceOnly: true, // 强制只减仓
- slippagePercent: '5.0',
- })
- if (result.success) {
- // 标记订单为已执行
- if (type === 'stop_loss') {
- ;(order as StopLossOrder).isActive = false
- } else {
- ;(order as TakeProfitOrder).isActive = false
- }
- const emoji = type === 'stop_loss' ? '🛑' : '🎯'
- const typeText = type === 'stop_loss' ? '止损' : '止盈'
- console.log(
- `${emoji} ${typeText}触发成功: ${order.symbol} @ $${currentPrice.toFixed(2)} (目标: $${triggerPrice.toFixed(
- 2,
- )})`,
- )
- this.stats.successfulTrades++
- this.stats.totalVolume += parseFloat(order.amount)
- // 更新账户状态
- this.updateAccountState(order.accountId, {
- side: order.side,
- amount: order.amount,
- success: true,
- })
- } else {
- logger.error(`${type}执行失败`, { error: result.error, order })
- }
- this.stats.totalTrades++
- this.stats.lastTradeTime = Date.now()
- } catch (error: any) {
- logger.error(`执行${type}触发失败`, { error: error.message, order })
- }
- }
- /**
- * 检查是否应该交易
- */
- 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 calculateIntelligentRiskScore(): Promise<{
- riskScore: number
- riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
- riskFactors: string[]
- recommendations: string[]
- }> {
- const factors: string[] = []
- const recommendations: string[] = []
- let riskScore = 0
- // 1. 交易成功率风险 (权重30%)
- const successRate = this.stats.totalTrades > 0 ? this.stats.successfulTrades / this.stats.totalTrades : 1
- if (successRate < 0.5) {
- riskScore += 30
- factors.push(`低成功率: ${(successRate * 100).toFixed(1)}%`)
- recommendations.push('建议降低交易频率或调整策略参数')
- } else if (successRate < 0.7) {
- riskScore += 15
- factors.push(`中等成功率: ${(successRate * 100).toFixed(1)}%`)
- }
- // 2. 仓位集中度风险 (权重25%) - 动态阈值基于账户余额
- const totalPosition = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + Math.abs(account.netPosition),
- 0,
- )
- const totalBalance = Array.from(this.accountStates.values()).reduce((sum, account) => sum + account.lastBalance, 0)
- const avgBalance = totalBalance / Math.max(1, this.accountStates.size)
- // 根据账户余额动态调整仓位风险阈值
- const highPositionThreshold = avgBalance > 1000 ? 0.02 : avgBalance > 500 ? 0.015 : avgBalance > 200 ? 0.01 : 0.005
- const mediumPositionThreshold =
- avgBalance > 1000 ? 0.01 : avgBalance > 500 ? 0.008 : avgBalance > 200 ? 0.005 : 0.003
- if (totalPosition > highPositionThreshold) {
- riskScore += 25
- factors.push(`高仓位集中度: ${totalPosition.toFixed(4)} BTC (~${(totalPosition * 65000).toFixed(0)} USDT)`)
- recommendations.push('立即执行平仓操作降低风险暴露')
- } else if (totalPosition > mediumPositionThreshold) {
- riskScore += 12
- factors.push(`中等仓位集中度: ${totalPosition.toFixed(4)} BTC (~${(totalPosition * 65000).toFixed(0)} USDT)`)
- recommendations.push('考虑部分平仓以控制风险')
- }
- // 3. 资金安全风险 (权重20%)
- if (avgBalance < 50) {
- riskScore += 20
- factors.push(`低资金余额: $${avgBalance.toFixed(2)}`)
- recommendations.push('资金不足,建议停止交易或充值')
- } else if (avgBalance < 200) {
- riskScore += 10
- factors.push(`中低资金余额: $${avgBalance.toFixed(2)}`)
- recommendations.push('谨慎交易,限制交易规模')
- }
- // 4. 交易频率风险 (权重15%)
- const sessionTime = (Date.now() - this.stats.sessionStartTime) / 1000 / 60 // 分钟
- const tradeFrequency = sessionTime > 0 ? this.stats.totalTrades / sessionTime : 0
- if (tradeFrequency > 3) {
- riskScore += 15
- factors.push(`高频交易: ${tradeFrequency.toFixed(2)}笔/分钟`)
- recommendations.push('降低交易频率,避免账户被限制')
- } else if (tradeFrequency > 2) {
- riskScore += 8
- factors.push(`中高频交易: ${tradeFrequency.toFixed(2)}笔/分钟`)
- }
- // 5. Delta中性风险 (权重10%) - 动态阈值基于账户余额
- const netDelta = Array.from(this.accountStates.values()).reduce((sum, account) => sum + account.netPosition, 0)
- // 动态Delta阈值:基于账户余额
- const highDeltaThreshold = avgBalance > 1000 ? 0.008 : avgBalance > 500 ? 0.005 : avgBalance > 200 ? 0.003 : 0.002
- const mediumDeltaThreshold = avgBalance > 1000 ? 0.004 : avgBalance > 500 ? 0.003 : avgBalance > 200 ? 0.002 : 0.001
- if (Math.abs(netDelta) > highDeltaThreshold) {
- riskScore += 10
- factors.push(`Delta偏离: ${netDelta.toFixed(4)} BTC (~${(netDelta * 65000).toFixed(0)} USDT)`)
- recommendations.push('立即执行对冲操作恢复Delta中性')
- } else if (Math.abs(netDelta) > mediumDeltaThreshold) {
- riskScore += 5
- factors.push(`轻微 Delta偏离: ${netDelta.toFixed(4)} BTC (~${(netDelta * 65000).toFixed(0)} USDT)`)
- }
- // 6. 基差风险监控 (权重10%) - 新增基差风险评估
- const basisRisk = await this.assessBasisRisk()
- if (basisRisk.riskLevel === 'HIGH') {
- riskScore += 10
- factors.push(`高基差风险: ${basisRisk.currentBasis?.toFixed(2) || 'N/A'}% 偏离`)
- recommendations.push('基差异常,谨慎执行套利交易')
- } else if (basisRisk.riskLevel === 'MEDIUM') {
- riskScore += 5
- factors.push(`中等基差风险: ${basisRisk.currentBasis?.toFixed(2) || 'N/A'}% 偏离`)
- recommendations.push('监控基差变化趋势')
- } else if (basisRisk.riskLevel === 'CRITICAL') {
- riskScore += 15
- factors.push(`极端基差风险: ${basisRisk.currentBasis?.toFixed(2) || 'N/A'}% 异常偏离`)
- recommendations.push('暂停所有基差相关交易,等待市场恢复正常')
- }
- // 确定风险等级
- let riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
- if (riskScore >= 60) {
- riskLevel = 'CRITICAL'
- recommendations.unshift('紧急停止所有交易并进行风险评估')
- } else if (riskScore >= 40) {
- riskLevel = 'HIGH'
- recommendations.unshift('高度警惕,考虑暂停交易')
- } else if (riskScore >= 20) {
- riskLevel = 'MEDIUM'
- recommendations.unshift('中等风险,加强监控')
- } else {
- riskLevel = 'LOW'
- recommendations.push('风险可控,可继续正常交易')
- }
- return {
- riskScore,
- riskLevel,
- riskFactors: factors,
- recommendations,
- }
- }
- /**
- * 风险检查 - 集成智能风险评估
- */
- private async performRiskCheck(): Promise<void> {
- // 执行智能风险评估
- const riskAssessment = await this.calculateIntelligentRiskScore()
- // 根据风险等级发出相应的警报
- if (riskAssessment.riskLevel === 'CRITICAL') {
- this.emit('risk_alert', {
- type: 'critical_risk',
- score: riskAssessment.riskScore,
- level: riskAssessment.riskLevel,
- factors: riskAssessment.riskFactors,
- recommendations: riskAssessment.recommendations,
- })
- logger.error('😨 关键风险警报', riskAssessment)
- } else if (riskAssessment.riskLevel === 'HIGH') {
- this.emit('risk_alert', {
- type: 'high_risk',
- score: riskAssessment.riskScore,
- level: riskAssessment.riskLevel,
- factors: riskAssessment.riskFactors,
- recommendations: riskAssessment.recommendations,
- })
- logger.warn('⚠️ 高风险警报', riskAssessment)
- } else if (riskAssessment.riskLevel === 'MEDIUM') {
- this.emit('risk_alert', {
- type: 'medium_risk',
- score: riskAssessment.riskScore,
- level: riskAssessment.riskLevel,
- factors: riskAssessment.riskFactors,
- recommendations: riskAssessment.recommendations,
- })
- logger.info('🔶 中等风险提醒', riskAssessment)
- }
- // 传统风险检查作为备用
- 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,
- })
- }
- }
- /**
- * 处理风险警报
- */
- 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 async displayDashboard(): Promise<void> {
- // 定期更新账户余额(每5次显示更新一次,并且初始时更新)
- if (this.stats.totalTrades % 5 === 0 || this.stats.totalTrades === 0) {
- await this.updateAccountBalances()
- }
- 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`)
- const currentSuccessRate =
- status.totalTrades > 0 ? ((this.stats.successfulTrades / status.totalTrades) * 100).toFixed(1) : '0.0'
- const successRateEmoji =
- parseFloat(currentSuccessRate) >= 80 ? '🟢' : parseFloat(currentSuccessRate) >= 60 ? '🟡' : '🔴'
- console.log(
- ` 成功率: ${successRateEmoji} ${currentSuccessRate}% (✅ ${this.stats.successfulTrades} | ❌ ${this.stats.failedTrades})`,
- )
- 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}%`)
- // 显示智能参数
- if (this.stats.totalTrades > 0) {
- const closeRatio = this.calculateDynamicCloseRatio()
- const closeThreshold = this.calculateDynamicCloseThreshold()
- console.log(`\n🧠 智能参数`)
- console.log(` 平仓概率: ${(closeRatio * 100).toFixed(1)}% (动态调整)`)
- console.log(` 平仓阈值: ${closeThreshold.toFixed(4)} BTC (动态调整)`)
- // 显示风险评估
- try {
- const riskAssessment = await this.calculateIntelligentRiskScore()
- const riskEmoji = {
- LOW: '🟢',
- MEDIUM: '🟡',
- HIGH: '🔴',
- CRITICAL: '⛔',
- }[riskAssessment.riskLevel]
- console.log(`\n🛡️ 智能风险评估`)
- console.log(` 风险等级: ${riskEmoji} ${riskAssessment.riskLevel} (得分: ${riskAssessment.riskScore})`)
- if (riskAssessment.riskFactors.length > 0) {
- console.log(` 风险因子: ${riskAssessment.riskFactors.slice(0, 2).join(', ')}`)
- }
- if (riskAssessment.recommendations.length > 0 && riskAssessment.riskLevel !== 'LOW') {
- console.log(` 建议: ${riskAssessment.recommendations[0]}`)
- }
- } catch (error: any) {
- console.log(`\n🛡️ 智能风险评估`)
- console.log(` 风险等级: 🟡 MEDIUM (评估暂时不可用)`)
- logger.debug('风险评估显示失败', { error: error.message })
- }
- }
- // 显示账户仓位和权益状态
- if (this.accountStates.size > 0) {
- console.log(`\n📍 账户详情`)
- this.accountStates.forEach((state, accountId) => {
- const positionType = state.netPosition > 0 ? '多头' : state.netPosition < 0 ? '空头' : '平仓'
- const positionTypeEmoji = state.netPosition > 0 ? '📈' : state.netPosition < 0 ? '📉' : '⚖️'
- const positionSizeBTC = Math.abs(state.netPosition).toFixed(4)
- const estimatedBTCPrice = 65000
- const positionSizeUSDT = (Math.abs(state.netPosition) * estimatedBTCPrice).toFixed(0)
- const balanceUSDT = state.lastBalance.toFixed(2)
- const availableUSDT = state.availableBalance.toFixed(2)
- // 健康度指标
- const healthEmoji =
- state.lastBalance > 100 ? '💚' : state.lastBalance > 50 ? '💛' : state.lastBalance > 20 ? '🧡' : '❤️'
- const utilizationRate =
- state.lastBalance > 0
- ? (((state.lastBalance - state.availableBalance) / state.lastBalance) * 100).toFixed(1)
- : '0.0'
- console.log(
- ` ${accountId}: ${positionTypeEmoji} ${positionType} ${positionSizeBTC} BTC (~$${positionSizeUSDT})`,
- )
- console.log(
- ` ${healthEmoji} 权益: $${balanceUSDT} | 可用: $${availableUSDT} | 使用率: ${utilizationRate}% | 交易: ${state.totalTrades}笔`,
- )
- })
- // 显示账户总权益
- const totalBalance = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + account.lastBalance,
- 0,
- )
- console.log(` 💎 总权益: $${totalBalance.toFixed(2)} USDT`)
- }
- console.log(`\n⚡ 交易活动状态`)
- const timeSinceLastTrade =
- this.stats.lastTradeTime > 0 ? Math.round((Date.now() - this.stats.lastTradeTime) / 1000) : 0
- const sessionTime = Math.max(0, (Date.now() - this.stats.sessionStartTime) / 1000 / 60)
- const tradeFrequency = sessionTime > 0 ? (this.stats.totalTrades / sessionTime).toFixed(2) : '0.00'
- console.log(` 上次交易: ${timeSinceLastTrade > 0 ? `${timeSinceLastTrade}秒前` : '无'}`)
- console.log(` 交易频率: ${tradeFrequency}笔/分钟 (主信号15s + 刷量8s)`)
- console.log(` 会话时长: ${sessionTime.toFixed(1)}分钟`)
- console.log(` 刷量状态: ${this.stats.totalTrades > 0 ? '🟢 活跃' : '⏸️ 等待'}`)
- // 显示总净仓位和敞口状态
- const totalNetPosition = Array.from(this.accountStates.values()).reduce(
- (sum, account) => sum + account.netPosition,
- 0,
- )
- const estimatedBTCPrice = 65000
- const totalNetPositionUSDT = totalNetPosition * estimatedBTCPrice
- // 使用动态阈值
- const exposureThreshold = this.calculateDynamicExposureThreshold()
- const exposureThresholdUSDT = exposureThreshold * estimatedBTCPrice
- // 计算最高使用率用于显示
- let maxUtilizationRate = 0
- Array.from(this.accountStates.values()).forEach(account => {
- if (account.lastBalance > 0) {
- const utilizationRate = (account.lastBalance - account.availableBalance) / account.lastBalance
- maxUtilizationRate = Math.max(maxUtilizationRate, utilizationRate)
- }
- })
- const isBalanced = Math.abs(totalNetPosition) <= exposureThreshold
- const exposureEmoji = isBalanced ? '✅' : '⚠️'
- const exposureStatus = isBalanced ? '平衡' : '失衡'
- console.log(
- ` 净敞口: ${exposureEmoji} ${totalNetPosition.toFixed(4)} BTC (~$${totalNetPositionUSDT.toFixed(
- 0,
- )}) - ${exposureStatus}`,
- )
- console.log(
- ` 动态阈值: ±${exposureThreshold.toFixed(4)} BTC (~±$${exposureThresholdUSDT.toFixed(0)}) | 最高使用率: ${(
- maxUtilizationRate * 100
- ).toFixed(1)}%`,
- )
- 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 {
- // 等待当前交易完成
- console.log('⏳ 等待当前交易完成...')
- await new Promise(resolve => setTimeout(resolve, 3000))
- // 检查Delta中性状态
- console.log('\n📊 Delta中性检查:')
- let totalDelta = 0
- this.accountStates.forEach(account => {
- totalDelta += account.netPosition
- })
- const absDelta = Math.abs(totalDelta)
- if (absDelta > 0.01) {
- console.log(`⚠️ 警告: 检测到 ${absDelta.toFixed(4)} BTC 净敞口`)
- console.log(`💡 建议: 退出前请确保Delta中性以避免风险`)
- console.log(`📝 当前账户状态:`)
- this.accountStates.forEach((state, accountId) => {
- console.log(` ${accountId}: ${state.netPosition.toFixed(4)} BTC`)
- })
- console.log(`\n⚠️ 系统将在保持当前状态下关闭`)
- console.log(`🔄 建议下次启动前手动平衡账户或重新启动系统进行自动平衡`)
- } else {
- console.log('✅ Delta中性状态确认,可以安全关闭')
- }
- // 保存当前状态到文件
- const stateData = {
- timestamp: Date.now(),
- totalDelta: totalDelta,
- accountStates: Object.fromEntries(this.accountStates),
- globalStats: this.stats,
- sessionDuration: Date.now() - this.startTime,
- }
- require('fs').writeFileSync('.system_state.json', JSON.stringify(stateData, null, 2))
- console.log('💾 系统状态已保存到 .system_state.json')
- // 清理资源
- 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)} 分钟`)
- console.log(` 最终Delta: ${totalDelta.toFixed(4)} BTC`)
- 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
- 🔧 配置有效的交易所账户
- 🔧 足够的账户余额
- 🔧 稳定的网络连接
- 安全特性:
- 🛡️ 多层风险控制
- 🛡️ 自动止损机制
- 🛡️ 交易频率限制
- 🛡️ 余额保护检查
- 🛡️ 异常自动恢复
- 监控功能:
- 📊 实时交易统计
- 📈 盈亏分析
- 🔍 系统健康检查
- ⚠️ 风险警报系统
- 📝 详细交易日志
- ⚠️ 风险提醒:
- 加密货币交易存在巨大风险,可能导致本金损失。
- 请确保您完全理解相关风险并具备相应的风险承受能力。
- 建议先在测试环境中运行,并使用小额资金测试。
- `)
- }
- // 主程序入口
- 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 }
|