Here is the `plot_graph()` that is in char of the bars, scatter and vertical line plot items.

Also all the necessary code  for the graph to be shown.
max_pain_chart
Nelson Torres 2025-02-03 18:38:40 -03:00
parent e8c5f7a531
commit 490aaa3874
1 changed files with 84 additions and 2 deletions

View File

@ -10,6 +10,11 @@ from piker.brokers.deribit.api import (
get_client, get_client,
maybe_open_oi_feed, maybe_open_oi_feed,
) )
import sys
import pyqtgraph as pg
from PyQt6 import QtCore
from pyqtgraph import ScatterPlotItem, InfiniteLine
from PyQt6.QtWidgets import QApplication
def check_if_complete( def check_if_complete(
oi: dict[str, dict[str, Decimal | None]] oi: dict[str, dict[str, Decimal | None]]
@ -87,6 +92,65 @@ async def max_pain_daemon(
return total_intrinsic_value, max_pain return total_intrinsic_value, max_pain
def plot_graph(
oi_by_strikes: dict[str, dict[str, Decimal]],
plot,
):
"""Update the bar graph with new open interest data."""
plot.clear()
intrinsic_values = get_total_intrinsic_values(oi_by_strikes)
for strike_str in sorted(oi_by_strikes, key=lambda x: int(x)):
strike = int(strike_str)
calls_val = float(oi_by_strikes[strike_str]['C'])
puts_val = float(oi_by_strikes[strike_str]['P'])
bar_c = pg.BarGraphItem(
x=[strike - 100],
height=[calls_val],
width=200,
pen='w',
brush=(0, 0, 255, 150)
)
plot.addItem(bar_c)
bar_p = pg.BarGraphItem(
x=[strike + 100],
height=[puts_val],
width=200,
pen='w',
brush=(255, 0, 0, 150)
)
plot.addItem(bar_p)
total_val = float(intrinsic_values[strike_str]['total']) / 100000
scatter_iv = ScatterPlotItem(
x=[strike],
y=[total_val],
pen=pg.mkPen(color=(0, 255, 0), width=2),
brush=pg.mkBrush(0, 255, 0, 150),
size=3,
symbol='o'
)
plot.addItem(scatter_iv)
_, max_pain = get_intrinsic_value_and_max_pain(intrinsic_values)
vertical_line = InfiniteLine(
pos=max_pain,
angle=90,
pen=pg.mkPen(color='yellow', width=1, style=QtCore.Qt.PenStyle.DotLine),
label=f'Max pain: {max_pain:,.0f}',
labelOpts={
'position': 0.85,
'color': 'yellow',
'movable': True
}
)
plot.addItem(vertical_line)
def update_oi_by_strikes(msg: tuple): def update_oi_by_strikes(msg: tuple):
nonlocal oi_by_strikes nonlocal oi_by_strikes
if 'oi' == msg[0]: if 'oi' == msg[0]:
@ -127,6 +191,16 @@ async def max_pain_daemon(
async with maybe_open_oi_feed( async with maybe_open_oi_feed(
instruments, instruments,
) as oi_feed: ) as oi_feed:
# Initialize QApplication
app = QApplication(sys.argv)
win = pg.GraphicsLayoutWidget(show=True)
win.setWindowTitle('Calls (blue) vs Puts (red)')
plot = win.addPlot(title='OI by Strikes')
plot.showGrid(x=True, y=True)
print('Plot initialized...')
async for msg in oi_feed: async for msg in oi_feed:
update_oi_by_strikes(msg) update_oi_by_strikes(msg)
@ -134,13 +208,21 @@ async def max_pain_daemon(
if 'oi' == msg[0]: if 'oi' == msg[0]:
timestamp = msg[1]['timestamp'] timestamp = msg[1]['timestamp']
max_pain = get_max_pain(oi_by_strikes) max_pain = get_max_pain(oi_by_strikes)
intrinsic_values = get_total_intrinsic_values(oi_by_strikes)
# graph here
plot_graph(oi_by_strikes, plot)
print('-----------------------------------------------') print('-----------------------------------------------')
print(f'timestamp: {datetime.fromtimestamp(max_pain['timestamp'])}') print(f'timestamp: {datetime.fromtimestamp(max_pain['timestamp'])}')
print(f'expiry_date: {max_pain['expiry_date']}') print(f'expiry_date: {max_pain['expiry_date']}')
print(f'max_pain: {max_pain['max_pain']}') print(f'max_pain: {max_pain['max_pain']:,.0f}')
print(f'total intrinsic value: {max_pain['total_intrinsic_value']}') print(f'total intrinsic value: {max_pain['total_intrinsic_value']:,.0f}')
print('-----------------------------------------------') print('-----------------------------------------------')
# Process GUI events to keep the window responsive
app.processEvents()
async def main(): async def main():