Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions indexer/packages/postgres/__tests__/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ export const defaultPerpetualPosition: PerpetualPositionCreateObject = {
openEventId: defaultTendermintEventId,
lastEventId: defaultTendermintEventId2,
settledFunding: '200000',
totalRealizedPnl: '100',
};

export const defaultPerpetualPositionId: string = PerpetualPositionTable.uuid(
Expand All @@ -564,6 +565,7 @@ export const isolatedPerpetualPosition: PerpetualPositionCreateObject = {
openEventId: defaultTendermintEventId,
lastEventId: defaultTendermintEventId2,
settledFunding: '200000',
totalRealizedPnl: '100',
};

export const isolatedPerpetualPositionId: string = PerpetualPositionTable.uuid(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as Knex from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable('perpetual_positions', (table) => {
table.decimal('totalRealizedPnl', null).nullable();
});

await knex.schema.alterTable('fills', (table) => {
table.decimal('positionSizeBefore', null).nullable();
table.decimal('entryPriceBefore', null).nullable();
table.enum('positionSideBefore', [
'LONG',
'SHORT',
]).nullable().defaultTo(null);
});
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable('perpetual_positions', (table) => {
table.dropColumn('totalRealizedPnl');
});

await knex.schema.alterTable('fills', (table) => {
table.dropColumn('positionSizeBefore');
table.dropColumn('entryPriceBefore');
table.dropColumn('positionSideBefore');
});
}
13 changes: 13 additions & 0 deletions indexer/packages/postgres/src/models/fill-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
IsoString,
Liquidity,
OrderSide,
PositionSide,
} from '../types';

export default class FillModel extends Model {
Expand Down Expand Up @@ -92,6 +93,9 @@ export default class FillModel extends Model {
builderAddress: { type: ['string', 'null'], default: null },
orderRouterAddress: { type: ['string', 'null'], default: null },
orderRouterFee: { type: ['string', 'null'], default: null },
positionSizeBefore: { type: ['string', 'null'], pattern: NumericPattern, default: null },
entryPriceBefore: { type: ['string', 'null'], pattern: NonNegativeNumericPattern, default: null },
positionSideBefore: { type: ['string', 'null'], enum: [...Object.values(PositionSide), null], default: null },
},
};
}
Expand Down Expand Up @@ -125,6 +129,9 @@ export default class FillModel extends Model {
builderAddress: 'string',
orderRouterAddress: 'string',
orderRouterFee: 'string',
positionSizeBefore: 'string',
entryPriceBefore: 'string',
positionSideBefore: 'string',
};
}

Expand Down Expand Up @@ -169,4 +176,10 @@ export default class FillModel extends Model {
orderRouterAddress!: string;

orderRouterFee!: string;

positionSizeBefore?: string;

entryPriceBefore?: string;

positionSideBefore?: PositionSide;
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default class PerpetualPositionModel extends Model {
createdAtHeight: { type: 'string', pattern: IntegerPattern },
closedAtHeight: { type: ['string', 'null'], default: null, pattern: IntegerPattern },
settledFunding: { type: 'string', pattern: NumericPattern },
totalRealizedPnl: { type: ['string', 'null'], default: null, pattern: NumericPattern },
},
};
}
Expand Down Expand Up @@ -128,6 +129,7 @@ export default class PerpetualPositionModel extends Model {
closeEventId: 'hex-string',
lastEventId: 'hex-string',
settledFunding: 'string',
totalRealizedPnl: 'string',
};
}

Expand Down Expand Up @@ -168,4 +170,6 @@ export default class PerpetualPositionModel extends Model {
lastEventId!: Buffer;

settledFunding!: string;

totalRealizedPnl?: string;
}
4 changes: 4 additions & 0 deletions indexer/packages/postgres/src/types/db-model-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export interface PerpetualPositionFromDatabase extends IdBasedModelFromDatabase
closeEventId?: Buffer,
lastEventId: Buffer,
settledFunding: string,
totalRealizedPnl?: string,
}

export interface OrderFromDatabase extends IdBasedModelFromDatabase {
Expand Down Expand Up @@ -127,6 +128,9 @@ export interface FillFromDatabase {
builderFee?: string,
orderRouterAddress?: string,
orderRouterFee?: string,
positionSizeBefore?: string,
entryPriceBefore?: string,
positionSideBefore?: PositionSide,
}

export interface BlockFromDatabase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface PerpetualPositionCreateObject {
closedAtHeight?: string,
closeEventId?: Buffer,
exitPrice?: string,
totalRealizedPnl?: string,
}

export interface PerpetualPositionUpdateObject {
Expand All @@ -53,6 +54,7 @@ export interface PerpetualPositionUpdateObject {
closeEventId?: Buffer | null,
lastEventId?: Buffer,
settledFunding?: string,
totalRealizedPnl?: string,
}

// Object used to update a subaccount's perpetual position in the SubaccountUpdateHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,7 @@ describe('addresses-controller#V4', () => {
maxSize: testConstants.defaultPerpetualPosition.maxSize,
// 200000 + 10*(10000-10050)=199500
netFunding: getFixedRepresentation('199500'),
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// size * (index-entry) = 10*(15000-20000) = -50000
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
Expand Down Expand Up @@ -290,7 +287,7 @@ describe('addresses-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// size * (index-entry) = 10*(15000-20000) = -50000
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
Expand Down Expand Up @@ -483,7 +480,7 @@ describe('addresses-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// size * (index-entry) = 10*(15000-20000) = -50000
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('perpetual-positions-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (long position):
// index price = 15_000, entry price = 20_000, size = 10
// unrealizedPnl = size * (index price - entry price)
Expand Down Expand Up @@ -132,7 +132,7 @@ describe('perpetual-positions-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('200500'),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (short position):
// index price = 15_000, entry price = 20_000, size = -10
// unrealizedPnl = size * (index price - entry price)
Expand Down Expand Up @@ -180,9 +180,7 @@ describe('perpetual-positions-controller#V4', () => {
netFunding: getFixedRepresentation(
testConstants.defaultPerpetualPosition.settledFunding,
),
realizedPnl: getFixedRepresentation(
testConstants.defaultPerpetualPosition.settledFunding,
),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (short position):
// index price = 15_000, entry price = 20_000, size = 10
// unrealizedPnl = size * (index price - entry price)
Expand Down Expand Up @@ -293,7 +291,7 @@ describe('perpetual-positions-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (long position):
// index price = 15_000, entry price = 20_000, size = 10
// unrealizedPnl = size * (index price - entry price)
Expand Down Expand Up @@ -324,7 +322,7 @@ describe('perpetual-positions-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('202000'),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (short position):
// index price = 1, entry price = 1.5, size = -10
// unrealizedPnl = size * (index price - entry price)
Expand Down Expand Up @@ -382,9 +380,7 @@ describe('perpetual-positions-controller#V4', () => {
netFunding: getFixedRepresentation(
testConstants.defaultPerpetualPosition.settledFunding,
),
realizedPnl: getFixedRepresentation(
testConstants.defaultPerpetualPosition.settledFunding,
),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (short position):
// index price = 15_000, entry price = 20_000, size = 10
// unrealizedPnl = size * (index price - entry price)
Expand All @@ -409,9 +405,7 @@ describe('perpetual-positions-controller#V4', () => {
netFunding: getFixedRepresentation(
testConstants.isolatedPerpetualPosition.settledFunding,
),
realizedPnl: getFixedRepresentation(
testConstants.isolatedPerpetualPosition.settledFunding,
),
realizedPnl: getFixedRepresentation('100'),
// For the calculation of the unrealized pnl (short position):
// index price = 1, entry price = 1.5, size = -10
// unrealizedPnl = size * (index price - entry price)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ describe('vault-controller#V4', () => {
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// size * (index-entry) = 10*(15000-20000) = -50000
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
Expand Down Expand Up @@ -521,7 +521,7 @@ describe('vault-controller#V4', () => {
),
maxSize: testConstants.defaultPerpetualPosition.maxSize,
netFunding: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
sumOpen: testConstants.defaultPerpetualPosition.sumOpen,
Expand All @@ -543,7 +543,6 @@ describe('vault-controller#V4', () => {
},
{
equity: getFixedRepresentation(10000),
perpetualPosition: undefined,
assetPosition: {
symbol: testConstants.defaultAsset.symbol,
size: testConstants.defaultAssetPosition.size,
Expand Down
5 changes: 1 addition & 4 deletions indexer/services/comlink/__tests__/lib/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -807,10 +807,7 @@ describe('helpers', () => {
maxSize: testConstants.defaultPerpetualPosition.maxSize,
// 200000 + 10*(10000-10050)=199500
netFunding: getFixedRepresentation('199500'),
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('100'),
// size * (index-entry) = 10*(15000-20000) = -50000
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
Expand Down
23 changes: 19 additions & 4 deletions indexer/services/comlink/public/api-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,10 @@ fetch(`${baseURL}/fills?address=string&subaccountNumber=0.1`,
"builderFee": "string",
"builderAddress": "string",
"orderRouterAddress": "string",
"orderRouterFee": "string"
"orderRouterFee": "string",
"positionSizeBefore": "string",
"entryPriceBefore": "string",
"positionSideBefore": "string"
}
]
}
Expand Down Expand Up @@ -1431,7 +1434,10 @@ fetch(`${baseURL}/fills/parentSubaccount?address=string&parentSubaccountNumber=0
"builderFee": "string",
"builderAddress": "string",
"orderRouterAddress": "string",
"orderRouterFee": "string"
"orderRouterFee": "string",
"positionSizeBefore": "string",
"entryPriceBefore": "string",
"positionSideBefore": "string"
}
]
}
Expand Down Expand Up @@ -5625,7 +5631,10 @@ This operation does not require authentication
"builderFee": "string",
"builderAddress": "string",
"orderRouterAddress": "string",
"orderRouterFee": "string"
"orderRouterFee": "string",
"positionSizeBefore": "string",
"entryPriceBefore": "string",
"positionSideBefore": "string"
}

```
Expand Down Expand Up @@ -5653,6 +5662,9 @@ This operation does not require authentication
|builderAddress|string|false|none|none|
|orderRouterAddress|string|false|none|none|
|orderRouterFee|string|false|none|none|
|positionSizeBefore|string|false|none|none|
|entryPriceBefore|string|false|none|none|
|positionSideBefore|string|false|none|none|

## FillResponse

Expand Down Expand Up @@ -5686,7 +5698,10 @@ This operation does not require authentication
"builderFee": "string",
"builderAddress": "string",
"orderRouterAddress": "string",
"orderRouterFee": "string"
"orderRouterFee": "string",
"positionSizeBefore": "string",
"entryPriceBefore": "string",
"positionSideBefore": "string"
}
]
}
Expand Down
9 changes: 9 additions & 0 deletions indexer/services/comlink/public/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,15 @@
},
"orderRouterFee": {
"type": "string"
},
"positionSizeBefore": {
"type": "string"
},
"entryPriceBefore": {
"type": "string"
},
"positionSideBefore": {
"type": "string"
}
},
"required": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,8 @@ export function perpetualPositionToResponseObject(
marketsMap: MarketsMap,
subaccountNumber: number,
): PerpetualPositionResponseObject {
// Realized pnl is calculated from the difference in price between the average entry/exit price
// (order depending on side of the position) multiplied by amount of the position that was closed
// in addition to the funding payments.
const priceDiff: Big = (position.side === PositionSide.LONG)
? Big(position.exitPrice ?? 0).minus(position.entryPrice)
: Big(position.entryPrice).minus(position.exitPrice ?? 0);
const netFunding: Big = Big(position.settledFunding).plus(position.unsettledFunding);
const realizedPnl: string = priceDiff
.mul(position.sumClose)
.plus(netFunding)
.toFixed();
const realizedPnl: string = position.totalRealizedPnl ?? '0';

return {
market: perpetualMarketsMap[position.perpetualId].ticker,
Expand Down Expand Up @@ -169,6 +160,9 @@ export function fillToResponseObject(
builderAddress: fill.builderAddress ?? undefined,
orderRouterAddress: fill.orderRouterAddress ?? undefined,
orderRouterFee: fill.orderRouterFee ?? undefined,
positionSizeBefore: fill.positionSizeBefore ?? undefined,
entryPriceBefore: fill.entryPriceBefore ?? undefined,
positionSideBefore: fill.positionSideBefore ?? undefined,
};
}

Expand Down
3 changes: 3 additions & 0 deletions indexer/services/comlink/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ export interface FillResponseObject {
builderAddress?: string,
orderRouterAddress?: string,
orderRouterFee?: string,
positionSizeBefore?: string,
entryPriceBefore?: string,
positionSideBefore?: string,
}

/* ------- TRANSFER TYPES ------- */
Expand Down
Loading
Loading