117 lines
4.0 KiB
TypeScript
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();
|