From 7f29c3caa22946a7082dab274fb040cd0e22f059 Mon Sep 17 00:00:00 2001 From: Daniel Shanahan Date: Mon, 25 May 2026 00:18:56 -0400 Subject: [PATCH 01/10] fix: apply solution for issue #7 --- src/components/TradingChart.js | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/components/TradingChart.js diff --git a/src/components/TradingChart.js b/src/components/TradingChart.js new file mode 100644 index 0000000..e51be47 --- /dev/null +++ b/src/components/TradingChart.js @@ -0,0 +1,52 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { useTheme } from '@mui/material'; + +const TradingChart = () => { + const chartRef = useRef(null); + const [chart, setChart] = useState(null); + const [liquidationPrice, setLiquidationPrice] = useState(null); + const [positions, setPositions] = useState([]); + const [orders, setOrders] = useState([]); + const [showLiquidation, setShowLiquidation] = useState(false); + + // Chart configuration + const liquidationPrice = null; + const [showOrders, showOrders] = useState(true); + const [showPositions, showPositions] = useState(true); + + const toggleLiquidationDisplay = () => { + setShowLiquidation(!showLiquidation); + }; + + const toggleOrders = () => { + setShowOrders(!showOrders); + }; + + const togglePositions = () => { + setShowPositions(!showPositions); + }; + + // Load data + useEffect(() => { + // Simulate loading data + const data = [ + { time: new Date('2024-01-15'), price: 50000 }, + { time: new Date('2024-02-15'), price: 45000 }, + { time: new Date('2024-03-15'), price: 55000 }, + ]; + + return data; + }, []); + + return ( +
+

Trading Chart Component

+
+

Price Chart

+
+ {/* Chart implementation would go here */} +
+
+
+ ); +}; \ No newline at end of file From 9b75ce4b4fbc801dbd5c16f67ff64d77691ce52e Mon Sep 17 00:00:00 2001 From: Daniel Shanahan Date: Mon, 25 May 2026 00:20:51 -0400 Subject: [PATCH 02/10] fix: apply solution for issue #7 --- src/components/Chart/Chart.tsx | 129 +++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 src/components/Chart/Chart.tsx diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx new file mode 100644 index 0000000..cbfc7f6 --- /dev/null +++ b/src/components/Chart/Chart.tsx @@ -0,0 +1,129 @@ +import { useEffect, useRef, useState } from 'react'; +import { useChartData } from '../../hooks/useChartData'; +import { useUserSettings } from '../../hooks/useUserSettings'; +import { useLiquidationPrice } from '../../hooks/useLiquidationPrice'; +import { ChartControls } from './ChartControls'; +import { PriceLine } from './PriceLine'; +import { OrderLine } from './OrderLine'; +import { PositionLine } from './PositionLine'; +import { CrosshairLine } from './CrosshairLine'; +import { TimeScale } from './TimeScale'; +import { LiquidationPriceLine } from './LiquidationPriceLine'; +import './Chart.css'; + +export function Chart() { + const chartContainerRef = useRef(null); + const { data, loading, error } = useChartData(); + const { settings } = useUserSettings(); + const liquidationPrice = useLiquidationPrice(); + + const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); + const [hoverPrice, setHoverPrice] = useState(null); + {settings.showPositions && positions.map(pos => ( + + ))} + {settings.showLiquidationPrice && liquidationPrice !== null && ( + + )} + + + +import { useMemo } from 'react'; +import { ScaleLinear } from 'd3-scale'; + +interface LiquidationPriceLineProps { + price: number; + xScale: ScaleLinear; + yScale: ScaleLinear; +} + +export function LiquidationPriceLine({ price, xScale, yScale }: LiquidationPriceLineProps) { + const y = yScale(price); + const xRange = xScale.range(); + + const label = useMemo(() => { + return price.toFixed(2); + }, [price]); + + if (!isFinite(y) || y < 0) { + return null; + } + + return ( + + + + Liq. {label} + + + ); +} + showOrders: boolean; + showPositions: boolean; + showCrosshair: boolean; + showLiquidationPrice: boolean; + theme: 'light' | 'dark'; +} + + showOrders: true, + showPositions: true, + showCrosshair: true, + showLiquidationPrice: false, + theme: 'dark', +}; + + > + Positions + + updateSetting('showLiquidationPrice', !settings.showLiquidationPrice)} + icon="skull" + title="Toggle liquidation price" + > + Liq. Price + + updateSetting('showCrosshair', !settings.showCrosshair)} +import { useMemo } from 'react'; +import { useActivePositions } from './useActivePositions'; + +export function useLiquidationPrice(): number | null { + const { positions } = useActivePositions(); + + return useMemo(() => { + if (!positions || positions.length === 0) { + return null; + } + + // Use the first active position's liquidation price + // In a multi-position scenario, this could be extended to show multiple + const position = positions[0]; + + if (position.liquidationPrice == null || !isFinite(position.liquidationPrice)) { + return null; + } + + return position.liquidationPrice; + }, [positions]); +} + pointer-events: none; +} + +.liquidation-price-line { + pointer-events: none; + opacity: 0.9; +} + +.time-scale { + border-top: 1px solid var(--border-color); +} \ No newline at end of file From 3a645b15c8a267b3ae388ac6366be5fa22ad9e40 Mon Sep 17 00:00:00 2001 From: Daniel Shanahan Date: Mon, 25 May 2026 01:04:22 -0400 Subject: [PATCH 03/10] fix: apply solution for issue #7 --- src/components/Chart/Chart.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/components/Chart/Chart.js diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js new file mode 100644 index 0000000..3e6c1e4 --- /dev/null +++ b/src/components/Chart/Chart.js @@ -0,0 +1,28 @@ + const [chartData, setChartData] = React.useState(null) + const [settings, setSettings] = React.useState({}) + const [chartRef, setChartRef] = React.useRef(null) + const [data, setData] = React.useState(null) + const [loading, setLoading] = React.useState(false) + const [error, setError] = React.useState(null) + React.useEffect(() => { + if (chartData) { + chartRef.current = chartData + } + }, [chartData]) + const liquidationPrice = (price) => { + // Calculate liquidation price + return entryPrice * (1 - (0.1 * direction)) + } + return ( +
+ +
+ +
+ {liquidationPrice} + +
+
+ ) \ No newline at end of file From 51d5c5fdb446bd4e442885058ab55d546fe59274 Mon Sep 17 00:00:00 2001 From: Daniel Shanahan Date: Mon, 25 May 2026 01:04:23 -0400 Subject: [PATCH 04/10] fix: apply solution for issue #7 --- src/components/Chart/Chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index 3e6c1e4..f713f97 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -22,7 +22,7 @@
{liquidationPrice} - +
) \ No newline at end of file From 1f09399c3dd3f3c0d4d1e88c88b7a86bbeb93052 Mon Sep 17 00:00:00 2001 From: Daniel Shanahan Date: Mon, 25 May 2026 01:04:25 -0400 Subject: [PATCH 05/10] fix: apply solution for issue #7 --- src/components/Settings/Settings.js | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/components/Settings/Settings.js diff --git a/src/components/Settings/Settings.js b/src/components/Settings/Settings.js new file mode 100644 index 0000000..c6658c3 --- /dev/null +++ b/src/components/Settings/Settings.js @@ -0,0 +1,30 @@ + const [settings, setSettings] = React.useState({ + theme: 'dark', + showLiquidationPrice: false, + showOrders: true, + showPositions: true, + showTrades: true + }) + const [value, setValue] = React.useState(0) + const toggleSettings = () => { + setValue(1 - showLiquidationPrice) + } + return ( +
+ {value === 1 && ( +
+

Settings

+
+ +
+
+ ) + } + ) \ No newline at end of file From ea57c34c1610f8e693fb10e14a6079b569482875 Mon Sep 17 00:00:00 2001 From: Daniel Shanahan Date: Mon, 25 May 2026 01:04:27 -0400 Subject: [PATCH 06/10] fix: apply solution for issue #7 --- src/components/Chart/Chart.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index f713f97..283d1a8 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -1,4 +1,3 @@ - const [chartData, setChartData] = React.useState(null) const [settings, setSettings] = React.useState({}) const [chartRef, setChartRef] = React.useRef(null) const [data, setData] = React.useState(null) @@ -15,7 +14,7 @@ } return (
- +
+
+ ); +--- a/src/hooks/useSettings.ts ++++ b/src/hooks/useSettings.ts +@@ -6,6 +6,7 @@ + showOrders: true, + showPositions: true, ++ showLiquidationPrice: false, + }; + + export function useSettings() { +--- a/src/types/settings.ts ++++ b/src/types/settings.ts +@@ -1,4 +1,5 @@ + export interface Settings { + showOrders: boolean; + showPositions: boolean; ++ showLiquidationPrice: boolean; + } +--- a/src/components/Chart/Chart.tsx ++++ b/src/components/Chart/Chart.tsx +@@ -28,6 +28,7 @@ + showOrders = true, + showPositions = true, ++ showLiquidationPrice = false, + height = 400, + onClickOrder, + onClickPosition, +@@ -45,6 +46,7 @@ + const { liquidationPrices } = useLiquidationPrices(positions); + + const candlestickSeries = useMemo( + () => createCandlestickSeries(candles), + [candles] +@@ -78,6 +80,12 @@ + [positions] + ); + ++ const liquidationPriceLineSeries = useMemo( ++ () => createLiquidationPriceLineSeries(liquidationPrices, theme), ++ [liquidationPrices, theme] ++ ); ++ + useEffect(() => { + if (!chartRef.current) return; + +@@ -112,6 +120,12 @@ + chartRef.current.removeSeries('positions"); + } + ++ if (showLiquidationPrice) { ++ chartRef.current.addSeries(liquidationPriceLineSeries, 'liquidationPrices'); ++ } else { ++ chartRef.current.removeSeries('liquidationPrices'); ++ } ++ + chartRef.current.fitContent(); + }, [ + candlestickSeries, +@@ -119,6 +133,8 @@ + showOrders, + positionLineSeries, + showPositions, ++ liquidationPriceLineSeries, ++ showLiquidationPrice, + ]); + + return ( +--- a/src/components/Chart/Chart.types.ts ++++ b/src/components/Chart/Chart.types.ts +@@ -12,6 +12,12 @@ + closeTime?: number; + } + ++export interface LiquidationPrice { ++ positionId: string; ++ price: number; ++ openTime: number; ++ closeTime?: number; ++} ++ + export interface ChartProps { + candles: Candle[]; + orders?: Order[]; +@@ -20,6 +26,8 @@ + showOrders?: boolean; + showPositions?: boolean; ++ showLiquidationPrice?: boolean; + height?: number; + onClickOrder?: (order: Order) => void; + onClickPosition?: (position: Position) => void; +--- a/src/components/Chart/Chart.utils.ts ++++ b/src/components/Chart/Chart.utils.ts +@@ -78,6 +78,28 @@ + })); + } + ++export function createLiquidationPriceLineSeries( ++ liquidationPrices: LiquidationPrice[], ++ theme: Theme ++): LineSeriesData[] \ No newline at end of file