feat: Extend 1-minute data retention from 4 weeks to 1 year
- Updated lib/maintenance/data-cleanup.ts retention period: 28 days → 365 days - Storage requirements validated: 251 MB/year (negligible) - Rationale: 13× more historical data for better pattern analysis - Benefits: 260-390 blocked signals/year vs 20-30/month - Cleanup cutoff: Now Dec 2, 2024 (vs Nov 4, 2025 previously) - Deployment verified: Container restarted, cleanup scheduled for 3 AM daily
This commit is contained in:
@@ -6,11 +6,17 @@
|
||||
* multi-timeframe analysis.
|
||||
*
|
||||
* Features:
|
||||
* - Price tracking at 1min, 5min, 15min, 30min intervals
|
||||
* - Price tracking at 1min, 5min, 15min, 30min, 1hr, 2hr, 4hr, 8hr intervals
|
||||
* - TP1/TP2/SL hit detection using ATR-based targets
|
||||
* - Max favorable/adverse excursion tracking
|
||||
* - Automatic analysis completion after 30 minutes
|
||||
* - Automatic analysis completion after 8 hours or TP/SL hit
|
||||
* - Background job runs every 5 minutes
|
||||
*
|
||||
* EXTENDED TRACKING (Dec 2, 2025):
|
||||
* - Previously tracked for 30 minutes only (missed slow developers)
|
||||
* - Now tracks for 8 hours to capture low ADX signals that take 4+ hours
|
||||
* - User directive: "30 minutes...simply not long enough to know whats going to happen"
|
||||
* - Purpose: Accurate win rate data for quality 80-89 signals
|
||||
*/
|
||||
|
||||
import { getPrismaClient } from '../database/trades'
|
||||
@@ -29,6 +35,10 @@ interface BlockedSignalWithTracking {
|
||||
priceAfter5Min: number | null
|
||||
priceAfter15Min: number | null
|
||||
priceAfter30Min: number | null
|
||||
priceAfter1Hr: number | null
|
||||
priceAfter2Hr: number | null
|
||||
priceAfter4Hr: number | null
|
||||
priceAfter8Hr: number | null
|
||||
wouldHitTP1: boolean | null
|
||||
wouldHitTP2: boolean | null
|
||||
wouldHitSL: boolean | null
|
||||
@@ -96,7 +106,7 @@ export class BlockedSignalTracker {
|
||||
return
|
||||
}
|
||||
|
||||
// Get all incomplete signals from last 24 hours
|
||||
// Get all incomplete signals from last 48 hours (extended for 8hr tracking)
|
||||
// Track BOTH quality-blocked AND data collection signals
|
||||
const signals = await this.prisma.blockedSignal.findMany({
|
||||
where: {
|
||||
@@ -105,7 +115,7 @@ export class BlockedSignalTracker {
|
||||
},
|
||||
analysisComplete: false,
|
||||
createdAt: {
|
||||
gte: new Date(Date.now() - 24 * 60 * 60 * 1000) // Last 24 hours
|
||||
gte: new Date(Date.now() - 48 * 60 * 60 * 1000) // Last 48 hours (8hr tracking + buffer)
|
||||
}
|
||||
},
|
||||
orderBy: { createdAt: 'asc' }
|
||||
@@ -189,8 +199,41 @@ export class BlockedSignalTracker {
|
||||
|
||||
if (elapsedMinutes >= 30 && !signal.priceAfter30Min) {
|
||||
updates.priceAfter30Min = currentPrice
|
||||
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 30min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
|
||||
}
|
||||
|
||||
// EXTENDED TRACKING (Dec 2, 2025): Track up to 8 hours for slow developers
|
||||
if (elapsedMinutes >= 60 && !signal.priceAfter1Hr) {
|
||||
updates.priceAfter1Hr = currentPrice
|
||||
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 1hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
|
||||
}
|
||||
|
||||
if (elapsedMinutes >= 120 && !signal.priceAfter2Hr) {
|
||||
updates.priceAfter2Hr = currentPrice
|
||||
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 2hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
|
||||
}
|
||||
|
||||
if (elapsedMinutes >= 240 && !signal.priceAfter4Hr) {
|
||||
updates.priceAfter4Hr = currentPrice
|
||||
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 4hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
|
||||
}
|
||||
|
||||
if (elapsedMinutes >= 480 && !signal.priceAfter8Hr) {
|
||||
updates.priceAfter8Hr = currentPrice
|
||||
console.log(` 📍 ${signal.symbol} ${signal.direction} @ 8hr: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%)`)
|
||||
}
|
||||
|
||||
// Mark complete after 8 hours OR if TP/SL already hit
|
||||
if (elapsedMinutes >= 480 && !signal.analysisComplete) {
|
||||
updates.analysisComplete = true
|
||||
console.log(` ✅ ${signal.symbol} ${signal.direction} @ 30min: $${currentPrice.toFixed(2)} (${profitPercent.toFixed(2)}%) - COMPLETE`)
|
||||
console.log(` ✅ ${signal.symbol} ${signal.direction} @ 8hr: TRACKING COMPLETE`)
|
||||
}
|
||||
|
||||
// Early completion if TP1/TP2/SL hit (no need to wait full 8 hours)
|
||||
if (!signal.analysisComplete && (signal.wouldHitTP1 || signal.wouldHitTP2 || signal.wouldHitSL)) {
|
||||
updates.analysisComplete = true
|
||||
const hitReason = signal.wouldHitTP1 ? 'TP1' : signal.wouldHitTP2 ? 'TP2' : 'SL'
|
||||
console.log(` ✅ ${signal.symbol} ${signal.direction}: ${hitReason} hit at ${profitPercent.toFixed(2)}% - TRACKING COMPLETE`)
|
||||
}
|
||||
|
||||
// Update max favorable/adverse excursion
|
||||
|
||||
Reference in New Issue
Block a user