Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: reduce allocations in risk & health code #993

Open
wants to merge 4 commits into
base: deploy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@
"@typescript-eslint/parser": "^8.0.1",
"axios": "^1.4.0",
"chai": "^4.3.4",
"cli-table3": "^0.6.3",
"console-table-printer": "^2.11.1",
"eslint": "^9.8.0",
"eslint-config-prettier": "^9.1.0",
"fast-csv": "^4.3.6",
Expand Down
12 changes: 8 additions & 4 deletions ts/client/scripts/update-risk-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ async function setupVsr(
return vsrClient;
}

/** unused
async function getTotalLiqorEquity(
client: MangoClient,
group: Group,
Expand All @@ -127,9 +128,8 @@ async function getTotalLiqorEquity(
)
).json()
).map((data) => new PublicKey(data['liqor']));
const ttlLiqorEquity = (
await getEquityForMangoAccounts(client, group, liqors, mangoAccounts)
).reduce((partialSum, ae) => partialSum + ae.Equity.val, 0);
const ttlLiqorEquity = getEquityForMangoAccounts(client, group, liqors, mangoAccounts)
.reduce((partialSum, ae) => partialSum + ae.Equity.val, 0);
return ttlLiqorEquity;
}

Expand All @@ -152,6 +152,8 @@ function getPriceImpactForBank(
const priceImpact = tokenToPriceImpact[getApiTokenName(bank.name)];
return priceImpact;
}
*/


async function updateTokenParams(): Promise<void> {
const [client, wallet] = await Promise.all([buildClient(), setupWallet()]);
Expand Down Expand Up @@ -208,7 +210,8 @@ async function updateTokenParams(): Promise<void> {
const builder = Builder(NullTokenEditParams);
let change = false;

// try {
// unused
/*
const tier = Object.values(LISTING_PRESETS).find((x) =>
x.initLiabWeight.toFixed(1) === '1.8'
? x.initLiabWeight.toFixed(1) ===
Expand All @@ -217,6 +220,7 @@ async function updateTokenParams(): Promise<void> {
: x.initLiabWeight.toFixed(1) ===
bank?.initLiabWeight.toNumber().toFixed(1),
);
*/

// eslint-disable-next-line no-constant-condition
if (true) {
Expand Down
72 changes: 31 additions & 41 deletions ts/client/src/accounts/healthCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,23 @@ 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 +69,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 +183,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 +197,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 +239,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 +277,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 +499,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 +921,10 @@ export class HealthCache {
targetFn: (cache) => I80F48,
): I80F48 {
if (
sourceBank.initLiabWeight
!sourceBank.initLiabWeight
.sub(targetBank.initAssetWeight)
.abs()
.lte(ZERO_I80F48())
.isPos()
) {
return ZERO_I80F48();
}
Expand Down Expand Up @@ -979,7 +969,7 @@ export class HealthCache {
.mul(price),
);

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

Expand Down Expand Up @@ -1044,9 +1034,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 +1096,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 +1111,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 +1128,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 @@ -1221,7 +1211,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 @@ -1244,7 +1234,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 @@ -1278,8 +1268,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 @@ -1310,7 +1300,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 @@ -1373,7 +1363,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 @@ -1794,7 +1784,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 @@ -1820,7 +1810,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
Loading
Loading