learning_ai_invt_trdg/backend/test_simulation_pro.ts

117 lines
4.0 KiB
TypeScript

import { ProStrategyEngine } from '../src/strategies/ProStrategyEngine.js';
import { IExchangeConnector, Candle } from '../src/connectors/types.js';
import { config } from '../src/config/index.js';
import logger from '../src/utils/logger.js';
// --- MOCK LIVE EXCHANGE ---
class LiveSimulationExchange implements IExchangeConnector {
private currentTime = Date.now();
private price = 50000;
private trend = 1; // 1 = Up, -1 = Down
async fetchOHLCV(symbol: string, timeframe: string, limit?: number): Promise<Candle[]> {
// Generate a history of candles ending at 'currentTime'
const candles: Candle[] = [];
let tempPrice = this.price - (300 * 10); // Start back in time
const count = limit || 100;
for (let i = 0; i < count; i++) {
// Add some "trend" bias based on our internal state
const noise = (Math.random() - 0.5) * 50;
const move = (this.trend * 50) + noise; // Stronger trend (was 20)
tempPrice += move;
candles.push({
timestamp: this.currentTime - ((count - i) * getMs(timeframe)),
open: tempPrice,
high: tempPrice + 50,
low: tempPrice - 50,
close: tempPrice, // Close is what matters for EMA typically
volume: 1000
});
}
return candles;
}
// Helper to advance the simulation
public tick() {
this.currentTime += 60 * 60 * 1000; // Advance 1 hour
this.price += this.trend * 100 + (Math.random() - 0.5) * 200; // Move price
}
public setTrend(dir: 1 | -1) {
this.trend = dir;
}
async placeOrder(symbol: string, side: 'buy' | 'sell', qty: number, type: 'market' | 'limit'): Promise<any> {
return { id: 'mock-sim-order' };
}
async getPosition(symbol: string): Promise<any> {
return null;
}
}
function getMs(tf: string): number {
if (tf === '4h') return 4 * 60 * 60 * 1000;
if (tf === '1h') return 1 * 60 * 60 * 1000;
return 60000;
}
// --- MAIN RUNNER ---
async function runLiveSimulation() {
console.log('🚀 INITIALIZING PRO STRATEGY LIVE SIMULATION...\n');
// 1. Setup Mock Exchange
const exchange = new LiveSimulationExchange();
const engine = new ProStrategyEngine(exchange);
// Mock Config
config.PRO_STRATEGY.PARAMETERS.SESSION_WINDOWS = [{ start: 0, end: 24 }];
config.PRO_STRATEGY.PARAMETERS.RSI_OVERBOUGHT = 99;
console.log('--- PHASE 1: WARMUP (Generating Uptrend Data) ---');
exchange.setTrend(1); // Uptrend
// Simulate 5 "Ticks" (Hours) of trading
for (let i = 1; i <= 5; i++) {
console.log(`\n⏰ HOUR ${i}: Fetching Market Data...`);
exchange.tick(); // Advance time/price
const result = await engine.execute('BTC/USD');
if (result?.passed) {
const reason = result.reason || 'No reason';
console.log(`✅ [Trade Taken] ${result.signal} | Reason: ${reason.split('\n')[0]}...`);
} else {
console.log(`⏸️ [Skipped] Reason: ${result?.reason}`);
}
// Sleep for effect
await new Promise(r => setTimeout(r, 500));
}
console.log('\n--- PHASE 2: MARKET CRASH (Trend Reversal) ---');
exchange.setTrend(-1); // Downtrend
for (let i = 1; i <= 10; i++) { // Need enough ticks to bend the 4H EMA
// Speed up simulation
exchange.tick();
exchange.tick();
exchange.tick();
}
console.log(`\n⏰ HOUR 6 (After Crash): Checking Logic...`);
const resultCrash = await engine.execute('BTC/USD');
if (!resultCrash?.passed) {
console.log(`✅ [Correctly Skipped] Market Crash filtered! Reason: ${resultCrash?.reason}`);
} else {
console.log(`❌ [BAD TRADE] Strategy bought during crash? Signal: ${resultCrash?.signal}`);
}
console.log('\n✨ SIMULATION COMPLETE');
}
runLiveSimulation();