chore: use previous groupings for calc
This commit is contained in:
@@ -24,13 +24,13 @@ import {
|
|||||||
SubscriberLookup,
|
SubscriberLookup,
|
||||||
addMarketSlotToResponse,
|
addMarketSlotToResponse,
|
||||||
addOracletoResponse,
|
addOracletoResponse,
|
||||||
aggregatePrices,
|
|
||||||
l2WithBNToStrings,
|
l2WithBNToStrings,
|
||||||
parsePositiveIntArray,
|
parsePositiveIntArray,
|
||||||
|
publishGroupings,
|
||||||
} from '../utils/utils';
|
} from '../utils/utils';
|
||||||
import { setHealthStatus, HEALTH_STATUS } from '../core/metrics';
|
import { setHealthStatus, HEALTH_STATUS } from '../core/metrics';
|
||||||
|
|
||||||
type wsMarketArgs = {
|
export type wsMarketArgs = {
|
||||||
marketIndex: number;
|
marketIndex: number;
|
||||||
marketType: MarketType;
|
marketType: MarketType;
|
||||||
marketName: string;
|
marketName: string;
|
||||||
@@ -39,12 +39,11 @@ type wsMarketArgs = {
|
|||||||
numVammOrders?: number;
|
numVammOrders?: number;
|
||||||
fallbackL2Generators?: L2OrderBookGenerator[];
|
fallbackL2Generators?: L2OrderBookGenerator[];
|
||||||
updateOnChange?: boolean;
|
updateOnChange?: boolean;
|
||||||
tickSize?: BN
|
tickSize?: BN;
|
||||||
};
|
};
|
||||||
|
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
export const GROUPING_OPTIONS = [1, 10, 100, 500, 1000];
|
|
||||||
const PERP_MAKRET_STALENESS_THRESHOLD = 30 * 60 * 1000;
|
const PERP_MAKRET_STALENESS_THRESHOLD = 30 * 60 * 1000;
|
||||||
const SPOT_MAKRET_STALENESS_THRESHOLD = 60 * 60 * 1000;
|
const SPOT_MAKRET_STALENESS_THRESHOLD = 60 * 60 * 1000;
|
||||||
const STALE_ORACLE_REMOVE_VAMM_THRESHOLD = 160;
|
const STALE_ORACLE_REMOVE_VAMM_THRESHOLD = 160;
|
||||||
@@ -120,7 +119,7 @@ export class DLOBSubscriberIO extends DLOBSubscriber {
|
|||||||
includeVamm,
|
includeVamm,
|
||||||
updateOnChange: false,
|
updateOnChange: false,
|
||||||
fallbackL2Generators: [],
|
fallbackL2Generators: [],
|
||||||
tickSize: perpMarket?.amm?.orderTickSize ?? ONE
|
tickSize: perpMarket?.amm?.orderTickSize ?? ONE,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (const market of config.spotMarketInfos) {
|
for (const market of config.spotMarketInfos) {
|
||||||
@@ -135,7 +134,8 @@ export class DLOBSubscriberIO extends DLOBSubscriber {
|
|||||||
config.spotMarketSubscribers[market.marketIndex].phoenix,
|
config.spotMarketSubscribers[market.marketIndex].phoenix,
|
||||||
config.spotMarketSubscribers[market.marketIndex].openbook,
|
config.spotMarketSubscribers[market.marketIndex].openbook,
|
||||||
].filter((a) => !!a),
|
].filter((a) => !!a),
|
||||||
tickSize: config.spotMarketSubscribers[market.marketIndex].tickSize ?? ONE
|
tickSize:
|
||||||
|
config.spotMarketSubscribers[market.marketIndex].tickSize ?? ONE,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,30 +399,15 @@ export class DLOBSubscriberIO extends DLOBSubscriber {
|
|||||||
}`,
|
}`,
|
||||||
l2Formatted_depth100
|
l2Formatted_depth100
|
||||||
);
|
);
|
||||||
|
|
||||||
GROUPING_OPTIONS.forEach(group => {
|
|
||||||
const pricePrecision = BigNum.from(group).mul(marketArgs.tickSize).toNum()
|
|
||||||
const aggregatedBids = aggregatePrices(l2Formatted.bids, 'bid', pricePrecision)
|
|
||||||
.sort((a, b) => b[0] - a[0])
|
|
||||||
.slice(0, 20)
|
|
||||||
|
|
||||||
const aggregatedAsks = aggregatePrices(l2Formatted.asks, 'ask', pricePrecision)
|
|
||||||
.sort((a, b) => a[0] - b[0])
|
|
||||||
.slice(0, 20)
|
|
||||||
|
|
||||||
const l2Formatted_grouped20 = Object.assign({}, l2Formatted, {
|
|
||||||
bids: aggregatedBids,
|
|
||||||
asks: aggregatedAsks,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.redisClient.publish(
|
|
||||||
`${clientPrefix}orderbook_${marketType}_${marketArgs.marketIndex}_grouped_${group}${
|
|
||||||
this.indicativeQuotesRedisClient ? '_indicative' : ''
|
|
||||||
}`,
|
|
||||||
l2Formatted_grouped20
|
|
||||||
);
|
|
||||||
})
|
|
||||||
|
|
||||||
|
publishGroupings(
|
||||||
|
l2Formatted,
|
||||||
|
marketArgs,
|
||||||
|
this.redisClient,
|
||||||
|
clientPrefix,
|
||||||
|
marketType,
|
||||||
|
this.indicativeQuotesRedisClient
|
||||||
|
);
|
||||||
|
|
||||||
if (!this.indicativeQuotesRedisClient) {
|
if (!this.indicativeQuotesRedisClient) {
|
||||||
const bids = this.dlob
|
const bids = this.dlob
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
BN,
|
BN,
|
||||||
|
BigNum,
|
||||||
DriftClient,
|
DriftClient,
|
||||||
DriftEnv,
|
DriftEnv,
|
||||||
L2Level,
|
|
||||||
L2OrderBook,
|
L2OrderBook,
|
||||||
L3OrderBook,
|
L3OrderBook,
|
||||||
MarketType,
|
MarketType,
|
||||||
@@ -21,6 +21,16 @@ import { logger } from './logger';
|
|||||||
import { NextFunction, Request, Response } from 'express';
|
import { NextFunction, Request, Response } from 'express';
|
||||||
import FEATURE_FLAGS from './featureFlags';
|
import FEATURE_FLAGS from './featureFlags';
|
||||||
import { Connection } from '@solana/web3.js';
|
import { Connection } from '@solana/web3.js';
|
||||||
|
import { wsMarketArgs } from 'src/dlob-subscriber/DLOBSubscriberIO';
|
||||||
|
|
||||||
|
export const GROUPING_OPTIONS = [1, 10, 100, 500, 1000];
|
||||||
|
export const GROUPING_DEPENDENCIES = {
|
||||||
|
1: null,
|
||||||
|
10: 1,
|
||||||
|
100: 10,
|
||||||
|
500: 100,
|
||||||
|
1000: 100,
|
||||||
|
};
|
||||||
|
|
||||||
export const l2WithBNToStrings = (l2: L2OrderBook): any => {
|
export const l2WithBNToStrings = (l2: L2OrderBook): any => {
|
||||||
for (const key of Object.keys(l2)) {
|
for (const key of Object.keys(l2)) {
|
||||||
@@ -181,7 +191,7 @@ export function aggregatePrices(entries, side, pricePrecision) {
|
|||||||
const price = parseFloat(entry.price);
|
const price = parseFloat(entry.price);
|
||||||
const data = {
|
const data = {
|
||||||
size: parseFloat(entry.size),
|
size: parseFloat(entry.size),
|
||||||
sources: entry.sources || {}
|
sources: entry.sources || {},
|
||||||
};
|
};
|
||||||
|
|
||||||
let bucketPrice, displayPrice;
|
let bucketPrice, displayPrice;
|
||||||
@@ -207,19 +217,85 @@ export function aggregatePrices(entries, side, pricePrecision) {
|
|||||||
bucketData.size += data.size;
|
bucketData.size += data.size;
|
||||||
|
|
||||||
if (data.sources) {
|
if (data.sources) {
|
||||||
Object.entries(data.sources).forEach(([sourceKey, sourceSize]: [string, string]) => {
|
Object.entries(data.sources).forEach(
|
||||||
if (!bucketData.sources[sourceKey]) {
|
([sourceKey, sourceSize]: [string, string]) => {
|
||||||
bucketData.sources[sourceKey] = 0;
|
if (!bucketData.sources[sourceKey]) {
|
||||||
|
bucketData.sources[sourceKey] = 0;
|
||||||
|
}
|
||||||
|
bucketData.sources[sourceKey] += parseFloat(sourceSize);
|
||||||
}
|
}
|
||||||
bucketData.sources[sourceKey] += parseFloat(sourceSize);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return Array.from(result.values());
|
return Array.from(result.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function publishGroupings(
|
||||||
|
l2Formatted,
|
||||||
|
marketArgs: wsMarketArgs,
|
||||||
|
redisClient: RedisClient,
|
||||||
|
clientPrefix: string,
|
||||||
|
marketType: string,
|
||||||
|
indicativeQuotesRedisClient: RedisClient
|
||||||
|
) {
|
||||||
|
const groupingResults = new Map();
|
||||||
|
|
||||||
|
GROUPING_OPTIONS.forEach((group) => {
|
||||||
|
const pricePrecision = BigNum.from(group).mul(marketArgs.tickSize).toNum();
|
||||||
|
const dependency = GROUPING_DEPENDENCIES[group];
|
||||||
|
|
||||||
|
let fullAggregatedBids, fullAggregatedAsks;
|
||||||
|
|
||||||
|
if (dependency && groupingResults.has(dependency)) {
|
||||||
|
const previousResults = groupingResults.get(dependency);
|
||||||
|
|
||||||
|
fullAggregatedBids = aggregatePrices(
|
||||||
|
previousResults.bids,
|
||||||
|
'bid',
|
||||||
|
pricePrecision
|
||||||
|
).sort((a, b) => b[0] - a[0]);
|
||||||
|
|
||||||
|
fullAggregatedAsks = aggregatePrices(
|
||||||
|
previousResults.asks,
|
||||||
|
'ask',
|
||||||
|
pricePrecision
|
||||||
|
).sort((a, b) => a[0] - b[0]);
|
||||||
|
} else {
|
||||||
|
fullAggregatedBids = aggregatePrices(
|
||||||
|
l2Formatted.bids,
|
||||||
|
'bid',
|
||||||
|
pricePrecision
|
||||||
|
).sort((a, b) => b[0] - a[0]);
|
||||||
|
|
||||||
|
fullAggregatedAsks = aggregatePrices(
|
||||||
|
l2Formatted.asks,
|
||||||
|
'ask',
|
||||||
|
pricePrecision
|
||||||
|
).sort((a, b) => a[0] - b[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupingResults.set(group, {
|
||||||
|
bids: fullAggregatedBids,
|
||||||
|
asks: fullAggregatedAsks,
|
||||||
|
});
|
||||||
|
|
||||||
|
const aggregatedBids = fullAggregatedBids.slice(0, 20);
|
||||||
|
const aggregatedAsks = fullAggregatedAsks.slice(0, 20);
|
||||||
|
const l2Formatted_grouped20 = Object.assign({}, l2Formatted, {
|
||||||
|
bids: aggregatedBids,
|
||||||
|
asks: aggregatedAsks,
|
||||||
|
});
|
||||||
|
|
||||||
|
redisClient.publish(
|
||||||
|
`${clientPrefix}orderbook_${marketType}_${
|
||||||
|
marketArgs.marketIndex
|
||||||
|
}_grouped_${group}${indicativeQuotesRedisClient ? '_indicative' : ''}`,
|
||||||
|
l2Formatted_grouped20
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes in a req.query like: `{
|
* Takes in a req.query like: `{
|
||||||
* marketName: 'SOL-PERP,BTC-PERP,ETH-PERP',
|
* marketName: 'SOL-PERP,BTC-PERP,ETH-PERP',
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ import express from 'express';
|
|||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
import { WebSocket, WebSocketServer } from 'ws';
|
import { WebSocket, WebSocketServer } from 'ws';
|
||||||
import { sleep, selectMostRecentBySlot } from './utils/utils';
|
import { sleep, selectMostRecentBySlot, GROUPING_OPTIONS } from './utils/utils';
|
||||||
import { register, Gauge, Counter } from 'prom-client';
|
import { register, Gauge, Counter } from 'prom-client';
|
||||||
import { DriftEnv, PerpMarkets, SpotMarkets } from '@drift-labs/sdk';
|
import { DriftEnv, PerpMarkets, SpotMarkets } from '@drift-labs/sdk';
|
||||||
import { RedisClient, RedisClientPrefix } from '@drift/common/clients';
|
import { RedisClient, RedisClientPrefix } from '@drift/common/clients';
|
||||||
import { GROUPING_OPTIONS } from './dlob-subscriber/DLOBSubscriberIO';
|
|
||||||
|
|
||||||
// Set up env constants
|
// Set up env constants
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|||||||
Reference in New Issue
Block a user