diff --git a/examples/max_pain.py b/examples/max_pain.py index e5deb96f..4fd2d4f8 100644 --- a/examples/max_pain.py +++ b/examples/max_pain.py @@ -49,6 +49,44 @@ async def max_pain_daemon( oi_by_strikes = client.get_strikes_dict(instruments) + def get_total_intrinsic_values( + oi_by_strikes: dict[str, dict[str, Decimal]] + ) -> dict[str, dict[str, Decimal]]: + call_cash: Decimal = Decimal(0) + put_cash: Decimal = Decimal(0) + intrinsic_values: dict[str, dict[str, Decimal]] = {} + closes: list = sorted(Decimal(close) for close in oi_by_strikes) + + for strike, oi in oi_by_strikes.items(): + s = Decimal(strike) + call_cash = sum(max(0, (s - c) * oi_by_strikes[str(c)]['C']) for c in closes) + put_cash = sum(max(0, (c - s) * oi_by_strikes[str(c)]['P']) for c in closes) + + intrinsic_values[strike] = { + 'C': call_cash, + 'P': put_cash, + 'total': call_cash + put_cash, + } + + return intrinsic_values + + def get_intrinsic_value_and_max_pain( + intrinsic_values: dict[str, dict[str, Decimal]] + ): + # We meed to find the lowest value, so we start at + # infinity to ensure that, and the max_pain must be + # an amount greater than zero. + total_intrinsic_value: Decimal = Decimal('Infinity') + max_pain: Decimal = Decimal(0) + + for strike, oi in oi_by_strikes.items(): + s = Decimal(strike) + if intrinsic_values[strike]['total'] < total_intrinsic_value: + total_intrinsic_value = intrinsic_values[strike]['total'] + max_pain = s + + return total_intrinsic_value, max_pain + def update_oi_by_strikes(msg: tuple): nonlocal oi_by_strikes if 'oi' == msg[0]: @@ -74,30 +112,10 @@ async def max_pain_daemon( ''' nonlocal timestamp - # We meed to find the lowest value, so we start at - # infinity to ensure that, and the max_pain must be - # an amount greater than zero. - total_intrinsic_value: Decimal = Decimal('Infinity') - max_pain: Decimal = Decimal(0) - call_cash: Decimal = Decimal(0) - put_cash: Decimal = Decimal(0) - intrinsic_values: dict[str, dict[str, Decimal]] = {} - closes: list = sorted(Decimal(close) for close in oi_by_strikes) - for strike, oi in oi_by_strikes.items(): - s = Decimal(strike) - call_cash = sum(max(0, (s - c) * oi_by_strikes[str(c)]['C']) for c in closes) - put_cash = sum(max(0, (c - s) * oi_by_strikes[str(c)]['P']) for c in closes) + intrinsic_values = get_total_intrinsic_values(oi_by_strikes) - intrinsic_values[strike] = { - 'C': call_cash, - 'P': put_cash, - 'total': call_cash + put_cash, - } - - if intrinsic_values[strike]['total'] < total_intrinsic_value: - total_intrinsic_value = intrinsic_values[strike]['total'] - max_pain = s + total_intrinsic_value, max_pain = get_intrinsic_value_and_max_pain(intrinsic_values) return { 'timestamp': timestamp,