@drift-labs/sdk 0.1.36-master.5 → 0.2.0-master.0
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/bulkAccountLoader.d.ts +7 -6
- package/lib/accounts/bulkAccountLoader.js +83 -93
- package/lib/accounts/bulkUserSubscription.js +13 -57
- package/lib/accounts/fetch.d.ts +4 -0
- package/lib/accounts/fetch.js +18 -0
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
- package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
- package/lib/accounts/pollingOracleSubscriber.js +37 -49
- package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
- package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
- package/lib/accounts/types.d.ts +34 -41
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
- package/lib/accounts/webSocketAccountSubscriber.js +39 -35
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
- package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
- package/lib/addresses/marketAddresses.d.ts +4 -0
- package/lib/addresses/marketAddresses.js +15 -0
- package/lib/addresses/pda.d.ts +12 -0
- package/lib/addresses/pda.js +83 -0
- package/lib/admin.d.ts +8 -12
- package/lib/admin.js +366 -490
- package/lib/clearingHouse.d.ts +84 -103
- package/lib/clearingHouse.js +779 -810
- package/lib/clearingHouseConfig.d.ts +34 -0
- package/lib/clearingHouseConfig.js +2 -0
- package/lib/clearingHouseUser.d.ts +19 -18
- package/lib/clearingHouseUser.js +157 -115
- package/lib/clearingHouseUserConfig.d.ts +14 -0
- package/lib/clearingHouseUserConfig.js +2 -0
- package/lib/config.d.ts +12 -0
- package/lib/config.js +35 -4
- package/lib/constants/banks.d.ts +16 -0
- package/lib/constants/banks.js +34 -0
- package/lib/constants/markets.d.ts +8 -3
- package/lib/constants/markets.js +13 -206
- package/lib/constants/numericConstants.d.ts +16 -0
- package/lib/constants/numericConstants.js +22 -6
- package/lib/events/eventList.d.ts +22 -0
- package/lib/events/eventList.js +77 -0
- package/lib/events/eventSubscriber.d.ts +34 -0
- package/lib/events/eventSubscriber.js +126 -0
- package/lib/events/fetchLogs.d.ts +13 -0
- package/lib/events/fetchLogs.js +39 -0
- package/lib/events/pollingLogProvider.d.ts +15 -0
- package/lib/events/pollingLogProvider.js +53 -0
- package/lib/events/sort.d.ts +2 -0
- package/lib/events/sort.js +44 -0
- package/lib/events/txEventCache.d.ts +24 -0
- package/lib/events/txEventCache.js +71 -0
- package/lib/events/types.d.ts +49 -0
- package/lib/events/types.js +20 -0
- package/lib/events/webSocketLogProvider.d.ts +12 -0
- package/lib/events/webSocketLogProvider.js +30 -0
- package/lib/examples/makeTradeExample.js +26 -27
- package/lib/factory/bigNum.d.ts +112 -0
- package/lib/factory/bigNum.js +356 -0
- package/lib/factory/oracleClient.d.ts +1 -2
- package/lib/factory/oracleClient.js +6 -2
- package/lib/idl/clearing_house.json +1739 -2287
- package/lib/index.d.ts +13 -4
- package/lib/index.js +13 -4
- package/lib/math/amm.d.ts +19 -29
- package/lib/math/amm.js +129 -179
- package/lib/math/auction.d.ts +5 -0
- package/lib/math/auction.js +39 -0
- package/lib/math/bankBalance.d.ts +9 -0
- package/lib/math/bankBalance.js +75 -0
- package/lib/math/conversion.d.ts +0 -1
- package/lib/math/conversion.js +1 -5
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +158 -175
- package/lib/math/market.d.ts +6 -6
- package/lib/math/market.js +10 -9
- package/lib/math/oracles.d.ts +3 -0
- package/lib/math/oracles.js +26 -0
- package/lib/math/orders.d.ts +5 -0
- package/lib/math/orders.js +31 -1
- package/lib/math/position.d.ts +7 -4
- package/lib/math/position.js +27 -9
- package/lib/math/repeg.d.ts +22 -0
- package/lib/math/repeg.js +128 -0
- package/lib/math/trade.d.ts +13 -8
- package/lib/math/trade.js +85 -22
- package/lib/mockUSDCFaucet.js +87 -116
- package/lib/oracles/oracleClientCache.d.ts +8 -0
- package/lib/oracles/oracleClientCache.js +19 -0
- package/lib/oracles/pythClient.d.ts +3 -5
- package/lib/oracles/pythClient.js +12 -30
- package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
- package/lib/oracles/quoteAssetOracleClient.js +21 -0
- package/lib/oracles/switchboardClient.d.ts +3 -5
- package/lib/oracles/switchboardClient.js +29 -47
- package/lib/oracles/types.d.ts +7 -1
- package/lib/orders.d.ts +6 -6
- package/lib/orders.js +10 -9
- package/lib/slot/SlotSubscriber.d.ts +12 -0
- package/lib/slot/SlotSubscriber.js +23 -0
- package/lib/tx/retryTxSender.d.ts +2 -2
- package/lib/tx/retryTxSender.js +108 -123
- package/lib/tx/types.d.ts +5 -1
- package/lib/tx/utils.d.ts +1 -1
- package/lib/tx/utils.js +11 -2
- package/lib/types.d.ts +105 -98
- package/lib/types.js +13 -1
- package/lib/userName.d.ts +4 -0
- package/lib/userName.js +20 -0
- package/lib/util/computeUnits.js +10 -21
- package/lib/util/tps.js +11 -22
- package/lib/wallet.js +7 -20
- package/package.json +10 -3
- package/src/accounts/bulkAccountLoader.ts +26 -15
- package/src/accounts/bulkUserSubscription.ts +1 -45
- package/src/accounts/fetch.ts +33 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
- package/src/accounts/pollingOracleSubscriber.ts +16 -8
- package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
- package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
- package/src/accounts/types.ts +41 -70
- package/src/accounts/webSocketAccountSubscriber.ts +33 -16
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
- package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
- package/src/addresses/marketAddresses.ts +18 -0
- package/src/addresses/pda.ts +118 -0
- package/src/admin.ts +209 -267
- package/src/clearingHouse.ts +921 -829
- package/src/clearingHouseConfig.ts +37 -0
- package/src/clearingHouseUser.ts +280 -127
- package/src/clearingHouseUserConfig.ts +18 -0
- package/src/config.ts +54 -1
- package/src/constants/banks.ts +43 -0
- package/src/constants/markets.ts +16 -207
- package/src/constants/numericConstants.ts +33 -5
- package/src/events/eventList.ts +94 -0
- package/src/events/eventSubscriber.ts +194 -0
- package/src/events/fetchLogs.ts +80 -0
- package/src/events/pollingLogProvider.ts +79 -0
- package/src/events/sort.ts +65 -0
- package/src/events/txEventCache.ts +74 -0
- package/src/events/types.ts +98 -0
- package/src/events/webSocketLogProvider.ts +38 -0
- package/src/examples/makeTradeExample.ts +20 -11
- package/src/factory/bigNum.ts +507 -0
- package/src/factory/oracleClient.ts +7 -4
- package/src/idl/clearing_house.json +1739 -2287
- package/src/index.ts +13 -4
- package/src/math/amm.ts +229 -245
- package/src/math/auction.ts +39 -0
- package/src/math/bankBalance.ts +112 -0
- package/src/math/conversion.ts +1 -11
- package/src/math/funding.ts +12 -9
- package/src/math/market.ts +37 -30
- package/src/math/oracles.ts +36 -0
- package/src/math/orders.ts +38 -0
- package/src/math/position.ts +48 -13
- package/src/math/repeg.ts +175 -0
- package/src/math/trade.ts +114 -36
- package/src/math/utils.js +27 -0
- package/src/math/utils.js.map +1 -0
- package/src/oracles/oracleClientCache.ts +20 -0
- package/src/oracles/pythClient.ts +5 -11
- package/src/oracles/quoteAssetOracleClient.ts +25 -0
- package/src/oracles/switchboardClient.ts +16 -24
- package/src/oracles/types.ts +8 -1
- package/src/orders.ts +35 -20
- package/src/slot/SlotSubscriber.ts +32 -0
- package/src/tx/retryTxSender.ts +6 -4
- package/src/tx/types.ts +6 -1
- package/src/tx/utils.ts +22 -3
- package/src/types.ts +108 -110
- package/src/userName.ts +20 -0
- package/src/util/computeUnits.js +17 -0
- package/src/util/computeUnits.js.map +1 -0
- package/tests/bn/test.ts +255 -0
- package/tsconfig.json +12 -12
- package/lib/addresses.d.ts +0 -9
- package/lib/addresses.js +0 -87
- package/lib/constants/accounts.d.ts +0 -15
- package/lib/constants/accounts.js +0 -18
- package/lib/factory/clearingHouse.d.ts +0 -35
- package/lib/factory/clearingHouse.js +0 -81
- package/lib/factory/clearingHouseUser.d.ts +0 -19
- package/lib/factory/clearingHouseUser.js +0 -34
- package/lib/math/insuranceFund.d.ts +0 -15
- package/lib/math/insuranceFund.js +0 -33
- package/lib/tx/defaultTxSender.d.ts +0 -8
- package/lib/tx/defaultTxSender.js +0 -12
- package/src/addresses.ts +0 -71
- package/src/constants/accounts.ts +0 -26
- package/src/factory/clearingHouse.ts +0 -173
- package/src/factory/clearingHouseUser.ts +0 -73
- package/src/math/insuranceFund.ts +0 -29
- package/src/tx/defaultTxSender.ts +0 -24
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isOracleValid = void 0;
|
|
4
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
5
|
+
const index_1 = require("../index");
|
|
6
|
+
function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
|
|
7
|
+
const isOraclePriceNonPositive = oraclePriceData.price.lt(numericConstants_1.ZERO);
|
|
8
|
+
const isOraclePriceTooVolatile = oraclePriceData.price
|
|
9
|
+
.div(index_1.BN.max(numericConstants_1.ONE, amm.lastOraclePriceTwap))
|
|
10
|
+
.gt(oracleGuardRails.validity.tooVolatileRatio) ||
|
|
11
|
+
amm.lastOraclePriceTwap
|
|
12
|
+
.div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.price))
|
|
13
|
+
.gt(oracleGuardRails.validity.tooVolatileRatio);
|
|
14
|
+
const isConfidenceTooLarge = oraclePriceData.price
|
|
15
|
+
.div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
|
|
16
|
+
.lt(oracleGuardRails.validity.confidenceIntervalMaxSize);
|
|
17
|
+
const oracleIsStale = oraclePriceData.slot
|
|
18
|
+
.sub(new index_1.BN(slot))
|
|
19
|
+
.gt(oracleGuardRails.validity.slotsBeforeStale);
|
|
20
|
+
return !(!oraclePriceData.hasSufficientNumberOfDataPoints ||
|
|
21
|
+
oracleIsStale ||
|
|
22
|
+
isOraclePriceNonPositive ||
|
|
23
|
+
isOraclePriceTooVolatile ||
|
|
24
|
+
isConfidenceTooLarge);
|
|
25
|
+
}
|
|
26
|
+
exports.isOracleValid = isOracleValid;
|
package/lib/math/orders.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import { ClearingHouseUser } from '../clearingHouseUser';
|
|
2
3
|
import { Order } from '../types';
|
|
4
|
+
import { BN } from '@project-serum/anchor';
|
|
5
|
+
import { OraclePriceData } from '../oracles/types';
|
|
3
6
|
export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Order): boolean;
|
|
4
7
|
export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
|
|
5
8
|
export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
|
|
9
|
+
export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
|
|
10
|
+
export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number): BN;
|
package/lib/math/orders.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
|
|
3
|
+
exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
7
|
+
const auction_1 = require("./auction");
|
|
6
8
|
function isOrderRiskIncreasing(user, order) {
|
|
7
9
|
if ((0, types_1.isVariant)(order.status, 'init')) {
|
|
8
10
|
return false;
|
|
@@ -71,3 +73,31 @@ function isOrderReduceOnly(user, order) {
|
|
|
71
73
|
return true;
|
|
72
74
|
}
|
|
73
75
|
exports.isOrderReduceOnly = isOrderReduceOnly;
|
|
76
|
+
function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
|
|
77
|
+
const remainder = baseAssetAmount.mod(stepSize);
|
|
78
|
+
return baseAssetAmount.sub(remainder);
|
|
79
|
+
}
|
|
80
|
+
exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
|
|
81
|
+
function getLimitPrice(order, oraclePriceData, slot) {
|
|
82
|
+
let limitPrice;
|
|
83
|
+
if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
|
|
84
|
+
const floatingPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
85
|
+
if (order.postOnly) {
|
|
86
|
+
limitPrice = (0, types_1.isVariant)(order.direction, 'long')
|
|
87
|
+
? anchor_1.BN.min(order.price, floatingPrice)
|
|
88
|
+
: anchor_1.BN.max(order.price, floatingPrice);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
limitPrice = floatingPrice;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
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
|
+
else {
|
|
99
|
+
limitPrice = order.price;
|
|
100
|
+
}
|
|
101
|
+
return limitPrice;
|
|
102
|
+
}
|
|
103
|
+
exports.getLimitPrice = getLimitPrice;
|
package/lib/math/position.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { BN } from '../';
|
|
3
|
-
import {
|
|
3
|
+
import { OraclePriceData } from '../oracles/types';
|
|
4
|
+
import { MarketAccount, PositionDirection, UserPosition } from '../types';
|
|
4
5
|
/**
|
|
5
6
|
* calculateBaseAssetValue
|
|
6
7
|
* = market value of closing entire position
|
|
7
8
|
* @param market
|
|
8
9
|
* @param userPosition
|
|
10
|
+
* @param oraclePriceData
|
|
9
11
|
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
10
12
|
*/
|
|
11
|
-
export declare function calculateBaseAssetValue(market:
|
|
13
|
+
export declare function calculateBaseAssetValue(market: MarketAccount, userPosition: UserPosition, oraclePriceData: OraclePriceData): BN;
|
|
12
14
|
/**
|
|
13
15
|
* calculatePositionPNL
|
|
14
16
|
* = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
|
|
@@ -17,14 +19,15 @@ export declare function calculateBaseAssetValue(market: Market, userPosition: Us
|
|
|
17
19
|
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
18
20
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
19
21
|
*/
|
|
20
|
-
export declare function calculatePositionPNL(market:
|
|
22
|
+
export declare function calculatePositionPNL(market: MarketAccount, marketPosition: UserPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
|
|
21
23
|
/**
|
|
22
24
|
*
|
|
23
25
|
* @param market
|
|
24
26
|
* @param marketPosition
|
|
25
27
|
* @returns // TODO-PRECISION
|
|
26
28
|
*/
|
|
27
|
-
export declare function calculatePositionFundingPNL(market:
|
|
29
|
+
export declare function calculatePositionFundingPNL(market: MarketAccount, marketPosition: UserPosition): BN;
|
|
30
|
+
export declare function positionIsAvailable(position: UserPosition): boolean;
|
|
28
31
|
/**
|
|
29
32
|
*
|
|
30
33
|
* @param userPosition
|
package/lib/math/position.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
|
|
3
|
+
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
|
|
4
4
|
const __1 = require("../");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
const types_1 = require("../types");
|
|
@@ -10,24 +10,38 @@ const amm_1 = require("./amm");
|
|
|
10
10
|
* = market value of closing entire position
|
|
11
11
|
* @param market
|
|
12
12
|
* @param userPosition
|
|
13
|
+
* @param oraclePriceData
|
|
13
14
|
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
14
15
|
*/
|
|
15
|
-
function calculateBaseAssetValue(market, userPosition) {
|
|
16
|
+
function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
|
|
16
17
|
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
17
18
|
return numericConstants_1.ZERO;
|
|
18
19
|
}
|
|
19
20
|
const directionToClose = findDirectionToClose(userPosition);
|
|
20
|
-
|
|
21
|
+
let prepegAmm;
|
|
22
|
+
if (market.amm.baseSpread > 0) {
|
|
23
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
|
|
24
|
+
prepegAmm = {
|
|
25
|
+
baseAssetReserve,
|
|
26
|
+
quoteAssetReserve,
|
|
27
|
+
sqrtK: sqrtK,
|
|
28
|
+
pegMultiplier: newPeg,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
|
|
33
|
+
}
|
|
34
|
+
const [newQuoteAssetReserve, _] = (0, amm_1.calculateAmmReservesAfterSwap)(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose));
|
|
21
35
|
switch (directionToClose) {
|
|
22
36
|
case types_1.PositionDirection.SHORT:
|
|
23
|
-
return
|
|
37
|
+
return prepegAmm.quoteAssetReserve
|
|
24
38
|
.sub(newQuoteAssetReserve)
|
|
25
|
-
.mul(
|
|
39
|
+
.mul(prepegAmm.pegMultiplier)
|
|
26
40
|
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
27
41
|
case types_1.PositionDirection.LONG:
|
|
28
42
|
return newQuoteAssetReserve
|
|
29
|
-
.sub(
|
|
30
|
-
.mul(
|
|
43
|
+
.sub(prepegAmm.quoteAssetReserve)
|
|
44
|
+
.mul(prepegAmm.pegMultiplier)
|
|
31
45
|
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
32
46
|
.add(numericConstants_1.ONE);
|
|
33
47
|
}
|
|
@@ -41,11 +55,11 @@ exports.calculateBaseAssetValue = calculateBaseAssetValue;
|
|
|
41
55
|
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
42
56
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
43
57
|
*/
|
|
44
|
-
function calculatePositionPNL(market, marketPosition, withFunding = false) {
|
|
58
|
+
function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
|
|
45
59
|
if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
46
60
|
return numericConstants_1.ZERO;
|
|
47
61
|
}
|
|
48
|
-
const baseAssetValue = calculateBaseAssetValue(market, marketPosition);
|
|
62
|
+
const baseAssetValue = calculateBaseAssetValue(market, marketPosition, oraclePriceData);
|
|
49
63
|
let pnl;
|
|
50
64
|
if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
51
65
|
pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
|
|
@@ -86,6 +100,10 @@ function calculatePositionFundingPNL(market, marketPosition) {
|
|
|
86
100
|
return perPositionFundingRate;
|
|
87
101
|
}
|
|
88
102
|
exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
|
|
103
|
+
function positionIsAvailable(position) {
|
|
104
|
+
return position.baseAssetAmount.eq(numericConstants_1.ZERO) && position.openOrders.eq(numericConstants_1.ZERO);
|
|
105
|
+
}
|
|
106
|
+
exports.positionIsAvailable = positionIsAvailable;
|
|
89
107
|
/**
|
|
90
108
|
*
|
|
91
109
|
* @param userPosition
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
2
|
+
import { BN } from '@project-serum/anchor';
|
|
3
|
+
import { AMM } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Helper function calculating adjust k cost
|
|
6
|
+
* @param amm
|
|
7
|
+
* @param numerator
|
|
8
|
+
* @param denomenator
|
|
9
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
10
|
+
*/
|
|
11
|
+
export declare function calculateAdjustKCost(amm: AMM, numerator: BN, denomenator: BN): BN;
|
|
12
|
+
/**
|
|
13
|
+
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
14
|
+
*
|
|
15
|
+
* @param amm
|
|
16
|
+
* @param newPeg
|
|
17
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
18
|
+
*/
|
|
19
|
+
export declare function calculateRepegCost(amm: AMM, newPeg: BN): BN;
|
|
20
|
+
export declare function calculateBudgetedKBN(x: BN, y: BN, budget: BN, Q: BN, d: BN): [BN, BN];
|
|
21
|
+
export declare function calculateBudgetedK(amm: AMM, cost: BN): [BN, BN];
|
|
22
|
+
export declare function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateBudgetedPeg = exports.calculateBudgetedK = exports.calculateBudgetedKBN = exports.calculateRepegCost = exports.calculateAdjustKCost = void 0;
|
|
4
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
5
|
+
const assert_1 = require("../assert/assert");
|
|
6
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
7
|
+
/**
|
|
8
|
+
* Helper function calculating adjust k cost
|
|
9
|
+
* @param amm
|
|
10
|
+
* @param numerator
|
|
11
|
+
* @param denomenator
|
|
12
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
13
|
+
*/
|
|
14
|
+
function calculateAdjustKCost(amm, numerator, denomenator) {
|
|
15
|
+
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
16
|
+
const x = amm.baseAssetReserve;
|
|
17
|
+
const y = amm.quoteAssetReserve;
|
|
18
|
+
const d = amm.netBaseAssetAmount;
|
|
19
|
+
const Q = amm.pegMultiplier;
|
|
20
|
+
const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
|
|
21
|
+
const p = numerator.mul(numericConstants_1.MARK_PRICE_PRECISION).div(denomenator);
|
|
22
|
+
const cost = quoteScale
|
|
23
|
+
.div(x.add(d))
|
|
24
|
+
.sub(quoteScale
|
|
25
|
+
.mul(p)
|
|
26
|
+
.div(numericConstants_1.MARK_PRICE_PRECISION)
|
|
27
|
+
.div(x.mul(p).div(numericConstants_1.MARK_PRICE_PRECISION).add(d)))
|
|
28
|
+
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
29
|
+
.div(numericConstants_1.PEG_PRECISION);
|
|
30
|
+
return cost.mul(new anchor_1.BN(-1));
|
|
31
|
+
}
|
|
32
|
+
exports.calculateAdjustKCost = calculateAdjustKCost;
|
|
33
|
+
/**
|
|
34
|
+
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
35
|
+
*
|
|
36
|
+
* @param amm
|
|
37
|
+
* @param newPeg
|
|
38
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
39
|
+
*/
|
|
40
|
+
function calculateRepegCost(amm, newPeg) {
|
|
41
|
+
const dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve);
|
|
42
|
+
const cost = dqar
|
|
43
|
+
.mul(newPeg.sub(amm.pegMultiplier))
|
|
44
|
+
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
45
|
+
.div(numericConstants_1.PEG_PRECISION);
|
|
46
|
+
return cost;
|
|
47
|
+
}
|
|
48
|
+
exports.calculateRepegCost = calculateRepegCost;
|
|
49
|
+
function calculateBudgetedKBN(x, y, budget, Q, d) {
|
|
50
|
+
(0, assert_1.assert)(Q.gt(new anchor_1.BN(0)));
|
|
51
|
+
const C = budget.mul(new anchor_1.BN(-1));
|
|
52
|
+
let dSign = new anchor_1.BN(1);
|
|
53
|
+
if (d.lt(new anchor_1.BN(0))) {
|
|
54
|
+
dSign = new anchor_1.BN(-1);
|
|
55
|
+
}
|
|
56
|
+
const pegged_y_d_d = y
|
|
57
|
+
.mul(d)
|
|
58
|
+
.mul(d)
|
|
59
|
+
.mul(Q)
|
|
60
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
61
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
62
|
+
.div(numericConstants_1.PEG_PRECISION);
|
|
63
|
+
const numer1 = pegged_y_d_d;
|
|
64
|
+
const numer2 = C.mul(d)
|
|
65
|
+
.div(numericConstants_1.QUOTE_PRECISION)
|
|
66
|
+
.mul(x.add(d))
|
|
67
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
68
|
+
.mul(dSign);
|
|
69
|
+
const denom1 = C.mul(x)
|
|
70
|
+
.mul(x.add(d))
|
|
71
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
72
|
+
.div(numericConstants_1.QUOTE_PRECISION);
|
|
73
|
+
const denom2 = pegged_y_d_d;
|
|
74
|
+
const numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
75
|
+
const denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
76
|
+
return [numerator, denominator];
|
|
77
|
+
}
|
|
78
|
+
exports.calculateBudgetedKBN = calculateBudgetedKBN;
|
|
79
|
+
function calculateBudgetedK(amm, cost) {
|
|
80
|
+
// wolframalpha.com
|
|
81
|
+
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
82
|
+
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*d*d*Q)
|
|
83
|
+
// numer
|
|
84
|
+
// = y*d*d*Q - Cxd - Cdd
|
|
85
|
+
// = y/x*Q*d*d - Cd - Cd/x
|
|
86
|
+
// = mark - C/d - C/(x)
|
|
87
|
+
// = mark/C - 1/d - 1/x
|
|
88
|
+
// denom
|
|
89
|
+
// = C*x*x + C*x*d + y*d*d*Q
|
|
90
|
+
// = x/d**2 + 1 / d + mark/C
|
|
91
|
+
// todo: assumes k = x * y
|
|
92
|
+
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
93
|
+
const x = amm.baseAssetReserve;
|
|
94
|
+
const y = amm.quoteAssetReserve;
|
|
95
|
+
const d = amm.netBaseAssetAmount;
|
|
96
|
+
const Q = amm.pegMultiplier;
|
|
97
|
+
const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
|
|
98
|
+
return [numerator, denominator];
|
|
99
|
+
}
|
|
100
|
+
exports.calculateBudgetedK = calculateBudgetedK;
|
|
101
|
+
function calculateBudgetedPeg(amm, cost, targetPrice) {
|
|
102
|
+
// wolframalpha.com
|
|
103
|
+
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
104
|
+
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
105
|
+
// todo: assumes k = x * y
|
|
106
|
+
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
107
|
+
const targetPeg = targetPrice
|
|
108
|
+
.mul(amm.baseAssetReserve)
|
|
109
|
+
.div(amm.quoteAssetReserve)
|
|
110
|
+
.div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
|
|
111
|
+
const k = amm.sqrtK.mul(amm.sqrtK);
|
|
112
|
+
const x = amm.baseAssetReserve;
|
|
113
|
+
const y = amm.quoteAssetReserve;
|
|
114
|
+
const d = amm.netBaseAssetAmount;
|
|
115
|
+
const Q = amm.pegMultiplier;
|
|
116
|
+
const C = cost.mul(new anchor_1.BN(-1));
|
|
117
|
+
const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
|
|
118
|
+
const pegChangeDirection = targetPeg.sub(Q);
|
|
119
|
+
const useTargetPeg = (deltaQuoteAssetReserves.lt(numericConstants_1.ZERO) && pegChangeDirection.gt(numericConstants_1.ZERO)) ||
|
|
120
|
+
(deltaQuoteAssetReserves.gt(numericConstants_1.ZERO) && pegChangeDirection.lt(numericConstants_1.ZERO));
|
|
121
|
+
if (deltaQuoteAssetReserves.eq(numericConstants_1.ZERO) || useTargetPeg) {
|
|
122
|
+
return targetPeg;
|
|
123
|
+
}
|
|
124
|
+
const deltaPegMultiplier = C.mul(numericConstants_1.MARK_PRICE_PRECISION).div(deltaQuoteAssetReserves.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO));
|
|
125
|
+
const newPeg = Q.sub(deltaPegMultiplier.mul(numericConstants_1.PEG_PRECISION).div(numericConstants_1.MARK_PRICE_PRECISION));
|
|
126
|
+
return newPeg;
|
|
127
|
+
}
|
|
128
|
+
exports.calculateBudgetedPeg = calculateBudgetedPeg;
|
package/lib/math/trade.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
|
-
import {
|
|
2
|
+
import { MarketAccount, PositionDirection } from '../types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
4
|
import { AssetType } from './amm';
|
|
5
|
+
import { OraclePriceData } from '../oracles/types';
|
|
5
6
|
export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' | 'priceDeltaAsNumber' | 'pctAvg' | 'pctMax' | 'quoteAssetAmount' | 'quoteAssetAmountPeg' | 'acquiredBaseAssetAmount' | 'acquiredQuoteAssetAmount' | 'all';
|
|
6
7
|
/**
|
|
7
8
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
8
9
|
* @param direction
|
|
9
10
|
* @param amount
|
|
10
11
|
* @param market
|
|
12
|
+
* @param inputAssetType which asset is being traded
|
|
13
|
+
* @param useSpread whether to consider spread with calculating slippage
|
|
11
14
|
* @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
|
|
12
15
|
*
|
|
13
16
|
* 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision MARK_PRICE_PRECISION
|
|
@@ -18,7 +21,7 @@ export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' |
|
|
|
18
21
|
*
|
|
19
22
|
* 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
|
|
20
23
|
*/
|
|
21
|
-
export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market:
|
|
24
|
+
export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [BN, BN, BN, BN];
|
|
22
25
|
/**
|
|
23
26
|
* Calculates acquired amounts for trade executed
|
|
24
27
|
* @param direction
|
|
@@ -27,23 +30,25 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
|
|
|
27
30
|
* @param inputAssetType
|
|
28
31
|
* @param useSpread
|
|
29
32
|
* @return
|
|
30
|
-
* | 'acquiredBase' => positive/negative change in user's base : BN
|
|
33
|
+
* | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
|
|
31
34
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
32
35
|
*/
|
|
33
|
-
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market:
|
|
36
|
+
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN];
|
|
34
37
|
/**
|
|
35
38
|
* calculateTargetPriceTrade
|
|
36
39
|
* simple function for finding arbitraging trades
|
|
37
40
|
* @param market
|
|
38
41
|
* @param targetPrice
|
|
39
42
|
* @param pct optional default is 100% gap filling, can set smaller.
|
|
43
|
+
* @param outputAssetType which asset to trade.
|
|
44
|
+
* @param useSpread whether or not to consider the spread when calculating the trade size
|
|
40
45
|
* @returns trade direction/size in order to push price to a targetPrice,
|
|
41
46
|
*
|
|
42
47
|
* [
|
|
43
|
-
* direction => direction of trade required,
|
|
48
|
+
* direction => direction of trade required, PositionDirection
|
|
44
49
|
* tradeSize => size of trade required, TODO-PRECISION
|
|
45
|
-
* entryPrice => the entry price for the trade,
|
|
46
|
-
* targetPrice => the target price
|
|
50
|
+
* entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
|
|
51
|
+
* targetPrice => the target price MARK_PRICE_PRECISION
|
|
47
52
|
* ]
|
|
48
53
|
*/
|
|
49
|
-
export declare function calculateTargetPriceTrade(market:
|
|
54
|
+
export declare function calculateTargetPriceTrade(market: MarketAccount, targetPrice: BN, pct?: BN, outputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [PositionDirection, BN, BN, BN];
|
package/lib/math/trade.js
CHANGED
|
@@ -8,12 +8,15 @@ const numericConstants_1 = require("../constants/numericConstants");
|
|
|
8
8
|
const market_1 = require("./market");
|
|
9
9
|
const amm_1 = require("./amm");
|
|
10
10
|
const utils_1 = require("./utils");
|
|
11
|
+
const types_2 = require("../types");
|
|
11
12
|
const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
|
|
12
13
|
/**
|
|
13
14
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
14
15
|
* @param direction
|
|
15
16
|
* @param amount
|
|
16
17
|
* @param market
|
|
18
|
+
* @param inputAssetType which asset is being traded
|
|
19
|
+
* @param useSpread whether to consider spread with calculating slippage
|
|
17
20
|
* @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
|
|
18
21
|
*
|
|
19
22
|
* 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision MARK_PRICE_PRECISION
|
|
@@ -24,19 +27,50 @@ const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
|
|
|
24
27
|
*
|
|
25
28
|
* 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
|
|
26
29
|
*/
|
|
27
|
-
function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote') {
|
|
28
|
-
|
|
30
|
+
function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
31
|
+
let oldPrice;
|
|
32
|
+
if (useSpread && market.amm.baseSpread > 0) {
|
|
33
|
+
if ((0, types_2.isVariant)(direction, 'long')) {
|
|
34
|
+
oldPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
oldPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
oldPrice = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
|
|
42
|
+
}
|
|
29
43
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
30
44
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
|
|
31
45
|
}
|
|
32
|
-
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType);
|
|
33
|
-
const
|
|
34
|
-
|
|
46
|
+
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, oraclePriceData, useSpread);
|
|
47
|
+
const swapDirection = (0, types_2.isVariant)(direction, 'long')
|
|
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
|
|
52
|
+
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
53
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
54
|
+
.div(acquiredBase.abs());
|
|
55
|
+
let amm;
|
|
56
|
+
if (useSpread && market.amm.baseSpread > 0) {
|
|
57
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
|
|
58
|
+
amm = {
|
|
59
|
+
baseAssetReserve,
|
|
60
|
+
quoteAssetReserve,
|
|
61
|
+
sqrtK: sqrtK,
|
|
62
|
+
pegMultiplier: newPeg,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
amm = market.amm;
|
|
67
|
+
}
|
|
68
|
+
const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBase), amm.quoteAssetReserve.sub(acquiredQuote), amm.pegMultiplier);
|
|
35
69
|
if (direction == types_1.PositionDirection.SHORT) {
|
|
36
|
-
(0, assert_1.assert)(newPrice.
|
|
70
|
+
(0, assert_1.assert)(newPrice.lte(oldPrice));
|
|
37
71
|
}
|
|
38
72
|
else {
|
|
39
|
-
(0, assert_1.assert)(oldPrice.
|
|
73
|
+
(0, assert_1.assert)(oldPrice.lte(newPrice));
|
|
40
74
|
}
|
|
41
75
|
const pctMaxSlippage = newPrice
|
|
42
76
|
.sub(oldPrice)
|
|
@@ -59,22 +93,22 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
|
|
|
59
93
|
* @param inputAssetType
|
|
60
94
|
* @param useSpread
|
|
61
95
|
* @return
|
|
62
|
-
* | 'acquiredBase' => positive/negative change in user's base : BN
|
|
96
|
+
* | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
|
|
63
97
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
64
98
|
*/
|
|
65
|
-
function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', useSpread = true) {
|
|
99
|
+
function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
66
100
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
67
101
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
68
102
|
}
|
|
69
103
|
const swapDirection = (0, amm_1.getSwapDirection)(inputAssetType, direction);
|
|
70
104
|
let amm;
|
|
71
105
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
72
|
-
const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.
|
|
106
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
|
|
73
107
|
amm = {
|
|
74
108
|
baseAssetReserve,
|
|
75
109
|
quoteAssetReserve,
|
|
76
|
-
sqrtK:
|
|
77
|
-
pegMultiplier:
|
|
110
|
+
sqrtK: sqrtK,
|
|
111
|
+
pegMultiplier: newPeg,
|
|
78
112
|
};
|
|
79
113
|
}
|
|
80
114
|
else {
|
|
@@ -92,43 +126,72 @@ exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
|
|
|
92
126
|
* @param market
|
|
93
127
|
* @param targetPrice
|
|
94
128
|
* @param pct optional default is 100% gap filling, can set smaller.
|
|
129
|
+
* @param outputAssetType which asset to trade.
|
|
130
|
+
* @param useSpread whether or not to consider the spread when calculating the trade size
|
|
95
131
|
* @returns trade direction/size in order to push price to a targetPrice,
|
|
96
132
|
*
|
|
97
133
|
* [
|
|
98
|
-
* direction => direction of trade required,
|
|
134
|
+
* direction => direction of trade required, PositionDirection
|
|
99
135
|
* tradeSize => size of trade required, TODO-PRECISION
|
|
100
|
-
* entryPrice => the entry price for the trade,
|
|
101
|
-
* targetPrice => the target price
|
|
136
|
+
* entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
|
|
137
|
+
* targetPrice => the target price MARK_PRICE_PRECISION
|
|
102
138
|
* ]
|
|
103
139
|
*/
|
|
104
|
-
function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote') {
|
|
140
|
+
function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
105
141
|
(0, assert_1.assert)(market.amm.baseAssetReserve.gt(numericConstants_1.ZERO));
|
|
106
142
|
(0, assert_1.assert)(targetPrice.gt(numericConstants_1.ZERO));
|
|
107
143
|
(0, assert_1.assert)(pct.lte(MAXPCT) && pct.gt(numericConstants_1.ZERO));
|
|
108
|
-
const markPriceBefore = (0, market_1.calculateMarkPrice)(market);
|
|
144
|
+
const markPriceBefore = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
|
|
145
|
+
const bidPriceBefore = (0, market_1.calculateBidPrice)(market, oraclePriceData);
|
|
146
|
+
const askPriceBefore = (0, market_1.calculateAskPrice)(market, oraclePriceData);
|
|
147
|
+
let direction;
|
|
109
148
|
if (targetPrice.gt(markPriceBefore)) {
|
|
110
149
|
const priceGap = targetPrice.sub(markPriceBefore);
|
|
111
150
|
const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
|
|
112
151
|
targetPrice = markPriceBefore.add(priceGapScaled);
|
|
152
|
+
direction = types_1.PositionDirection.LONG;
|
|
113
153
|
}
|
|
114
154
|
else {
|
|
115
155
|
const priceGap = markPriceBefore.sub(targetPrice);
|
|
116
156
|
const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
|
|
117
157
|
targetPrice = markPriceBefore.sub(priceGapScaled);
|
|
158
|
+
direction = types_1.PositionDirection.SHORT;
|
|
118
159
|
}
|
|
119
|
-
let direction;
|
|
120
160
|
let tradeSize;
|
|
121
161
|
let baseSize;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
162
|
+
let baseAssetReserveBefore;
|
|
163
|
+
let quoteAssetReserveBefore;
|
|
164
|
+
let peg = market.amm.pegMultiplier;
|
|
165
|
+
if (useSpread && market.amm.baseSpread > 0) {
|
|
166
|
+
const { baseAssetReserve, quoteAssetReserve, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
|
|
167
|
+
baseAssetReserveBefore = baseAssetReserve;
|
|
168
|
+
quoteAssetReserveBefore = quoteAssetReserve;
|
|
169
|
+
peg = newPeg;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
baseAssetReserveBefore = market.amm.baseAssetReserve;
|
|
173
|
+
quoteAssetReserveBefore = market.amm.quoteAssetReserve;
|
|
174
|
+
}
|
|
125
175
|
const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
126
176
|
const k = invariant.mul(numericConstants_1.MARK_PRICE_PRECISION);
|
|
127
177
|
let baseAssetReserveAfter;
|
|
128
178
|
let quoteAssetReserveAfter;
|
|
129
179
|
const biasModifier = new anchor_1.BN(1);
|
|
130
180
|
let markPriceAfter;
|
|
131
|
-
if (
|
|
181
|
+
if (useSpread &&
|
|
182
|
+
targetPrice.lt(askPriceBefore) &&
|
|
183
|
+
targetPrice.gt(bidPriceBefore)) {
|
|
184
|
+
// no trade, market is at target
|
|
185
|
+
if (markPriceBefore.gt(targetPrice)) {
|
|
186
|
+
direction = types_1.PositionDirection.SHORT;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
direction = types_1.PositionDirection.LONG;
|
|
190
|
+
}
|
|
191
|
+
tradeSize = numericConstants_1.ZERO;
|
|
192
|
+
return [direction, tradeSize, targetPrice, targetPrice];
|
|
193
|
+
}
|
|
194
|
+
else if (markPriceBefore.gt(targetPrice)) {
|
|
132
195
|
// overestimate y2
|
|
133
196
|
baseAssetReserveAfter = (0, utils_1.squareRootBN)(k.div(targetPrice).mul(peg).div(numericConstants_1.PEG_PRECISION).sub(biasModifier)).sub(new anchor_1.BN(1));
|
|
134
197
|
quoteAssetReserveAfter = k
|