feat: Orderbook shadow logging system - Phase 1 complete
Implementation:
- Added 7 orderbook fields to Trade model (spreadBps, imbalanceRatio, depths, impact, walls)
- Oracle-based estimates with 2bps spread assumption
- ENV flag: ENABLE_ORDERBOOK_LOGGING (defaults true)
- Execute wrapper lines 1037-1053 guards orderbook logic
Database:
- Direct SQL ALTER TABLE (avoided migration drift issues)
- All columns nullable DOUBLE PRECISION
- Prisma schema synced via db pull + generate
Deployment:
- Container rebuilt and deployed successfully
- All 7 columns verified accessible
- System operational, ready for live trade validation
Files changed:
- config/trading.ts (enableOrderbookLogging flag, line 127)
- types/trading.ts (orderbook interfaces)
- lib/database/trades.ts (createTrade saves orderbook data)
- app/api/trading/execute/route.ts (ENV wrapper lines 1037-1053)
- prisma/schema.prisma (7 orderbook fields)
- docs/ORDERBOOK_SHADOW_LOGGING.md (complete documentation)
Status: ✅ PRODUCTION READY - awaiting first trade for validation
This commit is contained in:
@@ -18,6 +18,7 @@ import { getPythPriceMonitor } from '@/lib/pyth/price-monitor'
|
||||
import { logCriticalError, logTradeExecution } from '@/lib/utils/persistent-logger'
|
||||
import { getSmartEntryTimer } from '@/lib/trading/smart-entry-timer'
|
||||
import { checkTradingAllowed, verifySLWithRetries } from '@/lib/safety/sl-verification'
|
||||
import { getOrderbookService } from '@/lib/drift/orderbook-service'
|
||||
|
||||
export interface ExecuteTradeRequest {
|
||||
symbol: string // TradingView symbol (e.g., 'SOLUSDT')
|
||||
@@ -1033,6 +1034,25 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
|
||||
console.log('🔍 DEBUG: Exit orders section complete, about to calculate quality score...')
|
||||
|
||||
// Get orderbook metrics at trade entry (Phase 1 shadow logging - Dec 19, 2025)
|
||||
let obMetrics: { spreadBps: number; imbalance: number; oppDepth0_2pctUSD: number; sameDepth0_2pctUSD: number; impactBpsAtNotional: number; largestOppWallBps: number; largestOppWallUSD: number } | undefined
|
||||
if (config.enableOrderbookLogging) {
|
||||
try {
|
||||
const obAnalysis = await getOrderbookService().getMetricsForDirection(
|
||||
driftSymbol,
|
||||
body.direction,
|
||||
positionSizeUSD * leverage // notionalUSD
|
||||
)
|
||||
if (obAnalysis) {
|
||||
obMetrics = obAnalysis.metrics
|
||||
console.log(`📊 Orderbook snapshot: spread=${obMetrics.spreadBps.toFixed(1)}bps, imbalance=${obMetrics.imbalance.toFixed(2)}, impact=${obMetrics.impactBpsAtNotional.toFixed(1)}bps`)
|
||||
}
|
||||
} catch (obError) {
|
||||
console.error('⚠️ Failed to get orderbook metrics (non-critical):', obError)
|
||||
// Continue without orderbook data - shadow logging only, not critical for execution
|
||||
}
|
||||
}
|
||||
|
||||
// Save trade to database FIRST (CRITICAL: Must succeed before Position Manager)
|
||||
let savedTrade
|
||||
try {
|
||||
@@ -1072,6 +1092,14 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
pricePositionAtEntry: body.pricePosition,
|
||||
signalQualityScore: qualityResult.score,
|
||||
indicatorVersion: body.indicatorVersion || 'v5', // Default to v5 for backward compatibility
|
||||
// Orderbook metrics at entry (Phase 1 shadow logging - Dec 17, 2025)
|
||||
obSpreadBps: obMetrics?.spreadBps,
|
||||
obImbalance: obMetrics?.imbalance,
|
||||
obOppDepth0_2pctUSD: obMetrics?.oppDepth0_2pctUSD,
|
||||
obSameDepth0_2pctUSD: obMetrics?.sameDepth0_2pctUSD,
|
||||
obImpactBpsAtNotional: obMetrics?.impactBpsAtNotional,
|
||||
obLargestOppWallBps: obMetrics?.largestOppWallBps,
|
||||
obLargestOppWallUSD: obMetrics?.largestOppWallUSD,
|
||||
})
|
||||
|
||||
console.log('🔍 DEBUG: createTrade() completed successfully')
|
||||
|
||||
Reference in New Issue
Block a user