diff --git a/docker-compose.yml b/docker-compose.yml index dc95e7b..32d7ccf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -80,6 +80,15 @@ services: depends_on: - postgres + deploy: + resources: + limits: + memory: 2G + cpus: '2.0' + reservations: + memory: 512M + cpus: '0.5' + healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] interval: 30s @@ -117,6 +126,14 @@ services: - ./prisma/init.sql:/docker-entrypoint-initdb.d/init.sql:ro networks: - trading-net + deploy: + resources: + limits: + memory: 1G + cpus: '1.0' + reservations: + memory: 512M + cpus: '0.25' healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s diff --git a/lib/trading/stop-hunt-tracker.ts b/lib/trading/stop-hunt-tracker.ts index 4513419..e9252dc 100644 --- a/lib/trading/stop-hunt-tracker.ts +++ b/lib/trading/stop-hunt-tracker.ts @@ -251,14 +251,14 @@ export class StopHuntTracker { metadata.lowestInZone = Math.min(metadata.lowestInZone, currentPrice) ;(stopHunt as any).revengeMetadata = metadata - // Check if we've been in zone for 60+ seconds (simulates candle close) + // Check if we've been in zone for 90+ seconds (1.5 minutes - partial candle confirmation) const timeInZone = now - metadata.firstCrossTime - if (timeInZone >= 60000) { - console.log(` ✅ LONG revenge: Price held below entry for ${(timeInZone/1000).toFixed(0)}s, confirmed!`) + if (timeInZone >= 90000) { // 90 seconds = 1.5 minutes + console.log(` ✅ LONG revenge: Price held below entry for ${(timeInZone/60000).toFixed(1)}min, confirmed!`) console.log(` Entry ${originalEntryPrice.toFixed(2)} → Current ${currentPrice.toFixed(2)}`) return true } else { - console.log(` ⏱️ LONG revenge: ${(timeInZone/1000).toFixed(0)}s in zone (need 60s)`) + console.log(` ⏱️ LONG revenge: ${(timeInZone/60000).toFixed(1)}min in zone (need 1.5min)`) return false } } else { @@ -287,14 +287,14 @@ export class StopHuntTracker { metadata.highestInZone = Math.max(metadata.highestInZone, currentPrice) ;(stopHunt as any).revengeMetadata = metadata - // Check if we've been in zone for 60+ seconds + // Check if we've been in zone for 90+ seconds (1.5 minutes - fast but filters wicks) const timeInZone = now - metadata.firstCrossTime - if (timeInZone >= 60000) { - console.log(` ✅ SHORT revenge: Price held above entry for ${(timeInZone/1000).toFixed(0)}s, confirmed!`) + if (timeInZone >= 90000) { // 90 seconds = 1.5 minutes + console.log(` ✅ SHORT revenge: Price held above entry for ${(timeInZone/60000).toFixed(1)}min, confirmed!`) console.log(` Entry ${originalEntryPrice.toFixed(2)} → Current ${currentPrice.toFixed(2)}`) return true } else { - console.log(` ⏱️ SHORT revenge: ${(timeInZone/1000).toFixed(0)}s in zone (need 60s)`) + console.log(` ⏱️ SHORT revenge: ${(timeInZone/60000).toFixed(1)}min in zone (need 1.5min)`) return false } } else {