library QuantMath {
    ...
    struct FixedPointInt {
        int256 value;
    }

    int256 private constant _SCALING_FACTOR = 1e27;
    uint256 private constant _BASE_DECIMALS = 27;

    ...

    function toScaledUint(
        FixedPointInt memory _a,
        uint256 _decimals,
        bool _roundDown
    ) internal pure returns (uint256) {
        uint256 scaledUint;

        if (_decimals == _BASE_DECIMALS) {
            scaledUint = _a.value.intToUint();
        } else if (_decimals > _BASE_DECIMALS) {
            uint256 exp = _decimals - _BASE_DECIMALS;
            scaledUint = (_a.value).intToUint() * 10**exp;
        } else {
            uint256 exp = _BASE_DECIMALS - _decimals;
            uint256 tailing;
            if (!_roundDown) {
                uint256 remainer = (_a.value).intToUint() % 10**exp;
                if (remainer > 0) tailing = 1;
            }
            scaledUint = (_a.value).intToUint() / 10**exp + tailing;
        }

        return scaledUint;
    }
    ...
}
    function mul(FixedPointInt memory a, FixedPointInt memory b)
        internal
        pure
        returns (FixedPointInt memory)
    {
        return FixedPointInt((a.value * b.value) / _SCALING_FACTOR);
    }


    function div(FixedPointInt memory a, FixedPointInt memory b)
        internal
        pure
        returns (FixedPointInt memory)
    {
        return FixedPointInt((a.value * _SCALING_FACTOR) / b.value);
    }
def callCreditSpreadCollateralRequirement(_qTokenToMintStrikePrice, _qTokenForCollateralStrikePrice, _optionsAmount):
        X1 = _qTokenToMintStrikePrice * 10^19
        X2 = _qTokenForCollateralStrikePrice * 10^19
        X3 = _optionsAmount * 10^9

        assert X1 < X2          #credit spread

        Y1 = (X2 - X1) * 10^27 // X2    #implicit round down due to div
        Y2 = Y1 * X3 // 10^27   #implicit round down due to mul

        Z = Y2 // 10^9
        if Y2 % 10^9 > 0:       #round up since we are minting spread (Controller is receiver)
                Z+=1
        return Z
def neutralizeCreditSpreadCollateralRequirement(_qTokenToMintStrikePrice, _qTokenForCollateralStrikePrice, _optionsAmount):
        X1 = _qTokenToMintStrikePrice * 10^19
        X2 = _qTokenForCollateralStrikePrice * 10^19
        X3 = _optionsAmount * 10^9

        assert X1 < X2          #credit spread

        Y1 = (X2 - X1) * 10^27 // X2    #implicit round down due to div
        Y2 = Y1 * X3 // 10^27   #implicit round down due to mul

        Z = Y2 // 10^9  #explicit scaling
        return Z
    function intToUint(int256 a) internal pure returns (uint256) {
        if (a < 0) {
            return uint256(-a);
        } else {
            return uint256(a);
        }
    }
----------- qTokenLong strike price

----------- expiryPrice

----------- qTokenShort strike price
def claimableCollateralCallCreditSpreadExpiryInbetween(_qTokenShortStrikePrice, _qTokenLongStrikePrice, _expiryPrice, _amount):

        def callCreditSpreadCollateralRequirement(_qTokenToMintStrikePrice, _qTokenForCollateralStrikePrice, _optionsAmount):
                X1 = _qTokenToMintStrikePrice * 10^19
                X2 = _qTokenForCollateralStrikePrice * 10^19
                X3 = _optionsAmount * 10^9

                Y1 = (X2 - X1) * 10^27 // X2
                Y2 = Y1 * X3 // 10^27
                return Y2

        def callCreditSpreadQTokenShortPayout(_strikePrice, _expiryPrice, _amount):
                X1 = _strikePrice * 10^19
                X2 = _expiryPrice * 10^19
                X3 = _amount * 10^9

                Y1 = (X2-X1) * X3 // 10^27
                Y2 = Y1 * 10^27 // X2
                return Y2


        assert _qTokenShortStrikePrice > _expiryPrice > _qTokenLongStrikePrice

        A1 = payoutFromLong = 0
        A2 = collateralRequirement = callCreditSpreadCollateralRequirement(_qTokenShortStrikePrice, _qTokenLongStrikePrice, _amount)
        A3 = payoutFromShort = callCreditSpreadQTokenShortPayout(_qTokenShortStrikePrice, _expiryPrice, _amount)

        B1 = A1 + A2 - A3

        Z = abs(B1) // 10^9
        return Z
X = _qTokenLongStrikePrice (8 decimals)
Y = _expiryPrice (8 decimals)
Z = _qTokenShortStrikePrice (8 decimals)
A = _amount (scaled to 27 decimals)

assert X>Y>Z>0
assert X,Y,Z are integers
assert (((X - Z) * 10^27 // X) * A // 10^27) < (((Y - Z) * A // 10^27) * 10^27 // Y)
(X-Z) / X - (Y-Z) / Y < 10^-27
=> Z / Y - Z / X < 10^-27
=> (Z = 1 yields best solution)
=> 1 / Y - 1 / X < 10^-27
=> X - Y < X * Y * 10^-27
=> 0 < X * Y - 10^27 * X + 10^27 * Y

=> require X > Y, so model Y as X - B, where B > 0 and B is an integer
=> 0 < X^2 - B * X - 10^27 * B
0 < (10^14 - 1)^2 - B * (10^14 - 1) - 10^27 * B
=> (10^14 - 1)^2 / (10^14 - 1 + 10^27) > B
=> B <= 9
