calcDeltasForRatio(uint128[] memory tokensHeld, uint128[] memory reserves, uint256[] calldata ratio) external view returns(int256[] memory deltas)

/// @dev Calculate quantities to trade to be able to close the `liquidity` amount
/// @param tokensHeld - tokens held as collateral for liquidity to pay
/// @param reserves - reserve token quantities in CFMM
/// @param liquidity - amount of liquidity to pay
/// @param collateralId - index of tokensHeld array to rebalance to (e.g. the collateral of the chosen index will be completely used up in repayment)
/// @return deltas - amounts of collateral to trade to be able to repay `liquidity`
function _calcDeltasToClose(uint128[] memory tokensHeld, uint128[] memory reserves, uint256 liquidity, uint256 collateralId) internal virtual override view returns(int256[] memory deltas) {
    require(collateralId < 2);
    deltas = new int256[](2);
    uint256 lastCFMMInvariant = calcInvariant(address(0), reserves);
    deltas[collateralId] = calcDeltasToClose(lastCFMMInvariant, reserves[collateralId], tokensHeld[collateralId], liquidity);
}

// how much collateral to trade to have enough to close a position
// reserve and collateral have to be of the same token
// if > 0 => have to buy token to have exact amount of token to close position
// if < 0 => have to sell token to have exact amount of token to close position
function calcDeltasToClose(uint256 lastCFMMInvariant, uint256 reserve, uint256 collateral, uint256 liquidity) public virtual pure returns(int256 delta) {
    uint256 left = reserve * liquidity;
    uint256 right = collateral * lastCFMMInvariant;
    bool isNeg = right > left;
    uint256 _delta = (isNeg ? right - left : left - right) / (lastCFMMInvariant + liquidity);
    delta = isNeg ? -int256(_delta) : int256(_delta);
}

_calcDeltasToClose calls calcDeltasToClose to find the necessary quantity to trade to rebalance the collateral so that we can repay the debt and only have one of the collateral amounts remaining in the loan. This function however, ignores the trading fees in the CFMM. This means that the rebalancing act can have a shortfall of approximately 0.15% in the most extreme case where 50% of the total liquidity of the pool needs to trade. The size of this shortfall is tolerable.

Formula

The formula for the above function to be able to close the position is the following.

Definitions:

A = Quantity of collateral tokenA

B = Quantity of collateral tokenB

A_hat = Quantity of reserves of tokenA in CFMM

B_hat = Quantity of reserves of tokenB in CFMM

L = liquidity debt of loan

Lp = total liquidity invariant in CFMM (geometric mean of reserves)

d = L / Lp

a = quantity to trade of tokenA

b = quantity to trade of tokenB