Skip to content

Commit

Permalink
Add defaultFunding to nextFunding calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyding committed Jan 22, 2025
1 parent 518a769 commit ca96470
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface PerpetualMarketUpdateObject {
subticksPerTick?: number,
stepBaseQuantums?: number,
liquidityTierId?: number,
defaultFundingRate1H?: string,
}

export enum PerpetualMarketColumns {
Expand Down
26 changes: 20 additions & 6 deletions indexer/packages/redis/__tests__/caches/next-funding-cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ describe('nextFundingCache', () => {
await addFundingSample('BTC', new Big('0.0001'), client);
await addFundingSample('BTC', new Big('0.0002'), client); // avg = 0.00015
await addFundingSample('ETH', new Big('0.0005'), client); // avg = 0.0005
expect(await getNextFunding(client, ['BTC', 'ETH'])).toEqual(
{ BTC: new Big('0.00015'), ETH: new Big('0.0005') },
expect(await getNextFunding(client, [
['BTC', '0.0001'],
['ETH', '0'],
])).toEqual(
{
BTC: new Big('0.00025'), // 0.00015 + 0.0001
ETH: new Big('0.0005'), // 0.0005 + 0
},
);
});

Expand All @@ -27,14 +33,22 @@ describe('nextFundingCache', () => {
await addFundingSample('BTC', new Big('0.0002'), client); // avg = 0.00015
await clearFundingSamples('BTC', client);
await addFundingSample('ETH', new Big('0.0005'), client); // avg = 0.0005
expect(await getNextFunding(client, ['BTC', 'ETH'])).toEqual(
{ BTC: undefined, ETH: new Big('0.0005') },
expect(await getNextFunding(client, [
['BTC', '0.0001'],
['ETH', '0.00015'],
])).toEqual(
{
BTC: new Big('0.0001'), // no samples, default to 0.0001
ETH: new Big('0.00065'), // 0.0005 + 0.00015
},
);
});

it('get next funding with no values', async () => {
expect(await getNextFunding(client, ['BTC'])).toEqual(
{ BTC: undefined },
expect(await getNextFunding(client, [
['BTC', '0'],
])).toEqual(
{ BTC: new Big('0') },
);
});
});
Expand Down
12 changes: 6 additions & 6 deletions indexer/packages/redis/src/caches/next-funding-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ function getKey(ticker: string): string {
*/
export async function getNextFunding(
client: RedisClient,
tickers: string[],
): Promise<{ [ticker: string]: Big | undefined }> {
const fundingRates: { [ticker: string]: Big | undefined } = {};
tickerDefaultFundingRate1HPairs: [string, string][],
): Promise<{ [ticker: string]: Big }> {
const fundingRates: { [ticker: string]: Big } = {};
await Promise.all(
tickers.map(async (ticker: string) => {
tickerDefaultFundingRate1HPairs.map(async ([ticker, defaultFundingRate1H]) => {
const rates: string[] = await lRangeAsync(
getKey(ticker),
client,
Expand All @@ -36,9 +36,9 @@ export async function getNextFunding(
new Big(0),
);
const avg: Big = sum.div(rates.length);
fundingRates[ticker] = avg;
fundingRates[ticker] = avg.plus(new Big(defaultFundingRate1H));
} else {
fundingRates[ticker] = undefined;
fundingRates[ticker] = new Big(defaultFundingRate1H);
}
}),
);
Expand Down
68 changes: 57 additions & 11 deletions indexer/services/ender/__tests__/handlers/funding-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FundingIndexUpdatesColumns,
FundingIndexUpdatesFromDatabase,
FundingIndexUpdatesTable,
PerpetualMarketTable,
OraclePriceTable,
Ordering,
perpetualMarketRefresher,
Expand Down Expand Up @@ -42,6 +43,7 @@ import Big from 'big.js';
import { redisClient } from '../../src/helpers/redis/redis-controller';
import { bigIntToBytes } from '@dydxprotocol-indexer/v4-proto-parser';
import { createPostgresFunctions } from '../../src/helpers/postgres/postgres-functions';
import { defaultPerpetualMarket } from '@dydxprotocol-indexer/postgres/build/__tests__/helpers/constants';

describe('fundingHandler', () => {
beforeAll(async () => {
Expand Down Expand Up @@ -127,10 +129,54 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
defaultFundingUpdateSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
);
});

it.each([
[
'Non-zero Default funding',
'TEST-USD',
'0.0001',
],
])('(%s) non-zero default funding rate', async (
_name: string,
ticker: string,
defaultFundingRate1H: string,
) => {
const testPerpetualMarket = await PerpetualMarketTable.create({
...defaultPerpetualMarket,
id: '1000', // Different id than `defaultPerpeptualMarket` to avoid conflict
ticker,
defaultFundingRate1H,
});

const fundingUpdateSampleEvent: FundingEventV1 = {
type: FundingEventV1_Type.TYPE_PREMIUM_SAMPLE,
updates: [
{
perpetualId: parseInt(testPerpetualMarket.id, 10),
fundingValuePpm: 120,
fundingIndex: bigIntToBytes(BigInt(0)),
},
],
};

const kafkaMessage: KafkaMessage = createKafkaMessageFromFundingEvents({
fundingEvents: [fundingUpdateSampleEvent],
height: defaultHeight,
time: defaultTime,
});

await onMessage(kafkaMessage);

await expectNextFundingRate(
new Big('0.000115'), // 0.000120 / 8 + default 0.0001
ticker,
defaultFundingRate1H,
);
});

Expand Down Expand Up @@ -160,14 +206,14 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big('0.000006875'),
'BTC-USD',
);
await expectNextFundingRate(
'ETH-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
fundingUpdateSampleEvent2.updates[1].fundingValuePpm,
)),
'ETH-USD',
);
});

Expand Down Expand Up @@ -204,10 +250,10 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
defaultFundingUpdateSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
);

const kafkaMessage2: KafkaMessage = createKafkaMessageFromFundingEvents({
Expand All @@ -218,8 +264,8 @@ describe('fundingHandler', () => {

await onMessage(kafkaMessage2);
await expectNextFundingRate(
new Big('0'),
'BTC-USD',
undefined,
);
const fundingIndices: FundingIndexUpdatesFromDatabase[] = await
FundingIndexUpdatesTable.findAll({}, [], {});
Expand Down Expand Up @@ -253,10 +299,10 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
defaultFundingUpdateSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
);

const kafkaMessage2: KafkaMessage = createKafkaMessageFromFundingEvents({
Expand All @@ -267,8 +313,8 @@ describe('fundingHandler', () => {

await onMessage(kafkaMessage2);
await expectNextFundingRate(
new Big(0),
'BTC-USD',
undefined,
);
const fundingIndices: FundingIndexUpdatesFromDatabase[] = await
FundingIndexUpdatesTable.findAll({}, [], {});
Expand Down Expand Up @@ -310,16 +356,16 @@ describe('fundingHandler', () => {

await Promise.all([
expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
fundingSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
),
expectNextFundingRate(
'ETH-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
fundingSampleEvent.updates[1].fundingValuePpm,
)),
'ETH-USD',
),
]);

Expand Down Expand Up @@ -347,12 +393,12 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage2);
await Promise.all([
expectNextFundingRate(
new Big('0'),
'BTC-USD',
undefined,
),
expectNextFundingRate(
new Big('0'),
'ETH-USD',
undefined,
),
]);
const fundingIndices: FundingIndexUpdatesFromDatabase[] = await
Expand Down
9 changes: 5 additions & 4 deletions indexer/services/ender/__tests__/helpers/redis-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import Big from 'big.js';
import { redisClient } from '../../src/helpers/redis/redis-controller';

export async function expectNextFundingRate(
expectedRate: Big,
ticker: string,
rate: Big | undefined,
defaultFundingRate1H: string = '0',
): Promise<void> {
const rates: { [ticker: string]: Big | undefined } = await NextFundingCache.getNextFunding(
const rates: { [ticker: string]: Big } = await NextFundingCache.getNextFunding(
redisClient,
[ticker],
[[ticker, defaultFundingRate1H]],
);
expect(rates[ticker]).toEqual(rate);
expect(rates[ticker]).toEqual(expectedRate);
}

export async function expectStateFilledQuantums(
Expand Down
14 changes: 10 additions & 4 deletions indexer/services/roundtable/src/tasks/market-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@ export default async function runTask(): Promise<void> {
PerpetualMarketFromDatabase[] = await PerpetualMarketTable.findAll({}, []);
const perpetualMarketIds: string[] = _.map(perpetualMarkets, PerpetualMarketColumns.id);
const clobPairIds: string[] = _.map(perpetualMarkets, PerpetualMarketColumns.clobPairId);
const tickers: string[] = _.map(perpetualMarkets, PerpetualMarketColumns.ticker);
const tickerDefaultFundingRate1HPairs: [string, string][] = _.map(
perpetualMarkets,
(market) => [
market[PerpetualMarketColumns.ticker],
// Use 0 as default for null default funding rate
market[PerpetualMarketColumns.defaultFundingRate1H] ?? '0',
],
);
const latestPrices: PriceMap = await OraclePriceTable.getLatestPrices();
const prices24hAgo: PriceMap = await OraclePriceTable.getPricesFrom24hAgo();

Expand All @@ -65,13 +72,12 @@ export default async function runTask(): Promise<void> {
]: [
_.Dictionary<Market24HourTradeVolumes>,
_.Dictionary<MarketOpenInterest>,
_.Dictionary<Big | undefined>,
_.Dictionary<Big>,
] = await Promise.all([
// TODO(DEC-1149 Add support for pulling information from candles
FillTable.get24HourInformation(clobPairIds),
PerpetualPositionTable.getOpenInterestLong(perpetualMarketIds),
// TODO(CT-1340): Need to add default funding rate to this value.
NextFundingCache.getNextFunding(redisClient, tickers),
NextFundingCache.getNextFunding(redisClient, tickerDefaultFundingRate1HPairs),
]);

stats.timing(
Expand Down

0 comments on commit ca96470

Please sign in to comment.