feat: implement dynamic risk-based analysis intervals

- Replace fixed 10-minute intervals with adaptive timing based on position risk
- CRITICAL/HIGH risk: 5 minutes (minimum to protect ChatGPT budget)
- MEDIUM risk: 10 minutes for regular monitoring
- LOW risk: 15 minutes for relaxed monitoring
- NO POSITION: 10 minutes for entry signal detection
- Dynamic monitoring queries position monitor API each cycle for risk assessment
- Budget protection: minimum 5-minute intervals (no 1-2 minute excessive usage)
- Fallback safety: defaults to 10 minutes if risk assessment fails
- Changed from setInterval to setTimeout chain for true dynamic adjustment
This commit is contained in:
mindesbunister
2025-07-27 11:26:31 +02:00
parent 4f68593682
commit 1b9dfd1242

View File

@@ -113,10 +113,9 @@ class SimpleAutomation {
console.log('TIMEFRAMES: [' + timeframes.join(', ') + ']');
console.log('MODE: ' + (config.mode || 'SIMULATION'));
// Start simple monitoring cycle (10 minutes for safety)
this.intervalId = setInterval(() => {
this.runCycle();
}, 10 * 60 * 1000); // 10 minutes
// Start dynamic monitoring cycle with risk-based intervals
this.currentInterval = 10 * 60 * 1000; // Start with 10 minutes
this.startDynamicMonitoring();
// First cycle after 30 seconds
setTimeout(() => {
@@ -144,7 +143,7 @@ class SimpleAutomation {
console.log('✅ AUTOMATION STATUS: isRunning =', this.isRunning);
if (this.intervalId) {
clearInterval(this.intervalId);
clearTimeout(this.intervalId); // Changed from clearInterval to clearTimeout
this.intervalId = null;
}
@@ -163,6 +162,75 @@ class SimpleAutomation {
}
}
// Dynamic monitoring with risk-based intervals
startDynamicMonitoring() {
const runMonitoringCycle = async () => {
if (!this.isRunning) return;
await this.runCycle();
// Get current risk level from position monitor
const nextInterval = await this.getNextInterval();
// Schedule next cycle with dynamic interval
this.intervalId = setTimeout(runMonitoringCycle, nextInterval);
};
// Start the dynamic cycle
this.intervalId = setTimeout(runMonitoringCycle, this.currentInterval);
}
// Determine next interval based on risk level
async getNextInterval() {
try {
// Check position monitor for current risk level
const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000';
const response = await fetch(`${baseUrl}/api/automation/position-monitor`, {
cache: 'no-store',
headers: { 'Cache-Control': 'no-cache' }
});
if (response.ok) {
const data = await response.json();
const riskLevel = data.monitor?.riskLevel || 'NONE';
// Dynamic intervals based on risk (5 min minimum to protect ChatGPT budget)
let intervalMinutes;
switch (riskLevel) {
case 'CRITICAL':
intervalMinutes = 5; // Most frequent: 5 minutes (was 1-2 min)
break;
case 'HIGH':
intervalMinutes = 5; // High risk: 5 minutes
break;
case 'MEDIUM':
intervalMinutes = 10; // Medium risk: 10 minutes
break;
case 'LOW':
intervalMinutes = 15; // Low risk: 15 minutes
break;
case 'NONE':
default:
intervalMinutes = 10; // No position: 10 minutes (looking for entries)
break;
}
const intervalMs = intervalMinutes * 60 * 1000;
console.log(`📊 DYNAMIC INTERVAL: Risk level ${riskLevel} → Next analysis in ${intervalMinutes} minutes`);
this.currentInterval = intervalMs;
return intervalMs;
}
} catch (error) {
console.warn('⚠️ Failed to get risk level for dynamic interval, using default 10 minutes:', error.message);
}
// Fallback to 10 minutes
this.currentInterval = 10 * 60 * 1000;
return this.currentInterval;
}
async runCycle() {
try {
// Check if automation should still be running
@@ -200,7 +268,7 @@ class SimpleAutomation {
this.stats.status = 'Stopped due to errors';
if (this.intervalId) {
clearInterval(this.intervalId);
clearTimeout(this.intervalId); // Changed from clearInterval to clearTimeout
this.intervalId = null;
}
return;