Database changes: - Added indicatorVersion field to Trade table - Added indicatorVersion field to BlockedSignal table - Tracks which Pine Script version (v5, v6, etc.) generated each signal Pine Script changes: - v6 now includes '| IND:v6' in alert messages - Enables differentiation between v5 and v6 signals in database Documentation: - Created INDICATOR_VERSION_TRACKING.md with full implementation guide - Includes n8n workflow update instructions - Includes SQL analysis queries for v5 vs v6 comparison - Includes rollback plan if needed Next steps (manual): 1. Update n8n workflow Parse Signal Enhanced node to extract IND field 2. Update n8n HTTP requests to pass indicatorVersion 3. Update API endpoints to accept and save indicatorVersion 4. Rebuild Docker container Benefits: - Compare v5 vs v6 Pine Script effectiveness - Track which version generated winning/losing trades - Validate that v6 price position filter reduces blocked signals - Data-driven decisions on Pine Script improvements
225 lines
7.4 KiB
Plaintext
225 lines
7.4 KiB
Plaintext
// Prisma Schema for Trading Bot v4
|
|
// Database: PostgreSQL
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// Trade records for analysis and performance tracking
|
|
model Trade {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// Trade identification
|
|
positionId String @unique // Transaction signature from entry order
|
|
symbol String // e.g., "SOL-PERP"
|
|
direction String // "long" or "short"
|
|
|
|
// Entry details
|
|
entryPrice Float
|
|
entryTime DateTime
|
|
entrySlippage Float?
|
|
positionSizeUSD Float // NOTIONAL position size (with leverage)
|
|
collateralUSD Float? // ACTUAL margin/collateral used (positionSizeUSD / leverage)
|
|
leverage Float
|
|
|
|
// Exit targets (planned)
|
|
stopLossPrice Float
|
|
softStopPrice Float? // Dual stop: soft stop-limit trigger
|
|
hardStopPrice Float? // Dual stop: hard stop-market trigger
|
|
takeProfit1Price Float
|
|
takeProfit2Price Float
|
|
tp1SizePercent Float
|
|
tp2SizePercent Float
|
|
|
|
// Exit details (actual)
|
|
exitPrice Float?
|
|
exitTime DateTime?
|
|
exitReason String? // "TP1", "TP2", "SL", "SOFT_SL", "HARD_SL", "manual", "emergency"
|
|
|
|
// Performance metrics
|
|
realizedPnL Float?
|
|
realizedPnLPercent Float?
|
|
holdTimeSeconds Int?
|
|
maxDrawdown Float? // Peak to valley during trade
|
|
maxGain Float? // Peak gain reached
|
|
|
|
// MAE/MFE Analysis (Maximum Adverse/Favorable Excursion)
|
|
maxFavorableExcursion Float? // Best profit % reached during trade
|
|
maxAdverseExcursion Float? // Worst drawdown % during trade
|
|
maxFavorablePrice Float? // Best price hit (direction-aware)
|
|
maxAdversePrice Float? // Worst price hit (direction-aware)
|
|
|
|
// Exit details - which levels actually filled
|
|
tp1Filled Boolean @default(false)
|
|
tp2Filled Boolean @default(false)
|
|
softSlFilled Boolean @default(false)
|
|
hardSlFilled Boolean @default(false)
|
|
tp1FillPrice Float?
|
|
tp2FillPrice Float?
|
|
slFillPrice Float?
|
|
|
|
// Timing metrics
|
|
timeToTp1 Int? // Seconds from entry to TP1 fill
|
|
timeToTp2 Int? // Seconds from entry to TP2 fill
|
|
timeToSl Int? // Seconds from entry to SL hit
|
|
|
|
// Market context at entry
|
|
atrAtEntry Float? // ATR% when trade opened
|
|
adxAtEntry Float? // ADX trend strength (0-50)
|
|
rsiAtEntry Float? // RSI momentum (0-100)
|
|
volumeAtEntry Float? // Volume relative to MA
|
|
pricePositionAtEntry Float? // Price position in range (0-100%)
|
|
signalQualityScore Int? // Calculated quality score (0-100)
|
|
signalQualityVersion String? @default("v4") // Tracks which scoring logic was used
|
|
indicatorVersion String? // Pine Script version (v5, v6, etc.)
|
|
fundingRateAtEntry Float? // Perp funding rate at entry
|
|
basisAtEntry Float? // Perp-spot basis at entry
|
|
|
|
// Slippage tracking
|
|
expectedEntryPrice Float? // Target entry from signal
|
|
entrySlippagePct Float? // Actual slippage %
|
|
expectedExitPrice Float? // Which TP/SL should have hit
|
|
exitSlippagePct Float? // Exit slippage %
|
|
|
|
// Order signatures
|
|
entryOrderTx String
|
|
tp1OrderTx String?
|
|
tp2OrderTx String?
|
|
slOrderTx String?
|
|
softStopOrderTx String? // Dual stop: soft stop tx
|
|
hardStopOrderTx String? // Dual stop: hard stop tx
|
|
exitOrderTx String?
|
|
|
|
// Configuration snapshot
|
|
configSnapshot Json // Store settings used for this trade
|
|
|
|
// Signal data
|
|
signalSource String? // "tradingview", "manual", etc.
|
|
signalStrength String? // "strong", "moderate", "weak"
|
|
timeframe String? // "5", "15", "60"
|
|
|
|
// Status
|
|
status String @default("open") // "open", "closed", "failed", "phantom"
|
|
isTestTrade Boolean @default(false) // Flag test trades for exclusion from analytics
|
|
|
|
// Phantom trade detection
|
|
isPhantom Boolean @default(false) // Position opened but size mismatch >50%
|
|
expectedSizeUSD Float? // Expected position size (when phantom)
|
|
actualSizeUSD Float? // Actual position size from Drift (when phantom)
|
|
phantomReason String? // "ORACLE_PRICE_MISMATCH", "PARTIAL_FILL", "ORDER_REJECTED"
|
|
|
|
// Relations
|
|
priceUpdates PriceUpdate[]
|
|
|
|
@@index([symbol])
|
|
@@index([createdAt])
|
|
@@index([status])
|
|
@@index([exitReason])
|
|
}
|
|
|
|
// Real-time price updates during trade (for analysis)
|
|
model PriceUpdate {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
|
|
tradeId String
|
|
trade Trade @relation(fields: [tradeId], references: [id], onDelete: Cascade)
|
|
|
|
price Float
|
|
pnl Float
|
|
pnlPercent Float
|
|
|
|
@@index([tradeId])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
// System events and errors
|
|
model SystemEvent {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
|
|
eventType String // "error", "warning", "info", "trade_executed", etc.
|
|
message String
|
|
details Json?
|
|
|
|
@@index([eventType])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
// Blocked signals for analysis (signals that didn't pass quality checks)
|
|
model BlockedSignal {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
|
|
// Signal identification
|
|
symbol String // e.g., "SOL-PERP"
|
|
direction String // "long" or "short"
|
|
timeframe String? // "5", "15", "60"
|
|
|
|
// Price at signal time
|
|
signalPrice Float // Price when signal was generated
|
|
|
|
// Market metrics at signal time
|
|
atr Float? // ATR% at signal
|
|
adx Float? // ADX trend strength
|
|
rsi Float? // RSI momentum
|
|
volumeRatio Float? // Volume relative to average
|
|
pricePosition Float? // Position in range (0-100%)
|
|
|
|
// Quality scoring
|
|
signalQualityScore Int // 0-100 score
|
|
signalQualityVersion String? // Which scoring version
|
|
scoreBreakdown Json? // Detailed breakdown of score components
|
|
minScoreRequired Int // What threshold was used (e.g., 65)
|
|
indicatorVersion String? // Pine Script version (v5, v6, etc.)
|
|
|
|
// Block reason
|
|
blockReason String // "QUALITY_SCORE_TOO_LOW", "DUPLICATE", "COOLDOWN", etc.
|
|
blockDetails String? // Human-readable details
|
|
|
|
// For later analysis: track if it would have been profitable
|
|
priceAfter1Min Float? // Price 1 minute after (filled by monitoring job)
|
|
priceAfter5Min Float? // Price 5 minutes after
|
|
priceAfter15Min Float? // Price 15 minutes after
|
|
priceAfter30Min Float? // Price 30 minutes after
|
|
wouldHitTP1 Boolean? // Would TP1 have been hit?
|
|
wouldHitTP2 Boolean? // Would TP2 have been hit?
|
|
wouldHitSL Boolean? // Would SL have been hit?
|
|
analysisComplete Boolean @default(false) // Has post-analysis been done?
|
|
|
|
@@index([symbol])
|
|
@@index([createdAt])
|
|
@@index([signalQualityScore])
|
|
@@index([blockReason])
|
|
}
|
|
|
|
// Performance analytics (daily aggregates)
|
|
model DailyStats {
|
|
id String @id @default(cuid())
|
|
date DateTime @unique
|
|
|
|
tradesCount Int
|
|
winningTrades Int
|
|
losingTrades Int
|
|
totalPnL Float
|
|
totalPnLPercent Float
|
|
winRate Float
|
|
avgWin Float
|
|
avgLoss Float
|
|
profitFactor Float
|
|
maxDrawdown Float
|
|
sharpeRatio Float?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([date])
|
|
}
|