SoftTraderFrontend/components/candlestick-chart/chartTypes.ts
2026-03-20 11:10:13 -04:00

248 lines
6.9 KiB
TypeScript

// Core candle data structure (normalized from API)
export interface Candle {
time: number; // UTC timestamp in milliseconds
open: number;
high: number;
low: number;
close: number;
volume: number;
}
// Chart size options
export type ChartSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
// Chart configuration props
export interface CandlestickGraphProps {
/** Stock symbol (e.g., "AAPL", "MSFT") */
symbol: string;
/** User identifier for API authentication */
user: string;
/** Start date for the data range (ISO string or Date) */
startDate: string | Date;
/** End date for the data range (ISO string or Date) */
endDate: string | Date;
/** Bar size / time interval for each candle */
barSize: string;
/** Predefined chart size or custom className */
size?: ChartSize;
/** Additional CSS classes */
className?: string;
}
// View model state for the chart
export interface ChartViewModel {
candles: Candle[];
visibleStartIndex: number;
visibleEndIndex: number;
hoveredIndex: number | null;
chartDimensions: ChartDimensions;
priceRange: PriceRange;
volumeRange: VolumeRange;
candleLayout: CandleLayout;
selectedIndicators: string[];
selectedEvents: string[];
}
export interface ChartDimensions {
width: number;
height: number;
priceChartHeight: number;
volumeChartHeight: number;
paddingTop: number;
paddingRight: number;
paddingBottom: number;
paddingLeft: number;
}
export interface PriceRange {
min: number;
max: number;
}
export interface VolumeRange {
min: number;
max: number;
}
export interface CandleLayout {
candleWidth: number;
candleSpacing: number;
xStep: number;
}
// Mouse interaction state
export interface MouseState {
x: number;
y: number;
isInChart: boolean;
}
// Measure point for the measure tool
export interface MeasurePoint {
x: number;
y: number;
price: number;
time: number;
index: number;
}
// Note annotation for the chart
export interface ChartNote {
id: string;
time: number; // UTC timestamp - x position
price: number; // price level - y position
text: string;
isMinimized: boolean;
createdAt: number;
}
// Draw line annotation for the chart
export interface DrawLine {
id: string;
startTime: number; // UTC timestamp - x position of start point
startPrice: number; // price level - y position of start point
endTime: number; // UTC timestamp - x position of end point
endPrice: number; // price level - y position of end point
lineType: 'line' | 'arrow' | 'dotted';
color: string;
createdAt: number;
}
// Combined annotations type for API persistence
export interface ChartAnnotations {
notes: ChartNote[];
drawLines: DrawLine[];
}
// Indicator types
export type IndicatorType = 'sma' | 'ema' | 'boll' | 'rsi' | 'macd' | 'volume';
export interface IndicatorParams {
period?: number;
stdDev?: number; // For Bollinger Bands
fastPeriod?: number; // For MACD
slowPeriod?: number; // For MACD
signalPeriod?: number; // For MACD
}
export interface ChartIndicator {
id: string;
type: IndicatorType;
params: IndicatorParams;
color: string;
enabled: boolean;
}
// Default indicator configurations
export const DEFAULT_INDICATOR_PARAMS: Record<IndicatorType, IndicatorParams> = {
sma: { period: 20 },
ema: { period: 12 },
boll: { period: 20, stdDev: 2 },
rsi: { period: 14 },
macd: { fastPeriod: 12, slowPeriod: 26, signalPeriod: 9 },
volume: {},
};
export const INDICATOR_COLORS = [
'#3b82f6', // blue
'#f59e0b', // amber
'#8b5cf6', // violet
'#ec4899', // pink
'#06b6d4', // cyan
'#84cc16', // lime
];
// Chart colors/theme
export interface ChartTheme {
background: string;
gridLine: string;
gridLineMajor: string;
bullishBody: string;
bullishWick: string;
bearishBody: string;
bearishWick: string;
volumeBullish: string;
volumeBearish: string;
crosshair: string;
axisText: string;
tooltipBackground: string;
tooltipBorder: string;
tooltipText: string;
}
/**
* Gets theme colors from CSS custom properties.
* This enables dark/light mode support.
*/
export function getChartTheme(): ChartTheme {
if (typeof window === 'undefined') {
// SSR fallback - use dark theme defaults
return {
background: '#0d0d0f',
gridLine: 'rgba(255, 255, 255, 0.04)',
gridLineMajor: 'rgba(255, 255, 255, 0.08)',
bullishBody: '#22c55e',
bullishWick: '#22c55e',
bearishBody: '#ef4444',
bearishWick: '#ef4444',
volumeBullish: 'rgba(34, 197, 94, 0.3)',
volumeBearish: 'rgba(239, 68, 68, 0.3)',
crosshair: 'rgba(255, 255, 255, 0.5)',
axisText: 'rgba(255, 255, 255, 0.5)',
tooltipBackground: '#1a1a1f',
tooltipBorder: 'rgba(255, 255, 255, 0.1)',
tooltipText: '#ffffff',
};
}
const styles = getComputedStyle(document.documentElement);
return {
background: styles.getPropertyValue('--chart-bg').trim() || '#0d0d0f',
gridLine: styles.getPropertyValue('--chart-grid').trim() || 'rgba(255, 255, 255, 0.04)',
gridLineMajor: styles.getPropertyValue('--chart-grid-major').trim() || 'rgba(255, 255, 255, 0.08)',
bullishBody: '#22c55e',
bullishWick: '#22c55e',
bearishBody: '#ef4444',
bearishWick: '#ef4444',
volumeBullish: 'rgba(34, 197, 94, 0.3)',
volumeBearish: 'rgba(239, 68, 68, 0.3)',
crosshair: styles.getPropertyValue('--chart-crosshair').trim() || 'rgba(255, 255, 255, 0.5)',
axisText: styles.getPropertyValue('--chart-axis-text').trim() || 'rgba(255, 255, 255, 0.5)',
tooltipBackground: styles.getPropertyValue('--chart-tooltip-bg').trim() || '#1a1a1f',
tooltipBorder: styles.getPropertyValue('--chart-tooltip-border').trim() || 'rgba(255, 255, 255, 0.1)',
tooltipText: styles.getPropertyValue('--foreground').trim() || '#ffffff',
};
}
// Default theme for initial render (dark mode)
export const DEFAULT_CHART_THEME: ChartTheme = {
background: '#0d0d0f',
gridLine: 'rgba(255, 255, 255, 0.04)',
gridLineMajor: 'rgba(255, 255, 255, 0.08)',
bullishBody: '#22c55e',
bullishWick: '#22c55e',
bearishBody: '#ef4444',
bearishWick: '#ef4444',
volumeBullish: 'rgba(34, 197, 94, 0.3)',
volumeBearish: 'rgba(239, 68, 68, 0.3)',
crosshair: 'rgba(255, 255, 255, 0.5)',
axisText: 'rgba(255, 255, 255, 0.5)',
tooltipBackground: '#1a1a1f',
tooltipBorder: 'rgba(255, 255, 255, 0.1)',
tooltipText: '#ffffff',
};
// Chart layout constants
export const CHART_LAYOUT = {
PRICE_CHART_RATIO: 0.75, // 75% for price, 25% for volume
PADDING_TOP: 20,
PADDING_RIGHT: 70, // Space for price axis
PADDING_BOTTOM: 30, // Space for time axis
PADDING_LEFT: 10,
MIN_CANDLE_WIDTH: 3,
MAX_CANDLE_WIDTH: 20,
CANDLE_SPACING_RATIO: 0.2, // 20% of candle width as spacing
VOLUME_SECTION_GAP: 10,
};