Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
pingustar committed Jan 24, 2024
1 parent b3eac0c commit 61acd51
Show file tree
Hide file tree
Showing 16 changed files with 400 additions and 74 deletions.
4 changes: 2 additions & 2 deletions src/libs/d3/charts/candlestick/Candlesticks.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ScaleBand, ScaleLinear } from 'd3';
import { D3ChartCandlestickData } from 'libs/d3';
import { CandlestickData } from 'libs/d3';

type CandlesticksProps = {
xScale: ScaleBand<string>;
yScale: ScaleLinear<number, number>;
data: D3ChartCandlestickData[];
data: CandlestickData[];
};

export function Candlesticks({ xScale, yScale, data }: CandlesticksProps) {
Expand Down
24 changes: 20 additions & 4 deletions src/libs/d3/charts/candlestick/D3ChartCandlestickWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { StrategyInputDispatch } from 'hooks/useStrategyInput';
import { SimChartWrapper } from 'libs/d3/sim/SimulatorChartWrapper';
import { SimulatorInputSearch } from 'libs/routing/routes/sim';
import { D3ChartCandlesticks } from './D3ChartCandlesticks';
import { useState } from 'react';
import { D3ChartSettingsProps, D3ChartCandlestickData } from './../../types';
import { D3ChartSettingsProps, CandlestickData } from './../../types';

type Props = {
data: D3ChartCandlestickData[];
data: CandlestickData[];
settings: D3ChartSettingsProps;
dispatch: StrategyInputDispatch;
state: SimulatorInputSearch;
};

const brushSize = 130;

export const D3ChartCandlestickWrapper = ({ data, settings }: Props) => {
export const D3ChartCandlestickWrapper = ({
data,
settings,
dispatch,
state,
}: Props) => {
const [brushExtent] = useState<[number, number]>();

if (!data.length) {
Expand All @@ -30,7 +39,14 @@ export const D3ChartCandlestickWrapper = ({ data, settings }: Props) => {

return (
<SimChartWrapper settings={settings}>
{(dms) => <D3ChartCandlesticks data={slicedData} dms={dms} />}
{(dms) => (
<D3ChartCandlesticks
state={state}
dispatch={dispatch}
data={data}
dms={dms}
/>
)}
</SimChartWrapper>
);
};
33 changes: 30 additions & 3 deletions src/libs/d3/charts/candlestick/D3ChartCandlesticks.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { max, min, scaleBand, scaleLinear } from 'd3';
import { StrategyInputDispatch } from 'hooks/useStrategyInput';
import { DragablePriceRange } from 'libs/d3/charts/candlestick/DragablePriceRange';
import { XAxis } from 'libs/d3/charts/candlestick/xAxis';
import { YAxis } from 'libs/d3/charts/candlestick/yAxis';
import { SimulatorInputSearch } from 'libs/routing/routes/sim';
import { useCallback } from 'react';
import { Candlesticks } from './Candlesticks';
import { D3ChartCandlestickData, D3ChartSettings } from 'libs/d3';
import { CandlestickData, D3ChartSettings } from 'libs/d3';

interface Props {
dms: D3ChartSettings;
data: D3ChartCandlestickData[];
data: CandlestickData[];
dispatch: StrategyInputDispatch;
state: SimulatorInputSearch;
}

export const D3ChartCandlesticks = ({ dms, data }: Props) => {
export const D3ChartCandlesticks = ({ dms, data, dispatch, state }: Props) => {
const xScale = scaleBand()
.domain(data.map((d) => d.date.toString()))
.range([0, dms.boundedWidth])
Expand All @@ -23,11 +29,32 @@ export const D3ChartCandlesticks = ({ dms, data }: Props) => {
.rangeRound([dms.boundedHeight, 0])
.nice();

const handleDrag = useCallback(
(key: keyof SimulatorInputSearch, value: number) => {
dispatch(key, yScale.invert(value).toString());
},
[dispatch, yScale]
);

return (
<>
<Candlesticks xScale={xScale} yScale={yScale} data={data} />
<YAxis yScale={yScale} />
<XAxis xScale={xScale} dms={dms} />
<DragablePriceRange
type="buy"
yScale={yScale}
onDrag={handleDrag}
state={state}
dms={dms}
/>
<DragablePriceRange
type="sell"
yScale={yScale}
onDrag={handleDrag}
state={state}
dms={dms}
/>
</>
);
};
177 changes: 177 additions & 0 deletions src/libs/d3/charts/candlestick/DragablePriceRange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { drag, ScaleLinear, select } from 'd3';
import { D3ChartSettings } from 'libs/d3/types';
import { SimulatorInputSearch } from 'libs/routing/routes/sim';
import { useEffect, useRef } from 'react';

const dragAccessor2 = function (this: Element) {
const me = select(this);
const line = me.select('line');
return {
y: Number(line.attr('y1')),
};
};

const dragAccessor = function (this: Element) {
const me = select(this);
return {
y: Number(me.attr('y')),
height: Number(me.attr('height')),
};
};

type OrderRangeProps = {
type: 'buy' | 'sell';
yScale: ScaleLinear<number, number>;
onDrag: (key: keyof SimulatorInputSearch, value: number) => void;
state: SimulatorInputSearch;
dms: D3ChartSettings;
};

export const DragablePriceRange = ({
type,
yScale,
onDrag,
state,
dms: { boundedWidth },
}: OrderRangeProps) => {
const isHovering = useRef(false);
const buyRectRef = useRef<SVGRectElement>(null);
const buyUpperLineRef = useRef<SVGLineElement>(null);
const buyLowerLineRef = useRef<SVGLineElement>(null);

const dragRect = drag()
.subject(dragAccessor)
.on('drag', function ({ y, subject: { height } }) {
const me = select(this);
const upperLine = select(buyUpperLineRef.current).select('line');
const upperHandle = select(buyUpperLineRef.current).select('rect');
const lowerLine = select(buyLowerLineRef.current).select('line');
const lowerHandle = select(buyLowerLineRef.current).select('rect');

me.attr('y', y);
upperHandle.attr('y', y);
upperLine.attr('y1', y).attr('y2', y);
lowerLine.attr('y1', y + height).attr('y2', y + height);
lowerHandle.attr('y', y + height);
onDrag(`${type}Max`, y);
onDrag(`${type}Min`, y + height);
});

const dragUpperLine = drag()
.subject(dragAccessor2)
.on('drag', function ({ y }) {
const me = select(this);
const handle = me.select('rect');
const upper = me.select('line');
const rect = select(buyRectRef.current);
const lower = select(buyLowerLineRef.current).select('line');

const lowerY = Number(lower.attr('y1'));

handle.attr('y', y);
rect.attr('y', y).attr('height', lowerY - y);
upper.attr('y1', y).attr('y2', y);
onDrag(`${type}Max`, y);
});

const dragLowerLine = drag()
.subject(dragAccessor2)
.on('drag', function ({ y }) {
const me = select(this);
const handle = me.select('rect');
const lower = me.select('line');
const upper = select(buyUpperLineRef.current).select('line');
const rect = select(buyRectRef.current);

const upperY = Number(upper.attr('y1'));

rect.attr('height', y - upperY);
handle.attr('y', y);
lower.attr('y1', y).attr('y2', y);
onDrag(`${type}Min`, y);
});

useEffect(() => {
// @ts-ignore
dragRect(select(buyRectRef.current));
// @ts-ignore
dragUpperLine(select(buyUpperLineRef.current));
// @ts-ignore
dragLowerLine(select(buyLowerLineRef.current));
}, []);

const color = type === 'buy' ? 'green' : 'red';

const handleDimensions = {
width: 40,
height: 20,
};

const max = state[`${type}Max`];
const min = state[`${type}Min`];

useEffect(() => {
if (!isHovering.current && max) {
const y = yScale(Number(max));
const me = select(buyUpperLineRef.current);
const handle = me.select('rect');
const upper = me.select('line');
const rect = select(buyRectRef.current);
const lower = select(buyLowerLineRef.current).select('line');

const lowerY = Number(lower.attr('y1'));

handle.attr('y', y);
rect.attr('y', y).attr('height', lowerY - y);
upper.attr('y1', y).attr('y2', y);
}
}, [max, type, yScale]);

return (
<g
onMouseEnter={() => {
isHovering.current = true;
}}
onMouseLeave={() => {
isHovering.current = false;
}}
>
<rect
ref={buyRectRef}
height={30}
width={boundedWidth}
fill={color}
fillOpacity={0.5}
/>
<g ref={buyUpperLineRef}>
<line x1={0} x2={boundedWidth} stroke={color} strokeWidth={10} />
<rect
{...handleDimensions}
fill={color}
transform={`translate(-${handleDimensions.width},-${
handleDimensions.height / 2
})`}
/>
</g>

<g ref={buyLowerLineRef}>
<line
y1={35}
y2={35}
x1={0}
x2={boundedWidth}
stroke={color}
strokeWidth={10}
/>
<rect
{...handleDimensions}
y={35}
fill={color}
transform={`translate(-${handleDimensions.width},-${
handleDimensions.height / 2
})`}
/>
</g>
</g>
);
};
5 changes: 3 additions & 2 deletions src/libs/d3/charts/candlestick/xAxis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ export const XAxis = ({ xScale, dms }: Props) => {
style={{ textAnchor: 'middle' }}
dy=".71em"
y={dms.boundedHeight + 14}
fill="currentColor"
>
{new Date(Number(tickValue)).getDate()}/
{new Date(Number(tickValue)).getMonth() + 1}
{new Date(Number(tickValue) * 1000).getDate()}/
{new Date(Number(tickValue) * 1000).getMonth() + 1}
</text>
</g>
));
Expand Down
2 changes: 1 addition & 1 deletion src/libs/d3/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type {
D3ChartSettings,
D3ChartSettingsProps,
D3ChartCandlestickData,
CandlestickData,
} from './types';
export { D3ChartCandlestick } from './charts/candlestick';
export { D3ChartSimulatorBalance } from './sim/D3ChartSimulatorBalance';
Expand Down
4 changes: 2 additions & 2 deletions src/libs/d3/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export interface D3ChartSettings extends Required<D3ChartSettingsProps> {
boundedHeight: number;
}

export type D3ChartCandlestickData = {
export type CandlestickData = {
date: number;
volume: number;
// volume: number;
open: number;
close: number;
high: number;
Expand Down
4 changes: 2 additions & 2 deletions src/libs/queries/extApi/simulator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { QueryKey } from 'libs/queries/queryKey';
import { SimulatorSearch } from 'libs/routing';
import { SimulatorResultSearch } from 'libs/routing';
import { carbonApi } from 'utils/carbonApi';
import { FIVE_MIN_IN_MS } from 'utils/time';

Expand Down Expand Up @@ -54,7 +54,7 @@ export type SimulatorReturn = {
bounds: SimulatorBounds;
};

export const useGetSimulator = (params: SimulatorSearch) => {
export const useGetSimulator = (params: SimulatorResultSearch) => {
return useQuery<SimulatorReturn>(
QueryKey.simulator(params),
async () => {
Expand Down
36 changes: 36 additions & 0 deletions src/libs/queries/extApi/tokenPrice.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useQueries, useQuery } from '@tanstack/react-query';
import { CandlestickData } from 'libs/d3';
import { QueryKey } from 'libs/queries/queryKey';
import { FIVE_MIN_IN_MS } from 'utils/time';
import { useStore } from 'store';
Expand Down Expand Up @@ -47,3 +48,38 @@ export const useGetMultipleTokenPrices = (addresses: string[] = []) => {
}),
});
};

export type TokenPriceHistoryResult = {
timestamp: number;
open: string;
close: string;
high: string;
low: string;
};

export interface TokenPriceHistorySearch {
baseToken: string;
quoteToken: string;
start: number;
end: number;
}

export const useGetTokenPriceHistory = (params: TokenPriceHistorySearch) => {
return useQuery<CandlestickData[]>(
QueryKey.tokenPriceHistory(params),
async () => {
const data = await carbonApi.getMarketRateHistory(params);

return data.map((item) => ({
date: item.timestamp,
open: Number(item.open),
close: Number(item.close),
high: Number(item.high),
low: Number(item.low),
}));
},
{
staleTime: FIVE_MIN_IN_MS,
}
);
};
Loading

0 comments on commit 61acd51

Please sign in to comment.