- 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
207 lines
6.2 KiB
TypeScript
207 lines
6.2 KiB
TypeScript
/**
|
|
* Test Full Trading Flow
|
|
*
|
|
* End-to-end test: Execute trade → Monitor → Auto-exit
|
|
*
|
|
* WARNING: This executes a REAL trade on Drift!
|
|
* Make sure you have a small position size configured.
|
|
*/
|
|
|
|
import 'dotenv/config'
|
|
|
|
const API_URL = process.env.API_URL || 'http://localhost:3000'
|
|
const API_KEY = process.env.API_KEY || ''
|
|
|
|
interface ExecuteResponse {
|
|
success: boolean
|
|
message: string
|
|
trade?: {
|
|
id: string
|
|
symbol: string
|
|
direction: string
|
|
entryPrice: number
|
|
positionSize: number
|
|
leverage: number
|
|
}
|
|
position?: any
|
|
}
|
|
|
|
interface PositionsResponse {
|
|
success: boolean
|
|
monitoring: {
|
|
isActive: boolean
|
|
tradeCount: number
|
|
symbols: string[]
|
|
}
|
|
positions: Array<{
|
|
id: string
|
|
symbol: string
|
|
direction: string
|
|
entryPrice: number
|
|
currentPrice: number
|
|
unrealizedPnL: number
|
|
profitPercent: number
|
|
accountPnL: number
|
|
tp1Hit: boolean
|
|
slMovedToBreakeven: boolean
|
|
}>
|
|
}
|
|
|
|
async function testFullFlow() {
|
|
console.log('🧪 Testing Full Trading Flow (END-TO-END)\n')
|
|
console.log('⚠️ WARNING: This will execute a REAL trade on Drift!')
|
|
console.log(' Make sure position size is small ($10-50)\n')
|
|
|
|
if (!API_KEY) {
|
|
console.error('❌ Error: API_KEY not set in .env')
|
|
console.log(' Add: API_KEY=your_secret_key_here')
|
|
process.exit(1)
|
|
}
|
|
|
|
// Wait for user confirmation
|
|
console.log('Press Ctrl+C to cancel, or wait 5 seconds to continue...')
|
|
await new Promise(resolve => setTimeout(resolve, 5000))
|
|
console.log()
|
|
|
|
// Step 1: Execute trade
|
|
console.log('📝 Step 1: Executing trade...')
|
|
|
|
const executePayload = {
|
|
symbol: 'SOLUSDT',
|
|
direction: 'long',
|
|
timeframe: '5',
|
|
}
|
|
|
|
console.log(' Payload:', JSON.stringify(executePayload, null, 2))
|
|
|
|
const executeResponse = await fetch(`${API_URL}/api/trading/execute`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${API_KEY}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(executePayload),
|
|
})
|
|
|
|
if (!executeResponse.ok) {
|
|
const error = await executeResponse.text()
|
|
console.error('❌ Execute failed:', error)
|
|
process.exit(1)
|
|
}
|
|
|
|
const executeData: ExecuteResponse = await executeResponse.json()
|
|
|
|
if (!executeData.success || !executeData.trade) {
|
|
console.error('❌ Execute failed:', executeData.message)
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('✅ Trade executed!')
|
|
console.log(' ID:', executeData.trade.id)
|
|
console.log(' Symbol:', executeData.trade.symbol)
|
|
console.log(' Direction:', executeData.trade.direction.toUpperCase())
|
|
console.log(' Entry Price: $', executeData.trade.entryPrice.toFixed(4))
|
|
console.log(' Position Size: $', executeData.trade.positionSize.toFixed(2))
|
|
console.log(' Leverage:', executeData.trade.leverage + 'x')
|
|
console.log()
|
|
|
|
const tradeId = executeData.trade.id
|
|
|
|
// Step 2: Monitor position
|
|
console.log('📝 Step 2: Monitoring position...')
|
|
console.log(' Duration: 120 seconds (2 minutes)')
|
|
console.log(' Updates: Every 10 seconds')
|
|
console.log(' Waiting for automatic exit...\n')
|
|
|
|
const startTime = Date.now()
|
|
let lastStatus: PositionsResponse | null = null
|
|
|
|
for (let i = 0; i < 12; i++) { // 12 x 10s = 120s
|
|
await new Promise(resolve => setTimeout(resolve, 10000))
|
|
|
|
const elapsed = (Date.now() - startTime) / 1000
|
|
console.log(`⏱️ ${elapsed.toFixed(0)}s elapsed...`)
|
|
|
|
// Fetch positions
|
|
const positionsResponse = await fetch(`${API_URL}/api/trading/positions`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${API_KEY}`,
|
|
},
|
|
})
|
|
|
|
if (!positionsResponse.ok) {
|
|
console.error(' ⚠️ Failed to fetch positions')
|
|
continue
|
|
}
|
|
|
|
const positionsData: PositionsResponse = await positionsResponse.json()
|
|
lastStatus = positionsData
|
|
|
|
// Find our trade
|
|
const ourTrade = positionsData.positions.find(p => p.id === tradeId)
|
|
|
|
if (!ourTrade) {
|
|
console.log(' ✅ TRADE CLOSED AUTOMATICALLY!')
|
|
console.log(' Position no longer in active list')
|
|
break
|
|
}
|
|
|
|
// Display status
|
|
console.log(` Current Price: $${ourTrade.currentPrice.toFixed(4)}`)
|
|
console.log(` Unrealized P&L: $${ourTrade.unrealizedPnL.toFixed(2)} (${ourTrade.accountPnL.toFixed(2)}% account)`)
|
|
console.log(` TP1 Hit: ${ourTrade.tp1Hit ? 'YES ✅' : 'No'}`)
|
|
console.log(` SL Moved: ${ourTrade.slMovedToBreakeven ? 'YES ✅' : 'No'}`)
|
|
console.log()
|
|
}
|
|
|
|
// Step 3: Final check
|
|
console.log('📝 Step 3: Final check...')
|
|
|
|
const finalResponse = await fetch(`${API_URL}/api/trading/positions`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${API_KEY}`,
|
|
},
|
|
})
|
|
|
|
if (finalResponse.ok) {
|
|
const finalData: PositionsResponse = await finalResponse.json()
|
|
const stillActive = finalData.positions.find(p => p.id === tradeId)
|
|
|
|
if (stillActive) {
|
|
console.log('⚠️ Trade still active after 2 minutes')
|
|
console.log(' This is normal if price hasn\'t hit targets yet')
|
|
console.log(' Position will auto-close when TP/SL is hit')
|
|
console.log()
|
|
console.log(' Current status:')
|
|
console.log(' Price:', stillActive.currentPrice)
|
|
console.log(' P&L:', stillActive.unrealizedPnL.toFixed(2))
|
|
console.log(' TP1 Hit:', stillActive.tp1Hit)
|
|
} else {
|
|
console.log('✅ Trade successfully closed automatically!')
|
|
console.log(' Check your Drift account for final P&L')
|
|
}
|
|
}
|
|
|
|
console.log()
|
|
console.log('🎉 End-to-end test complete!')
|
|
console.log()
|
|
console.log('📊 What happened:')
|
|
console.log(' 1. Trade was executed via API')
|
|
console.log(' 2. Position manager started monitoring')
|
|
console.log(' 3. Pyth price monitor updated every 2s')
|
|
console.log(' 4. Exit conditions checked automatically')
|
|
console.log(' 5. Trade closed when TP/SL was hit')
|
|
console.log()
|
|
console.log('💡 Next steps:')
|
|
console.log(' 1. Trigger more trades from TradingView')
|
|
console.log(' 2. Monitor the logs for auto-exits')
|
|
console.log(' 3. Verify P&L on Drift UI')
|
|
console.log(' 4. Adjust parameters if needed')
|
|
}
|
|
|
|
// Run test
|
|
testFullFlow().catch(error => {
|
|
console.error('❌ Test failed:', error)
|
|
process.exit(1)
|
|
})
|