fix(market-depth): fix depth chart data upate, use market depth as mid price source (#3242)
This commit is contained in:
parent
faa359e2fb
commit
9f3026aa4b
@ -74,7 +74,7 @@ describe('updateLevels', () => {
|
|||||||
|
|
||||||
const updates = [{ price: '132', volume: '200' }];
|
const updates = [{ price: '132', volume: '200' }];
|
||||||
|
|
||||||
expect(updateLevels(priceLevels, updates, 2, 0, true)).toEqual([
|
expect(updateLevels(priceLevels, updates, 2, 0, false)).toEqual([
|
||||||
{ price: 1.35, volume: 200 },
|
{ price: 1.35, volume: 200 },
|
||||||
{ price: 1.32, volume: 200 },
|
{ price: 1.32, volume: 200 },
|
||||||
{ price: 1.28, volume: 100 },
|
{ price: 1.28, volume: 100 },
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { addDecimal } from '@vegaprotocol/utils';
|
import { addDecimal } from '@vegaprotocol/utils';
|
||||||
|
import uniqBy from 'lodash/uniqBy';
|
||||||
|
import reverse from 'lodash/reverse';
|
||||||
|
|
||||||
interface PriceLevel {
|
interface PriceLevel {
|
||||||
price: number;
|
price: number;
|
||||||
@ -41,9 +43,9 @@ export const updateLevels = (
|
|||||||
updates: RawPriceLevel[],
|
updates: RawPriceLevel[],
|
||||||
decimalPlaces: number,
|
decimalPlaces: number,
|
||||||
positionDecimalPlaces: number,
|
positionDecimalPlaces: number,
|
||||||
reverse = false
|
ascending = true
|
||||||
) => {
|
) => {
|
||||||
updates.forEach((update) => {
|
uniqBy(reverse(updates || []), 'price').forEach((update) => {
|
||||||
const updateLevel = parseLevel(
|
const updateLevel = parseLevel(
|
||||||
update,
|
update,
|
||||||
decimalPlaces,
|
decimalPlaces,
|
||||||
@ -63,9 +65,9 @@ export const updateLevels = (
|
|||||||
}
|
}
|
||||||
} else if (update.volume !== '0') {
|
} else if (update.volume !== '0') {
|
||||||
index = levels.findIndex((level) =>
|
index = levels.findIndex((level) =>
|
||||||
reverse
|
ascending
|
||||||
? level.price < updateLevel.price
|
? level.price > updateLevel.price
|
||||||
: level.price > updateLevel.price
|
: level.price < updateLevel.price
|
||||||
);
|
);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
levels.splice(index, 0, updateLevel);
|
levels.splice(index, 0, updateLevel);
|
||||||
|
@ -9,6 +9,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|||||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||||
import type { MarketData } from '@vegaprotocol/market-list';
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
import type {
|
import type {
|
||||||
|
MarketDepthQuery,
|
||||||
MarketDepthUpdateSubscription,
|
MarketDepthUpdateSubscription,
|
||||||
PriceLevelFieldsFragment,
|
PriceLevelFieldsFragment,
|
||||||
} from './__generated__/MarketDepth';
|
} from './__generated__/MarketDepth';
|
||||||
@ -22,6 +23,18 @@ interface DepthChartManagerProps {
|
|||||||
const formatMidPrice = (midPrice: string, decimalPlaces: number) =>
|
const formatMidPrice = (midPrice: string, decimalPlaces: number) =>
|
||||||
Number(addDecimal(midPrice, decimalPlaces));
|
Number(addDecimal(midPrice, decimalPlaces));
|
||||||
|
|
||||||
|
const getMidPrice = (
|
||||||
|
sell: PriceLevelFieldsFragment[] | null | undefined,
|
||||||
|
buy: PriceLevelFieldsFragment[] | null | undefined,
|
||||||
|
decimalPlaces: number
|
||||||
|
) =>
|
||||||
|
buy?.length && sell?.length
|
||||||
|
? formatMidPrice(
|
||||||
|
((BigInt(buy[0].price) + BigInt(sell[0].price)) / BigInt(2)).toString(),
|
||||||
|
decimalPlaces
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
type DepthData = Pick<DepthChartProps, 'data' | 'midPrice'>;
|
type DepthData = Pick<DepthChartProps, 'data' | 'midPrice'>;
|
||||||
|
|
||||||
export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
||||||
@ -30,6 +43,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
const [depthData, setDepthData] = useState<DepthData | null>(null);
|
const [depthData, setDepthData] = useState<DepthData | null>(null);
|
||||||
const dataRef = useRef<DepthData | null>(null);
|
const dataRef = useRef<DepthData | null>(null);
|
||||||
const marketDataRef = useRef<MarketData | null>(null);
|
const marketDataRef = useRef<MarketData | null>(null);
|
||||||
|
const rawDataRef = useRef<MarketDepthQuery['market'] | null>(null);
|
||||||
const deltaRef = useRef<{
|
const deltaRef = useRef<{
|
||||||
sell: PriceLevelFieldsFragment[];
|
sell: PriceLevelFieldsFragment[];
|
||||||
buy: PriceLevelFieldsFragment[];
|
buy: PriceLevelFieldsFragment[];
|
||||||
@ -56,28 +70,28 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
}
|
}
|
||||||
dataRef.current = {
|
dataRef.current = {
|
||||||
...dataRef.current,
|
...dataRef.current,
|
||||||
midPrice: marketDataRef.current?.staticMidPrice
|
midPrice: getMidPrice(
|
||||||
? formatMidPrice(
|
rawDataRef.current?.depth.sell,
|
||||||
marketDataRef.current?.staticMidPrice,
|
rawDataRef.current?.depth.buy,
|
||||||
market.decimalPlaces
|
market.decimalPlaces
|
||||||
)
|
),
|
||||||
: undefined,
|
|
||||||
data: {
|
data: {
|
||||||
buy: deltaRef.current.buy
|
buy: deltaRef.current.buy.length
|
||||||
? updateLevels(
|
? updateLevels(
|
||||||
dataRef.current.data.buy,
|
dataRef.current.data.buy,
|
||||||
deltaRef.current.buy,
|
deltaRef.current.buy,
|
||||||
market.decimalPlaces,
|
market.decimalPlaces,
|
||||||
market.positionDecimalPlaces,
|
market.positionDecimalPlaces,
|
||||||
true
|
false
|
||||||
)
|
)
|
||||||
: dataRef.current.data.buy,
|
: dataRef.current.data.buy,
|
||||||
sell: deltaRef.current.sell
|
sell: deltaRef.current.sell.length
|
||||||
? updateLevels(
|
? updateLevels(
|
||||||
dataRef.current.data.sell,
|
dataRef.current.data.sell,
|
||||||
deltaRef.current.sell,
|
deltaRef.current.sell,
|
||||||
market.decimalPlaces,
|
market.decimalPlaces,
|
||||||
market.positionDecimalPlaces
|
market.positionDecimalPlaces,
|
||||||
|
true
|
||||||
)
|
)
|
||||||
: dataRef.current.data.sell,
|
: dataRef.current.data.sell,
|
||||||
},
|
},
|
||||||
@ -85,16 +99,23 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
deltaRef.current.buy = [];
|
deltaRef.current.buy = [];
|
||||||
deltaRef.current.sell = [];
|
deltaRef.current.sell = [];
|
||||||
setDepthData(dataRef.current);
|
setDepthData(dataRef.current);
|
||||||
}, 1000),
|
}, 250),
|
||||||
[market]
|
[market]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
deltaRef.current.buy = [];
|
||||||
|
deltaRef.current.sell = [];
|
||||||
|
}, [marketId]);
|
||||||
|
|
||||||
// Apply updates to the table
|
// Apply updates to the table
|
||||||
const update = useCallback(
|
const update = useCallback(
|
||||||
({
|
({
|
||||||
delta: deltas,
|
delta: deltas,
|
||||||
|
data: rawData,
|
||||||
}: {
|
}: {
|
||||||
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'];
|
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'] | null;
|
||||||
|
data: NonNullable<MarketDepthQuery['market']> | null;
|
||||||
}) => {
|
}) => {
|
||||||
if (!dataRef.current) {
|
if (!dataRef.current) {
|
||||||
return false;
|
return false;
|
||||||
@ -109,6 +130,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
if (delta.buy) {
|
if (delta.buy) {
|
||||||
deltaRef.current.buy.push(...delta.buy);
|
deltaRef.current.buy.push(...delta.buy);
|
||||||
}
|
}
|
||||||
|
rawDataRef.current = rawData;
|
||||||
updateDepthData();
|
updateDepthData();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -116,7 +138,11 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
[marketId, updateDepthData]
|
[marketId, updateDepthData]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error, loading } = useDataProvider({
|
const { data, error, loading } = useDataProvider<
|
||||||
|
NonNullable<MarketDepthQuery['market']> | null,
|
||||||
|
MarketDepthUpdateSubscription['marketsDepthUpdate'],
|
||||||
|
{ marketId: string }
|
||||||
|
>({
|
||||||
dataProvider: marketDepthProvider,
|
dataProvider: marketDepthProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables,
|
||||||
@ -155,9 +181,11 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dataRef.current = {
|
dataRef.current = {
|
||||||
midPrice: marketData.staticMidPrice
|
midPrice: getMidPrice(
|
||||||
? formatMidPrice(marketData.staticMidPrice, market.decimalPlaces)
|
data.depth.sell,
|
||||||
: undefined,
|
data.depth.buy,
|
||||||
|
market.decimalPlaces
|
||||||
|
),
|
||||||
data: {
|
data: {
|
||||||
buy:
|
buy:
|
||||||
data.depth.buy?.map((priceLevel) =>
|
data.depth.buy?.map((priceLevel) =>
|
||||||
@ -177,8 +205,12 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
) ?? [],
|
) ?? [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
rawDataRef.current = data;
|
||||||
setDepthData(dataRef.current);
|
setDepthData(dataRef.current);
|
||||||
}, [data, marketData, market]);
|
return () => {
|
||||||
|
updateDepthData.cancel();
|
||||||
|
};
|
||||||
|
}, [data, marketData, market, updateDepthData]);
|
||||||
|
|
||||||
const volumeFormat = useCallback(
|
const volumeFormat = useCallback(
|
||||||
(volume: number) =>
|
(volume: number) =>
|
||||||
|
@ -75,6 +75,11 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
}, 250)
|
}, 250)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
deltaRef.current.buy = [];
|
||||||
|
deltaRef.current.sell = [];
|
||||||
|
}, [marketId]);
|
||||||
|
|
||||||
const update = useCallback(
|
const update = useCallback(
|
||||||
({
|
({
|
||||||
delta: deltas,
|
delta: deltas,
|
||||||
|
Loading…
Reference in New Issue
Block a user