Skip to content

Commit

Permalink
reduce allocations in risk code
Browse files Browse the repository at this point in the history
  • Loading branch information
mschneider authored and microwavedcola1 committed Aug 30, 2024
1 parent 1b6aef5 commit 2ff8db3
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 45 deletions.
72 changes: 29 additions & 43 deletions ts/client/src/accounts/healthCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,22 @@ import { MarketIndex, Serum3Market, Serum3Side } from './serum3';
// ██████████████████████████████████████████
// warning: this code is copy pasta from rust, keep in sync with health.rs

/**
* WARNING this potentially modifies health & starting spot inplace
*/
function spotAmountTakenForHealthZero(
health: I80F48,
startingSpot: I80F48,
assetWeightedPrice: I80F48,
liabWeightedPrice: I80F48,
): I80F48 {
if (health.lte(ZERO_I80F48())) {
if (!health.isPos()) {
return ZERO_I80F48();
}

let takenSpot = ZERO_I80F48();
if (startingSpot.gt(ZERO_I80F48())) {
if (assetWeightedPrice.gt(ZERO_I80F48())) {
if (startingSpot.isPos()) {
if (assetWeightedPrice.isPos()) {
const assetMax = health.div(assetWeightedPrice);
if (assetMax.lte(startingSpot)) {
return assetMax;
Expand All @@ -65,29 +68,15 @@ function spotAmountTakenForHealthZero(
takenSpot = startingSpot;
health.isub(startingSpot.mul(assetWeightedPrice));
}
if (health.gt(ZERO_I80F48())) {
if (liabWeightedPrice.lte(ZERO_I80F48())) {
if (health.isPos()) {
if (!liabWeightedPrice.isPos()) {
throw new Error('LiabWeightedPrice must be greater than 0!');
}
takenSpot.iadd(health.div(liabWeightedPrice));
}
return takenSpot;
}

function _spotAmountGivenForHealthZero(
health: I80F48,
startingSpot: I80F48,
assetWeightedPrice: I80F48,
liabWeightedPrice: I80F48,
): I80F48 {
return spotAmountTakenForHealthZero(
health.neg(),
startingSpot.neg(),
liabWeightedPrice,
assetWeightedPrice,
);
}

export class HealthCache {
constructor(
public tokenInfos: TokenInfo[],
Expand Down Expand Up @@ -193,7 +182,7 @@ export class HealthCache {
quoteAsset.div(baseLiab),
);
let allReservedAsBase;
if (!info.reservedQuoteAsBaseHighestBid.eq(ZERO_I80F48())) {
if (!info.reservedQuoteAsBaseHighestBid.isZero()) {
allReservedAsBase = reservedBase.add(
reservedQuoteAsBaseOracle.min(info.reservedQuoteAsBaseHighestBid),
);
Expand All @@ -207,7 +196,7 @@ export class HealthCache {
baseAsset.div(quoteLiab),
);
let allReservedAsQuote;
if (!info.reservedBaseAsQuoteLowestAsk.eq(ZERO_I80F48())) {
if (!info.reservedBaseAsQuoteLowestAsk.isZero()) {
allReservedAsQuote = reservedQuote.add(
reservedBaseAsQuoteOracle.min(info.reservedBaseAsQuoteLowestAsk),
);
Expand Down Expand Up @@ -249,7 +238,7 @@ export class HealthCache {
);
const perpSettleToken = tokenBalances[settleTokenIndex];
const healthUnsettled = perpInfo.healthUnsettledPnl(healthType);
if (!ignoreNegativePerp || healthUnsettled.gt(ZERO_I80F48())) {
if (!ignoreNegativePerp || healthUnsettled.isPos()) {
perpSettleToken.spotAndPerp.iadd(healthUnsettled);
}
}
Expand Down Expand Up @@ -287,7 +276,7 @@ export class HealthCache {
group.getMintDecimalsByTokenIndex(perpInfo.settleTokenIndex),
),
});
if (!ignoreNegativePerp || healthUnsettled.gt(ZERO_I80F48())) {
if (!ignoreNegativePerp || healthUnsettled.isPos()) {
perpSettleToken.spotAndPerp.iadd(healthUnsettled);
}
}
Expand Down Expand Up @@ -509,11 +498,11 @@ export class HealthCache {

public healthRatio(healthType: HealthType): I80F48 {
const res = this.healthAssetsAndLiabsStableLiabs(healthType);
const hundred = I80F48.fromNumber(100);
// console.log(`assets ${res.assets}`);
// console.log(`liabs ${res.liabs}`);
if (res.liabs.gt(I80F48.fromNumber(0.001))) {
return hundred.mul(res.assets.sub(res.liabs)).div(res.liabs);
const hundred = I80F48.fromNumber(100);
return hundred.imul(res.assets.sub(res.liabs)).idiv(res.liabs);
}
return MAX_I80F48();
}
Expand Down Expand Up @@ -931,10 +920,7 @@ export class HealthCache {
targetFn: (cache) => I80F48,
): I80F48 {
if (
sourceBank.initLiabWeight
.sub(targetBank.initAssetWeight)
.abs()
.lte(ZERO_I80F48())
!sourceBank.initLiabWeight.sub(targetBank.initAssetWeight).abs().isPos()
) {
return ZERO_I80F48();
}
Expand Down Expand Up @@ -979,7 +965,7 @@ export class HealthCache {
.mul(price),
);

if (finalHealthSlope.gte(ZERO_I80F48())) {
if (!finalHealthSlope.isNeg()) {
return MAX_I80F48();
}

Expand Down Expand Up @@ -1044,9 +1030,9 @@ export class HealthCache {
const healthAtMaxValue = cacheAfterSwap(amountForMaxValue).health(
HealthType.init,
);
if (healthAtMaxValue.eq(ZERO_I80F48())) {
if (healthAtMaxValue.isZero()) {
return amountForMaxValue;
} else if (healthAtMaxValue.lt(ZERO_I80F48())) {
} else if (healthAtMaxValue.isNeg()) {
return ZERO_I80F48();
}
const zeroHealthEstimate = amountForMaxValue.sub(
Expand Down Expand Up @@ -1106,7 +1092,7 @@ export class HealthCache {
const initialAmount = ZERO_I80F48();
const initialHealth = this.health(HealthType.init);
const initialRatio = this.healthRatio(HealthType.init);
if (initialRatio.lte(ZERO_I80F48())) {
if (!initialRatio.isPos()) {
return ZERO_I80F48();
}

Expand All @@ -1121,7 +1107,7 @@ export class HealthCache {
// and when its a bid, then quote->bid
let zeroAmount;
if (side == Serum3Side.ask) {
const quoteBorrows = quote.balanceSpot.lt(ZERO_I80F48())
const quoteBorrows = quote.balanceSpot.isNeg()
? quote.balanceSpot.abs().mul(quote.prices.liab(HealthType.init))
: ZERO_I80F48();
const max = base.balanceSpot.mul(base.prices.oracle).max(quoteBorrows);
Expand All @@ -1138,7 +1124,7 @@ export class HealthCache {
// console.log(` - quoteBorrows ${quoteBorrows.toLocaleString()}`);
// console.log(` - max ${max.toLocaleString()}`);
} else {
const baseBorrows = base.balanceSpot.lt(ZERO_I80F48())
const baseBorrows = base.balanceSpot.isNeg()
? base.balanceSpot.abs().mul(base.prices.liab(HealthType.init))
: ZERO_I80F48();
const max = quote.balanceSpot.mul(quote.prices.oracle).max(baseBorrows);
Expand Down Expand Up @@ -1220,7 +1206,7 @@ export class HealthCache {
const healthCacheClone: HealthCache = deepClone<HealthCache>(this);

const initialRatio = this.healthRatio(HealthType.init);
if (initialRatio.lt(ZERO_I80F48())) {
if (initialRatio.isNeg()) {
return ZERO_I80F48();
}

Expand All @@ -1243,7 +1229,7 @@ export class HealthCache {
.neg()
.mul(prices.liab(HealthType.init))
.add(price);
if (finalHealthSlope.gte(ZERO_I80F48())) {
if (!finalHealthSlope.isNeg()) {
return MAX_I80F48();
}
finalHealthSlope.imul(settleInfo.liabWeightedPrice(HealthType.init));
Expand Down Expand Up @@ -1277,8 +1263,8 @@ export class HealthCache {
// 1. We are increasing abs(baseLots)
// 2. We are bringing the base position to 0, and then going to case 1.
const hasCase2 =
(initialBaseLots.gt(ZERO_I80F48()) && direction == -1) ||
(initialBaseLots.lt(ZERO_I80F48()) && direction == 1);
(initialBaseLots.isPos() && direction == -1) ||
(initialBaseLots.isNeg() && direction == 1);

let case1Start: I80F48, case1StartRatio: I80F48;
if (hasCase2) {
Expand Down Expand Up @@ -1309,7 +1295,7 @@ export class HealthCache {
settleInfo.initAssetWeight = settleInfo.initLiabWeight;
settleInfo.initScaledAssetWeight = settleInfo.initScaledLiabWeight;
const startHealth = startCache.health(HealthType.init);
if (startHealth.lte(ZERO_I80F48())) {
if (!startHealth.isPos()) {
return ZERO_I80F48();
}

Expand Down Expand Up @@ -1372,7 +1358,7 @@ export class HealthCache {
if (perpPosition.getBasePosition(perpMarket).isPos()) {
const zero = ZERO_I80F48();
const healthAtPriceZero = healthAfterPriceChange(zero);
if (healthAtPriceZero.gt(ZERO_I80F48())) {
if (healthAtPriceZero.isPos()) {
return null;
}

Expand Down Expand Up @@ -1793,7 +1779,7 @@ export class PerpInfo {
if (this.settleTokenIndex !== settleToken.tokenIndex) {
throw new Error('Settle token index should match!');
}
if (unweighted.gt(ZERO_I80F48())) {
if (unweighted.isPos()) {
return (
healthType == HealthType.init
? settleToken.initScaledAssetWeight
Expand All @@ -1819,7 +1805,7 @@ export class PerpInfo {
unweighted: I80F48,
healthType: HealthType | undefined,
): I80F48 {
if (unweighted.gt(ZERO_I80F48())) {
if (unweighted.isPos()) {
return (
healthType == HealthType.init || healthType == HealthType.liquidationEnd
? this.initOverallAssetWeight
Expand Down
4 changes: 2 additions & 2 deletions ts/client/src/accounts/mangoAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,10 @@ export class MangoAccount {
)) {
const oo = this.serum3OosMapByMarketIndex.get(serum3Market.marketIndex);
if (serum3Market.baseTokenIndex == bank.tokenIndex && oo) {
bal.add(I80F48.fromI64(oo.baseTokenFree));
bal.iadd(I80F48.fromI64(oo.baseTokenFree));
}
if (serum3Market.quoteTokenIndex == bank.tokenIndex && oo) {
bal.add(I80F48.fromI64(oo.quoteTokenFree));
bal.iadd(I80F48.fromI64(oo.quoteTokenFree));
}
}
return bal;
Expand Down

0 comments on commit 2ff8db3

Please sign in to comment.