112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import type { Candle } from './chartTypes';
|
|
|
|
/**
|
|
* Generates realistic mock candlestick data for development/testing.
|
|
* The data simulates price movements with trends, volatility, and volume patterns.
|
|
*/
|
|
export function generateMockCandles(
|
|
symbol: string,
|
|
timeframe: string,
|
|
barSize: string,
|
|
count: number = 200
|
|
): Candle[] {
|
|
// Base price varies by symbol for realistic appearance
|
|
const symbolHash = symbol.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
let basePrice = 100 + (symbolHash % 900); // Price between 100-1000
|
|
|
|
// Timeframe affects interval between candles
|
|
const intervalMs = getIntervalMs(barSize);
|
|
|
|
// Start from a past time
|
|
const now = Date.now();
|
|
const startTime = now - (count * intervalMs);
|
|
|
|
const candles: Candle[] = [];
|
|
let currentPrice = basePrice;
|
|
let trend = 0; // -1 to 1, represents current trend direction
|
|
let volatility = 0.02; // 2% base volatility
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
// Slowly drift the trend
|
|
trend += (Math.random() - 0.5) * 0.1;
|
|
trend = Math.max(-1, Math.min(1, trend)); // Clamp trend
|
|
|
|
// Occasionally spike volatility
|
|
if (Math.random() < 0.05) {
|
|
volatility = 0.02 + Math.random() * 0.03;
|
|
} else {
|
|
volatility = volatility * 0.95 + 0.02 * 0.05; // Decay back to base
|
|
}
|
|
|
|
// Calculate price movement
|
|
const trendComponent = trend * volatility * currentPrice * 0.5;
|
|
const randomComponent = (Math.random() - 0.5) * volatility * currentPrice;
|
|
const priceChange = trendComponent + randomComponent;
|
|
|
|
// Generate OHLC
|
|
const open = currentPrice;
|
|
const close = currentPrice + priceChange;
|
|
|
|
// High and low extend beyond open/close
|
|
const range = Math.abs(close - open);
|
|
const wickExtension = range * (0.3 + Math.random() * 0.7);
|
|
const high = Math.max(open, close) + wickExtension * Math.random();
|
|
const low = Math.min(open, close) - wickExtension * Math.random();
|
|
|
|
// Volume correlates with price movement
|
|
const baseVolume = 1000000 + symbolHash * 1000;
|
|
const volumeMultiplier = 0.5 + Math.abs(priceChange / currentPrice) * 10 + Math.random();
|
|
const volume = Math.floor(baseVolume * volumeMultiplier);
|
|
|
|
candles.push({
|
|
time: startTime + i * intervalMs,
|
|
open: roundPrice(open),
|
|
high: roundPrice(high),
|
|
low: roundPrice(low),
|
|
close: roundPrice(close),
|
|
volume,
|
|
});
|
|
|
|
currentPrice = close;
|
|
}
|
|
|
|
return candles;
|
|
}
|
|
|
|
function getIntervalMs(barSize: string): number {
|
|
const intervals: Record<string, number> = {
|
|
'1m': 60 * 1000,
|
|
'5m': 5 * 60 * 1000,
|
|
'15m': 15 * 60 * 1000,
|
|
'30m': 30 * 60 * 1000,
|
|
'1h': 60 * 60 * 1000,
|
|
'4h': 4 * 60 * 60 * 1000,
|
|
'1d': 24 * 60 * 60 * 1000,
|
|
'1w': 7 * 24 * 60 * 60 * 1000,
|
|
};
|
|
return intervals[barSize] || intervals['1h'];
|
|
}
|
|
|
|
function roundPrice(price: number): number {
|
|
// Round to 2 decimal places
|
|
return Math.round(price * 100) / 100;
|
|
}
|
|
|
|
/**
|
|
* Simulates an async API fetch with realistic delay.
|
|
* TODO: Replace with real API integration.
|
|
*/
|
|
export async function fetchMockCandles(
|
|
symbol: string,
|
|
user: string,
|
|
timeframe: string,
|
|
barSize: string
|
|
): Promise<Candle[]> {
|
|
// Simulate network delay
|
|
await new Promise(resolve => setTimeout(resolve, 300 + Math.random() * 200));
|
|
|
|
// Generate candles (user param would be used for personalized data in real API)
|
|
console.log(`[v0] Fetching candles for ${symbol} (user: ${user}, timeframe: ${timeframe}, barSize: ${barSize})`);
|
|
return generateMockCandles(symbol, timeframe, barSize, 200);
|
|
}
|