fix(market-depth): fix depth chart data upate, use market depth as mid price source (#3242)

This commit is contained in:
Bartłomiej Głownia 2023-03-21 16:46:04 +01:00 committed by GitHub
parent faa359e2fb
commit 9f3026aa4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 23 deletions

View File

@ -74,7 +74,7 @@ describe('updateLevels', () => {
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.32, volume: 200 },
{ price: 1.28, volume: 100 },

View File

@ -1,4 +1,6 @@
import { addDecimal } from '@vegaprotocol/utils';
import uniqBy from 'lodash/uniqBy';
import reverse from 'lodash/reverse';
interface PriceLevel {
price: number;
@ -41,9 +43,9 @@ export const updateLevels = (
updates: RawPriceLevel[],
decimalPlaces: number,
positionDecimalPlaces: number,
reverse = false
ascending = true
) => {
updates.forEach((update) => {
uniqBy(reverse(updates || []), 'price').forEach((update) => {
const updateLevel = parseLevel(
update,
decimalPlaces,
@ -63,9 +65,9 @@ export const updateLevels = (
}
} else if (update.volume !== '0') {
index = levels.findIndex((level) =>
reverse
? level.price < updateLevel.price
: level.price > updateLevel.price
ascending
? level.price > updateLevel.price
: level.price < updateLevel.price
);
if (index !== -1) {
levels.splice(index, 0, updateLevel);

View File

@ -9,6 +9,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/market-list';
import type {
MarketDepthQuery,
MarketDepthUpdateSubscription,
PriceLevelFieldsFragment,
} from './__generated__/MarketDepth';
@ -22,6 +23,18 @@ interface DepthChartManagerProps {
const formatMidPrice = (midPrice: string, decimalPlaces: number) =>
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'>;
export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
@ -30,6 +43,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
const [depthData, setDepthData] = useState<DepthData | null>(null);
const dataRef = useRef<DepthData | null>(null);
const marketDataRef = useRef<MarketData | null>(null);
const rawDataRef = useRef<MarketDepthQuery['market'] | null>(null);
const deltaRef = useRef<{
sell: PriceLevelFieldsFragment[];
buy: PriceLevelFieldsFragment[];
@ -56,28 +70,28 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
}
dataRef.current = {
...dataRef.current,
midPrice: marketDataRef.current?.staticMidPrice
? formatMidPrice(
marketDataRef.current?.staticMidPrice,
market.decimalPlaces
)
: undefined,
midPrice: getMidPrice(
rawDataRef.current?.depth.sell,
rawDataRef.current?.depth.buy,
market.decimalPlaces
),
data: {
buy: deltaRef.current.buy
buy: deltaRef.current.buy.length
? updateLevels(
dataRef.current.data.buy,
deltaRef.current.buy,
market.decimalPlaces,
market.positionDecimalPlaces,
true
false
)
: dataRef.current.data.buy,
sell: deltaRef.current.sell
sell: deltaRef.current.sell.length
? updateLevels(
dataRef.current.data.sell,
deltaRef.current.sell,
market.decimalPlaces,
market.positionDecimalPlaces
market.positionDecimalPlaces,
true
)
: dataRef.current.data.sell,
},
@ -85,16 +99,23 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
deltaRef.current.buy = [];
deltaRef.current.sell = [];
setDepthData(dataRef.current);
}, 1000),
}, 250),
[market]
);
useEffect(() => {
deltaRef.current.buy = [];
deltaRef.current.sell = [];
}, [marketId]);
// Apply updates to the table
const update = useCallback(
({
delta: deltas,
data: rawData,
}: {
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'];
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'] | null;
data: NonNullable<MarketDepthQuery['market']> | null;
}) => {
if (!dataRef.current) {
return false;
@ -109,6 +130,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
if (delta.buy) {
deltaRef.current.buy.push(...delta.buy);
}
rawDataRef.current = rawData;
updateDepthData();
}
return true;
@ -116,7 +138,11 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
[marketId, updateDepthData]
);
const { data, error, loading } = useDataProvider({
const { data, error, loading } = useDataProvider<
NonNullable<MarketDepthQuery['market']> | null,
MarketDepthUpdateSubscription['marketsDepthUpdate'],
{ marketId: string }
>({
dataProvider: marketDepthProvider,
update,
variables,
@ -155,9 +181,11 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
return;
}
dataRef.current = {
midPrice: marketData.staticMidPrice
? formatMidPrice(marketData.staticMidPrice, market.decimalPlaces)
: undefined,
midPrice: getMidPrice(
data.depth.sell,
data.depth.buy,
market.decimalPlaces
),
data: {
buy:
data.depth.buy?.map((priceLevel) =>
@ -177,8 +205,12 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
) ?? [],
},
};
rawDataRef.current = data;
setDepthData(dataRef.current);
}, [data, marketData, market]);
return () => {
updateDepthData.cancel();
};
}, [data, marketData, market, updateDepthData]);
const volumeFormat = useCallback(
(volume: number) =>

View File

@ -75,6 +75,11 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
}, 250)
);
useEffect(() => {
deltaRef.current.buy = [];
deltaRef.current.sell = [];
}, [marketId]);
const update = useCallback(
({
delta: deltas,