@drift-labs/sdk 2.34.1-beta.2 → 2.34.1-beta.4
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/VERSION +1 -1
- package/lib/dlob/DLOB.js +3 -12
- package/lib/math/funding.d.ts +3 -12
- package/lib/math/funding.js +71 -113
- package/lib/user.d.ts +2 -1
- package/lib/user.js +36 -3
- package/package.json +2 -1
- package/src/dlob/DLOB.ts +3 -12
- package/src/math/funding.ts +142 -142
- package/src/user.ts +57 -6
- package/tests/amm/test.ts +122 -0
- package/tests/dlob/helpers.ts +6 -5
- package/tests/spot/test.ts +43 -2
- package/tests/user/helpers.ts +89 -0
- package/tests/user/test.ts +286 -0
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.34.1-beta.
|
|
1
|
+
2.34.1-beta.4
|
package/lib/dlob/DLOB.js
CHANGED
|
@@ -490,18 +490,9 @@ class DLOB {
|
|
|
490
490
|
return nodesToFill;
|
|
491
491
|
}
|
|
492
492
|
// All bids/asks that can expire
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
nodeLists.floatingLimit.bid.getGenerator(),
|
|
497
|
-
nodeLists.market.bid.getGenerator(),
|
|
498
|
-
];
|
|
499
|
-
const askGenerators = [
|
|
500
|
-
nodeLists.takingLimit.ask.getGenerator(),
|
|
501
|
-
nodeLists.restingLimit.ask.getGenerator(),
|
|
502
|
-
nodeLists.floatingLimit.ask.getGenerator(),
|
|
503
|
-
nodeLists.market.ask.getGenerator(),
|
|
504
|
-
];
|
|
493
|
+
// dont try to expire limit orders with tif as its inefficient use of blockspace
|
|
494
|
+
const bidGenerators = [nodeLists.market.bid.getGenerator()];
|
|
495
|
+
const askGenerators = [nodeLists.market.ask.getGenerator()];
|
|
505
496
|
for (const bidGenerator of bidGenerators) {
|
|
506
497
|
for (const bid of bidGenerator) {
|
|
507
498
|
if ((0, __1.isOrderExpired)(bid.order, ts)) {
|
package/lib/math/funding.d.ts
CHANGED
|
@@ -8,16 +8,15 @@ import { OraclePriceData } from '../oracles/types';
|
|
|
8
8
|
* @param periodAdjustment
|
|
9
9
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
10
10
|
*/
|
|
11
|
-
export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData,
|
|
11
|
+
export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN, BN, BN, BN]>;
|
|
12
12
|
/**
|
|
13
13
|
*
|
|
14
14
|
* @param market
|
|
15
15
|
* @param oraclePriceData
|
|
16
16
|
* @param periodAdjustment
|
|
17
|
-
* @param estimationMethod
|
|
18
17
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
19
18
|
*/
|
|
20
|
-
export declare function
|
|
19
|
+
export declare function calculateLongShortFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN]>;
|
|
21
20
|
/**
|
|
22
21
|
*
|
|
23
22
|
* @param market
|
|
@@ -25,15 +24,7 @@ export declare function calculateEstimatedFundingRate(market: PerpMarketAccount,
|
|
|
25
24
|
* @param periodAdjustment
|
|
26
25
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
27
26
|
*/
|
|
28
|
-
export declare function
|
|
29
|
-
/**
|
|
30
|
-
*
|
|
31
|
-
* @param market
|
|
32
|
-
* @param oraclePriceData
|
|
33
|
-
* @param periodAdjustment
|
|
34
|
-
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
35
|
-
*/
|
|
36
|
-
export declare function calculateLongShortFundingRateAndLiveTwaps(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN]>;
|
|
27
|
+
export declare function calculateLongShortFundingRateAndLiveTwaps(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN, BN, BN]>;
|
|
37
28
|
/**
|
|
38
29
|
*
|
|
39
30
|
* @param market
|
package/lib/math/funding.js
CHANGED
|
@@ -1,10 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.
|
|
3
|
+
exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.calculateAllEstimatedFundingRate = void 0;
|
|
4
4
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
7
|
const amm_1 = require("./amm");
|
|
8
|
+
const oracles_1 = require("./oracles");
|
|
9
|
+
function calculateLiveMarkTwap(market, oraclePriceData, markPrice, now, period = new anchor_1.BN(3600)) {
|
|
10
|
+
now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
|
|
11
|
+
const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
|
|
12
|
+
const lastMarkPriceTwapTs = market.amm.lastMarkPriceTwapTs;
|
|
13
|
+
const timeSinceLastMarkChange = now.sub(lastMarkPriceTwapTs);
|
|
14
|
+
const markTwapTimeSinceLastUpdate = anchor_1.BN.max(period, anchor_1.BN.max(numericConstants_1.ZERO, period.sub(timeSinceLastMarkChange)));
|
|
15
|
+
if (!markPrice) {
|
|
16
|
+
const [bid, ask] = (0, amm_1.calculateBidAskPrice)(market.amm, oraclePriceData);
|
|
17
|
+
markPrice = bid.add(ask).div(new anchor_1.BN(2));
|
|
18
|
+
}
|
|
19
|
+
const markTwapWithMantissa = markTwapTimeSinceLastUpdate
|
|
20
|
+
.mul(lastMarkTwapWithMantissa)
|
|
21
|
+
.add(timeSinceLastMarkChange.mul(markPrice))
|
|
22
|
+
.div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
|
|
23
|
+
return markTwapWithMantissa;
|
|
24
|
+
}
|
|
25
|
+
function shrinkStaleTwaps(market, markTwapWithMantissa, oracleTwapWithMantissa, now) {
|
|
26
|
+
now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
|
|
27
|
+
let newMarkTwap = markTwapWithMantissa;
|
|
28
|
+
let newOracleTwap = oracleTwapWithMantissa;
|
|
29
|
+
if (market.amm.lastMarkPriceTwapTs.gt(market.amm.historicalOracleData.lastOraclePriceTwapTs)) {
|
|
30
|
+
// shrink oracle based on invalid intervals
|
|
31
|
+
const oracleInvalidDuration = anchor_1.BN.max(numericConstants_1.ZERO, market.amm.lastMarkPriceTwapTs.sub(market.amm.historicalOracleData.lastOraclePriceTwapTs));
|
|
32
|
+
const timeSinceLastOracleTwapUpdate = now.sub(market.amm.historicalOracleData.lastOraclePriceTwapTs);
|
|
33
|
+
const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(numericConstants_1.ONE, anchor_1.BN.min(market.amm.fundingPeriod, anchor_1.BN.max(numericConstants_1.ONE, market.amm.fundingPeriod.sub(timeSinceLastOracleTwapUpdate))));
|
|
34
|
+
newOracleTwap = oracleTwapTimeSinceLastUpdate
|
|
35
|
+
.mul(oracleTwapWithMantissa)
|
|
36
|
+
.add(oracleInvalidDuration.mul(markTwapWithMantissa))
|
|
37
|
+
.div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
|
|
38
|
+
}
|
|
39
|
+
else if (market.amm.lastMarkPriceTwapTs.lt(market.amm.historicalOracleData.lastOraclePriceTwapTs)) {
|
|
40
|
+
// shrink mark to oracle twap over tradless intervals
|
|
41
|
+
const tradelessDuration = anchor_1.BN.max(numericConstants_1.ZERO, market.amm.historicalOracleData.lastOraclePriceTwapTs.sub(market.amm.lastMarkPriceTwapTs));
|
|
42
|
+
const timeSinceLastMarkTwapUpdate = now.sub(market.amm.lastMarkPriceTwapTs);
|
|
43
|
+
const markTwapTimeSinceLastUpdate = anchor_1.BN.max(numericConstants_1.ONE, anchor_1.BN.min(market.amm.fundingPeriod, anchor_1.BN.max(numericConstants_1.ONE, market.amm.fundingPeriod.sub(timeSinceLastMarkTwapUpdate))));
|
|
44
|
+
newMarkTwap = markTwapTimeSinceLastUpdate
|
|
45
|
+
.mul(markTwapWithMantissa)
|
|
46
|
+
.add(tradelessDuration.mul(oracleTwapWithMantissa))
|
|
47
|
+
.div(markTwapTimeSinceLastUpdate.add(tradelessDuration));
|
|
48
|
+
}
|
|
49
|
+
return [newMarkTwap, newOracleTwap];
|
|
50
|
+
}
|
|
8
51
|
/**
|
|
9
52
|
*
|
|
10
53
|
* @param market
|
|
@@ -12,76 +55,38 @@ const amm_1 = require("./amm");
|
|
|
12
55
|
* @param periodAdjustment
|
|
13
56
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
14
57
|
*/
|
|
15
|
-
async function calculateAllEstimatedFundingRate(market, oraclePriceData,
|
|
16
|
-
// periodAdjustment
|
|
17
|
-
// 1: hourly
|
|
18
|
-
// 24: daily
|
|
19
|
-
// 24 * 365.25: annualized
|
|
20
|
-
const secondsInHour = new anchor_1.BN(3600);
|
|
21
|
-
const hoursInDay = new anchor_1.BN(24);
|
|
22
|
-
const ONE = new anchor_1.BN(1);
|
|
58
|
+
async function calculateAllEstimatedFundingRate(market, oraclePriceData, markPrice, now) {
|
|
23
59
|
if ((0, types_1.isVariant)(market.status, 'uninitialized')) {
|
|
24
60
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
25
61
|
}
|
|
26
|
-
const payFreq = new anchor_1.BN(market.amm.fundingPeriod);
|
|
27
62
|
// todo: sufficiently differs from blockchain timestamp?
|
|
28
63
|
now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
.div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
|
|
41
|
-
// calculate real-time (predicted) oracle twap
|
|
42
|
-
// note: oracle twap depends on `when the chord is struck` (market is trade)
|
|
43
|
-
const lastOracleTwapWithMantissa = market.amm.historicalOracleData.lastOraclePriceTwap;
|
|
44
|
-
const lastOraclePriceTwapTs = market.amm.historicalOracleData.lastOraclePriceTwapTs;
|
|
45
|
-
const oracleInvalidDuration = anchor_1.BN.max(numericConstants_1.ZERO, lastMarkPriceTwapTs.sub(lastOraclePriceTwapTs));
|
|
46
|
-
const timeSinceLastOracleTwapUpdate = now.sub(lastOraclePriceTwapTs);
|
|
47
|
-
const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(ONE, anchor_1.BN.min(secondsInHour, anchor_1.BN.max(ONE, secondsInHour.sub(timeSinceLastOracleTwapUpdate))));
|
|
48
|
-
let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
|
|
49
|
-
// if passing live oracle data, improve predicted calc estimate
|
|
50
|
-
if (oraclePriceData) {
|
|
51
|
-
const oraclePrice = oraclePriceData.price;
|
|
52
|
-
const oracleLiveVsTwap = oraclePrice
|
|
53
|
-
.sub(lastOracleTwapWithMantissa)
|
|
54
|
-
.abs()
|
|
55
|
-
.mul(numericConstants_1.PRICE_PRECISION)
|
|
56
|
-
.mul(new anchor_1.BN(100))
|
|
57
|
-
.div(lastOracleTwapWithMantissa);
|
|
58
|
-
// verify pyth live input is within 20% of last twap for live update
|
|
59
|
-
if (oracleLiveVsTwap.lte(numericConstants_1.PRICE_PRECISION.mul(new anchor_1.BN(20)))) {
|
|
60
|
-
oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
61
|
-
.mul(lastOracleTwapWithMantissa)
|
|
62
|
-
.add(timeSinceLastMarkChange.mul(oraclePrice))
|
|
63
|
-
.div(timeSinceLastMarkChange.add(oracleTwapTimeSinceLastUpdate));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const shrunkLastOracleTwapwithMantissa = oracleTwapTimeSinceLastUpdate
|
|
67
|
-
.mul(oracleTwapWithMantissa)
|
|
68
|
-
.add(oracleInvalidDuration.mul(lastMarkTwapWithMantissa))
|
|
69
|
-
.div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
|
|
70
|
-
const twapSpread = markTwapWithMantissa.sub(shrunkLastOracleTwapwithMantissa);
|
|
64
|
+
// calculate real-time mark and oracle twap
|
|
65
|
+
const liveMarkTwap = calculateLiveMarkTwap(market, oraclePriceData, markPrice, now, market.amm.fundingPeriod);
|
|
66
|
+
const liveOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(market.amm.historicalOracleData, oraclePriceData, now, market.amm.fundingPeriod);
|
|
67
|
+
const [markTwap, oracleTwap] = shrinkStaleTwaps(market, liveMarkTwap, liveOracleTwap, now);
|
|
68
|
+
// if(!markTwap.eq(liveMarkTwap)){
|
|
69
|
+
// console.log('shrink mark:', liveMarkTwap.toString(), '->', markTwap.toString());
|
|
70
|
+
// }
|
|
71
|
+
// if(!oracleTwap.eq(liveOracleTwap)){
|
|
72
|
+
// console.log('shrink orac:', liveOracleTwap.toString(), '->', oracleTwap.toString());
|
|
73
|
+
// }
|
|
74
|
+
const twapSpread = markTwap.sub(oracleTwap);
|
|
71
75
|
const twapSpreadPct = twapSpread
|
|
72
76
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
73
77
|
.mul(new anchor_1.BN(100))
|
|
74
|
-
.div(
|
|
78
|
+
.div(oracleTwap);
|
|
79
|
+
const secondsInHour = new anchor_1.BN(3600);
|
|
80
|
+
const hoursInDay = new anchor_1.BN(24);
|
|
81
|
+
const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
|
|
75
82
|
const lowerboundEst = twapSpreadPct
|
|
76
|
-
.mul(
|
|
83
|
+
.mul(market.amm.fundingPeriod)
|
|
77
84
|
.mul(anchor_1.BN.min(secondsInHour, timeSinceLastUpdate))
|
|
78
|
-
.mul(periodAdjustment)
|
|
79
85
|
.div(secondsInHour)
|
|
80
86
|
.div(secondsInHour)
|
|
81
87
|
.div(hoursInDay);
|
|
82
|
-
const interpEst = twapSpreadPct.
|
|
88
|
+
const interpEst = twapSpreadPct.div(hoursInDay);
|
|
83
89
|
const interpRateQuote = twapSpreadPct
|
|
84
|
-
.mul(periodAdjustment)
|
|
85
90
|
.div(hoursInDay)
|
|
86
91
|
.div(numericConstants_1.PRICE_PRECISION.div(numericConstants_1.QUOTE_PRECISION));
|
|
87
92
|
let feePoolSize = calculateFundingPool(market);
|
|
@@ -95,36 +100,18 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
|
|
|
95
100
|
largerSide = market.amm.baseAssetAmountLong.abs();
|
|
96
101
|
smallerSide = market.amm.baseAssetAmountShort.abs();
|
|
97
102
|
if (twapSpread.gt(new anchor_1.BN(0))) {
|
|
98
|
-
return [
|
|
99
|
-
markTwapWithMantissa,
|
|
100
|
-
oracleTwapWithMantissa,
|
|
101
|
-
lowerboundEst,
|
|
102
|
-
interpEst,
|
|
103
|
-
interpEst,
|
|
104
|
-
];
|
|
103
|
+
return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
|
|
105
104
|
}
|
|
106
105
|
}
|
|
107
106
|
else if (market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())) {
|
|
108
107
|
largerSide = market.amm.baseAssetAmountShort.abs();
|
|
109
108
|
smallerSide = market.amm.baseAssetAmountLong.abs();
|
|
110
109
|
if (twapSpread.lt(new anchor_1.BN(0))) {
|
|
111
|
-
return [
|
|
112
|
-
markTwapWithMantissa,
|
|
113
|
-
oracleTwapWithMantissa,
|
|
114
|
-
lowerboundEst,
|
|
115
|
-
interpEst,
|
|
116
|
-
interpEst,
|
|
117
|
-
];
|
|
110
|
+
return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
|
|
118
111
|
}
|
|
119
112
|
}
|
|
120
113
|
else {
|
|
121
|
-
return [
|
|
122
|
-
markTwapWithMantissa,
|
|
123
|
-
oracleTwapWithMantissa,
|
|
124
|
-
lowerboundEst,
|
|
125
|
-
interpEst,
|
|
126
|
-
interpEst,
|
|
127
|
-
];
|
|
114
|
+
return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
|
|
128
115
|
}
|
|
129
116
|
if (largerSide.gt(numericConstants_1.ZERO)) {
|
|
130
117
|
// funding smaller flow
|
|
@@ -136,8 +123,7 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
|
|
|
136
123
|
cappedAltEst = cappedAltEst
|
|
137
124
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
138
125
|
.mul(new anchor_1.BN(100))
|
|
139
|
-
.div(
|
|
140
|
-
.mul(periodAdjustment);
|
|
126
|
+
.div(oracleTwap);
|
|
141
127
|
if (cappedAltEst.abs().gte(interpEst.abs())) {
|
|
142
128
|
cappedAltEst = interpEst;
|
|
143
129
|
}
|
|
@@ -145,37 +131,9 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
|
|
|
145
131
|
else {
|
|
146
132
|
cappedAltEst = interpEst;
|
|
147
133
|
}
|
|
148
|
-
return [
|
|
149
|
-
markTwapWithMantissa,
|
|
150
|
-
oracleTwapWithMantissa,
|
|
151
|
-
lowerboundEst,
|
|
152
|
-
cappedAltEst,
|
|
153
|
-
interpEst,
|
|
154
|
-
];
|
|
134
|
+
return [markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst];
|
|
155
135
|
}
|
|
156
136
|
exports.calculateAllEstimatedFundingRate = calculateAllEstimatedFundingRate;
|
|
157
|
-
/**
|
|
158
|
-
*
|
|
159
|
-
* @param market
|
|
160
|
-
* @param oraclePriceData
|
|
161
|
-
* @param periodAdjustment
|
|
162
|
-
* @param estimationMethod
|
|
163
|
-
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
164
|
-
*/
|
|
165
|
-
async function calculateEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1), estimationMethod) {
|
|
166
|
-
const [_1, _2, lowerboundEst, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
|
|
167
|
-
if (estimationMethod == 'lowerbound') {
|
|
168
|
-
//assuming remaining funding period has no gap
|
|
169
|
-
return lowerboundEst;
|
|
170
|
-
}
|
|
171
|
-
else if (estimationMethod == 'capped') {
|
|
172
|
-
return cappedAltEst;
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
return interpEst;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
exports.calculateEstimatedFundingRate = calculateEstimatedFundingRate;
|
|
179
137
|
/**
|
|
180
138
|
*
|
|
181
139
|
* @param market
|
|
@@ -183,8 +141,8 @@ exports.calculateEstimatedFundingRate = calculateEstimatedFundingRate;
|
|
|
183
141
|
* @param periodAdjustment
|
|
184
142
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
185
143
|
*/
|
|
186
|
-
async function calculateLongShortFundingRate(market, oraclePriceData,
|
|
187
|
-
const [_1, _2, _, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData,
|
|
144
|
+
async function calculateLongShortFundingRate(market, oraclePriceData, markPrice, now) {
|
|
145
|
+
const [_1, _2, _, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, markPrice, now);
|
|
188
146
|
if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort)) {
|
|
189
147
|
return [cappedAltEst, interpEst];
|
|
190
148
|
}
|
|
@@ -203,8 +161,8 @@ exports.calculateLongShortFundingRate = calculateLongShortFundingRate;
|
|
|
203
161
|
* @param periodAdjustment
|
|
204
162
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
205
163
|
*/
|
|
206
|
-
async function calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData,
|
|
207
|
-
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData,
|
|
164
|
+
async function calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData, markPrice, now) {
|
|
165
|
+
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, markPrice, now);
|
|
208
166
|
if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())) {
|
|
209
167
|
return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
|
|
210
168
|
}
|
package/lib/user.d.ts
CHANGED
|
@@ -190,10 +190,11 @@ export declare class User {
|
|
|
190
190
|
getTotalAssetValue(marginCategory?: MarginCategory): BN;
|
|
191
191
|
/**
|
|
192
192
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
193
|
+
* for large sizes where imf factor activates, result is a lower bound
|
|
193
194
|
* @params category {Initial, Maintenance}
|
|
194
195
|
* @returns : Precision TEN_THOUSAND
|
|
195
196
|
*/
|
|
196
|
-
getMaxLeverageForPerp(perpMarketIndex: number,
|
|
197
|
+
getMaxLeverageForPerp(perpMarketIndex: number, marginCategory?: MarginCategory): BN;
|
|
197
198
|
/**
|
|
198
199
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
199
200
|
* @param spotMarketIndex
|
package/lib/user.js
CHANGED
|
@@ -791,11 +791,13 @@ class User {
|
|
|
791
791
|
}
|
|
792
792
|
/**
|
|
793
793
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
794
|
+
* for large sizes where imf factor activates, result is a lower bound
|
|
794
795
|
* @params category {Initial, Maintenance}
|
|
795
796
|
* @returns : Precision TEN_THOUSAND
|
|
796
797
|
*/
|
|
797
|
-
getMaxLeverageForPerp(perpMarketIndex,
|
|
798
|
+
getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial') {
|
|
798
799
|
const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
|
|
800
|
+
const marketPrice = this.driftClient.getOracleDataForPerpMarket(perpMarketIndex).price;
|
|
799
801
|
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
800
802
|
const totalAssetValue = spotAssetValue.add(perpPnl);
|
|
801
803
|
const netAssetValue = totalAssetValue.sub(spotLiabilityValue);
|
|
@@ -803,9 +805,40 @@ class User {
|
|
|
803
805
|
return numericConstants_1.ZERO;
|
|
804
806
|
}
|
|
805
807
|
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
806
|
-
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, numericConstants_1.ZERO, // todo
|
|
807
|
-
category);
|
|
808
808
|
const freeCollateral = this.getFreeCollateral();
|
|
809
|
+
let rawMarginRatio;
|
|
810
|
+
switch (marginCategory) {
|
|
811
|
+
case 'Initial':
|
|
812
|
+
rawMarginRatio = market.marginRatioInitial;
|
|
813
|
+
break;
|
|
814
|
+
case 'Maintenance':
|
|
815
|
+
rawMarginRatio = market.marginRatioMaintenance;
|
|
816
|
+
break;
|
|
817
|
+
default:
|
|
818
|
+
rawMarginRatio = market.marginRatioInitial;
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
// absolute max fesible size (upper bound)
|
|
822
|
+
const maxSize = _1.BN.max(numericConstants_1.ZERO, freeCollateral
|
|
823
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
824
|
+
.div(new _1.BN(rawMarginRatio))
|
|
825
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
826
|
+
.div(marketPrice));
|
|
827
|
+
// margin ratio incorporting upper bound on size
|
|
828
|
+
let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory);
|
|
829
|
+
// use more fesible size since imf factor activated
|
|
830
|
+
let attempts = 0;
|
|
831
|
+
while (marginRatio > rawMarginRatio + 1e-4 && attempts < 10) {
|
|
832
|
+
// more fesible size (upper bound)
|
|
833
|
+
const targetSize = _1.BN.max(numericConstants_1.ZERO, freeCollateral
|
|
834
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
835
|
+
.div(new _1.BN(marginRatio))
|
|
836
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
837
|
+
.div(marketPrice));
|
|
838
|
+
// margin ratio incorporting more fesible target size
|
|
839
|
+
marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory);
|
|
840
|
+
attempts += 1;
|
|
841
|
+
}
|
|
809
842
|
// how much more liabilities can be opened w remaining free collateral
|
|
810
843
|
const additionalLiabilities = freeCollateral
|
|
811
844
|
.mul(numericConstants_1.MARGIN_PRECISION)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.34.1-beta.
|
|
3
|
+
"version": "2.34.1-beta.4",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"eslint": "^7.29.0",
|
|
54
54
|
"eslint-config-prettier": "^8.3.0",
|
|
55
55
|
"eslint-plugin-prettier": "^3.4.0",
|
|
56
|
+
"lodash": "^4.17.21",
|
|
56
57
|
"mocha": "^10.0.0",
|
|
57
58
|
"prettier": "^2.4.1",
|
|
58
59
|
"ts-node": "^10.8.0",
|
package/src/dlob/DLOB.ts
CHANGED
|
@@ -930,18 +930,9 @@ export class DLOB {
|
|
|
930
930
|
}
|
|
931
931
|
|
|
932
932
|
// All bids/asks that can expire
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
nodeLists.floatingLimit.bid.getGenerator(),
|
|
937
|
-
nodeLists.market.bid.getGenerator(),
|
|
938
|
-
];
|
|
939
|
-
const askGenerators = [
|
|
940
|
-
nodeLists.takingLimit.ask.getGenerator(),
|
|
941
|
-
nodeLists.restingLimit.ask.getGenerator(),
|
|
942
|
-
nodeLists.floatingLimit.ask.getGenerator(),
|
|
943
|
-
nodeLists.market.ask.getGenerator(),
|
|
944
|
-
];
|
|
933
|
+
// dont try to expire limit orders with tif as its inefficient use of blockspace
|
|
934
|
+
const bidGenerators = [nodeLists.market.bid.getGenerator()];
|
|
935
|
+
const askGenerators = [nodeLists.market.ask.getGenerator()];
|
|
945
936
|
|
|
946
937
|
for (const bidGenerator of bidGenerators) {
|
|
947
938
|
for (const bid of bidGenerator) {
|