feat: Add ML prediction overlay components for trading charts
Add complete implementation of ML overlay components: - MLPredictionOverlay: Renders ML price predictions as line overlay - SignalMarkers: Displays BUY/SELL signal markers on chart - ICTConceptsOverlay: Renders Order Blocks, FVG, and Liquidity zones - useMlOverlayData: Custom hook with TanStack Query for data fetching - mlOverlay.types.ts: Type definitions for all ML overlay data Features: - Uses lightweight-charts API for efficient rendering - Automatic caching with 60s stale time - Configurable colors and visibility - Clean up on component unmount - Full TypeScript support Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
261dc4c71c
commit
d3f4aa3385
91
src/hooks/charts/useMlOverlayData.ts
Normal file
91
src/hooks/charts/useMlOverlayData.ts
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* useMlOverlayData Hook
|
||||
* Custom hook for fetching and caching ML overlay data for trading charts
|
||||
* Uses TanStack Query for efficient data fetching and caching
|
||||
*/
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import type {
|
||||
MLPrediction,
|
||||
SignalMarker,
|
||||
ICTConcept,
|
||||
MLPredictionResponse,
|
||||
} from '../../types/mlOverlay.types';
|
||||
|
||||
// ============================================================================
|
||||
// Constants
|
||||
// ============================================================================
|
||||
|
||||
const ML_API_URL = import.meta.env.VITE_ML_URL || 'http://localhost:3083';
|
||||
const STALE_TIME = 60000; // 60 seconds
|
||||
const CACHE_TIME = 300000; // 5 minutes
|
||||
|
||||
// ============================================================================
|
||||
// API Functions
|
||||
// ============================================================================
|
||||
|
||||
async function fetchMLPredictions(
|
||||
symbol: string,
|
||||
timeframe: string
|
||||
): Promise<MLPredictionResponse> {
|
||||
const response = await fetch(
|
||||
`${ML_API_URL}/api/ml/predictions/${symbol}/${timeframe}`
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch ML predictions: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Hook
|
||||
// ============================================================================
|
||||
|
||||
export interface UseMlOverlayDataOptions {
|
||||
symbol: string;
|
||||
timeframe: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface UseMlOverlayDataResult {
|
||||
predictions: MLPrediction[];
|
||||
signals: SignalMarker[];
|
||||
ictConcepts: ICTConcept[];
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
export function useMlOverlayData({
|
||||
symbol,
|
||||
timeframe,
|
||||
enabled = true,
|
||||
}: UseMlOverlayDataOptions): UseMlOverlayDataResult {
|
||||
const {
|
||||
data,
|
||||
isLoading,
|
||||
error,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ['ml-predictions', symbol, timeframe],
|
||||
queryFn: () => fetchMLPredictions(symbol, timeframe),
|
||||
staleTime: STALE_TIME,
|
||||
gcTime: CACHE_TIME,
|
||||
enabled,
|
||||
retry: 2,
|
||||
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 10000),
|
||||
});
|
||||
|
||||
return {
|
||||
predictions: data?.predictions || [],
|
||||
signals: data?.signals || [],
|
||||
ictConcepts: data?.ictConcepts || [],
|
||||
isLoading,
|
||||
error: error as Error | null,
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
||||
export default useMlOverlayData;
|
||||
@ -0,0 +1,134 @@
|
||||
/**
|
||||
* ICTConceptsOverlay Component
|
||||
* Renders ICT concepts (Order Blocks, FVG, Liquidity) as rectangles on the chart
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { IChartApi, ISeriesApi, Time } from 'lightweight-charts';
|
||||
import type { ICTConcept } from '../../../../../types/mlOverlay.types';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
export interface ICTConceptsOverlayProps {
|
||||
chartRef: React.RefObject<IChartApi>;
|
||||
ictConcepts: ICTConcept[];
|
||||
visible?: boolean;
|
||||
colors?: {
|
||||
OrderBlock: string;
|
||||
FVG: string;
|
||||
Liquidity: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface RectangleData {
|
||||
time: Time;
|
||||
value: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Default Colors
|
||||
// ============================================================================
|
||||
|
||||
const DEFAULT_COLORS = {
|
||||
OrderBlock: 'rgba(59, 130, 246, 0.3)', // Blue
|
||||
FVG: 'rgba(251, 191, 36, 0.3)', // Yellow
|
||||
Liquidity: 'rgba(249, 115, 22, 0.3)', // Orange
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Component
|
||||
// ============================================================================
|
||||
|
||||
export const ICTConceptsOverlay: React.FC<ICTConceptsOverlayProps> = ({
|
||||
chartRef,
|
||||
ictConcepts,
|
||||
visible = true,
|
||||
colors = DEFAULT_COLORS,
|
||||
}) => {
|
||||
const conceptSeriesRef = useRef<Map<string, ISeriesApi<'Area'>>>(new Map());
|
||||
|
||||
// Initialize series for each ICT concept
|
||||
useEffect(() => {
|
||||
if (!chartRef.current || !visible) return;
|
||||
|
||||
const chart = chartRef.current;
|
||||
const seriesMap = new Map<string, ISeriesApi<'Area'>>();
|
||||
|
||||
// Create series for each concept type
|
||||
ictConcepts.forEach((concept, index) => {
|
||||
const conceptId = `${concept.type}-${index}`;
|
||||
|
||||
if (!conceptSeriesRef.current.has(conceptId)) {
|
||||
const color = colors[concept.type] || DEFAULT_COLORS[concept.type];
|
||||
|
||||
const series = chart.addAreaSeries({
|
||||
topColor: color,
|
||||
bottomColor: color,
|
||||
lineColor: color.replace('0.3', '0.8'),
|
||||
lineWidth: 1,
|
||||
crosshairMarkerVisible: false,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: `${concept.type}`,
|
||||
});
|
||||
|
||||
seriesMap.set(conceptId, series);
|
||||
}
|
||||
});
|
||||
|
||||
conceptSeriesRef.current = seriesMap;
|
||||
|
||||
return () => {
|
||||
// Cleanup: remove all series
|
||||
conceptSeriesRef.current.forEach((series) => {
|
||||
chart.removeSeries(series);
|
||||
});
|
||||
conceptSeriesRef.current.clear();
|
||||
};
|
||||
}, [chartRef, ictConcepts, ictConcepts.length, visible, colors]);
|
||||
|
||||
// Update concept data
|
||||
useEffect(() => {
|
||||
if (!chartRef.current || !visible || ictConcepts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ictConcepts.forEach((concept, index) => {
|
||||
const conceptId = `${concept.type}-${index}`;
|
||||
const series = conceptSeriesRef.current.get(conceptId);
|
||||
|
||||
if (!series) return;
|
||||
|
||||
// Create rectangle data
|
||||
const timeStart = (concept.timeStart / 1000) as Time;
|
||||
const timeEnd = (concept.timeEnd / 1000) as Time;
|
||||
|
||||
const rectangleData: RectangleData[] = [
|
||||
{ time: timeStart, value: concept.priceTop },
|
||||
{ time: timeStart, value: concept.priceBottom },
|
||||
{ time: timeEnd, value: concept.priceBottom },
|
||||
{ time: timeEnd, value: concept.priceTop },
|
||||
{ time: timeStart, value: concept.priceTop },
|
||||
];
|
||||
|
||||
series.setData(rectangleData);
|
||||
});
|
||||
}, [chartRef, ictConcepts, visible]);
|
||||
|
||||
// Update visibility
|
||||
useEffect(() => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
conceptSeriesRef.current.forEach((series) => {
|
||||
series.applyOptions({
|
||||
visible,
|
||||
});
|
||||
});
|
||||
}, [chartRef, visible]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default ICTConceptsOverlay;
|
||||
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* MLPredictionOverlay Component
|
||||
* Renders ML price predictions as a line overlay on the trading chart
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { IChartApi, ISeriesApi, LineData, Time } from 'lightweight-charts';
|
||||
import type { MLPrediction } from '../../../../../types/mlOverlay.types';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
export interface MLPredictionOverlayProps {
|
||||
chartRef: React.RefObject<IChartApi>;
|
||||
predictions: MLPrediction[];
|
||||
visible?: boolean;
|
||||
lineColor?: string;
|
||||
lineWidth?: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Component
|
||||
// ============================================================================
|
||||
|
||||
export const MLPredictionOverlay: React.FC<MLPredictionOverlayProps> = ({
|
||||
chartRef,
|
||||
predictions,
|
||||
visible = true,
|
||||
lineColor = '#3b82f6',
|
||||
lineWidth = 2,
|
||||
}) => {
|
||||
const predictionSeriesRef = useRef<ISeriesApi<'Line'> | null>(null);
|
||||
|
||||
// Initialize prediction line series
|
||||
useEffect(() => {
|
||||
if (!chartRef.current || !visible) return;
|
||||
|
||||
const chart = chartRef.current;
|
||||
|
||||
// Create line series for predictions
|
||||
const predictionSeries = chart.addLineSeries({
|
||||
color: lineColor,
|
||||
lineWidth: lineWidth as 1 | 2 | 3 | 4,
|
||||
lineStyle: 0,
|
||||
crosshairMarkerVisible: true,
|
||||
crosshairMarkerRadius: 6,
|
||||
crosshairMarkerBorderColor: lineColor,
|
||||
crosshairMarkerBackgroundColor: lineColor,
|
||||
lastValueVisible: true,
|
||||
priceLineVisible: true,
|
||||
title: 'ML Prediction',
|
||||
});
|
||||
|
||||
predictionSeriesRef.current = predictionSeries;
|
||||
|
||||
return () => {
|
||||
if (predictionSeriesRef.current) {
|
||||
chart.removeSeries(predictionSeriesRef.current);
|
||||
predictionSeriesRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [chartRef, visible, lineColor, lineWidth]);
|
||||
|
||||
// Update prediction data
|
||||
useEffect(() => {
|
||||
if (!predictionSeriesRef.current || !visible || predictions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert predictions to line data
|
||||
const lineData: LineData[] = predictions.map((pred) => ({
|
||||
time: (pred.timestamp / 1000) as Time,
|
||||
value: pred.price,
|
||||
}));
|
||||
|
||||
// Sort by time (required by lightweight-charts)
|
||||
lineData.sort((a, b) => (a.time as number) - (b.time as number));
|
||||
|
||||
predictionSeriesRef.current.setData(lineData);
|
||||
}, [predictions, visible]);
|
||||
|
||||
// Update visibility
|
||||
useEffect(() => {
|
||||
if (!predictionSeriesRef.current) return;
|
||||
|
||||
predictionSeriesRef.current.applyOptions({
|
||||
visible,
|
||||
});
|
||||
}, [visible]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default MLPredictionOverlay;
|
||||
154
src/modules/trading/components/charts/overlays/README.md
Normal file
154
src/modules/trading/components/charts/overlays/README.md
Normal file
@ -0,0 +1,154 @@
|
||||
# ML Chart Overlays
|
||||
|
||||
Componentes de React para visualizar predicciones ML en gráficos de trading usando lightweight-charts.
|
||||
|
||||
## Componentes
|
||||
|
||||
### 1. MLPredictionOverlay
|
||||
Renderiza predicciones de precio ML como una línea sobre el gráfico.
|
||||
|
||||
**Props:**
|
||||
- `chartRef`: Referencia al chart de lightweight-charts
|
||||
- `predictions`: Array de predicciones ML
|
||||
- `visible`: Mostrar/ocultar overlay (default: true)
|
||||
- `lineColor`: Color de la línea (default: '#3b82f6')
|
||||
- `lineWidth`: Grosor de línea (default: 2)
|
||||
|
||||
### 2. SignalMarkers
|
||||
Renderiza marcadores de señales BUY/SELL en el gráfico.
|
||||
|
||||
**Props:**
|
||||
- `chartRef`: Referencia al chart de lightweight-charts
|
||||
- `candleSeriesRef`: Referencia a la serie de velas
|
||||
- `signals`: Array de señales
|
||||
- `visible`: Mostrar/ocultar markers (default: true)
|
||||
|
||||
### 3. ICTConceptsOverlay
|
||||
Renderiza conceptos ICT (Order Blocks, FVG, Liquidity) como rectángulos.
|
||||
|
||||
**Props:**
|
||||
- `chartRef`: Referencia al chart de lightweight-charts
|
||||
- `ictConcepts`: Array de conceptos ICT
|
||||
- `visible`: Mostrar/ocultar overlay (default: true)
|
||||
- `colors`: Objeto con colores por tipo de concepto
|
||||
|
||||
## Hook
|
||||
|
||||
### useMlOverlayData
|
||||
Hook personalizado para obtener datos ML desde el backend con caché automático.
|
||||
|
||||
**Opciones:**
|
||||
- `symbol`: Símbolo del activo (ej: 'EURUSD')
|
||||
- `timeframe`: Temporalidad (ej: '1h', '4h')
|
||||
- `enabled`: Activar/desactivar fetch (default: true)
|
||||
|
||||
**Retorna:**
|
||||
- `predictions`: Array de predicciones
|
||||
- `signals`: Array de señales
|
||||
- `ictConcepts`: Array de conceptos ICT
|
||||
- `isLoading`: Estado de carga
|
||||
- `error`: Error si existe
|
||||
- `refetch`: Función para refetch manual
|
||||
|
||||
## Ejemplo de Uso
|
||||
|
||||
```tsx
|
||||
import { useRef } from 'react';
|
||||
import { IChartApi, ISeriesApi } from 'lightweight-charts';
|
||||
import { useMlOverlayData } from '@/hooks/charts/useMlOverlayData';
|
||||
import {
|
||||
MLPredictionOverlay,
|
||||
SignalMarkers,
|
||||
ICTConceptsOverlay,
|
||||
} from '@/modules/trading/components/charts/overlays';
|
||||
|
||||
function TradingChart() {
|
||||
const chartRef = useRef<IChartApi>(null);
|
||||
const candleSeriesRef = useRef<ISeriesApi<'Candlestick'>>(null);
|
||||
|
||||
const { predictions, signals, ictConcepts, isLoading } = useMlOverlayData({
|
||||
symbol: 'EURUSD',
|
||||
timeframe: '1h',
|
||||
});
|
||||
|
||||
if (isLoading) return <div>Loading...</div>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Tu componente de chart aquí */}
|
||||
|
||||
<MLPredictionOverlay
|
||||
chartRef={chartRef}
|
||||
predictions={predictions}
|
||||
visible={true}
|
||||
/>
|
||||
|
||||
<SignalMarkers
|
||||
chartRef={chartRef}
|
||||
candleSeriesRef={candleSeriesRef}
|
||||
signals={signals}
|
||||
visible={true}
|
||||
/>
|
||||
|
||||
<ICTConceptsOverlay
|
||||
chartRef={chartRef}
|
||||
ictConcepts={ictConcepts}
|
||||
visible={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Backend
|
||||
|
||||
Los componentes esperan que el backend exponga el siguiente endpoint:
|
||||
|
||||
```
|
||||
GET /api/ml/predictions/:symbol/:timeframe
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"symbol": "EURUSD",
|
||||
"timeframe": "1h",
|
||||
"predictions": [
|
||||
{
|
||||
"timestamp": 1706400000000,
|
||||
"price": 1.0850,
|
||||
"confidence": 0.85,
|
||||
"type": "buy"
|
||||
}
|
||||
],
|
||||
"signals": [
|
||||
{
|
||||
"time": 1706400000000,
|
||||
"position": "belowBar",
|
||||
"color": "#10b981",
|
||||
"text": "BUY",
|
||||
"shape": "arrowUp"
|
||||
}
|
||||
],
|
||||
"ictConcepts": [
|
||||
{
|
||||
"type": "OrderBlock",
|
||||
"timeStart": 1706400000000,
|
||||
"timeEnd": 1706403600000,
|
||||
"priceTop": 1.0860,
|
||||
"priceBottom": 1.0840
|
||||
}
|
||||
],
|
||||
"generatedAt": "2026-01-28T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
- Los componentes usan TanStack Query para caché automático (60s stale time)
|
||||
- Las timestamps deben estar en milisegundos
|
||||
- Los overlays se limpian automáticamente al desmontar
|
||||
- Los colores predeterminados son:
|
||||
- OrderBlock: Azul (#3b82f6)
|
||||
- FVG: Amarillo (#fbbf24)
|
||||
- Liquidity: Naranja (#f97316)
|
||||
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* SignalMarkers Component
|
||||
* Renders buy/sell signal markers on the trading chart
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { IChartApi, ISeriesApi, Time, SeriesMarker } from 'lightweight-charts';
|
||||
import type { SignalMarker } from '../../../../../types/mlOverlay.types';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
export interface SignalMarkersProps {
|
||||
chartRef: React.RefObject<IChartApi>;
|
||||
candleSeriesRef: React.RefObject<ISeriesApi<'Candlestick'>>;
|
||||
signals: SignalMarker[];
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Helper Functions
|
||||
// ============================================================================
|
||||
|
||||
function convertToLightweightMarkers(signals: SignalMarker[]): SeriesMarker<Time>[] {
|
||||
return signals.map((signal) => ({
|
||||
time: (signal.time / 1000) as Time,
|
||||
position: signal.position,
|
||||
color: signal.color,
|
||||
shape: signal.shape,
|
||||
text: signal.text,
|
||||
}));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Component
|
||||
// ============================================================================
|
||||
|
||||
export const SignalMarkers: React.FC<SignalMarkersProps> = ({
|
||||
chartRef,
|
||||
candleSeriesRef,
|
||||
signals,
|
||||
visible = true,
|
||||
}) => {
|
||||
const markersSetRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chartRef.current || !candleSeriesRef.current || !visible || signals.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const candleSeries = candleSeriesRef.current;
|
||||
|
||||
// Convert and set markers
|
||||
const markers = convertToLightweightMarkers(signals);
|
||||
candleSeries.setMarkers(markers);
|
||||
markersSetRef.current = true;
|
||||
|
||||
return () => {
|
||||
// Clear markers on cleanup
|
||||
if (markersSetRef.current && candleSeriesRef.current) {
|
||||
candleSeriesRef.current.setMarkers([]);
|
||||
markersSetRef.current = false;
|
||||
}
|
||||
};
|
||||
}, [chartRef, candleSeriesRef, signals, visible]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default SignalMarkers;
|
||||
13
src/modules/trading/components/charts/overlays/index.ts
Normal file
13
src/modules/trading/components/charts/overlays/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Chart Overlays - Barrel Export
|
||||
* Exports all ML chart overlay components
|
||||
*/
|
||||
|
||||
export { MLPredictionOverlay } from './MLPredictionOverlay';
|
||||
export type { MLPredictionOverlayProps } from './MLPredictionOverlay';
|
||||
|
||||
export { SignalMarkers } from './SignalMarkers';
|
||||
export type { SignalMarkersProps } from './SignalMarkers';
|
||||
|
||||
export { ICTConceptsOverlay } from './ICTConceptsOverlay';
|
||||
export type { ICTConceptsOverlayProps } from './ICTConceptsOverlay';
|
||||
106
src/types/mlOverlay.types.ts
Normal file
106
src/types/mlOverlay.types.ts
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* ML Overlay Types
|
||||
* Type definitions for ML predictions overlays on trading charts
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// ML Prediction Types
|
||||
// ============================================================================
|
||||
|
||||
export type PredictionType = 'buy' | 'sell' | 'neutral';
|
||||
|
||||
export interface MLPrediction {
|
||||
timestamp: number;
|
||||
price: number;
|
||||
confidence: number;
|
||||
type: PredictionType;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Signal Marker Types
|
||||
// ============================================================================
|
||||
|
||||
export type MarkerPosition = 'aboveBar' | 'belowBar';
|
||||
export type MarkerShape = 'arrowUp' | 'arrowDown' | 'circle';
|
||||
|
||||
export interface SignalMarker {
|
||||
time: number;
|
||||
position: MarkerPosition;
|
||||
color: string;
|
||||
text: string;
|
||||
shape: MarkerShape;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ICT Concept Types
|
||||
// ============================================================================
|
||||
|
||||
export type ICTConceptType = 'OrderBlock' | 'FVG' | 'Liquidity';
|
||||
|
||||
export interface ICTConcept {
|
||||
type: ICTConceptType;
|
||||
timeStart: number;
|
||||
timeEnd: number;
|
||||
priceTop: number;
|
||||
priceBottom: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Overlay Configuration Types
|
||||
// ============================================================================
|
||||
|
||||
export interface MLOverlayConfig {
|
||||
showPredictions: boolean;
|
||||
showSignals: boolean;
|
||||
showICTConcepts: boolean;
|
||||
predictionLineColor: string;
|
||||
predictionLineWidth: number;
|
||||
signalColors: {
|
||||
buy: string;
|
||||
sell: string;
|
||||
};
|
||||
ictColors: {
|
||||
OrderBlock: string;
|
||||
FVG: string;
|
||||
Liquidity: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const DEFAULT_OVERLAY_CONFIG: MLOverlayConfig = {
|
||||
showPredictions: true,
|
||||
showSignals: true,
|
||||
showICTConcepts: true,
|
||||
predictionLineColor: '#3b82f6',
|
||||
predictionLineWidth: 2,
|
||||
signalColors: {
|
||||
buy: '#10b981',
|
||||
sell: '#ef4444',
|
||||
},
|
||||
ictColors: {
|
||||
OrderBlock: '#3b82f6',
|
||||
FVG: '#fbbf24',
|
||||
Liquidity: '#f97316',
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// API Response Types
|
||||
// ============================================================================
|
||||
|
||||
export interface MLPredictionResponse {
|
||||
symbol: string;
|
||||
timeframe: string;
|
||||
predictions: MLPrediction[];
|
||||
signals: SignalMarker[];
|
||||
ictConcepts: ICTConcept[];
|
||||
generatedAt: string;
|
||||
}
|
||||
|
||||
export interface MLOverlayData {
|
||||
predictions: MLPrediction[];
|
||||
signals: SignalMarker[];
|
||||
ictConcepts: ICTConcept[];
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
lastUpdated: string | null;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user