- 1-minute data is pure market sampling, not trading signals - signalQualityVersion now null for timeframe='1' - Other timeframes still labeled with v9 - Prevents confusion in analytics/reporting
208 lines
6.0 KiB
TypeScript
208 lines
6.0 KiB
TypeScript
/**
|
|
* Test Position Manager
|
|
*
|
|
* Tests position tracking, monitoring, and automatic exit logic
|
|
*/
|
|
|
|
import { getPositionManager } from '../lib/trading/position-manager'
|
|
import type { ActiveTrade } from '../lib/trading/position-manager'
|
|
|
|
async function testPositionManager() {
|
|
console.log('🧪 Testing Position Manager...\n')
|
|
|
|
const manager = getPositionManager()
|
|
|
|
// Test 1: Add a simulated long trade
|
|
console.log('📝 Test 1: Adding simulated LONG trade...')
|
|
|
|
const entryPrice = 140.0
|
|
const positionSize = 10000
|
|
const leverage = 10
|
|
|
|
const longTrade: ActiveTrade = {
|
|
id: `test-long-${Date.now()}`,
|
|
positionId: 'test-signature-long',
|
|
symbol: 'SOL-PERP',
|
|
direction: 'long',
|
|
entryPrice,
|
|
entryTime: Date.now(),
|
|
positionSize,
|
|
leverage,
|
|
|
|
// Exit prices
|
|
stopLossPrice: entryPrice * 0.985, // -1.5%
|
|
tp1Price: entryPrice * 1.007, // +0.7%
|
|
tp2Price: entryPrice * 1.015, // +1.5%
|
|
emergencyStopPrice: entryPrice * 0.98, // -2.0%
|
|
|
|
// Position state
|
|
currentSize: positionSize,
|
|
tp1Hit: false,
|
|
tp2Hit: false,
|
|
slMovedToBreakeven: false,
|
|
slMovedToProfit: false,
|
|
|
|
// Trailing stop
|
|
trailingStopActive: false,
|
|
peakPrice: entryPrice,
|
|
|
|
// P&L tracking
|
|
realizedPnL: 0,
|
|
unrealizedPnL: 0,
|
|
peakPnL: 0,
|
|
|
|
// MAE/MFE tracking
|
|
maxFavorableExcursion: 0,
|
|
maxAdverseExcursion: 0,
|
|
maxFavorablePrice: entryPrice,
|
|
maxAdversePrice: entryPrice,
|
|
|
|
// Scaling tracking
|
|
originalAdx: 20,
|
|
timesScaled: 0,
|
|
totalScaleAdded: 0,
|
|
|
|
// Monitoring
|
|
priceCheckCount: 0,
|
|
lastPrice: entryPrice,
|
|
lastUpdateTime: Date.now(),
|
|
}
|
|
|
|
await manager.addTrade(longTrade)
|
|
console.log('✅ Long trade added')
|
|
console.log(` Entry: $${entryPrice}`)
|
|
console.log(` SL: $${longTrade.stopLossPrice.toFixed(2)} (-1.5%)`)
|
|
console.log(` TP1: $${longTrade.tp1Price.toFixed(2)} (+0.7%)`)
|
|
console.log(` TP2: $${longTrade.tp2Price.toFixed(2)} (+1.5%)`)
|
|
console.log()
|
|
|
|
// Test 2: Add a simulated short trade
|
|
console.log('📝 Test 2: Adding simulated SHORT trade...')
|
|
|
|
const shortTrade: ActiveTrade = {
|
|
id: `test-short-${Date.now()}`,
|
|
positionId: 'test-signature-short',
|
|
symbol: 'BTC-PERP',
|
|
direction: 'short',
|
|
entryPrice: 43000,
|
|
entryTime: Date.now(),
|
|
positionSize: 10000,
|
|
leverage: 10,
|
|
|
|
// Exit prices (reversed for short)
|
|
stopLossPrice: 43000 * 1.015, // +1.5% (loss on short)
|
|
tp1Price: 43000 * 0.993, // -0.7% (profit on short)
|
|
tp2Price: 43000 * 0.985, // -1.5% (profit on short)
|
|
emergencyStopPrice: 43000 * 1.02, // +2.0% (emergency)
|
|
|
|
// Position state
|
|
currentSize: 10000,
|
|
tp1Hit: false,
|
|
tp2Hit: false,
|
|
slMovedToBreakeven: false,
|
|
slMovedToProfit: false,
|
|
|
|
// Trailing stop
|
|
trailingStopActive: false,
|
|
peakPrice: 43000,
|
|
|
|
// P&L tracking
|
|
realizedPnL: 0,
|
|
unrealizedPnL: 0,
|
|
peakPnL: 0,
|
|
|
|
// MAE/MFE tracking
|
|
maxFavorableExcursion: 0,
|
|
maxAdverseExcursion: 0,
|
|
maxFavorablePrice: 43000,
|
|
maxAdversePrice: 43000,
|
|
|
|
// Scaling tracking
|
|
originalAdx: 18,
|
|
timesScaled: 0,
|
|
totalScaleAdded: 0,
|
|
|
|
// Monitoring
|
|
priceCheckCount: 0,
|
|
lastPrice: 43000,
|
|
lastUpdateTime: Date.now(),
|
|
}
|
|
|
|
await manager.addTrade(shortTrade)
|
|
console.log('✅ Short trade added')
|
|
console.log(` Entry: $${shortTrade.entryPrice}`)
|
|
console.log(` SL: $${shortTrade.stopLossPrice.toFixed(2)} (+1.5%)`)
|
|
console.log(` TP1: $${shortTrade.tp1Price.toFixed(2)} (-0.7%)`)
|
|
console.log(` TP2: $${shortTrade.tp2Price.toFixed(2)} (-1.5%)`)
|
|
console.log()
|
|
|
|
// Test 3: Check status
|
|
console.log('📝 Test 3: Checking manager status...')
|
|
const status = manager.getStatus()
|
|
console.log('✅ Status:', JSON.stringify(status, null, 2))
|
|
console.log()
|
|
|
|
// Test 4: Monitor for 60 seconds
|
|
console.log('📝 Test 4: Monitoring positions for 60 seconds...')
|
|
console.log(' (Real prices from Pyth will update every 2s)')
|
|
console.log(' Watch for automatic exit conditions!\n')
|
|
|
|
let updates = 0
|
|
const startTime = Date.now()
|
|
const interval = setInterval(() => {
|
|
const elapsed = (Date.now() - startTime) / 1000
|
|
const currentStatus = manager.getStatus()
|
|
|
|
if (updates % 5 === 0) { // Print every 10 seconds
|
|
console.log(`⏱️ ${elapsed.toFixed(0)}s - Active trades: ${currentStatus.activeTradesCount}`)
|
|
|
|
if (currentStatus.activeTradesCount === 0) {
|
|
console.log(' All trades closed!')
|
|
clearInterval(interval)
|
|
}
|
|
}
|
|
|
|
updates++
|
|
}, 2000)
|
|
|
|
// Run for 60 seconds
|
|
await new Promise(resolve => setTimeout(resolve, 60000))
|
|
clearInterval(interval)
|
|
|
|
// Test 5: Check final status
|
|
console.log('\n📝 Test 5: Final status check...')
|
|
const finalStatus = manager.getStatus()
|
|
console.log('Status:', JSON.stringify(finalStatus, null, 2))
|
|
console.log()
|
|
|
|
// Test 6: Close all remaining positions
|
|
if (finalStatus.activeTradesCount > 0) {
|
|
console.log('📝 Test 6: Closing all remaining positions...')
|
|
await manager.closeAll()
|
|
console.log('✅ All positions closed')
|
|
} else {
|
|
console.log('📝 Test 6: No positions to close (already closed automatically!)')
|
|
}
|
|
|
|
console.log()
|
|
console.log('🎉 Position manager test complete!')
|
|
console.log()
|
|
console.log('📊 What to check:')
|
|
console.log(' ✅ Both trades were added successfully')
|
|
console.log(' ✅ Manager started monitoring (check logs)')
|
|
console.log(' ✅ Real prices were fetched from Pyth')
|
|
console.log(' ✅ Exit conditions were checked every 2s')
|
|
console.log(' ✅ If price hit targets, trades closed automatically')
|
|
console.log()
|
|
console.log('💡 Next steps:')
|
|
console.log(' 1. Review the logs for price updates')
|
|
console.log(' 2. Check if any exits were triggered')
|
|
console.log(' 3. Run test-full-flow.ts for end-to-end test')
|
|
}
|
|
|
|
// Run test
|
|
testPositionManager().catch(error => {
|
|
console.error('❌ Test failed:', error)
|
|
process.exit(1)
|
|
})
|