feat(chart): candle build indicator as direction line #1
@@ -6,12 +6,13 @@ import ChartSideToolbar from './ChartSideToolbar';
|
||||
import ChartToolbar from './ChartToolbar';
|
||||
import TradingChart from './TradingChart';
|
||||
import type { FibAnchor, FibRetracement } from './FibRetracementPrimitive';
|
||||
import type { IChartApi } from 'lightweight-charts';
|
||||
import { LineStyle, type IChartApi } from 'lightweight-charts';
|
||||
import type { OverlayLayer } from './ChartPanel.types';
|
||||
|
||||
type Props = {
|
||||
candles: Candle[];
|
||||
indicators: ChartIndicators;
|
||||
dlobQuotes?: { bid: number | null; ask: number | null; mid: number | null } | null;
|
||||
timeframe: string;
|
||||
bucketSeconds: number;
|
||||
seriesKey: string;
|
||||
@@ -45,6 +46,7 @@ function isEditableTarget(t: EventTarget | null): boolean {
|
||||
export default function ChartPanel({
|
||||
candles,
|
||||
indicators,
|
||||
dlobQuotes,
|
||||
timeframe,
|
||||
bucketSeconds,
|
||||
seriesKey,
|
||||
@@ -61,6 +63,7 @@ export default function ChartPanel({
|
||||
const [fib, setFib] = useState<FibRetracement | null>(null);
|
||||
const [fibDraft, setFibDraft] = useState<FibRetracement | null>(null);
|
||||
const [layers, setLayers] = useState<OverlayLayer[]>([
|
||||
{ id: 'dlob-quotes', name: 'DLOB Quotes', visible: true, locked: false, opacity: 0.9 },
|
||||
{ id: 'drawings', name: 'Drawings', visible: true, locked: false, opacity: 1 },
|
||||
]);
|
||||
const [layersOpen, setLayersOpen] = useState(false);
|
||||
@@ -196,6 +199,37 @@ export default function ChartPanel({
|
||||
return Math.max(0, Math.min(1, v));
|
||||
}
|
||||
|
||||
const quotesLayer = useMemo(() => layers.find((l) => l.id === 'dlob-quotes'), [layers]);
|
||||
const quotesVisible = Boolean(quotesLayer?.visible);
|
||||
const quotesOpacity = clamp01(quotesLayer?.opacity ?? 1);
|
||||
|
||||
const priceLines = useMemo(() => {
|
||||
if (!quotesVisible) return [];
|
||||
return [
|
||||
{
|
||||
id: 'dlob-bid',
|
||||
title: 'DLOB Bid',
|
||||
price: dlobQuotes?.bid ?? null,
|
||||
color: `rgba(34,197,94,${quotesOpacity})`,
|
||||
lineStyle: LineStyle.Dotted,
|
||||
},
|
||||
{
|
||||
id: 'dlob-mid',
|
||||
title: 'DLOB Mid',
|
||||
price: dlobQuotes?.mid ?? null,
|
||||
color: `rgba(230,233,239,${quotesOpacity})`,
|
||||
lineStyle: LineStyle.Dashed,
|
||||
},
|
||||
{
|
||||
id: 'dlob-ask',
|
||||
title: 'DLOB Ask',
|
||||
price: dlobQuotes?.ask ?? null,
|
||||
color: `rgba(239,68,68,${quotesOpacity})`,
|
||||
lineStyle: LineStyle.Dotted,
|
||||
},
|
||||
];
|
||||
}, [dlobQuotes?.ask, dlobQuotes?.bid, dlobQuotes?.mid, quotesOpacity, quotesVisible]);
|
||||
|
||||
function updateLayer(layerId: string, patch: Partial<OverlayLayer>) {
|
||||
setLayers((prev) => prev.map((l) => (l.id === layerId ? { ...l, ...patch } : l)));
|
||||
}
|
||||
@@ -309,6 +343,7 @@ export default function ChartPanel({
|
||||
showBuild={showBuild}
|
||||
bucketSeconds={bucketSeconds}
|
||||
seriesKey={seriesKey}
|
||||
priceLines={priceLines}
|
||||
fib={fibRenderable}
|
||||
fibOpacity={fibEffectiveOpacity}
|
||||
fibSelected={fibSelected}
|
||||
|
||||
Reference in New Issue
Block a user