@drift-labs/sdk 0.2.0-master.1 → 0.2.0-master.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/lib/accounts/types.d.ts +1 -0
- package/lib/admin.d.ts +4 -1
- package/lib/admin.js +29 -2
- package/lib/clearingHouse.d.ts +11 -14
- package/lib/clearingHouse.js +73 -73
- package/lib/config.js +1 -1
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.js +2 -1
- package/lib/factory/bigNum.d.ts +8 -2
- package/lib/factory/bigNum.js +14 -6
- package/lib/idl/clearing_house.json +189 -52
- package/lib/index.d.ts +2 -1
- package/lib/index.js +6 -1
- package/lib/math/amm.d.ts +6 -1
- package/lib/math/amm.js +124 -41
- package/lib/math/auction.js +4 -1
- package/lib/math/orders.d.ts +2 -2
- package/lib/math/orders.js +18 -11
- package/lib/math/repeg.js +1 -1
- package/lib/math/trade.d.ts +1 -1
- package/lib/math/trade.js +7 -10
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +8 -96
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +6 -85
- package/lib/types.d.ts +62 -1
- package/lib/types.js +37 -1
- package/package.json +3 -3
- package/src/admin.ts +48 -4
- package/src/clearingHouse.ts +102 -151
- package/src/config.ts +1 -1
- package/src/constants/numericConstants.ts +1 -0
- package/src/factory/bigNum.ts +26 -9
- package/src/idl/clearing_house.json +189 -52
- package/src/index.ts +2 -1
- package/src/math/amm.ts +207 -52
- package/src/math/auction.ts +5 -1
- package/src/math/orders.ts +17 -13
- package/src/math/repeg.ts +2 -1
- package/src/math/trade.ts +23 -25
- package/src/orderParams.ts +20 -141
- package/src/orders.ts +7 -131
- package/src/types.ts +58 -3
package/lib/math/amm.js
CHANGED
|
@@ -1,25 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = void 0;
|
|
3
|
+
exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateSpreadBN = exports.calculateMaxSpread = exports.calculateEffectiveLeverage = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = exports.calculateOptimalPegAndBudget = exports.calculatePegFromTargetPrice = void 0;
|
|
4
4
|
const anchor_1 = require("@project-serum/anchor");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
7
|
const assert_1 = require("../assert/assert");
|
|
8
8
|
const __1 = require("..");
|
|
9
9
|
const repeg_1 = require("./repeg");
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
function calculatePegFromTargetPrice(targetPrice, baseAssetReserve, quoteAssetReserve) {
|
|
11
|
+
return targetPrice
|
|
12
|
+
.mul(baseAssetReserve)
|
|
13
|
+
.div(quoteAssetReserve)
|
|
14
|
+
.add(numericConstants_1.PRICE_DIV_PEG.div(new anchor_1.BN(2)))
|
|
15
|
+
.div(numericConstants_1.PRICE_DIV_PEG);
|
|
16
|
+
}
|
|
17
|
+
exports.calculatePegFromTargetPrice = calculatePegFromTargetPrice;
|
|
18
|
+
function calculateOptimalPegAndBudget(amm, oraclePriceData) {
|
|
19
|
+
const markPriceBefore = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
13
20
|
const targetPrice = oraclePriceData.price;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
.div(amm.quoteAssetReserve)
|
|
17
|
-
.add(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION).div(new anchor_1.BN(2)))
|
|
18
|
-
.div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
|
|
19
|
-
let prePegCost = (0, repeg_1.calculateRepegCost)(amm, newPeg);
|
|
21
|
+
const newPeg = calculatePegFromTargetPrice(targetPrice, amm.baseAssetReserve, amm.quoteAssetReserve);
|
|
22
|
+
const prePegCost = (0, repeg_1.calculateRepegCost)(amm, newPeg);
|
|
20
23
|
const totalFeeLB = amm.totalExchangeFee.div(new anchor_1.BN(2));
|
|
21
24
|
const budget = anchor_1.BN.max(numericConstants_1.ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
|
|
22
|
-
if (
|
|
25
|
+
if (budget.lt(prePegCost)) {
|
|
26
|
+
const maxPriceSpread = new anchor_1.BN(amm.maxSpread)
|
|
27
|
+
.mul(targetPrice)
|
|
28
|
+
.div(numericConstants_1.BID_ASK_SPREAD_PRECISION);
|
|
29
|
+
let newTargetPrice;
|
|
30
|
+
let newOptimalPeg;
|
|
31
|
+
let newBudget;
|
|
32
|
+
const targetPriceGap = markPriceBefore.sub(targetPrice);
|
|
33
|
+
if (targetPriceGap.abs().gt(maxPriceSpread)) {
|
|
34
|
+
const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
|
|
35
|
+
if (targetPriceGap.lt(new anchor_1.BN(0))) {
|
|
36
|
+
newTargetPrice = markPriceBefore.add(markAdj);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
newTargetPrice = markPriceBefore.sub(markAdj);
|
|
40
|
+
}
|
|
41
|
+
newOptimalPeg = calculatePegFromTargetPrice(newTargetPrice, amm.baseAssetReserve, amm.quoteAssetReserve);
|
|
42
|
+
newBudget = (0, repeg_1.calculateRepegCost)(amm, newOptimalPeg);
|
|
43
|
+
return [newTargetPrice, newOptimalPeg, newBudget, false];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [targetPrice, newPeg, budget, true];
|
|
47
|
+
}
|
|
48
|
+
exports.calculateOptimalPegAndBudget = calculateOptimalPegAndBudget;
|
|
49
|
+
function calculateNewAmm(amm, oraclePriceData) {
|
|
50
|
+
let pKNumer = new anchor_1.BN(1);
|
|
51
|
+
let pKDenom = new anchor_1.BN(1);
|
|
52
|
+
const [targetPrice, _newPeg, budget, checkLowerBound] = calculateOptimalPegAndBudget(amm, oraclePriceData);
|
|
53
|
+
let prePegCost = (0, repeg_1.calculateRepegCost)(amm, _newPeg);
|
|
54
|
+
let newPeg = _newPeg;
|
|
55
|
+
if (prePegCost.gt(budget) && checkLowerBound) {
|
|
23
56
|
[pKNumer, pKDenom] = [new anchor_1.BN(999), new anchor_1.BN(1000)];
|
|
24
57
|
const deficitMadeup = (0, repeg_1.calculateAdjustKCost)(amm, pKNumer, pKDenom);
|
|
25
58
|
(0, assert_1.assert)(deficitMadeup.lte(new anchor_1.BN(0)));
|
|
@@ -73,8 +106,14 @@ function calculateUpdatedAMMSpreadReserves(amm, direction, oraclePriceData) {
|
|
|
73
106
|
return result;
|
|
74
107
|
}
|
|
75
108
|
exports.calculateUpdatedAMMSpreadReserves = calculateUpdatedAMMSpreadReserves;
|
|
76
|
-
function calculateBidAskPrice(amm, oraclePriceData) {
|
|
77
|
-
|
|
109
|
+
function calculateBidAskPrice(amm, oraclePriceData, withUpdate = true) {
|
|
110
|
+
let newAmm;
|
|
111
|
+
if (withUpdate) {
|
|
112
|
+
newAmm = calculateUpdatedAMM(amm, oraclePriceData);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
newAmm = amm;
|
|
116
|
+
}
|
|
78
117
|
const askReserves = calculateSpreadReserves(newAmm, types_1.PositionDirection.LONG, oraclePriceData);
|
|
79
118
|
const bidReserves = calculateSpreadReserves(newAmm, types_1.PositionDirection.SHORT, oraclePriceData);
|
|
80
119
|
const askPrice = calculatePrice(askReserves.baseAssetReserve, askReserves.quoteAssetReserve, newAmm.pegMultiplier);
|
|
@@ -126,44 +165,88 @@ function calculateAmmReservesAfterSwap(amm, inputAssetType, swapAmount, swapDire
|
|
|
126
165
|
return [newQuoteAssetReserve, newBaseAssetReserve];
|
|
127
166
|
}
|
|
128
167
|
exports.calculateAmmReservesAfterSwap = calculateAmmReservesAfterSwap;
|
|
168
|
+
function calculateEffectiveLeverage(baseSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions) {
|
|
169
|
+
// inventory skew
|
|
170
|
+
const netBaseAssetValue = quoteAssetReserve
|
|
171
|
+
.sub(terminalQuoteAssetReserve)
|
|
172
|
+
.mul(pegMultiplier)
|
|
173
|
+
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
174
|
+
const localBaseAssetValue = netBaseAssetAmount
|
|
175
|
+
.mul(markPrice)
|
|
176
|
+
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
|
|
177
|
+
const effectiveLeverage = localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
|
|
178
|
+
(Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
|
|
179
|
+
1 / numericConstants_1.QUOTE_PRECISION.toNumber();
|
|
180
|
+
return effectiveLeverage;
|
|
181
|
+
}
|
|
182
|
+
exports.calculateEffectiveLeverage = calculateEffectiveLeverage;
|
|
183
|
+
function calculateMaxSpread(marginRatioInitial) {
|
|
184
|
+
const maxTargetSpread = new anchor_1.BN(marginRatioInitial)
|
|
185
|
+
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(numericConstants_1.MARGIN_PRECISION))
|
|
186
|
+
.toNumber();
|
|
187
|
+
return maxTargetSpread;
|
|
188
|
+
}
|
|
189
|
+
exports.calculateMaxSpread = calculateMaxSpread;
|
|
190
|
+
function calculateSpreadBN(baseSpread, lastOracleMarkSpreadPct, lastOracleConfPct, maxSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions) {
|
|
191
|
+
let longSpread = baseSpread / 2;
|
|
192
|
+
let shortSpread = baseSpread / 2;
|
|
193
|
+
if (lastOracleMarkSpreadPct.gt(numericConstants_1.ZERO)) {
|
|
194
|
+
shortSpread = Math.max(shortSpread, lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber());
|
|
195
|
+
}
|
|
196
|
+
else if (lastOracleMarkSpreadPct.lt(numericConstants_1.ZERO)) {
|
|
197
|
+
longSpread = Math.max(longSpread, lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber());
|
|
198
|
+
}
|
|
199
|
+
const maxTargetSpread = maxSpread;
|
|
200
|
+
const MAX_INVENTORY_SKEW = 5;
|
|
201
|
+
const effectiveLeverage = calculateEffectiveLeverage(baseSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions);
|
|
202
|
+
if (totalFeeMinusDistributions.gt(numericConstants_1.ZERO)) {
|
|
203
|
+
const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
204
|
+
if (netBaseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
205
|
+
longSpread *= spreadScale;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
shortSpread *= spreadScale;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
longSpread *= MAX_INVENTORY_SKEW;
|
|
213
|
+
shortSpread *= MAX_INVENTORY_SKEW;
|
|
214
|
+
}
|
|
215
|
+
const totalSpread = longSpread + shortSpread;
|
|
216
|
+
if (totalSpread > maxTargetSpread) {
|
|
217
|
+
if (longSpread > shortSpread) {
|
|
218
|
+
longSpread = Math.min(longSpread, maxTargetSpread);
|
|
219
|
+
shortSpread = maxTargetSpread - longSpread;
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
shortSpread = Math.min(shortSpread, maxTargetSpread);
|
|
223
|
+
longSpread = maxTargetSpread - shortSpread;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return [longSpread, shortSpread];
|
|
227
|
+
}
|
|
228
|
+
exports.calculateSpreadBN = calculateSpreadBN;
|
|
129
229
|
function calculateSpread(amm, direction, oraclePriceData) {
|
|
130
|
-
let spread = amm.baseSpread / 2;
|
|
131
230
|
if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
|
|
132
|
-
return
|
|
231
|
+
return amm.baseSpread / 2;
|
|
133
232
|
}
|
|
134
233
|
const markPrice = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
135
234
|
const targetPrice = (oraclePriceData === null || oraclePriceData === void 0 ? void 0 : oraclePriceData.price) || markPrice;
|
|
235
|
+
const confInterval = oraclePriceData.confidence || numericConstants_1.ZERO;
|
|
136
236
|
const targetMarkSpreadPct = markPrice
|
|
137
237
|
.sub(targetPrice)
|
|
138
238
|
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
|
|
139
239
|
.div(markPrice);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
240
|
+
const confIntervalPct = confInterval
|
|
241
|
+
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
|
|
242
|
+
.div(markPrice);
|
|
243
|
+
const [longSpread, shortSpread] = calculateSpreadBN(amm.baseSpread, targetMarkSpreadPct, confIntervalPct, amm.maxSpread, amm.quoteAssetReserve, amm.terminalQuoteAssetReserve, amm.pegMultiplier, amm.netBaseAssetAmount, markPrice, amm.totalFeeMinusDistributions);
|
|
244
|
+
let spread;
|
|
245
|
+
if ((0, types_1.isVariant)(direction, 'long')) {
|
|
246
|
+
spread = longSpread;
|
|
144
247
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if ((amm.netBaseAssetAmount.gt(numericConstants_1.ZERO) && (0, types_1.isVariant)(direction, 'long')) ||
|
|
148
|
-
(amm.netBaseAssetAmount.lt(numericConstants_1.ZERO) && (0, types_1.isVariant)(direction, 'short')) ||
|
|
149
|
-
amm.totalFeeMinusDistributions.eq(numericConstants_1.ZERO)) {
|
|
150
|
-
const netCostBasis = amm.quoteAssetAmountLong.sub(amm.quoteAssetAmountShort);
|
|
151
|
-
const netBaseAssetValue = amm.quoteAssetReserve
|
|
152
|
-
.sub(amm.terminalQuoteAssetReserve)
|
|
153
|
-
.mul(amm.pegMultiplier)
|
|
154
|
-
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
155
|
-
const localBaseAssetValue = amm.netBaseAssetAmount
|
|
156
|
-
.mul(markPrice)
|
|
157
|
-
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
|
|
158
|
-
const netPnl = netBaseAssetValue.sub(netCostBasis);
|
|
159
|
-
const localPnl = localBaseAssetValue.sub(netCostBasis);
|
|
160
|
-
let effectiveLeverage = MAX_INVENTORY_SKEW;
|
|
161
|
-
if (amm.totalFeeMinusDistributions.gt(numericConstants_1.ZERO)) {
|
|
162
|
-
effectiveLeverage =
|
|
163
|
-
localPnl.sub(netPnl).toNumber() /
|
|
164
|
-
amm.totalFeeMinusDistributions.toNumber();
|
|
165
|
-
}
|
|
166
|
-
spread *= Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
248
|
+
else {
|
|
249
|
+
spread = shortSpread;
|
|
167
250
|
}
|
|
168
251
|
return spread;
|
|
169
252
|
}
|
package/lib/math/auction.js
CHANGED
|
@@ -4,7 +4,10 @@ exports.getAuctionPrice = exports.isAuctionComplete = void 0;
|
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const _1 = require("../.");
|
|
6
6
|
function isAuctionComplete(order, slot) {
|
|
7
|
-
|
|
7
|
+
if (order.auctionDuration === 0) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return new _1.BN(slot).sub(order.slot).gt(new _1.BN(order.auctionDuration));
|
|
8
11
|
}
|
|
9
12
|
exports.isAuctionComplete = isAuctionComplete;
|
|
10
13
|
function getAuctionPrice(order, slot) {
|
package/lib/math/orders.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { ClearingHouseUser } from '../clearingHouseUser';
|
|
3
|
-
import { Order } from '../types';
|
|
3
|
+
import { MarketAccount, Order } from '../types';
|
|
4
4
|
import { BN } from '@project-serum/anchor';
|
|
5
5
|
import { OraclePriceData } from '../oracles/types';
|
|
6
6
|
export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Order): boolean;
|
|
7
7
|
export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
|
|
8
8
|
export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
|
|
9
9
|
export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
|
|
10
|
-
export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number): BN;
|
|
10
|
+
export declare function getLimitPrice(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
|
package/lib/math/orders.js
CHANGED
|
@@ -5,6 +5,7 @@ const types_1 = require("../types");
|
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
const anchor_1 = require("@project-serum/anchor");
|
|
7
7
|
const auction_1 = require("./auction");
|
|
8
|
+
const market_1 = require("./market");
|
|
8
9
|
function isOrderRiskIncreasing(user, order) {
|
|
9
10
|
if ((0, types_1.isVariant)(order.status, 'init')) {
|
|
10
11
|
return false;
|
|
@@ -78,23 +79,29 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
|
|
|
78
79
|
return baseAssetAmount.sub(remainder);
|
|
79
80
|
}
|
|
80
81
|
exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
|
|
81
|
-
function getLimitPrice(order, oraclePriceData, slot) {
|
|
82
|
+
function getLimitPrice(order, market, oraclePriceData, slot) {
|
|
82
83
|
let limitPrice;
|
|
83
84
|
if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
86
|
+
}
|
|
87
|
+
else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
|
|
88
|
+
if ((0, auction_1.isAuctionComplete)(order, slot)) {
|
|
89
|
+
limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
|
|
90
|
+
}
|
|
91
|
+
else if (!order.price.eq(numericConstants_1.ZERO)) {
|
|
92
|
+
limitPrice = order.price;
|
|
93
|
+
}
|
|
94
|
+
else if ((0, types_1.isVariant)(order.direction, 'long')) {
|
|
95
|
+
const askPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
|
|
96
|
+
const delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
|
|
97
|
+
limitPrice = askPrice.add(delta);
|
|
89
98
|
}
|
|
90
99
|
else {
|
|
91
|
-
|
|
100
|
+
const bidPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
|
|
101
|
+
const delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
|
|
102
|
+
limitPrice = bidPrice.sub(delta);
|
|
92
103
|
}
|
|
93
104
|
}
|
|
94
|
-
else if ((0, types_1.isVariant)(order.orderType, 'market') ||
|
|
95
|
-
(0, types_1.isVariant)(order.orderType, 'triggerMarket')) {
|
|
96
|
-
limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
|
|
97
|
-
}
|
|
98
105
|
else {
|
|
99
106
|
limitPrice = order.price;
|
|
100
107
|
}
|
package/lib/math/repeg.js
CHANGED
|
@@ -107,7 +107,7 @@ function calculateBudgetedPeg(amm, cost, targetPrice) {
|
|
|
107
107
|
const targetPeg = targetPrice
|
|
108
108
|
.mul(amm.baseAssetReserve)
|
|
109
109
|
.div(amm.quoteAssetReserve)
|
|
110
|
-
.div(numericConstants_1.
|
|
110
|
+
.div(numericConstants_1.PRICE_DIV_PEG);
|
|
111
111
|
const k = amm.sqrtK.mul(amm.sqrtK);
|
|
112
112
|
const x = amm.baseAssetReserve;
|
|
113
113
|
const y = amm.quoteAssetReserve;
|
package/lib/math/trade.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
|
|
|
33
33
|
* | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
|
|
34
34
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
35
35
|
*/
|
|
36
|
-
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN];
|
|
36
|
+
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN, BN];
|
|
37
37
|
/**
|
|
38
38
|
* calculateTargetPriceTrade
|
|
39
39
|
* simple function for finding arbitraging trades
|
package/lib/math/trade.js
CHANGED
|
@@ -43,15 +43,11 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
|
|
|
43
43
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
44
44
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
|
|
45
45
|
}
|
|
46
|
-
const [
|
|
47
|
-
const
|
|
48
|
-
? types_1.SwapDirection.REMOVE
|
|
49
|
-
: types_1.SwapDirection.ADD;
|
|
50
|
-
const quoteAssetAmountAcquired = (0, amm_1.calculateQuoteAssetAmountSwapped)(acquiredQuote.abs(), market.amm.pegMultiplier, swapDirection);
|
|
51
|
-
const entryPrice = quoteAssetAmountAcquired
|
|
46
|
+
const [acquiredBaseReserve, acquiredQuoteReserve, acquiredQuoteAssetAmount] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, oraclePriceData, useSpread);
|
|
47
|
+
const entryPrice = acquiredQuoteAssetAmount
|
|
52
48
|
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
53
49
|
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
54
|
-
.div(
|
|
50
|
+
.div(acquiredBaseReserve.abs());
|
|
55
51
|
let amm;
|
|
56
52
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
57
53
|
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
|
|
@@ -65,7 +61,7 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
|
|
|
65
61
|
else {
|
|
66
62
|
amm = market.amm;
|
|
67
63
|
}
|
|
68
|
-
const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(
|
|
64
|
+
const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBaseReserve), amm.quoteAssetReserve.sub(acquiredQuoteReserve), amm.pegMultiplier);
|
|
69
65
|
if (direction == types_1.PositionDirection.SHORT) {
|
|
70
66
|
(0, assert_1.assert)(newPrice.lte(oldPrice));
|
|
71
67
|
}
|
|
@@ -98,7 +94,7 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
|
|
|
98
94
|
*/
|
|
99
95
|
function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
100
96
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
101
|
-
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
97
|
+
return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
102
98
|
}
|
|
103
99
|
const swapDirection = (0, amm_1.getSwapDirection)(inputAssetType, direction);
|
|
104
100
|
let amm;
|
|
@@ -117,7 +113,8 @@ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType
|
|
|
117
113
|
const [newQuoteAssetReserve, newBaseAssetReserve] = (0, amm_1.calculateAmmReservesAfterSwap)(amm, inputAssetType, amount, swapDirection);
|
|
118
114
|
const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
|
|
119
115
|
const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
|
|
120
|
-
|
|
116
|
+
const acquiredQuoteAssetamount = (0, amm_1.calculateQuoteAssetAmountSwapped)(acquiredQuote.abs(), amm.pegMultiplier, swapDirection);
|
|
117
|
+
return [acquiredBase, acquiredQuote, acquiredQuoteAssetamount];
|
|
121
118
|
}
|
|
122
119
|
exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
|
|
123
120
|
/**
|
package/lib/orderParams.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
|
-
import {
|
|
2
|
+
import { OptionalOrderParams, OrderTriggerCondition } from './types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
|
-
export declare function getLimitOrderParams(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export declare function
|
|
4
|
+
export declare function getLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
|
|
5
|
+
price: BN;
|
|
6
|
+
}): OptionalOrderParams;
|
|
7
|
+
export declare function getTriggerMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
|
|
8
|
+
triggerCondition: OrderTriggerCondition;
|
|
9
|
+
triggerPrice: BN;
|
|
10
|
+
}): OptionalOrderParams;
|
|
11
|
+
export declare function getTriggerLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
|
|
12
|
+
triggerCondition: OrderTriggerCondition;
|
|
13
|
+
triggerPrice: BN;
|
|
14
|
+
price: BN;
|
|
15
|
+
}): OptionalOrderParams;
|
|
16
|
+
export declare function getMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'>): OptionalOrderParams;
|
package/lib/orderParams.js
CHANGED
|
@@ -2,107 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getMarketOrderParams = exports.getTriggerLimitOrderParams = exports.getTriggerMarketOrderParams = exports.getLimitOrderParams = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return {
|
|
8
|
-
orderType: types_1.OrderType.LIMIT,
|
|
9
|
-
userOrderId,
|
|
10
|
-
marketIndex,
|
|
11
|
-
direction,
|
|
12
|
-
quoteAssetAmount: numericConstants_1.ZERO,
|
|
13
|
-
baseAssetAmount,
|
|
14
|
-
price,
|
|
15
|
-
reduceOnly,
|
|
16
|
-
postOnly,
|
|
17
|
-
immediateOrCancel,
|
|
18
|
-
positionLimit: numericConstants_1.ZERO,
|
|
19
|
-
padding0: true,
|
|
20
|
-
padding1: numericConstants_1.ZERO,
|
|
21
|
-
optionalAccounts: {
|
|
22
|
-
discountToken,
|
|
23
|
-
referrer,
|
|
24
|
-
},
|
|
25
|
-
triggerCondition: types_1.OrderTriggerCondition.ABOVE,
|
|
26
|
-
triggerPrice: numericConstants_1.ZERO,
|
|
27
|
-
oraclePriceOffset,
|
|
28
|
-
};
|
|
5
|
+
function getLimitOrderParams(params) {
|
|
6
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.LIMIT });
|
|
29
7
|
}
|
|
30
8
|
exports.getLimitOrderParams = getLimitOrderParams;
|
|
31
|
-
function getTriggerMarketOrderParams(
|
|
32
|
-
return {
|
|
33
|
-
orderType: types_1.OrderType.TRIGGER_MARKET,
|
|
34
|
-
userOrderId,
|
|
35
|
-
marketIndex,
|
|
36
|
-
direction,
|
|
37
|
-
quoteAssetAmount: numericConstants_1.ZERO,
|
|
38
|
-
baseAssetAmount,
|
|
39
|
-
price: numericConstants_1.ZERO,
|
|
40
|
-
reduceOnly,
|
|
41
|
-
postOnly: false,
|
|
42
|
-
immediateOrCancel: false,
|
|
43
|
-
positionLimit: numericConstants_1.ZERO,
|
|
44
|
-
padding0: true,
|
|
45
|
-
padding1: numericConstants_1.ZERO,
|
|
46
|
-
optionalAccounts: {
|
|
47
|
-
discountToken,
|
|
48
|
-
referrer,
|
|
49
|
-
},
|
|
50
|
-
triggerCondition,
|
|
51
|
-
triggerPrice,
|
|
52
|
-
oraclePriceOffset: numericConstants_1.ZERO,
|
|
53
|
-
};
|
|
9
|
+
function getTriggerMarketOrderParams(params) {
|
|
10
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_MARKET });
|
|
54
11
|
}
|
|
55
12
|
exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
|
|
56
|
-
function getTriggerLimitOrderParams(
|
|
57
|
-
return {
|
|
58
|
-
orderType: types_1.OrderType.TRIGGER_LIMIT,
|
|
59
|
-
userOrderId,
|
|
60
|
-
marketIndex,
|
|
61
|
-
direction,
|
|
62
|
-
quoteAssetAmount: numericConstants_1.ZERO,
|
|
63
|
-
baseAssetAmount,
|
|
64
|
-
price,
|
|
65
|
-
reduceOnly,
|
|
66
|
-
postOnly: false,
|
|
67
|
-
immediateOrCancel: false,
|
|
68
|
-
positionLimit: numericConstants_1.ZERO,
|
|
69
|
-
padding0: true,
|
|
70
|
-
padding1: numericConstants_1.ZERO,
|
|
71
|
-
optionalAccounts: {
|
|
72
|
-
discountToken,
|
|
73
|
-
referrer,
|
|
74
|
-
},
|
|
75
|
-
triggerCondition,
|
|
76
|
-
triggerPrice,
|
|
77
|
-
oraclePriceOffset: numericConstants_1.ZERO,
|
|
78
|
-
};
|
|
13
|
+
function getTriggerLimitOrderParams(params) {
|
|
14
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_LIMIT });
|
|
79
15
|
}
|
|
80
16
|
exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
|
|
81
|
-
function getMarketOrderParams(
|
|
82
|
-
|
|
83
|
-
throw Error('baseAssetAmount or quoteAssetAmount must be zero');
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
orderType: types_1.OrderType.MARKET,
|
|
87
|
-
userOrderId: 0,
|
|
88
|
-
marketIndex,
|
|
89
|
-
direction,
|
|
90
|
-
quoteAssetAmount,
|
|
91
|
-
baseAssetAmount,
|
|
92
|
-
price,
|
|
93
|
-
reduceOnly,
|
|
94
|
-
postOnly: false,
|
|
95
|
-
immediateOrCancel: false,
|
|
96
|
-
positionLimit: numericConstants_1.ZERO,
|
|
97
|
-
padding0: true,
|
|
98
|
-
padding1: numericConstants_1.ZERO,
|
|
99
|
-
optionalAccounts: {
|
|
100
|
-
discountToken,
|
|
101
|
-
referrer,
|
|
102
|
-
},
|
|
103
|
-
triggerCondition: types_1.OrderTriggerCondition.ABOVE,
|
|
104
|
-
triggerPrice: numericConstants_1.ZERO,
|
|
105
|
-
oraclePriceOffset: numericConstants_1.ZERO,
|
|
106
|
-
};
|
|
17
|
+
function getMarketOrderParams(params) {
|
|
18
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.MARKET });
|
|
107
19
|
}
|
|
108
20
|
exports.getMarketOrderParams = getMarketOrderParams;
|
package/lib/orders.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { MarketAccount, Order, UserAccount, UserPosition } from './types';
|
|
3
|
-
import { BN
|
|
3
|
+
import { BN } from '.';
|
|
4
4
|
import { OraclePriceData } from '.';
|
|
5
5
|
export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: MarketAccount, order: Order): [UserAccount, UserPosition, MarketAccount] | null;
|
|
6
6
|
export declare function calculateBaseAssetAmountMarketCanExecute(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
|
|
7
7
|
export declare function calculateAmountToTradeForLimit(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
|
|
8
8
|
export declare function calculateAmountToTradeForTriggerLimit(market: MarketAccount, order: Order): BN;
|
|
9
|
-
export declare function calculateBaseAssetAmountUserCanExecute(market: MarketAccount, order: Order, user: ClearingHouseUser, oraclePriceData?: OraclePriceData): BN;
|
package/lib/orders.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = exports.calculateNewStateAfterOrder = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
5
|
const _1 = require(".");
|
|
6
6
|
const market_1 = require("./math/market");
|
|
@@ -88,7 +88,6 @@ function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData
|
|
|
88
88
|
return calculateAmountToTradeForTriggerLimit(market, order);
|
|
89
89
|
}
|
|
90
90
|
else if ((0, types_1.isVariant)(order.orderType, 'market')) {
|
|
91
|
-
// should never be a market order queued
|
|
92
91
|
return numericConstants_1.ZERO;
|
|
93
92
|
}
|
|
94
93
|
else {
|
|
@@ -102,15 +101,7 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
|
|
|
102
101
|
if (!oraclePriceData) {
|
|
103
102
|
throw Error('Cant calculate limit price for oracle offset oracle without OraclePriceData');
|
|
104
103
|
}
|
|
105
|
-
|
|
106
|
-
if (order.postOnly) {
|
|
107
|
-
limitPrice = (0, types_1.isVariant)(order.direction, 'long')
|
|
108
|
-
? _1.BN.min(order.price, floatingPrice)
|
|
109
|
-
: _1.BN.max(order.price, floatingPrice);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
limitPrice = floatingPrice;
|
|
113
|
-
}
|
|
104
|
+
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
114
105
|
}
|
|
115
106
|
const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction);
|
|
116
107
|
const baseAssetAmount = (0, _1.standardizeBaseAssetAmount)(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
|
|
@@ -125,11 +116,8 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
|
|
|
125
116
|
}
|
|
126
117
|
exports.calculateAmountToTradeForLimit = calculateAmountToTradeForLimit;
|
|
127
118
|
function calculateAmountToTradeForTriggerLimit(market, order) {
|
|
128
|
-
if (order.
|
|
129
|
-
|
|
130
|
-
if (baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
131
|
-
return numericConstants_1.ZERO;
|
|
132
|
-
}
|
|
119
|
+
if (!order.triggered) {
|
|
120
|
+
return numericConstants_1.ZERO;
|
|
133
121
|
}
|
|
134
122
|
return calculateAmountToTradeForLimit(market, order);
|
|
135
123
|
}
|
|
@@ -139,75 +127,8 @@ function isSameDirection(firstDirection, secondDirection) {
|
|
|
139
127
|
((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
|
|
140
128
|
}
|
|
141
129
|
function calculateAmountToTradeForTriggerMarket(market, order) {
|
|
142
|
-
|
|
143
|
-
? order.baseAssetAmount
|
|
144
|
-
: numericConstants_1.ZERO;
|
|
145
|
-
}
|
|
146
|
-
function isTriggerConditionSatisfied(market, order, oraclePriceData) {
|
|
147
|
-
const markPrice = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
|
|
148
|
-
if ((0, types_1.isVariant)(order.triggerCondition, 'above')) {
|
|
149
|
-
return markPrice.gt(order.triggerPrice);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
return markPrice.lt(order.triggerPrice);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function calculateBaseAssetAmountUserCanExecute(market, order, user, oraclePriceData) {
|
|
156
|
-
const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
|
|
157
|
-
const freeCollateral = user.getFreeCollateral();
|
|
158
|
-
let quoteAssetAmount;
|
|
159
|
-
if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
|
|
160
|
-
quoteAssetAmount = freeCollateral.mul(maxLeverage).div(_1.TEN_THOUSAND);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
const position = user.getUserPosition(order.marketIndex) ||
|
|
164
|
-
user.getEmptyPosition(order.marketIndex);
|
|
165
|
-
const positionValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
|
|
166
|
-
quoteAssetAmount = freeCollateral
|
|
167
|
-
.mul(maxLeverage)
|
|
168
|
-
.div(_1.TEN_THOUSAND)
|
|
169
|
-
.add(positionValue.mul(numericConstants_1.TWO));
|
|
170
|
-
}
|
|
171
|
-
if (quoteAssetAmount.lte(numericConstants_1.ZERO)) {
|
|
130
|
+
if (!order.triggered) {
|
|
172
131
|
return numericConstants_1.ZERO;
|
|
173
132
|
}
|
|
174
|
-
|
|
175
|
-
? types_1.SwapDirection.ADD
|
|
176
|
-
: types_1.SwapDirection.REMOVE;
|
|
177
|
-
const useSpread = !order.postOnly;
|
|
178
|
-
let amm;
|
|
179
|
-
if (useSpread) {
|
|
180
|
-
const { baseAssetReserve, quoteAssetReserve } = (0, _1.calculateSpreadReserves)(market.amm, order.direction, oraclePriceData);
|
|
181
|
-
amm = {
|
|
182
|
-
baseAssetReserve,
|
|
183
|
-
quoteAssetReserve,
|
|
184
|
-
sqrtK: market.amm.sqrtK,
|
|
185
|
-
pegMultiplier: market.amm.pegMultiplier,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
amm = market.amm;
|
|
190
|
-
}
|
|
191
|
-
const baseAssetReservesBefore = amm.baseAssetReserve;
|
|
192
|
-
const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(amm, 'quote', quoteAssetAmount, swapDirection);
|
|
193
|
-
let baseAssetAmount = baseAssetReservesBefore
|
|
194
|
-
.sub(baseAssetReservesAfter)
|
|
195
|
-
.abs();
|
|
196
|
-
if (order.reduceOnly) {
|
|
197
|
-
const position = user.getUserPosition(order.marketIndex) ||
|
|
198
|
-
user.getEmptyPosition(order.marketIndex);
|
|
199
|
-
if ((0, types_1.isVariant)(order.direction, 'long') &&
|
|
200
|
-
position.baseAssetAmount.gte(numericConstants_1.ZERO)) {
|
|
201
|
-
baseAssetAmount = numericConstants_1.ZERO;
|
|
202
|
-
}
|
|
203
|
-
else if ((0, types_1.isVariant)(order.direction, 'short') &&
|
|
204
|
-
position.baseAssetAmount.lte(numericConstants_1.ZERO)) {
|
|
205
|
-
baseAssetAmount = numericConstants_1.ZERO;
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
_1.BN.min(baseAssetAmount, position.baseAssetAmount.abs());
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return baseAssetAmount;
|
|
133
|
+
return order.baseAssetAmount;
|
|
212
134
|
}
|
|
213
|
-
exports.calculateBaseAssetAmountUserCanExecute = calculateBaseAssetAmountUserCanExecute;
|