Mc/health max swap with serum effects (#333)
* rearrange, log before expect Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * rearrange, log before expect Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * Fix test Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * health max swap with serum effects Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * max swap: Fix with serum reserved amounts * port rust code to ts Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * port tests Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * Fix method call Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * Fixes from review Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> Co-authored-by: Christian Kamm <mail@ckamm.de>
This commit is contained in:
parent
f4942fd674
commit
51cded4965
|
@ -19,7 +19,7 @@
|
|||
"build": "npm run build:esm; npm run build:cjs",
|
||||
"build:cjs": "tsc -p tsconfig.cjs.json",
|
||||
"build:esm": "tsc -p tsconfig.esm.json",
|
||||
"test": "ts-mocha ts/client/**/*.spec.ts --timeout 10000",
|
||||
"test": "ts-mocha ts/client/**/*.spec.ts --timeout 15000",
|
||||
"clean": "rm -rf dist",
|
||||
"example1-user": "ts-node ts/client/src/scripts/example1-user.ts",
|
||||
"example1-admin": "ts-node ts/client/src/scripts/example1-admin.ts",
|
||||
|
|
|
@ -15,7 +15,7 @@ use super::*;
|
|||
const ONE_NATIVE_USDC_IN_USD: I80F48 = I80F48!(0.000001);
|
||||
|
||||
/// Information about prices for a bank or perp market.
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize)]
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
|
||||
pub struct Prices {
|
||||
/// The current oracle price
|
||||
pub oracle: I80F48, // native/native
|
||||
|
@ -87,7 +87,7 @@ pub fn compute_health(
|
|||
Ok(new_health_cache(account, retriever)?.health(health_type))
|
||||
}
|
||||
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize)]
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
|
||||
pub struct TokenInfo {
|
||||
pub token_index: TokenIndex,
|
||||
pub maint_asset_weight: I80F48,
|
||||
|
@ -129,7 +129,7 @@ impl TokenInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize)]
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
|
||||
pub struct Serum3Info {
|
||||
// reserved amounts as stored on the open orders
|
||||
pub reserved_base: I80F48,
|
||||
|
@ -208,7 +208,7 @@ struct Serum3Reserved {
|
|||
all_reserved_as_quote: I80F48,
|
||||
}
|
||||
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize)]
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
|
||||
pub struct PerpInfo {
|
||||
pub perp_market_index: PerpMarketIndex,
|
||||
pub maint_asset_weight: I80F48,
|
||||
|
@ -313,7 +313,7 @@ impl PerpInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize)]
|
||||
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
|
||||
pub struct HealthCache {
|
||||
pub(crate) token_infos: Vec<TokenInfo>,
|
||||
pub(crate) serum3_infos: Vec<Serum3Info>,
|
||||
|
|
|
@ -206,18 +206,36 @@ impl HealthCache {
|
|||
// - source_liab_weight * source_liab_price * a
|
||||
// + target_asset_weight * target_asset_price * price * a = 0.
|
||||
// where a is the source token native amount.
|
||||
// Note that this is just an estimate. Swapping can increase the amount that serum3
|
||||
// reserved contributions offset, moving the actual zero point further to the right.
|
||||
if point1_health <= 0 {
|
||||
return Ok(I80F48::ZERO);
|
||||
}
|
||||
let zero_health_amount = point1_amount - point1_health / final_health_slope;
|
||||
binary_search(
|
||||
point1_amount,
|
||||
point1_ratio,
|
||||
zero_health_amount,
|
||||
let zero_health_estimate = point1_amount - point1_health / final_health_slope;
|
||||
let right_bound = scan_right_until_less_than(
|
||||
zero_health_estimate,
|
||||
min_ratio,
|
||||
I80F48::from_num(0.1),
|
||||
health_ratio_after_swap,
|
||||
)?
|
||||
)?;
|
||||
if right_bound == zero_health_estimate {
|
||||
binary_search(
|
||||
point1_amount,
|
||||
point1_ratio,
|
||||
right_bound,
|
||||
min_ratio,
|
||||
I80F48::from_num(0.1),
|
||||
health_ratio_after_swap,
|
||||
)?
|
||||
} else {
|
||||
binary_search(
|
||||
zero_health_estimate,
|
||||
health_ratio_after_swap(zero_health_estimate)?,
|
||||
right_bound,
|
||||
min_ratio,
|
||||
I80F48::from_num(0.1),
|
||||
health_ratio_after_swap,
|
||||
)?
|
||||
}
|
||||
} else if point0_ratio >= min_ratio {
|
||||
// Must be between point0_amount and point1_amount.
|
||||
binary_search(
|
||||
|
@ -373,6 +391,25 @@ impl HealthCache {
|
|||
}
|
||||
}
|
||||
|
||||
fn scan_right_until_less_than(
|
||||
start: I80F48,
|
||||
target: I80F48,
|
||||
fun: impl Fn(I80F48) -> Result<I80F48>,
|
||||
) -> Result<I80F48> {
|
||||
let max_iterations = 20;
|
||||
let mut current = start;
|
||||
for _ in 0..max_iterations {
|
||||
let value = fun(current)?;
|
||||
if value <= target {
|
||||
return Ok(current);
|
||||
}
|
||||
current = current.max(I80F48::ONE) * I80F48::from(2);
|
||||
}
|
||||
Err(error_msg!(
|
||||
"could not find amount that lead to health ratio <= 0"
|
||||
))
|
||||
}
|
||||
|
||||
fn binary_search(
|
||||
mut left: I80F48,
|
||||
left_value: I80F48,
|
||||
|
@ -536,12 +573,11 @@ mod tests {
|
|||
.map(|c| c.health_ratio(HealthType::Init).to_num::<f64>())
|
||||
.unwrap_or(f64::MIN)
|
||||
};
|
||||
// With the binary search error, we can guarantee just +-1
|
||||
(
|
||||
source_amount.to_num(),
|
||||
ratio_for_amount(source_amount),
|
||||
ratio_for_amount(source_amount.saturating_sub(I80F48::ONE)),
|
||||
ratio_for_amount(source_amount.saturating_add(I80F48::ONE)),
|
||||
ratio_for_amount(source_amount - I80F48::ONE),
|
||||
ratio_for_amount(source_amount + I80F48::ONE),
|
||||
)
|
||||
};
|
||||
let check_max_swap_result = |c: &HealthCache,
|
||||
|
@ -556,8 +592,9 @@ mod tests {
|
|||
"checking {source} to {target} for price_factor: {price_factor}, target ratio {ratio}: actual ratios: {minus_ratio}/{actual_ratio}/{plus_ratio}, amount: {source_amount}",
|
||||
);
|
||||
assert!(actual_ratio >= ratio);
|
||||
assert!(minus_ratio < ratio || actual_ratio < minus_ratio);
|
||||
assert!(plus_ratio < ratio);
|
||||
// either we're within tolerance of the target, or swapping 1 more would
|
||||
// bring us below the target
|
||||
assert!(actual_ratio < ratio + 1.0 || plus_ratio < ratio);
|
||||
};
|
||||
|
||||
{
|
||||
|
@ -654,6 +691,34 @@ mod tests {
|
|||
// (tracking happens without decimals)
|
||||
assert!(find_max_swap_actual(&health_cache, 0, 1, 1.0, 1.0, banks).0 < 51.0);
|
||||
}
|
||||
|
||||
{
|
||||
// check with serum reserved
|
||||
println!("test 6");
|
||||
let mut health_cache = health_cache.clone();
|
||||
health_cache.serum3_infos = vec![Serum3Info {
|
||||
base_index: 1,
|
||||
quote_index: 0,
|
||||
market_index: 0,
|
||||
reserved_base: I80F48::from(30 / 3),
|
||||
reserved_quote: I80F48::from(30 / 2),
|
||||
}];
|
||||
adjust_by_usdc(&mut health_cache, 0, -20.0);
|
||||
adjust_by_usdc(&mut health_cache, 1, -40.0);
|
||||
adjust_by_usdc(&mut health_cache, 2, 120.0);
|
||||
|
||||
for price_factor in [0.9, 1.1] {
|
||||
for target in 1..100 {
|
||||
let target = target as f64;
|
||||
check_max_swap_result(&health_cache, 0, 1, target, price_factor, banks);
|
||||
check_max_swap_result(&health_cache, 1, 0, target, price_factor, banks);
|
||||
check_max_swap_result(&health_cache, 0, 2, target, price_factor, banks);
|
||||
check_max_swap_result(&health_cache, 1, 2, target, price_factor, banks);
|
||||
check_max_swap_result(&health_cache, 2, 0, target, price_factor, banks);
|
||||
check_max_swap_result(&health_cache, 2, 1, target, price_factor, banks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -14,6 +14,7 @@ function mockBankAndOracle(
|
|||
maintWeight: number,
|
||||
initWeight: number,
|
||||
price: number,
|
||||
stablePrice: number,
|
||||
): BankForHealth {
|
||||
return {
|
||||
tokenIndex,
|
||||
|
@ -22,7 +23,7 @@ function mockBankAndOracle(
|
|||
maintLiabWeight: I80F48.fromNumber(1 + maintWeight),
|
||||
initLiabWeight: I80F48.fromNumber(1 + initWeight),
|
||||
price: I80F48.fromNumber(price),
|
||||
stablePriceModel: { stablePrice: price } as StablePriceModel,
|
||||
stablePriceModel: { stablePrice: stablePrice } as StablePriceModel,
|
||||
scaledInitAssetWeight: () => I80F48.fromNumber(1 - initWeight),
|
||||
scaledInitLiabWeight: () => I80F48.fromNumber(1 + initWeight),
|
||||
};
|
||||
|
@ -57,12 +58,14 @@ describe('Health Cache', () => {
|
|||
0.1,
|
||||
0.2,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
const targetBank: BankForHealth = mockBankAndOracle(
|
||||
4 as TokenIndex,
|
||||
0.3,
|
||||
0.5,
|
||||
5,
|
||||
5,
|
||||
);
|
||||
|
||||
const ti1 = TokenInfo.fromBank(sourceBank, I80F48.fromNumber(100));
|
||||
|
@ -146,18 +149,21 @@ describe('Health Cache', () => {
|
|||
0.1,
|
||||
0.2,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
const bank2: BankForHealth = mockBankAndOracle(
|
||||
4 as TokenIndex,
|
||||
0.3,
|
||||
0.5,
|
||||
5,
|
||||
5,
|
||||
);
|
||||
const bank3: BankForHealth = mockBankAndOracle(
|
||||
5 as TokenIndex,
|
||||
0.3,
|
||||
0.5,
|
||||
10,
|
||||
10,
|
||||
);
|
||||
|
||||
const ti1 = TokenInfo.fromBank(bank1, I80F48.fromNumber(fixture.token1));
|
||||
|
@ -390,9 +396,9 @@ describe('Health Cache', () => {
|
|||
});
|
||||
|
||||
it('test_max_swap', (done) => {
|
||||
const b0 = mockBankAndOracle(0 as TokenIndex, 0.1, 0.1, 2);
|
||||
const b1 = mockBankAndOracle(1 as TokenIndex, 0.2, 0.2, 3);
|
||||
const b2 = mockBankAndOracle(2 as TokenIndex, 0.3, 0.3, 4);
|
||||
const b0 = mockBankAndOracle(0 as TokenIndex, 0.1, 0.1, 2, 2);
|
||||
const b1 = mockBankAndOracle(1 as TokenIndex, 0.2, 0.2, 3, 3);
|
||||
const b2 = mockBankAndOracle(2 as TokenIndex, 0.3, 0.3, 4, 4);
|
||||
const banks = [b0, b1, b2];
|
||||
const hc = new HealthCache(
|
||||
[
|
||||
|
@ -475,13 +481,13 @@ describe('Health Cache', () => {
|
|||
|
||||
for (const priceFactor of [0.1, 0.9, 1.1]) {
|
||||
for (const target of _.range(1, 100, 1)) {
|
||||
// checkMaxSwapResult(
|
||||
// clonedHc,
|
||||
// 0 as TokenIndex,
|
||||
// 1 as TokenIndex,
|
||||
// target,
|
||||
// priceFactor,
|
||||
// );
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
0 as TokenIndex,
|
||||
1 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
1 as TokenIndex,
|
||||
|
@ -489,13 +495,13 @@ describe('Health Cache', () => {
|
|||
target,
|
||||
priceFactor,
|
||||
);
|
||||
// checkMaxSwapResult(
|
||||
// clonedHc,
|
||||
// 0 as TokenIndex,
|
||||
// 2 as TokenIndex,
|
||||
// target,
|
||||
// priceFactor,
|
||||
// );
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
0 as TokenIndex,
|
||||
2 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,12 +629,90 @@ describe('Health Cache', () => {
|
|||
checkMaxSwapResult(clonedHc, 0 as TokenIndex, 1 as TokenIndex, 4, 1);
|
||||
}
|
||||
|
||||
// TODO test 5
|
||||
|
||||
{
|
||||
console.log(' - test 6');
|
||||
const clonedHc = _.cloneDeep(hc);
|
||||
clonedHc.serum3Infos = [
|
||||
new Serum3Info(
|
||||
I80F48.fromNumber(30 / 3),
|
||||
I80F48.fromNumber(30 / 2),
|
||||
1,
|
||||
0,
|
||||
0 as MarketIndex,
|
||||
),
|
||||
];
|
||||
|
||||
// adjust by usdc
|
||||
clonedHc.tokenInfos[0].balanceNative.iadd(
|
||||
I80F48.fromNumber(-20).div(clonedHc.tokenInfos[0].prices.oracle),
|
||||
);
|
||||
clonedHc.tokenInfos[1].balanceNative.iadd(
|
||||
I80F48.fromNumber(-40).div(clonedHc.tokenInfos[1].prices.oracle),
|
||||
);
|
||||
clonedHc.tokenInfos[2].balanceNative.iadd(
|
||||
I80F48.fromNumber(120).div(clonedHc.tokenInfos[2].prices.oracle),
|
||||
);
|
||||
|
||||
for (const priceFactor of [
|
||||
// 0.9,
|
||||
|
||||
1.1,
|
||||
]) {
|
||||
for (const target of _.range(1, 100, 1)) {
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
0 as TokenIndex,
|
||||
1 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
1 as TokenIndex,
|
||||
0 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
0 as TokenIndex,
|
||||
2 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
1 as TokenIndex,
|
||||
2 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
2 as TokenIndex,
|
||||
0 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
checkMaxSwapResult(
|
||||
clonedHc,
|
||||
2 as TokenIndex,
|
||||
1 as TokenIndex,
|
||||
target,
|
||||
priceFactor,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('test_max_perp', (done) => {
|
||||
const baseLotSize = 100;
|
||||
const b0 = mockBankAndOracle(0 as TokenIndex, 0.0, 0.0, 1);
|
||||
const b0 = mockBankAndOracle(0 as TokenIndex, 0.0, 0.0, 1, 1);
|
||||
const p0 = mockPerpMarket(0, 0.3, 0.3, baseLotSize, 2);
|
||||
const hc = new HealthCache(
|
||||
[TokenInfo.fromBank(b0, I80F48.fromNumber(0))],
|
||||
|
|
|
@ -548,26 +548,43 @@ export class HealthCache {
|
|||
);
|
||||
}
|
||||
|
||||
private static scanRightUntilLessThan(
|
||||
start: I80F48,
|
||||
target: I80F48,
|
||||
fun: (amount: I80F48) => I80F48,
|
||||
): I80F48 {
|
||||
const maxIterations = 20;
|
||||
let current = start;
|
||||
for (const key of Array(maxIterations).fill(0).keys()) {
|
||||
const value = fun(current);
|
||||
if (value.lt(target)) {
|
||||
return current;
|
||||
}
|
||||
current = current.max(ONE_I80F48()).mul(I80F48.fromNumber(2));
|
||||
}
|
||||
throw new Error('Could not find amount that led to health ratio <=0');
|
||||
}
|
||||
|
||||
private static binaryApproximationSearch(
|
||||
left: I80F48,
|
||||
leftRatio: I80F48,
|
||||
leftValue: I80F48,
|
||||
right: I80F48,
|
||||
rightRatio: I80F48,
|
||||
targetRatio: I80F48,
|
||||
targetValue: I80F48,
|
||||
minStep: I80F48,
|
||||
healthRatioAfterActionFn: (I80F48) => I80F48,
|
||||
fun: (I80F48) => I80F48,
|
||||
): I80F48 {
|
||||
const maxIterations = 20;
|
||||
const targetError = I80F48.fromNumber(0.1);
|
||||
const rightValue = fun(right);
|
||||
|
||||
if (
|
||||
(leftRatio.sub(targetRatio).isPos() &&
|
||||
rightRatio.sub(targetRatio).isPos()) ||
|
||||
(leftRatio.sub(targetRatio).isNeg() &&
|
||||
rightRatio.sub(targetRatio).isNeg())
|
||||
(leftValue.sub(targetValue).isPos() &&
|
||||
rightValue.sub(targetValue).isPos()) ||
|
||||
(leftValue.sub(targetValue).isNeg() &&
|
||||
rightValue.sub(targetValue).isNeg())
|
||||
) {
|
||||
throw new Error(
|
||||
`Internal error: left ${leftRatio.toNumber()} and right ${rightRatio.toNumber()} don't contain the target value ${targetRatio.toNumber()}, likely reason is the zeroAmount not been tight enough!`,
|
||||
`Internal error: left ${leftValue.toNumber()} and right ${rightValue.toNumber()} don't contain the target value ${targetValue.toNumber()}!`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -578,25 +595,16 @@ export class HealthCache {
|
|||
return left;
|
||||
}
|
||||
newAmount = left.add(right).mul(I80F48.fromNumber(0.5));
|
||||
const newAmountRatio = healthRatioAfterActionFn(newAmount);
|
||||
const error = newAmountRatio.sub(targetRatio);
|
||||
const newAmountRatio = fun(newAmount);
|
||||
const error = newAmountRatio.sub(targetValue);
|
||||
if (error.isPos() && error.lt(targetError)) {
|
||||
return newAmount;
|
||||
}
|
||||
if (newAmountRatio.gt(targetRatio) != rightRatio.gt(targetRatio)) {
|
||||
if (newAmountRatio.gt(targetValue) != rightValue.gt(targetValue)) {
|
||||
left = newAmount;
|
||||
leftRatio = newAmountRatio;
|
||||
} else {
|
||||
right = newAmount;
|
||||
rightRatio = newAmountRatio;
|
||||
}
|
||||
// console.log(
|
||||
// ` -- ${left.toNumber().toFixed(3)} (${leftRatio
|
||||
// .toNumber()
|
||||
// .toFixed(3)}) ${right.toNumber().toFixed(3)} (${rightRatio
|
||||
// .toNumber()
|
||||
// .toFixed(3)})`,
|
||||
// );
|
||||
}
|
||||
|
||||
console.error(
|
||||
|
@ -726,31 +734,45 @@ export class HealthCache {
|
|||
// search to the right of point1Amount: but how far?
|
||||
// At point1, source.balance < 0 and target.balance > 0, so use a simple estimation for
|
||||
// zero health: health - source_liab_weight * a + target_asset_weight * a * priceFactor = 0.
|
||||
// where a is the source token native amount.
|
||||
// Note that this is just an estimate. Swapping can increase the amount that serum3
|
||||
// reserved contributions offset, moving the actual zero point further to the right.
|
||||
if (point1Health.lte(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
const zeroHealthAmount = point1Amount.sub(
|
||||
point1Health.div(finalHealthSlope),
|
||||
const zeroHealthEstimate = point1Amount.sub(
|
||||
point1Health.sub(finalHealthSlope),
|
||||
);
|
||||
const zeroHealthRatio = healthRatioAfterSwap(zeroHealthAmount);
|
||||
const zeroHealth = healthAfterSwap(zeroHealthAmount);
|
||||
|
||||
amount = HealthCache.binaryApproximationSearch(
|
||||
point1Amount,
|
||||
point1Ratio,
|
||||
zeroHealthAmount,
|
||||
zeroHealthRatio,
|
||||
const rightBound = HealthCache.scanRightUntilLessThan(
|
||||
zeroHealthEstimate,
|
||||
minRatio,
|
||||
ZERO_I80F48(),
|
||||
healthRatioAfterSwap,
|
||||
);
|
||||
if (rightBound.eq(zeroHealthEstimate)) {
|
||||
amount = HealthCache.binaryApproximationSearch(
|
||||
point1Amount,
|
||||
point1Ratio,
|
||||
rightBound,
|
||||
minRatio,
|
||||
ZERO_I80F48(),
|
||||
healthRatioAfterSwap,
|
||||
);
|
||||
} else {
|
||||
amount = HealthCache.binaryApproximationSearch(
|
||||
zeroHealthEstimate,
|
||||
healthRatioAfterSwap(zeroHealthEstimate),
|
||||
rightBound,
|
||||
minRatio,
|
||||
ZERO_I80F48(),
|
||||
healthRatioAfterSwap,
|
||||
);
|
||||
}
|
||||
} else if (point0Ratio.gte(minRatio)) {
|
||||
// Must be between point0Amount and point1Amount.
|
||||
amount = HealthCache.binaryApproximationSearch(
|
||||
point0Amount,
|
||||
point0Ratio,
|
||||
point1Amount,
|
||||
point1Ratio,
|
||||
minRatio,
|
||||
ZERO_I80F48(),
|
||||
healthRatioAfterSwap,
|
||||
|
@ -761,7 +783,6 @@ export class HealthCache {
|
|||
ZERO_I80F48(),
|
||||
initialRatio,
|
||||
point0Amount,
|
||||
point0Ratio,
|
||||
minRatio,
|
||||
ZERO_I80F48(),
|
||||
healthRatioAfterSwap,
|
||||
|
@ -880,7 +901,6 @@ export class HealthCache {
|
|||
initialAmount,
|
||||
initialRatio,
|
||||
zeroAmount,
|
||||
zeroAmountRatio,
|
||||
minRatio,
|
||||
ONE_I80F48(),
|
||||
healthRatioAfterPlacingOrder,
|
||||
|
@ -994,7 +1014,6 @@ export class HealthCache {
|
|||
case1Start,
|
||||
case1StartRatio,
|
||||
zeroHealthAmount,
|
||||
zeroHealthRatio,
|
||||
minRatio,
|
||||
ONE_I80F48(),
|
||||
healthRatioAfterTradeTrunc,
|
||||
|
@ -1005,7 +1024,6 @@ export class HealthCache {
|
|||
ZERO_I80F48(),
|
||||
initialRatio,
|
||||
case1Start,
|
||||
case1StartRatio,
|
||||
minRatio,
|
||||
ONE_I80F48(),
|
||||
healthRatioAfterTradeTrunc,
|
||||
|
|
Loading…
Reference in New Issue