Files
trading_bot_v4/prisma/schema.prisma
mindesbunister 702e027aba feat: Stop Hunt Revenge System - DEPLOYED (Nov 20, 2025)
Automatically re-enters positions after high-quality signals get stopped out

Features:
- Tracks quality 85+ signals that get stopped out
- Monitors for price reversal through original entry (4-hour window)
- Executes revenge trade at 1.2x size (recover losses faster)
- Telegram notification: 🔥 REVENGE TRADE ACTIVATED
- Database: StopHunt table with 20 fields, 4 indexes
- Monitoring: 30-second checks for active stop hunts

Technical:
- Fixed: Database query hanging in startStopHuntTracking()
- Solution: Added try-catch with error handling
- Import path: Corrected to use '../database/trades'
- Singleton pattern: Single tracker instance per server
- Integration: Position Manager records on SL close

Files:
- lib/trading/stop-hunt-tracker.ts (293 lines, 8 methods)
- lib/startup/init-position-manager.ts (startup integration)
- lib/trading/position-manager.ts (recording logic, ready for next deployment)
- prisma/schema.prisma (StopHunt model)

Commits: Import fix, debug logs, error handling, cleanup
Tested: Container starts successfully, tracker initializes, database query works
Status: 100% operational, waiting for first quality 85+ stop-out to test live
2025-11-20 19:17:43 +01:00

273 lines
9.3 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", "DATA_COLLECTION_ONLY", etc.
blockDetails String? // Human-readable details
// Entry tracking (for multi-timeframe analysis)
entryPrice Float @default(0) // Price at signal time
// 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?
// Max favorable/adverse excursion (mirror Trade model)
maxFavorablePrice Float? // Price at max profit
maxAdversePrice Float? // Price at max loss
maxFavorableExcursion Float? // Best profit % during tracking
maxAdverseExcursion Float? // Worst loss % during tracking
analysisComplete Boolean @default(false) // Has post-analysis been done?
@@index([symbol])
@@index([createdAt])
@@index([signalQualityScore])
@@index([blockReason])
}
// Stop Hunt Revenge Tracker (Nov 20, 2025)
// Tracks high-quality stop-outs and auto re-enters when stop hunt reverses
model StopHunt {
id String @id @default(cuid())
createdAt DateTime @default(now())
// Original trade that got stopped out
originalTradeId String // References Trade.id
symbol String // e.g., "SOL-PERP"
direction String // "long" or "short"
// Stop hunt details
stopHuntPrice Float // Price where we got stopped out
originalEntryPrice Float // Where we originally entered
originalQualityScore Int // Must be 85+ to qualify
originalADX Float? // Trend strength at entry
originalATR Float? // Volatility at entry
stopLossAmount Float // How much we lost
stopHuntTime DateTime // When stop hunt occurred
// Revenge tracking
revengeTradeId String? // References Trade.id if revenge executed
revengeExecuted Boolean @default(false)
revengeEntryPrice Float? // Where revenge trade entered
revengeTime DateTime? // When revenge executed
revengeWindowExpired Boolean @default(false)
revengeExpiresAt DateTime // 4 hours after stop hunt
// Monitoring state
highestPriceAfterStop Float? // Track if stop hunt reverses
lowestPriceAfterStop Float? // Track if stop hunt reverses
@@index([symbol])
@@index([revengeExecuted])
@@index([revengeWindowExpired])
@@index([stopHuntTime])
}
// 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])
}