feat: causal lab
This commit is contained in:
@@ -24,6 +24,12 @@ interface ChartEvent {
|
||||
description?: string
|
||||
}
|
||||
|
||||
interface TheoPoint {
|
||||
date: string
|
||||
cumulative_pips: number
|
||||
contributions: { template_name: string; event_name: string; event_date: string; pips: number; decay_factor: number }[]
|
||||
}
|
||||
|
||||
interface Props {
|
||||
priceData: PriceCandle[]
|
||||
indicators: Record<string, LinePoint[]>
|
||||
@@ -31,8 +37,11 @@ interface Props {
|
||||
height?: number
|
||||
chartType?: 'candles' | 'line'
|
||||
onDateHover?: (date: string | null) => void
|
||||
theoryCurve?: TheoPoint[]
|
||||
}
|
||||
|
||||
export type { TheoPoint }
|
||||
|
||||
const MA_COLORS: Record<string, string> = {
|
||||
ma20: '#f59e0b',
|
||||
ma50: '#3b82f6',
|
||||
@@ -58,7 +67,7 @@ const CAT_LABELS: Record<string, string> = {
|
||||
technical: 'Tech.',
|
||||
}
|
||||
|
||||
export default function InstrumentChart({ priceData, indicators, events = [], height = 420, chartType = 'candles', onDateHover }: Props) {
|
||||
export default function InstrumentChart({ priceData, indicators, events = [], height = 420, chartType = 'candles', onDateHover, theoryCurve }: Props) {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const cleanupRef = useRef<(() => void) | null>(null)
|
||||
const onHoverRef = useRef(onDateHover)
|
||||
@@ -173,6 +182,30 @@ export default function InstrumentChart({ priceData, indicators, events = [], he
|
||||
chart.addLineSeries(bbOpts).setData(indicators.bb_lower)
|
||||
}
|
||||
|
||||
// ── Theoretical curve — left scale (pips) ─────────────────────────────
|
||||
if (theoryCurve?.length) {
|
||||
chart.priceScale('left').applyOptions({
|
||||
visible: true,
|
||||
borderColor: 'rgba(167,139,250,0.25)',
|
||||
textColor: '#a78bfa',
|
||||
scaleMargins: { top: 0.1, bottom: 0.1 },
|
||||
})
|
||||
const theorySeries = chart.addLineSeries({
|
||||
color: 'rgba(167,139,250,0.75)',
|
||||
lineWidth: 1.5,
|
||||
priceScaleId: 'left',
|
||||
title: 'Δ pips théorique',
|
||||
priceLineVisible: false,
|
||||
lastValueVisible: true,
|
||||
crosshairMarkerVisible: true,
|
||||
crosshairMarkerRadius: 3,
|
||||
})
|
||||
const theoryData = theoryCurve
|
||||
.filter(p => p.contributions.length > 0)
|
||||
.map(p => ({ time: p.date as any, value: p.cumulative_pips }))
|
||||
if (theoryData.length) theorySeries.setData(theoryData)
|
||||
}
|
||||
|
||||
chart.timeScale().fitContent()
|
||||
|
||||
// ── Star overlay — ★ icons positioned via chart coordinate API ────────
|
||||
@@ -293,7 +326,7 @@ export default function InstrumentChart({ priceData, indicators, events = [], he
|
||||
cleanupRef.current?.()
|
||||
cleanupRef.current = null
|
||||
}
|
||||
}, [priceData, indicators, events, height, chartType])
|
||||
}, [priceData, indicators, events, height, chartType, theoryCurve])
|
||||
|
||||
return (
|
||||
<div className="bg-dark-900/60 rounded-xl border border-slate-700/40 overflow-hidden">
|
||||
@@ -307,6 +340,12 @@ export default function InstrumentChart({ priceData, indicators, events = [], he
|
||||
<span className="flex items-center gap-1.5 opacity-40">
|
||||
<span className="inline-block w-5 border-t border-dashed border-slate-400" />BB(20,2)
|
||||
</span>
|
||||
{theoryCurve?.some(p => p.contributions.length > 0) && (
|
||||
<span className="flex items-center gap-1.5" style={{ color: '#a78bfa' }}>
|
||||
<span className="inline-block w-5 h-0.5 rounded" style={{ background: '#a78bfa' }} />
|
||||
Théorie (pips)
|
||||
</span>
|
||||
)}
|
||||
<span className="ml-auto flex items-center gap-2.5">
|
||||
{Object.entries(CAT_COLORS).map(([cat, c]) => (
|
||||
<span key={cat} className="flex items-center gap-0.5" style={{ color: c }}>
|
||||
|
||||
Reference in New Issue
Block a user