Skip to content

Commit

Permalink
sdk: update leverage calculations (#339)
Browse files Browse the repository at this point in the history
* update leverage calcs

* update getHealth

* fix liquidateSpot test

* CHANGELOG

Co-authored-by: Chris Heaney <[email protected]>
  • Loading branch information
lowkeynicc and crispheaney committed Jan 26, 2023
1 parent 527ac50 commit 3dfd9ad
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- program: enforce min order size when trading against amm ([#334](https://github.com/drift-labs/protocol-v2/pull/334))

### Fixes
- ts-sdk: update methods to account for new leverage formula ([#339](https://github.com/drift-labs/protocol-v2/pull/339))

### Breaking

Expand Down
4 changes: 3 additions & 1 deletion sdk/src/driftClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2990,7 +2990,9 @@ export class DriftClient {

const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
if (!openOrder) {
throw new Error(`No open order with user order id ${userOrderId.toString()}`);
throw new Error(
`No open order with user order id ${userOrderId.toString()}`
);
}
const cancelOrderIx = await this.getCancelOrderIx(openOrder.orderId);

Expand Down
73 changes: 52 additions & 21 deletions sdk/src/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,17 +804,12 @@ export class User {
} else if (totalCollateral.lte(ZERO)) {
health = 0;
} else {
// const totalCollateral = this.getTotalCollateral('Initial');
// const maintenanceMarginReq = this.getMaintenanceMarginRequirement();

const marginRatio =
this.getMarginRatio().toNumber() / MARGIN_PRECISION.toNumber();

const maintenanceRatio =
(maintenanceMarginReq.toNumber() / totalCollateral.toNumber()) *
marginRatio;

const healthP1 = Math.max(0, (marginRatio - maintenanceRatio) * 100) + 1;
const healthP1 =
Math.max(
0,
(totalCollateral.toNumber() / maintenanceMarginReq.toNumber() - 1) *
100
) + 1;

health = Math.min(1, Math.log(healthP1) / Math.log(100)) * 100;
if (health > 1) {
Expand Down Expand Up @@ -1072,12 +1067,27 @@ export class User {
): BN {
const market = this.driftClient.getPerpMarketAccount(marketIndex);

const totalPerpLiability = this.getTotalPerpPositionValue(
undefined,
undefined,
true
);
const totalSpotLiability = this.getSpotMarketLiabilityValue(
undefined,
undefined,
undefined,
true
);

const totalAssetValue = this.getTotalAssetValue();
if (totalAssetValue.eq(ZERO)) {

const netAssetValue = totalAssetValue.sub(totalSpotLiability);

if (netAssetValue.eq(ZERO)) {
return ZERO;
}

const totalLiabilityValue = this.getTotalLiabilityValue();
const totalLiabilityValue = totalPerpLiability.add(totalSpotLiability);

const marginRatio = calculateMarketMarginRatio(
market,
Expand All @@ -1095,23 +1105,36 @@ export class User {
return totalLiabilityValue
.add(additionalLiabilities)
.mul(TEN_THOUSAND)
.div(totalAssetValue);
.div(netAssetValue);
}

/**
* calculates margin ratio: total collateral / |total position value|
* @returns : Precision TEN_THOUSAND
*/
public getMarginRatio(marginCategory?: MarginCategory): BN {
const totalLiabilityValue = this.getTotalLiabilityValue(marginCategory);
const totalPerpLiability = this.getTotalPerpPositionValue(
undefined,
undefined,
true
);
const totalSpotLiability = this.getSpotMarketLiabilityValue(
undefined,
undefined,
undefined,
true
);

const totalLiabilityValue = totalPerpLiability.add(totalSpotLiability);

if (totalLiabilityValue.eq(ZERO)) {
return BN_MAX;
}

const totalAssetValue = this.getTotalAssetValue(marginCategory);
const netAssetValue = totalAssetValue.sub(totalSpotLiability);

return totalAssetValue.mul(TEN_THOUSAND).div(totalLiabilityValue);
return netAssetValue.mul(TEN_THOUSAND).div(totalLiabilityValue);
}

public canBeLiquidated(): boolean {
Expand Down Expand Up @@ -1597,21 +1620,29 @@ export class User {

const totalAssetValue = this.getTotalAssetValue();

const totalPerpPositionValue = currentPerpPositionAfterTrade
const totalPerpPositionLiability = currentPerpPositionAfterTrade
.add(totalPositionAfterTradeExcludingTargetMarket)
.abs();

const totalLiabilitiesAfterTrade = totalPerpPositionValue.add(
this.getSpotMarketLiabilityValue(undefined, undefined, undefined, false)
const totalSpotLiability = this.getSpotMarketLiabilityValue(
undefined,
undefined,
undefined,
includeOpenOrders
);

if (totalAssetValue.eq(ZERO) && totalLiabilitiesAfterTrade.eq(ZERO)) {
const totalLiabilitiesAfterTrade =
totalPerpPositionLiability.add(totalSpotLiability);

const netAssetValue = totalAssetValue.sub(totalSpotLiability);

if (netAssetValue.eq(ZERO)) {
return ZERO;
}

const newLeverage = totalLiabilitiesAfterTrade
.mul(TEN_THOUSAND)
.div(totalAssetValue);
.div(netAssetValue);

return newLeverage;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/liquidateSpot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ describe('liquidate spot', () => {
await driftClient.fetchAccounts();
const healthBefore100 = user.getHealth();
console.log('healthBefore100:', healthBefore100);
assert(healthBefore100 == 98);
assert(healthBefore100 == 96);

console.log(
'spotLiquidationPrice:',
Expand All @@ -170,7 +170,7 @@ describe('liquidate spot', () => {
await user.fetchAccounts();
const healthBefore179 = user.getHealth();
console.log('healthBefore179:', healthBefore179);
assert(healthBefore179 == 22);
assert(healthBefore179 == 21);
console.log(
'spotLiquidationPrice:',
convertToNumber(user.spotLiquidationPrice(user.getSpotPosition(1)))
Expand Down

0 comments on commit 3dfd9ad

Please sign in to comment.