@gainsnetwork/sdk 0.0.0-v10.rc10 → 0.0.0-v10.rc14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/markets/holdingFees/index.d.ts +46 -0
- package/lib/markets/holdingFees/index.js +105 -0
- package/lib/markets/holdingFees/types.d.ts +23 -0
- package/lib/markets/holdingFees/types.js +5 -0
- package/lib/markets/index.d.ts +1 -0
- package/lib/markets/index.js +1 -0
- package/lib/markets/oi/converter.d.ts +1 -2
- package/lib/markets/oi/converter.js +5 -6
- package/lib/markets/oi/index.d.ts +44 -5
- package/lib/markets/oi/index.js +63 -23
- package/lib/markets/oi/types.d.ts +3 -12
- package/lib/trade/fees/holdingFees/index.d.ts +46 -0
- package/lib/trade/fees/holdingFees/index.js +105 -0
- package/lib/trade/fees/holdingFees/types.d.ts +23 -0
- package/lib/trade/fees/holdingFees/types.js +5 -0
- package/lib/trade/fees/index.d.ts +1 -0
- package/lib/trade/fees/index.js +1 -0
- package/lib/trade/pnl/index.d.ts +12 -1
- package/lib/trade/pnl/index.js +24 -8
- package/lib/trade/pnl/types.d.ts +0 -1
- package/lib/trade/priceImpact/close/index.js +12 -9
- package/package.json +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dev Holding fees calculation utilities for v10+ markets
|
|
3
|
+
* @dev Combines funding fees and borrowing v2 fees
|
|
4
|
+
*/
|
|
5
|
+
import { FundingFeeParams, PairFundingFeeData, PairOiAfterV10 } from "../../trade/fees/fundingFees/types";
|
|
6
|
+
import { BorrowingFeeParams, PairBorrowingFeeData } from "../../trade/fees/borrowingV2/types";
|
|
7
|
+
export type HoldingFeeRates = {
|
|
8
|
+
longHourlyRate: number;
|
|
9
|
+
shortHourlyRate: number;
|
|
10
|
+
fundingFeeLongHourlyRate: number;
|
|
11
|
+
fundingFeeShortHourlyRate: number;
|
|
12
|
+
borrowingFeeHourlyRate: number;
|
|
13
|
+
currentFundingRatePerSecondP: number;
|
|
14
|
+
currentBorrowingRatePerSecondP: number;
|
|
15
|
+
};
|
|
16
|
+
export type GetPairHoldingFeeRatesInput = {
|
|
17
|
+
fundingParams: FundingFeeParams;
|
|
18
|
+
fundingData: PairFundingFeeData;
|
|
19
|
+
pairOiToken: PairOiAfterV10;
|
|
20
|
+
netExposureToken: number;
|
|
21
|
+
netExposureUsd: number;
|
|
22
|
+
borrowingParams: BorrowingFeeParams | null;
|
|
23
|
+
borrowingData: PairBorrowingFeeData | null;
|
|
24
|
+
currentPairPrice: number;
|
|
25
|
+
currentTimestamp: number;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* @dev Calculates current holding fee rates per hour for display
|
|
29
|
+
* @param input Input parameters for calculation
|
|
30
|
+
* @returns Holding fee rates per hour with breakdown
|
|
31
|
+
*/
|
|
32
|
+
export declare const getPairHoldingFeeRates: (input: GetPairHoldingFeeRatesInput) => HoldingFeeRates;
|
|
33
|
+
/**
|
|
34
|
+
* @dev Converts a per-second rate to annual percentage rate (APR)
|
|
35
|
+
* @param ratePerSecond Rate per second
|
|
36
|
+
* @returns Annual percentage rate
|
|
37
|
+
*/
|
|
38
|
+
export declare const convertRatePerSecondToAPR: (ratePerSecond: number) => number;
|
|
39
|
+
/**
|
|
40
|
+
* @dev Formats a holding fee rate for display
|
|
41
|
+
* @param rate Hourly rate (can be negative)
|
|
42
|
+
* @param decimals Number of decimal places
|
|
43
|
+
* @returns Formatted string with sign
|
|
44
|
+
*/
|
|
45
|
+
export declare const formatHoldingFeeRate: (rate: number, decimals?: number) => string;
|
|
46
|
+
export * as HoldingFees from "./types";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @dev Holding fees calculation utilities for v10+ markets
|
|
4
|
+
* @dev Combines funding fees and borrowing v2 fees
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
23
|
+
if (mod && mod.__esModule) return mod;
|
|
24
|
+
var result = {};
|
|
25
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
26
|
+
__setModuleDefault(result, mod);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.HoldingFees = exports.formatHoldingFeeRate = exports.convertRatePerSecondToAPR = exports.getPairHoldingFeeRates = void 0;
|
|
31
|
+
const fundingFees_1 = require("../../trade/fees/fundingFees");
|
|
32
|
+
const SECONDS_PER_HOUR = 3600;
|
|
33
|
+
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
|
|
34
|
+
const PERCENTAGE_PRECISION = 100;
|
|
35
|
+
/**
|
|
36
|
+
* @dev Calculates current holding fee rates per hour for display
|
|
37
|
+
* @param input Input parameters for calculation
|
|
38
|
+
* @returns Holding fee rates per hour with breakdown
|
|
39
|
+
*/
|
|
40
|
+
const getPairHoldingFeeRates = (input) => {
|
|
41
|
+
const { fundingParams, fundingData, pairOiToken, netExposureToken, netExposureUsd, borrowingParams, borrowingData, currentPairPrice, currentTimestamp, } = input;
|
|
42
|
+
// Calculate funding fee rates
|
|
43
|
+
let fundingFeeLongHourlyRate = 0;
|
|
44
|
+
let fundingFeeShortHourlyRate = 0;
|
|
45
|
+
let currentFundingRatePerSecondP = 0;
|
|
46
|
+
if (fundingParams.fundingFeesEnabled) {
|
|
47
|
+
// Get current funding rate
|
|
48
|
+
const pendingFunding = (0, fundingFees_1.getPairPendingAccFundingFees)(fundingParams, fundingData, currentPairPrice, pairOiToken, netExposureToken, netExposureUsd, currentTimestamp);
|
|
49
|
+
currentFundingRatePerSecondP = pendingFunding.currentFundingRatePerSecondP;
|
|
50
|
+
// Get APR multipliers
|
|
51
|
+
const { longAprMultiplier, shortAprMultiplier } = (0, fundingFees_1.getLongShortAprMultiplier)(currentFundingRatePerSecondP, pairOiToken.oiLongToken, pairOiToken.oiShortToken, fundingParams.aprMultiplierEnabled);
|
|
52
|
+
// Calculate hourly rates
|
|
53
|
+
// Funding rate * seconds per hour * current price * APR multiplier / 100
|
|
54
|
+
const baseHourlyRate = (currentFundingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
|
|
55
|
+
PERCENTAGE_PRECISION;
|
|
56
|
+
// Long side pays when rate is positive, earns when negative
|
|
57
|
+
fundingFeeLongHourlyRate = baseHourlyRate * longAprMultiplier;
|
|
58
|
+
// Short side is opposite
|
|
59
|
+
fundingFeeShortHourlyRate = -baseHourlyRate * shortAprMultiplier;
|
|
60
|
+
}
|
|
61
|
+
// Calculate borrowing v2 rates
|
|
62
|
+
let borrowingFeeHourlyRate = 0;
|
|
63
|
+
let currentBorrowingRatePerSecondP = 0;
|
|
64
|
+
if (borrowingParams && borrowingData) {
|
|
65
|
+
currentBorrowingRatePerSecondP = borrowingParams.borrowingRatePerSecondP;
|
|
66
|
+
// Borrowing rate * seconds per hour * current price / 100
|
|
67
|
+
borrowingFeeHourlyRate =
|
|
68
|
+
(currentBorrowingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
|
|
69
|
+
PERCENTAGE_PRECISION;
|
|
70
|
+
}
|
|
71
|
+
// Total holding fees (funding can be negative/positive, borrowing always positive cost)
|
|
72
|
+
const longHourlyRate = fundingFeeLongHourlyRate + borrowingFeeHourlyRate;
|
|
73
|
+
const shortHourlyRate = fundingFeeShortHourlyRate + borrowingFeeHourlyRate;
|
|
74
|
+
return {
|
|
75
|
+
longHourlyRate,
|
|
76
|
+
shortHourlyRate,
|
|
77
|
+
fundingFeeLongHourlyRate,
|
|
78
|
+
fundingFeeShortHourlyRate,
|
|
79
|
+
borrowingFeeHourlyRate,
|
|
80
|
+
currentFundingRatePerSecondP,
|
|
81
|
+
currentBorrowingRatePerSecondP,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
exports.getPairHoldingFeeRates = getPairHoldingFeeRates;
|
|
85
|
+
/**
|
|
86
|
+
* @dev Converts a per-second rate to annual percentage rate (APR)
|
|
87
|
+
* @param ratePerSecond Rate per second
|
|
88
|
+
* @returns Annual percentage rate
|
|
89
|
+
*/
|
|
90
|
+
const convertRatePerSecondToAPR = (ratePerSecond) => {
|
|
91
|
+
return ratePerSecond * SECONDS_PER_YEAR * PERCENTAGE_PRECISION;
|
|
92
|
+
};
|
|
93
|
+
exports.convertRatePerSecondToAPR = convertRatePerSecondToAPR;
|
|
94
|
+
/**
|
|
95
|
+
* @dev Formats a holding fee rate for display
|
|
96
|
+
* @param rate Hourly rate (can be negative)
|
|
97
|
+
* @param decimals Number of decimal places
|
|
98
|
+
* @returns Formatted string with sign
|
|
99
|
+
*/
|
|
100
|
+
const formatHoldingFeeRate = (rate, decimals = 4) => {
|
|
101
|
+
const sign = rate > 0 ? "+" : "";
|
|
102
|
+
return `${sign}${rate.toFixed(decimals)}%`;
|
|
103
|
+
};
|
|
104
|
+
exports.formatHoldingFeeRate = formatHoldingFeeRate;
|
|
105
|
+
exports.HoldingFees = __importStar(require("./types"));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dev Type definitions for holding fees (funding + borrowing v2)
|
|
3
|
+
*/
|
|
4
|
+
export interface HoldingFeeRates {
|
|
5
|
+
longHourlyRate: number;
|
|
6
|
+
shortHourlyRate: number;
|
|
7
|
+
fundingFeeLongHourlyRate: number;
|
|
8
|
+
fundingFeeShortHourlyRate: number;
|
|
9
|
+
borrowingFeeHourlyRate: number;
|
|
10
|
+
currentFundingRatePerSecondP: number;
|
|
11
|
+
currentBorrowingRatePerSecondP: number;
|
|
12
|
+
}
|
|
13
|
+
export interface GetPairHoldingFeeRatesInput {
|
|
14
|
+
fundingParams: import("../../trade/fees/fundingFees/types").FundingFeeParams;
|
|
15
|
+
fundingData: import("../../trade/fees/fundingFees/types").PairFundingFeeData;
|
|
16
|
+
pairOiToken: import("../../trade/fees/fundingFees/types").PairOiAfterV10;
|
|
17
|
+
netExposureToken: number;
|
|
18
|
+
netExposureUsd: number;
|
|
19
|
+
borrowingParams: import("../../trade/fees/borrowingV2/types").BorrowingFeeParams | null;
|
|
20
|
+
borrowingData: import("../../trade/fees/borrowingV2/types").PairBorrowingFeeData | null;
|
|
21
|
+
currentPairPrice: number;
|
|
22
|
+
currentTimestamp: number;
|
|
23
|
+
}
|
package/lib/markets/index.d.ts
CHANGED
package/lib/markets/index.js
CHANGED
|
@@ -7,10 +7,9 @@ import { UnifiedPairOi, ComputedOi } from "./types";
|
|
|
7
7
|
/**
|
|
8
8
|
* @dev Converts pre-v10 OI from contract format
|
|
9
9
|
* @param contractOi Contract OpenInterest struct from BorrowingFeesStorage
|
|
10
|
-
* @param precision Collateral precision for conversion
|
|
11
10
|
* @returns Normalized OI with long/short values
|
|
12
11
|
*/
|
|
13
|
-
export declare const convertBeforeV10Collateral: (contractOi: IBorrowingFees.OpenInterestStructOutput
|
|
12
|
+
export declare const convertBeforeV10Collateral: (contractOi: IBorrowingFees.OpenInterestStructOutput) => {
|
|
14
13
|
long: number;
|
|
15
14
|
short: number;
|
|
16
15
|
};
|
|
@@ -8,13 +8,12 @@ exports.computeOiValues = exports.convertPairOiArray = exports.convertPairOi = e
|
|
|
8
8
|
/**
|
|
9
9
|
* @dev Converts pre-v10 OI from contract format
|
|
10
10
|
* @param contractOi Contract OpenInterest struct from BorrowingFeesStorage
|
|
11
|
-
* @param precision Collateral precision for conversion
|
|
12
11
|
* @returns Normalized OI with long/short values
|
|
13
12
|
*/
|
|
14
|
-
const convertBeforeV10Collateral = (contractOi
|
|
13
|
+
const convertBeforeV10Collateral = (contractOi) => {
|
|
15
14
|
return {
|
|
16
|
-
long: Number(contractOi.long) /
|
|
17
|
-
short: Number(contractOi.short) /
|
|
15
|
+
long: Number(contractOi.long) / 1e10,
|
|
16
|
+
short: Number(contractOi.short) / 1e10,
|
|
18
17
|
};
|
|
19
18
|
};
|
|
20
19
|
exports.convertBeforeV10Collateral = convertBeforeV10Collateral;
|
|
@@ -54,8 +53,8 @@ exports.convertTokenOi = convertTokenOi;
|
|
|
54
53
|
*/
|
|
55
54
|
const convertPairOi = (beforeV10, afterV10Collateral, afterV10Token, collateralPrecision) => {
|
|
56
55
|
return {
|
|
57
|
-
maxCollateral: Number(beforeV10.max) /
|
|
58
|
-
beforeV10Collateral: (0, exports.convertBeforeV10Collateral)(beforeV10
|
|
56
|
+
maxCollateral: Number(beforeV10.max) / 1e10,
|
|
57
|
+
beforeV10Collateral: (0, exports.convertBeforeV10Collateral)(beforeV10),
|
|
59
58
|
collateral: (0, exports.convertCollateralOi)(afterV10Collateral, collateralPrecision),
|
|
60
59
|
token: (0, exports.convertTokenOi)(afterV10Token),
|
|
61
60
|
};
|
|
@@ -2,9 +2,48 @@
|
|
|
2
2
|
* @dev Main export file for OI module
|
|
3
3
|
* @dev Provides unified Open Interest management functionality
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
import { GenericPairOiContext } from "./types";
|
|
6
|
+
export declare const getPairTotalOisCollateral: (pairIndex: number, context: GenericPairOiContext) => {
|
|
7
|
+
long: number;
|
|
8
|
+
short: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens
|
|
12
|
+
* @param pairIndex index of pair
|
|
13
|
+
* @param context contains UnifiedPairOi array and current pair price
|
|
14
|
+
* @returns dynamic OI for long and short sides in collateral precision
|
|
15
|
+
*/
|
|
16
|
+
export declare const getPairTotalOisDynamicCollateral: (pairIndex: number, context: GenericPairOiContext & {
|
|
17
|
+
currentPairPrice: number;
|
|
18
|
+
}) => {
|
|
19
|
+
long: number;
|
|
20
|
+
short: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens on one side only
|
|
24
|
+
* @param pairIndex index of pair
|
|
25
|
+
* @param long true if long, false if short
|
|
26
|
+
* @param context contains UnifiedPairOi array and current pair price
|
|
27
|
+
* @returns dynamic OI for the specified side in collateral precision
|
|
28
|
+
*/
|
|
29
|
+
export declare const getPairTotalOiDynamicCollateral: (pairIndex: number, long: boolean, context: GenericPairOiContext & {
|
|
30
|
+
currentPairPrice: number;
|
|
31
|
+
}) => number;
|
|
32
|
+
/**
|
|
33
|
+
* @dev Returns pair open interest skew (v10 only) in tokens
|
|
34
|
+
* @param pairIndex index of pair
|
|
35
|
+
* @param context contains UnifiedPairOi array
|
|
36
|
+
* @returns skew in token amount (positive = more longs, negative = more shorts)
|
|
37
|
+
*/
|
|
38
|
+
export declare const getPairV10OiTokenSkewCollateral: (pairIndex: number, context: GenericPairOiContext) => number;
|
|
39
|
+
/**
|
|
40
|
+
* @dev Returns pair dynamic skew (v10 only) in collateral tokens
|
|
41
|
+
* @param pairIndex index of pair
|
|
42
|
+
* @param context contains UnifiedPairOi array and current pair price
|
|
43
|
+
* @returns dynamic skew in collateral precision
|
|
44
|
+
*/
|
|
45
|
+
export declare const getPairV10OiDynamicSkewCollateral: (pairIndex: number, context: GenericPairOiContext & {
|
|
46
|
+
currentPairPrice: number;
|
|
47
|
+
}) => number;
|
|
48
|
+
export { UnifiedPairOi, GroupOi, ComputedOi } from "./types";
|
|
6
49
|
export { convertBeforeV10Collateral, convertCollateralOi, convertTokenOi, convertPairOi, convertPairOiArray, computeOiValues, } from "./converter";
|
|
7
|
-
export { fetchPairOi, fetchMultiplePairOi, createOiContext, fetchOiForUseCase, } from "./fetcher";
|
|
8
|
-
export { withinMaxPairOi, calculateDynamicOi, getRemainingOiCapacity, withinMaxGroupOiDynamic, getGroupDynamicOi, validateOiLimits, } from "./validation";
|
|
9
|
-
import { OiUsageMetadata } from "./types";
|
|
10
|
-
export declare const OI_USAGE: OiUsageMetadata;
|
package/lib/markets/oi/index.js
CHANGED
|
@@ -4,7 +4,69 @@
|
|
|
4
4
|
* @dev Provides unified Open Interest management functionality
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.computeOiValues = exports.convertPairOiArray = exports.convertPairOi = exports.convertTokenOi = exports.convertCollateralOi = exports.convertBeforeV10Collateral = exports.getPairV10OiDynamicSkewCollateral = exports.getPairV10OiTokenSkewCollateral = exports.getPairTotalOiDynamicCollateral = exports.getPairTotalOisDynamicCollateral = exports.getPairTotalOisCollateral = void 0;
|
|
8
|
+
const getPairTotalOisCollateral = (pairIndex, context) => {
|
|
9
|
+
return {
|
|
10
|
+
long: context.pairOis[pairIndex].beforeV10Collateral.long +
|
|
11
|
+
context.pairOis[pairIndex].collateral.long,
|
|
12
|
+
short: context.pairOis[pairIndex].beforeV10Collateral.short +
|
|
13
|
+
context.pairOis[pairIndex].collateral.short,
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
exports.getPairTotalOisCollateral = getPairTotalOisCollateral;
|
|
17
|
+
/**
|
|
18
|
+
* @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens
|
|
19
|
+
* @param pairIndex index of pair
|
|
20
|
+
* @param context contains UnifiedPairOi array and current pair price
|
|
21
|
+
* @returns dynamic OI for long and short sides in collateral precision
|
|
22
|
+
*/
|
|
23
|
+
const getPairTotalOisDynamicCollateral = (pairIndex, context) => {
|
|
24
|
+
const pairOi = context.pairOis[pairIndex];
|
|
25
|
+
// We have to use the initial collateral OIs for pre-v10 trades because we don't have OIs in token amount
|
|
26
|
+
const oiLongCollateralDynamicAfterV10 = pairOi.beforeV10Collateral.long +
|
|
27
|
+
pairOi.token.long * context.currentPairPrice;
|
|
28
|
+
const oiShortCollateralDynamicAfterV10 = pairOi.beforeV10Collateral.short +
|
|
29
|
+
pairOi.token.short * context.currentPairPrice;
|
|
30
|
+
return {
|
|
31
|
+
long: oiLongCollateralDynamicAfterV10,
|
|
32
|
+
short: oiShortCollateralDynamicAfterV10,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
exports.getPairTotalOisDynamicCollateral = getPairTotalOisDynamicCollateral;
|
|
36
|
+
/**
|
|
37
|
+
* @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens on one side only
|
|
38
|
+
* @param pairIndex index of pair
|
|
39
|
+
* @param long true if long, false if short
|
|
40
|
+
* @param context contains UnifiedPairOi array and current pair price
|
|
41
|
+
* @returns dynamic OI for the specified side in collateral precision
|
|
42
|
+
*/
|
|
43
|
+
const getPairTotalOiDynamicCollateral = (pairIndex, long, context) => {
|
|
44
|
+
const dynamicOis = (0, exports.getPairTotalOisDynamicCollateral)(pairIndex, context);
|
|
45
|
+
return long ? dynamicOis.long : dynamicOis.short;
|
|
46
|
+
};
|
|
47
|
+
exports.getPairTotalOiDynamicCollateral = getPairTotalOiDynamicCollateral;
|
|
48
|
+
/**
|
|
49
|
+
* @dev Returns pair open interest skew (v10 only) in tokens
|
|
50
|
+
* @param pairIndex index of pair
|
|
51
|
+
* @param context contains UnifiedPairOi array
|
|
52
|
+
* @returns skew in token amount (positive = more longs, negative = more shorts)
|
|
53
|
+
*/
|
|
54
|
+
const getPairV10OiTokenSkewCollateral = (pairIndex, context) => {
|
|
55
|
+
const pairOi = context.pairOis[pairIndex];
|
|
56
|
+
return pairOi.token.long - pairOi.token.short;
|
|
57
|
+
};
|
|
58
|
+
exports.getPairV10OiTokenSkewCollateral = getPairV10OiTokenSkewCollateral;
|
|
59
|
+
/**
|
|
60
|
+
* @dev Returns pair dynamic skew (v10 only) in collateral tokens
|
|
61
|
+
* @param pairIndex index of pair
|
|
62
|
+
* @param context contains UnifiedPairOi array and current pair price
|
|
63
|
+
* @returns dynamic skew in collateral precision
|
|
64
|
+
*/
|
|
65
|
+
const getPairV10OiDynamicSkewCollateral = (pairIndex, context) => {
|
|
66
|
+
return ((0, exports.getPairV10OiTokenSkewCollateral)(pairIndex, context) *
|
|
67
|
+
context.currentPairPrice);
|
|
68
|
+
};
|
|
69
|
+
exports.getPairV10OiDynamicSkewCollateral = getPairV10OiDynamicSkewCollateral;
|
|
8
70
|
// Converters
|
|
9
71
|
var converter_1 = require("./converter");
|
|
10
72
|
Object.defineProperty(exports, "convertBeforeV10Collateral", { enumerable: true, get: function () { return converter_1.convertBeforeV10Collateral; } });
|
|
@@ -13,25 +75,3 @@ Object.defineProperty(exports, "convertTokenOi", { enumerable: true, get: functi
|
|
|
13
75
|
Object.defineProperty(exports, "convertPairOi", { enumerable: true, get: function () { return converter_1.convertPairOi; } });
|
|
14
76
|
Object.defineProperty(exports, "convertPairOiArray", { enumerable: true, get: function () { return converter_1.convertPairOiArray; } });
|
|
15
77
|
Object.defineProperty(exports, "computeOiValues", { enumerable: true, get: function () { return converter_1.computeOiValues; } });
|
|
16
|
-
// Fetchers
|
|
17
|
-
var fetcher_1 = require("./fetcher");
|
|
18
|
-
Object.defineProperty(exports, "fetchPairOi", { enumerable: true, get: function () { return fetcher_1.fetchPairOi; } });
|
|
19
|
-
Object.defineProperty(exports, "fetchMultiplePairOi", { enumerable: true, get: function () { return fetcher_1.fetchMultiplePairOi; } });
|
|
20
|
-
Object.defineProperty(exports, "createOiContext", { enumerable: true, get: function () { return fetcher_1.createOiContext; } });
|
|
21
|
-
Object.defineProperty(exports, "fetchOiForUseCase", { enumerable: true, get: function () { return fetcher_1.fetchOiForUseCase; } });
|
|
22
|
-
// Validation
|
|
23
|
-
var validation_1 = require("./validation");
|
|
24
|
-
Object.defineProperty(exports, "withinMaxPairOi", { enumerable: true, get: function () { return validation_1.withinMaxPairOi; } });
|
|
25
|
-
Object.defineProperty(exports, "calculateDynamicOi", { enumerable: true, get: function () { return validation_1.calculateDynamicOi; } });
|
|
26
|
-
Object.defineProperty(exports, "getRemainingOiCapacity", { enumerable: true, get: function () { return validation_1.getRemainingOiCapacity; } });
|
|
27
|
-
Object.defineProperty(exports, "withinMaxGroupOiDynamic", { enumerable: true, get: function () { return validation_1.withinMaxGroupOiDynamic; } });
|
|
28
|
-
Object.defineProperty(exports, "getGroupDynamicOi", { enumerable: true, get: function () { return validation_1.getGroupDynamicOi; } });
|
|
29
|
-
Object.defineProperty(exports, "validateOiLimits", { enumerable: true, get: function () { return validation_1.validateOiLimits; } });
|
|
30
|
-
exports.OI_USAGE = {
|
|
31
|
-
borrowingV1: ["beforeV10Collateral", "token"],
|
|
32
|
-
fundingFees: ["token"],
|
|
33
|
-
skewImpact: ["token"],
|
|
34
|
-
maxPairOi: ["beforeV10Collateral", "token"],
|
|
35
|
-
maxGroupOi: ["beforeV10Collateral", "token"],
|
|
36
|
-
maxSkew: ["token"], // V10+ only: uses token OI
|
|
37
|
-
};
|
|
@@ -37,23 +37,14 @@ export interface UnifiedPairOi {
|
|
|
37
37
|
short: number;
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
+
export type GenericPairOiContext = {
|
|
41
|
+
pairOis: UnifiedPairOi[];
|
|
42
|
+
};
|
|
40
43
|
/**
|
|
41
44
|
* @dev Group OI remains unchanged - only used by borrowing v1
|
|
42
45
|
* @dev Re-export existing type for consistency
|
|
43
46
|
*/
|
|
44
47
|
export { OpenInterest as GroupOi } from "../../trade/types";
|
|
45
|
-
/**
|
|
46
|
-
* @dev Metadata describing which OI systems are used by different features
|
|
47
|
-
* @dev Helps consumers understand OI usage patterns
|
|
48
|
-
*/
|
|
49
|
-
export interface OiUsageMetadata {
|
|
50
|
-
borrowingV1: Array<"beforeV10Collateral" | "token">;
|
|
51
|
-
fundingFees: Array<"token">;
|
|
52
|
-
skewImpact: Array<"token">;
|
|
53
|
-
maxPairOi: Array<"beforeV10Collateral" | "token">;
|
|
54
|
-
maxGroupOi: Array<"beforeV10Collateral" | "token">;
|
|
55
|
-
maxSkew: Array<"token">;
|
|
56
|
-
}
|
|
57
48
|
/**
|
|
58
49
|
* @dev Helper type for computed OI values
|
|
59
50
|
*/
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dev Holding fees calculation utilities for v10+ markets
|
|
3
|
+
* @dev Combines funding fees and borrowing v2 fees
|
|
4
|
+
*/
|
|
5
|
+
import { FundingFeeParams, PairFundingFeeData, PairOiAfterV10 } from "../fundingFees/types";
|
|
6
|
+
import { BorrowingFeeParams, PairBorrowingFeeData } from "../borrowingV2/types";
|
|
7
|
+
export type HoldingFeeRates = {
|
|
8
|
+
longHourlyRate: number;
|
|
9
|
+
shortHourlyRate: number;
|
|
10
|
+
fundingFeeLongHourlyRate: number;
|
|
11
|
+
fundingFeeShortHourlyRate: number;
|
|
12
|
+
borrowingFeeHourlyRate: number;
|
|
13
|
+
currentFundingRatePerSecondP: number;
|
|
14
|
+
currentBorrowingRatePerSecondP: number;
|
|
15
|
+
};
|
|
16
|
+
export type GetPairHoldingFeeRatesInput = {
|
|
17
|
+
fundingParams: FundingFeeParams;
|
|
18
|
+
fundingData: PairFundingFeeData;
|
|
19
|
+
pairOiToken: PairOiAfterV10;
|
|
20
|
+
netExposureToken: number;
|
|
21
|
+
netExposureUsd: number;
|
|
22
|
+
borrowingParams: BorrowingFeeParams | null;
|
|
23
|
+
borrowingData: PairBorrowingFeeData | null;
|
|
24
|
+
currentPairPrice: number;
|
|
25
|
+
currentTimestamp: number;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* @dev Calculates current holding fee rates per hour for display
|
|
29
|
+
* @param input Input parameters for calculation
|
|
30
|
+
* @returns Holding fee rates per hour with breakdown
|
|
31
|
+
*/
|
|
32
|
+
export declare const getPairHoldingFeeRates: (input: GetPairHoldingFeeRatesInput) => HoldingFeeRates;
|
|
33
|
+
/**
|
|
34
|
+
* @dev Converts a per-second rate to annual percentage rate (APR)
|
|
35
|
+
* @param ratePerSecond Rate per second
|
|
36
|
+
* @returns Annual percentage rate
|
|
37
|
+
*/
|
|
38
|
+
export declare const convertRatePerSecondToAPR: (ratePerSecond: number) => number;
|
|
39
|
+
/**
|
|
40
|
+
* @dev Formats a holding fee rate for display
|
|
41
|
+
* @param rate Hourly rate (can be negative)
|
|
42
|
+
* @param decimals Number of decimal places
|
|
43
|
+
* @returns Formatted string with sign
|
|
44
|
+
*/
|
|
45
|
+
export declare const formatHoldingFeeRate: (rate: number, decimals?: number) => string;
|
|
46
|
+
export * as HoldingFees from "./types";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @dev Holding fees calculation utilities for v10+ markets
|
|
4
|
+
* @dev Combines funding fees and borrowing v2 fees
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
23
|
+
if (mod && mod.__esModule) return mod;
|
|
24
|
+
var result = {};
|
|
25
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
26
|
+
__setModuleDefault(result, mod);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.HoldingFees = exports.formatHoldingFeeRate = exports.convertRatePerSecondToAPR = exports.getPairHoldingFeeRates = void 0;
|
|
31
|
+
const fundingFees_1 = require("../fundingFees");
|
|
32
|
+
const SECONDS_PER_HOUR = 3600;
|
|
33
|
+
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
|
|
34
|
+
const PERCENTAGE_PRECISION = 100;
|
|
35
|
+
/**
|
|
36
|
+
* @dev Calculates current holding fee rates per hour for display
|
|
37
|
+
* @param input Input parameters for calculation
|
|
38
|
+
* @returns Holding fee rates per hour with breakdown
|
|
39
|
+
*/
|
|
40
|
+
const getPairHoldingFeeRates = (input) => {
|
|
41
|
+
const { fundingParams, fundingData, pairOiToken, netExposureToken, netExposureUsd, borrowingParams, borrowingData, currentPairPrice, currentTimestamp, } = input;
|
|
42
|
+
// Calculate funding fee rates
|
|
43
|
+
let fundingFeeLongHourlyRate = 0;
|
|
44
|
+
let fundingFeeShortHourlyRate = 0;
|
|
45
|
+
let currentFundingRatePerSecondP = 0;
|
|
46
|
+
if (fundingParams.fundingFeesEnabled) {
|
|
47
|
+
// Get current funding rate
|
|
48
|
+
const pendingFunding = (0, fundingFees_1.getPairPendingAccFundingFees)(fundingParams, fundingData, currentPairPrice, pairOiToken, netExposureToken, netExposureUsd, currentTimestamp);
|
|
49
|
+
currentFundingRatePerSecondP = pendingFunding.currentFundingRatePerSecondP;
|
|
50
|
+
// Get APR multipliers
|
|
51
|
+
const { longAprMultiplier, shortAprMultiplier } = (0, fundingFees_1.getLongShortAprMultiplier)(currentFundingRatePerSecondP, pairOiToken.oiLongToken, pairOiToken.oiShortToken, fundingParams.aprMultiplierEnabled);
|
|
52
|
+
// Calculate hourly rates
|
|
53
|
+
// Funding rate * seconds per hour * current price * APR multiplier / 100
|
|
54
|
+
const baseHourlyRate = (currentFundingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
|
|
55
|
+
PERCENTAGE_PRECISION;
|
|
56
|
+
// Long side pays when rate is positive, earns when negative
|
|
57
|
+
fundingFeeLongHourlyRate = baseHourlyRate * longAprMultiplier;
|
|
58
|
+
// Short side is opposite
|
|
59
|
+
fundingFeeShortHourlyRate = -baseHourlyRate * shortAprMultiplier;
|
|
60
|
+
}
|
|
61
|
+
// Calculate borrowing v2 rates
|
|
62
|
+
let borrowingFeeHourlyRate = 0;
|
|
63
|
+
let currentBorrowingRatePerSecondP = 0;
|
|
64
|
+
if (borrowingParams && borrowingData) {
|
|
65
|
+
currentBorrowingRatePerSecondP = borrowingParams.borrowingRatePerSecondP;
|
|
66
|
+
// Borrowing rate * seconds per hour * current price / 100
|
|
67
|
+
borrowingFeeHourlyRate =
|
|
68
|
+
(currentBorrowingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
|
|
69
|
+
PERCENTAGE_PRECISION;
|
|
70
|
+
}
|
|
71
|
+
// Total holding fees (funding can be negative/positive, borrowing always positive cost)
|
|
72
|
+
const longHourlyRate = fundingFeeLongHourlyRate + borrowingFeeHourlyRate;
|
|
73
|
+
const shortHourlyRate = fundingFeeShortHourlyRate + borrowingFeeHourlyRate;
|
|
74
|
+
return {
|
|
75
|
+
longHourlyRate,
|
|
76
|
+
shortHourlyRate,
|
|
77
|
+
fundingFeeLongHourlyRate,
|
|
78
|
+
fundingFeeShortHourlyRate,
|
|
79
|
+
borrowingFeeHourlyRate,
|
|
80
|
+
currentFundingRatePerSecondP,
|
|
81
|
+
currentBorrowingRatePerSecondP,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
exports.getPairHoldingFeeRates = getPairHoldingFeeRates;
|
|
85
|
+
/**
|
|
86
|
+
* @dev Converts a per-second rate to annual percentage rate (APR)
|
|
87
|
+
* @param ratePerSecond Rate per second
|
|
88
|
+
* @returns Annual percentage rate
|
|
89
|
+
*/
|
|
90
|
+
const convertRatePerSecondToAPR = (ratePerSecond) => {
|
|
91
|
+
return ratePerSecond * SECONDS_PER_YEAR * PERCENTAGE_PRECISION;
|
|
92
|
+
};
|
|
93
|
+
exports.convertRatePerSecondToAPR = convertRatePerSecondToAPR;
|
|
94
|
+
/**
|
|
95
|
+
* @dev Formats a holding fee rate for display
|
|
96
|
+
* @param rate Hourly rate (can be negative)
|
|
97
|
+
* @param decimals Number of decimal places
|
|
98
|
+
* @returns Formatted string with sign
|
|
99
|
+
*/
|
|
100
|
+
const formatHoldingFeeRate = (rate, decimals = 4) => {
|
|
101
|
+
const sign = rate > 0 ? "+" : "";
|
|
102
|
+
return `${sign}${rate.toFixed(decimals)}%`;
|
|
103
|
+
};
|
|
104
|
+
exports.formatHoldingFeeRate = formatHoldingFeeRate;
|
|
105
|
+
exports.HoldingFees = __importStar(require("./types"));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dev Type definitions for holding fees (funding + borrowing v2)
|
|
3
|
+
*/
|
|
4
|
+
export interface HoldingFeeRates {
|
|
5
|
+
longHourlyRate: number;
|
|
6
|
+
shortHourlyRate: number;
|
|
7
|
+
fundingFeeLongHourlyRate: number;
|
|
8
|
+
fundingFeeShortHourlyRate: number;
|
|
9
|
+
borrowingFeeHourlyRate: number;
|
|
10
|
+
currentFundingRatePerSecondP: number;
|
|
11
|
+
currentBorrowingRatePerSecondP: number;
|
|
12
|
+
}
|
|
13
|
+
export interface GetPairHoldingFeeRatesInput {
|
|
14
|
+
fundingParams: import("../fundingFees/types").FundingFeeParams;
|
|
15
|
+
fundingData: import("../fundingFees/types").PairFundingFeeData;
|
|
16
|
+
pairOiToken: import("../fundingFees/types").PairOiAfterV10;
|
|
17
|
+
netExposureToken: number;
|
|
18
|
+
netExposureUsd: number;
|
|
19
|
+
borrowingParams: import("../borrowingV2/types").BorrowingFeeParams | null;
|
|
20
|
+
borrowingData: import("../borrowingV2/types").PairBorrowingFeeData | null;
|
|
21
|
+
currentPairPrice: number;
|
|
22
|
+
currentTimestamp: number;
|
|
23
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./borrowing";
|
|
2
2
|
export * from "./tiers";
|
|
3
3
|
export * from "./trading";
|
|
4
|
+
export * from "../../markets/holdingFees";
|
|
4
5
|
export { convertTradeFeesData, convertTradeFeesDataArray, convertUiRealizedPnlData, convertUiRealizedPnlDataArray, encodeTradeFeesData, encodeUiRealizedPnlData, } from "./converter";
|
|
5
6
|
export { BorrowingFeeV2, borrowingFeeV2Utils, getPairPendingAccBorrowingFees as getPairPendingAccBorrowingFeesV2, getTradeBorrowingFeesCollateral as getTradeBorrowingFeesCollateralV2, getPairBorrowingFees as getPairBorrowingFeesV2, MAX_BORROWING_RATE_PER_SECOND as MAX_BORROWING_RATE_PER_SECOND_V2, BORROWING_V2_PRECISION, } from "./borrowingV2";
|
|
6
7
|
export { convertBorrowingFeeParams as convertBorrowingFeeParamsV2, convertBorrowingFeeParamsArray as convertBorrowingFeeParamsArrayV2, convertPairBorrowingFeeData as convertPairBorrowingFeeDataV2, convertPairBorrowingFeeDataArray as convertPairBorrowingFeeDataArrayV2, convertTradeInitialAccFees as convertTradeInitialAccFeesV2, convertTradeInitialAccFeesArray as convertTradeInitialAccFeesArrayV2, createBorrowingV2Context, isValidBorrowingRate as isValidBorrowingRateV2, borrowingRateToAPR as borrowingRateToAPRV2, aprToBorrowingRate as aprToBorrowingRateV2, } from "./borrowingV2/converter";
|
package/lib/trade/fees/index.js
CHANGED
|
@@ -19,6 +19,7 @@ exports.FUNDING_FEES_PRECISION = exports.calculateVelocityFromSkew = exports.apr
|
|
|
19
19
|
__exportStar(require("./borrowing"), exports);
|
|
20
20
|
__exportStar(require("./tiers"), exports);
|
|
21
21
|
__exportStar(require("./trading"), exports);
|
|
22
|
+
__exportStar(require("../../markets/holdingFees"), exports);
|
|
22
23
|
// TradeFeesData and UiRealizedPnlData converters
|
|
23
24
|
var converter_1 = require("./converter");
|
|
24
25
|
Object.defineProperty(exports, "convertTradeFeesData", { enumerable: true, get: function () { return converter_1.convertTradeFeesData; } });
|
package/lib/trade/pnl/index.d.ts
CHANGED
|
@@ -2,10 +2,21 @@
|
|
|
2
2
|
* @dev PnL calculation module
|
|
3
3
|
* @dev Provides functions matching v10 contract implementations
|
|
4
4
|
*/
|
|
5
|
-
import { Trade, TradeInfo, LiquidationParams, Fee, GlobalTradeFeeParams } from "../types";
|
|
5
|
+
import { Trade, TradeInfo, LiquidationParams, Fee, GlobalTradeFeeParams, TradeFeesData } from "../types";
|
|
6
6
|
import { ComprehensivePnlResult, GetComprehensivePnlContext } from "./types";
|
|
7
7
|
import { BorrowingFee } from "../fees/borrowing";
|
|
8
8
|
import { ContractsVersion } from "../../contracts/types";
|
|
9
|
+
/**
|
|
10
|
+
* @dev Gets trade realized PnL components from TradeFeesData
|
|
11
|
+
* @dev Mirrors contract's getTradeRealizedPnlCollateral function
|
|
12
|
+
* @param tradeFeesData Trade fees data containing realized components
|
|
13
|
+
* @returns Tuple of [realizedPnlCollateral, realizedTradingFeesCollateral, totalRealizedPnlCollateral]
|
|
14
|
+
*/
|
|
15
|
+
export declare const getTradeRealizedPnlCollateral: (tradeFeesData: TradeFeesData) => {
|
|
16
|
+
realizedPnlCollateral: number;
|
|
17
|
+
realizedTradingFeesCollateral: number;
|
|
18
|
+
totalRealizedPnlCollateral: number;
|
|
19
|
+
};
|
|
9
20
|
/**
|
|
10
21
|
* @dev Calculates PnL percentage for a position
|
|
11
22
|
* @dev Mirrors contract's getPnlPercent function
|
package/lib/trade/pnl/index.js
CHANGED
|
@@ -18,10 +18,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.getPriceForTargetPnlPercentage = exports.getPnl = exports.getComprehensivePnl = exports.getTradeValue = exports.getPnlPercent = void 0;
|
|
21
|
+
exports.getPriceForTargetPnlPercentage = exports.getPnl = exports.getComprehensivePnl = exports.getTradeValue = exports.getPnlPercent = exports.getTradeRealizedPnlCollateral = void 0;
|
|
22
22
|
const borrowing_1 = require("../fees/borrowing");
|
|
23
23
|
const trading_1 = require("../fees/trading");
|
|
24
24
|
const liquidation_1 = require("../liquidation");
|
|
25
|
+
/**
|
|
26
|
+
* @dev Gets trade realized PnL components from TradeFeesData
|
|
27
|
+
* @dev Mirrors contract's getTradeRealizedPnlCollateral function
|
|
28
|
+
* @param tradeFeesData Trade fees data containing realized components
|
|
29
|
+
* @returns Tuple of [realizedPnlCollateral, realizedTradingFeesCollateral, totalRealizedPnlCollateral]
|
|
30
|
+
*/
|
|
31
|
+
const getTradeRealizedPnlCollateral = (tradeFeesData) => {
|
|
32
|
+
const realizedPnlCollateral = tradeFeesData.realizedPnlCollateral;
|
|
33
|
+
const realizedTradingFeesCollateral = tradeFeesData.realizedTradingFeesCollateral;
|
|
34
|
+
const totalRealizedPnlCollateral = realizedPnlCollateral - realizedTradingFeesCollateral;
|
|
35
|
+
return {
|
|
36
|
+
realizedPnlCollateral,
|
|
37
|
+
realizedTradingFeesCollateral,
|
|
38
|
+
totalRealizedPnlCollateral,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
exports.getTradeRealizedPnlCollateral = getTradeRealizedPnlCollateral;
|
|
25
42
|
/**
|
|
26
43
|
* @dev Calculates PnL percentage for a position
|
|
27
44
|
* @dev Mirrors contract's getPnlPercent function
|
|
@@ -93,7 +110,8 @@ const getComprehensivePnl = (trade, currentPrice, tradeInfo, context) => {
|
|
|
93
110
|
traderFeeMultiplier: context.trading.traderFeeMultiplier,
|
|
94
111
|
});
|
|
95
112
|
// Total fees
|
|
96
|
-
const
|
|
113
|
+
const totalHoldingFees = borrowingFeeV1 + borrowingFeeV2 + fundingFee;
|
|
114
|
+
const totalFees = totalHoldingFees + closingFee;
|
|
97
115
|
// Check liquidation
|
|
98
116
|
const liquidationThreshold = ((_a = context.tradeData) === null || _a === void 0 ? void 0 : _a.liquidationParams)
|
|
99
117
|
? (0, liquidation_1.getLiqPnlThresholdP)(context.tradeData.liquidationParams, trade.leverage) *
|
|
@@ -104,20 +122,19 @@ const getComprehensivePnl = (trade, currentPrice, tradeInfo, context) => {
|
|
|
104
122
|
if (isLiquidated) {
|
|
105
123
|
pnlPercent = -100;
|
|
106
124
|
}
|
|
125
|
+
// Get realized PnL components from TradeFeesData
|
|
126
|
+
const { totalRealizedPnlCollateral } = (0, exports.getTradeRealizedPnlCollateral)(context.tradeData.tradeFeesData);
|
|
107
127
|
// Calculate final trade value
|
|
108
128
|
const tradeValue = (0, exports.getTradeValue)(trade.collateralAmount, pnlPercent, totalFees);
|
|
109
129
|
// Calculate PnL in collateral
|
|
110
130
|
const pnlCollateral = trade.collateralAmount * (pnlPercent / 100);
|
|
111
131
|
// Calculate leveraged position size
|
|
112
132
|
const leveragedPositionSize = trade.collateralAmount * trade.leverage;
|
|
113
|
-
// Calculate net PnL after fees
|
|
114
|
-
const netPnlAfterFees = pnlCollateral - totalFees;
|
|
115
133
|
// Calculate unrealized PnL (before closing fee, after holding fees)
|
|
116
|
-
const
|
|
117
|
-
const uPnlCollateral = pnlCollateral - totalHoldingFees;
|
|
134
|
+
const uPnlCollateral = pnlCollateral - totalHoldingFees + totalRealizedPnlCollateral;
|
|
118
135
|
const uPnlPercent = (uPnlCollateral / trade.collateralAmount) * 100;
|
|
119
136
|
// Realized PnL (after all fees including closing)
|
|
120
|
-
const realizedPnlCollateral = pnlCollateral - totalFees;
|
|
137
|
+
const realizedPnlCollateral = pnlCollateral - totalFees + totalRealizedPnlCollateral;
|
|
121
138
|
const realizedPnlPercent = (realizedPnlCollateral / trade.collateralAmount) * 100;
|
|
122
139
|
return {
|
|
123
140
|
// Core PnL values
|
|
@@ -143,7 +160,6 @@ const getComprehensivePnl = (trade, currentPrice, tradeInfo, context) => {
|
|
|
143
160
|
isProfitable: pnlPercent > 0,
|
|
144
161
|
// Additional info
|
|
145
162
|
leveragedPositionSize,
|
|
146
|
-
netPnlAfterFees,
|
|
147
163
|
};
|
|
148
164
|
};
|
|
149
165
|
exports.getComprehensivePnl = getComprehensivePnl;
|
package/lib/trade/pnl/types.d.ts
CHANGED
|
@@ -12,17 +12,20 @@ const types_1 = require("../../../contracts/types");
|
|
|
12
12
|
var builder_1 = require("./builder");
|
|
13
13
|
Object.defineProperty(exports, "buildTradeClosingPriceImpactContext", { enumerable: true, get: function () { return builder_1.buildTradeClosingPriceImpactContext; } });
|
|
14
14
|
/**
|
|
15
|
-
* @dev Calculates position size in tokens for
|
|
16
|
-
* @param
|
|
15
|
+
* @dev Calculates position size in tokens for the portion being closed
|
|
16
|
+
* @param positionSizeCollateral Position size in collateral units being closed
|
|
17
|
+
* @param originalPositionSizeToken Original total position size in tokens
|
|
17
18
|
* @param originalCollateral Original collateral amount
|
|
18
|
-
* @param
|
|
19
|
-
* @returns
|
|
19
|
+
* @param originalLeverage Original leverage
|
|
20
|
+
* @returns Position size in tokens for the closing portion
|
|
20
21
|
*/
|
|
21
|
-
const calculateClosingPositionSizeToken = (originalPositionSizeToken, originalCollateral,
|
|
22
|
-
|
|
22
|
+
const calculateClosingPositionSizeToken = (positionSizeCollateral, originalPositionSizeToken, originalCollateral, originalLeverage) => {
|
|
23
|
+
const totalPositionSizeCollateral = originalCollateral * originalLeverage;
|
|
24
|
+
if (totalPositionSizeCollateral === 0)
|
|
23
25
|
return 0;
|
|
24
|
-
//
|
|
25
|
-
return (
|
|
26
|
+
// Match contract logic: (positionSizeCollateral * originalPositionSizeToken) / totalPositionSizeCollateral
|
|
27
|
+
return ((positionSizeCollateral * originalPositionSizeToken) /
|
|
28
|
+
totalPositionSizeCollateral);
|
|
26
29
|
};
|
|
27
30
|
/**
|
|
28
31
|
* @dev Calculates all price impacts for trade closing
|
|
@@ -46,7 +49,7 @@ const getTradeClosingPriceImpact = (input, context) => {
|
|
|
46
49
|
}
|
|
47
50
|
// Calculate position size in tokens (proportional to collateral being closed)
|
|
48
51
|
const positionSizeToken = input.trade.positionSizeToken
|
|
49
|
-
? calculateClosingPositionSizeToken(input.trade.positionSizeToken, input.trade.collateralAmount, input.
|
|
52
|
+
? calculateClosingPositionSizeToken(input.positionSizeCollateral, input.trade.positionSizeToken, input.trade.collateralAmount, input.trade.leverage)
|
|
50
53
|
: 0;
|
|
51
54
|
// Calculate fixed spread (reversed for closing)
|
|
52
55
|
const fixedSpreadP = (0, cumulVol_1.getFixedSpreadP)(input.pairSpreadP, input.trade.long, false // closing
|