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:
mindesbunister
2025-12-19 08:51:36 +01:00
parent bfb73150ab
commit 6990f20d6f
7 changed files with 729 additions and 286 deletions

View File

@@ -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')