feat(visualizer): add build overlay toggle
Default is off so candles match production; enable via the new Build button when needed.
This commit is contained in:
@@ -107,6 +107,7 @@ function TradeApp({ user, onLogout }: { user: string; onLogout: () => void }) {
|
||||
const [pollMs, setPollMs] = useLocalStorageState('trade.pollMs', envNumber('VITE_POLL_MS', 1000));
|
||||
const [limit, setLimit] = useLocalStorageState('trade.limit', envNumber('VITE_LIMIT', 300));
|
||||
const [showIndicators, setShowIndicators] = useLocalStorageState('trade.showIndicators', true);
|
||||
const [showBuild, setShowBuild] = useLocalStorageState('trade.showBuild', false);
|
||||
const [tab, setTab] = useLocalStorageState<'orderbook' | 'trades'>('trade.sidebarTab', 'orderbook');
|
||||
const [bottomTab, setBottomTab] = useLocalStorageState<
|
||||
'positions' | 'orders' | 'balances' | 'orderHistory' | 'positionHistory'
|
||||
@@ -288,6 +289,8 @@ function TradeApp({ user, onLogout }: { user: string; onLogout: () => void }) {
|
||||
onTimeframeChange={setTf}
|
||||
showIndicators={showIndicators}
|
||||
onToggleIndicators={() => setShowIndicators((v) => !v)}
|
||||
showBuild={showBuild}
|
||||
onToggleBuild={() => setShowBuild((v) => !v)}
|
||||
seriesLabel={seriesLabel}
|
||||
/>
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ type Props = {
|
||||
onTimeframeChange: (tf: string) => void;
|
||||
showIndicators: boolean;
|
||||
onToggleIndicators: () => void;
|
||||
showBuild: boolean;
|
||||
onToggleBuild: () => void;
|
||||
seriesLabel: string;
|
||||
};
|
||||
|
||||
@@ -49,6 +51,8 @@ export default function ChartPanel({
|
||||
onTimeframeChange,
|
||||
showIndicators,
|
||||
onToggleIndicators,
|
||||
showBuild,
|
||||
onToggleBuild,
|
||||
seriesLabel,
|
||||
}: Props) {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
@@ -272,6 +276,8 @@ export default function ChartPanel({
|
||||
onTimeframeChange={onTimeframeChange}
|
||||
showIndicators={showIndicators}
|
||||
onToggleIndicators={onToggleIndicators}
|
||||
showBuild={showBuild}
|
||||
onToggleBuild={onToggleBuild}
|
||||
priceAutoScale={priceAutoScale}
|
||||
onTogglePriceAutoScale={() => setPriceAutoScale((v) => !v)}
|
||||
seriesLabel={seriesLabel}
|
||||
@@ -300,6 +306,7 @@ export default function ChartPanel({
|
||||
ema20={indicators.ema20}
|
||||
bb20={indicators.bb20}
|
||||
showIndicators={showIndicators}
|
||||
showBuild={showBuild}
|
||||
bucketSeconds={bucketSeconds}
|
||||
seriesKey={seriesKey}
|
||||
fib={fibRenderable}
|
||||
|
||||
@@ -5,6 +5,8 @@ type Props = {
|
||||
onTimeframeChange: (tf: string) => void;
|
||||
showIndicators: boolean;
|
||||
onToggleIndicators: () => void;
|
||||
showBuild: boolean;
|
||||
onToggleBuild: () => void;
|
||||
priceAutoScale: boolean;
|
||||
onTogglePriceAutoScale: () => void;
|
||||
seriesLabel: string;
|
||||
@@ -19,6 +21,8 @@ export default function ChartToolbar({
|
||||
onTimeframeChange,
|
||||
showIndicators,
|
||||
onToggleIndicators,
|
||||
showBuild,
|
||||
onToggleBuild,
|
||||
priceAutoScale,
|
||||
onTogglePriceAutoScale,
|
||||
seriesLabel,
|
||||
@@ -45,6 +49,9 @@ export default function ChartToolbar({
|
||||
<Button size="sm" variant={showIndicators ? 'primary' : 'ghost'} onClick={onToggleIndicators} type="button">
|
||||
Indicators
|
||||
</Button>
|
||||
<Button size="sm" variant={showBuild ? 'primary' : 'ghost'} onClick={onToggleBuild} type="button">
|
||||
Build
|
||||
</Button>
|
||||
<Button size="sm" variant={priceAutoScale ? 'primary' : 'ghost'} onClick={onTogglePriceAutoScale} type="button">
|
||||
Auto Scale
|
||||
</Button>
|
||||
|
||||
@@ -25,6 +25,7 @@ type Props = {
|
||||
ema20?: SeriesPoint[];
|
||||
bb20?: { upper: SeriesPoint[]; lower: SeriesPoint[]; mid: SeriesPoint[] };
|
||||
showIndicators: boolean;
|
||||
showBuild: boolean;
|
||||
bucketSeconds: number;
|
||||
seriesKey: string;
|
||||
fib?: FibRetracement | null;
|
||||
@@ -116,6 +117,7 @@ export default function TradingChart({
|
||||
ema20,
|
||||
bb20,
|
||||
showIndicators,
|
||||
showBuild,
|
||||
bucketSeconds,
|
||||
seriesKey,
|
||||
fib,
|
||||
@@ -596,12 +598,29 @@ export default function TradingChart({
|
||||
s.bbLower?.setData(bbLower);
|
||||
s.bbMid?.setData(bbMid);
|
||||
|
||||
s.build.applyOptions({ visible: showBuild });
|
||||
if (!showBuild) {
|
||||
buildSamplesRef.current.clear();
|
||||
buildKeyRef.current = seriesKey;
|
||||
lastBuildCandleStartRef.current = null;
|
||||
s.build.setData([]);
|
||||
}
|
||||
|
||||
if (buildKeyRef.current !== seriesKey) {
|
||||
buildSamplesRef.current.clear();
|
||||
buildKeyRef.current = seriesKey;
|
||||
lastBuildCandleStartRef.current = null;
|
||||
}
|
||||
|
||||
if (!showBuild) {
|
||||
s.sma20?.applyOptions({ visible: showIndicators });
|
||||
s.ema20?.applyOptions({ visible: showIndicators });
|
||||
s.bbUpper?.applyOptions({ visible: showIndicators });
|
||||
s.bbLower?.applyOptions({ visible: showIndicators });
|
||||
s.bbMid?.applyOptions({ visible: showIndicators });
|
||||
return;
|
||||
}
|
||||
|
||||
const bs = resolveBucketSeconds(bucketSeconds, candles);
|
||||
const eps = 1e-3;
|
||||
const maxPointsPerCandle = 600;
|
||||
@@ -714,7 +733,21 @@ export default function TradingChart({
|
||||
s.bbUpper?.applyOptions({ visible: showIndicators });
|
||||
s.bbLower?.applyOptions({ visible: showIndicators });
|
||||
s.bbMid?.applyOptions({ visible: showIndicators });
|
||||
}, [candleData, volumeData, oracleData, smaData, emaData, bbUpper, bbLower, bbMid, showIndicators, candles, bucketSeconds, seriesKey]);
|
||||
}, [
|
||||
candleData,
|
||||
volumeData,
|
||||
oracleData,
|
||||
smaData,
|
||||
emaData,
|
||||
bbUpper,
|
||||
bbLower,
|
||||
bbMid,
|
||||
showIndicators,
|
||||
showBuild,
|
||||
candles,
|
||||
bucketSeconds,
|
||||
seriesKey,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const s = seriesRef.current;
|
||||
|
||||
Reference in New Issue
Block a user