messy work. backtests / mock-data

This commit is contained in:
Boki 2025-07-03 08:37:23 -04:00
parent 4e4a048988
commit fa70ada2bb
51 changed files with 2576 additions and 887 deletions

View file

@ -1,4 +1,6 @@
import { logger } from '@stock-bot/logger';
import { getLogger } from '@stock-bot/logger';
const logger = getLogger('DataManager');
import { StorageService } from '../services/StorageService';
import { MarketData, Bar } from '../types';
import { EventEmitter } from 'events';
@ -62,13 +64,19 @@ export class DataManager extends EventEmitter {
for (const symbol of symbols) {
try {
// Load raw data
const data = await this.storageService.getHistoricalBars(
let data = await this.storageService.getHistoricalBars(
symbol,
startDate,
endDate,
resolution
);
// If no data found, generate mock data
if (!data || data.length === 0) {
logger.warn(`No historical data found for ${symbol}, generating mock data`);
data = this.generateMockBars(symbol, startDate, endDate, resolution);
}
// Apply corporate actions
const adjustedData = await this.applyCorporateActions(symbol, data, startDate, endDate);
@ -432,4 +440,62 @@ export class DataManager extends EventEmitter {
this.aggregatedCache.clear();
this.dataQualityIssues = [];
}
private generateMockBars(
symbol: string,
startDate: Date,
endDate: Date,
resolution: string
): any[] {
const bars: any[] = [];
const resolutionMs = DataManager.RESOLUTIONS[resolution]?.milliseconds || 86400000; // Default to 1 day
let currentTime = startDate.getTime();
const endTime = endDate.getTime();
// Base price varies by symbol
let basePrice = 100;
if (symbol === 'AAPL') basePrice = 150;
else if (symbol === 'GOOGL') basePrice = 140;
else if (symbol === 'MSFT') basePrice = 380;
else if (symbol === 'TSLA') basePrice = 250;
let price = basePrice;
while (currentTime <= endTime) {
// Generate realistic intraday movement
const volatility = 0.02; // 2% daily volatility
const trend = 0.0001; // Slight upward trend
// Random walk with trend
const changePercent = (Math.random() - 0.5) * volatility + trend;
price = price * (1 + changePercent);
// Generate OHLC
const open = price;
const intraDayVolatility = volatility / 4;
const high = price * (1 + Math.random() * intraDayVolatility);
const low = price * (1 - Math.random() * intraDayVolatility);
const close = low + Math.random() * (high - low);
// Volume with some randomness
const baseVolume = 10000000; // 10M shares
const volume = baseVolume * (0.5 + Math.random());
bars.push({
timestamp: new Date(currentTime),
open: Number(open.toFixed(2)),
high: Number(high.toFixed(2)),
low: Number(low.toFixed(2)),
close: Number(close.toFixed(2)),
volume: Math.floor(volume),
vwap: Number(((high + low + close) / 3).toFixed(2))
});
currentTime += resolutionMs;
price = close; // Next bar opens at previous close
}
return bars;
}
}