Spaces:
Runtime error
Runtime error
import streamlit as st | |
import requests | |
import pandas as pd | |
import altair as alt | |
# Function to fetch data from the API | |
def fetch_data(url, headers): | |
response = requests.get(url, headers=headers) | |
if response.status_code == 200: | |
return response.json()['data'] | |
else: | |
st.error("Failed to fetch data") | |
return [] | |
# Altair chart for combined volume and average price | |
def create_chart(df, option_type, strike): | |
# Ensure datetime is correctly parsed and localized | |
df['tape_time'] = pd.to_datetime(df['tape_time']).dt.tz_localize(None) | |
# Volume chart with custom colors for bid, ask, and mid volumes | |
volume_chart = alt.Chart(df).transform_fold( | |
fold=['bid_volume', 'ask_volume', 'mid_volume'], | |
as_=['Volume Type', 'Volume'] | |
).mark_bar().encode( | |
x='tape_time:T', | |
y=alt.Y('Volume:Q', title='Volume'), | |
color=alt.Color('Volume Type:N', scale=alt.Scale(domain=['bid_volume', 'ask_volume', 'mid_volume'], range=['#ee5365', '#1fb386', '#2448fb'])), | |
tooltip=['tape_time:T', 'bid_volume:Q', 'ask_volume:Q', 'mid_volume:Q'] | |
).properties( | |
width=300, | |
height=300 | |
) | |
# Average price line chart | |
price_chart = alt.Chart(df).mark_line(color='#ffa421').encode( | |
x='tape_time:T', | |
y=alt.Y('avg_price:Q', title='Average Price', scale=alt.Scale(zero=False)), | |
tooltip=['tape_time:T', 'avg_price:Q'] | |
) | |
# Implied Volatility High line chart | |
iv_high_chart = alt.Chart(df).mark_line(color='purple').encode( | |
x='tape_time:T', | |
y=alt.Y('iv_high:Q', title='IV High', scale=alt.Scale(zero=False)), | |
tooltip=['tape_time:T', 'iv_high:Q'] | |
) | |
# Combine the charts | |
combined_chart = alt.layer(volume_chart, price_chart, iv_high_chart).resolve_scale( | |
y='independent' | |
).properties( | |
title=f"{option_type} Option Chart for Strike {strike}", | |
width=600, | |
height=300 | |
) | |
return combined_chart | |
# Streamlit UI | |
st.title('Stacked Market Data Chart for Calls and Puts') | |
with st.form(key='data_form'): | |
index = st.text_input('Index (e.g., SPXW)', value='SPXW') | |
expiry = st.date_input('Expiry Date') | |
atm_strike = st.number_input('ATM Strike (e.g., 52350)', value=52350) | |
submit_button = st.form_submit_button('Load Charts') | |
if submit_button: | |
headers = { | |
"Accept": "application/json", | |
"Accept-Encoding": "gzip, deflate, br, zstd", | |
"Accept-Language": "en-IN,en-DE;q=0.9,en;q=0.8,de-DE;q=0.7,de;q=0.6,en-US;q=0.5,en-GB;q=0.4,ga;q=0.3", | |
"Authorization": "Bearer Qo2zhp0Xf3qI88x81tEvgizT_fH29PlLqhrnRcMHP8gvZ_5OCjWl_r23GdbBzolL", | |
"Content-Type": "application/json", | |
"Origin": "https://unusualwhales.com", | |
"Referer": "https://unusualwhales.com/", | |
"Sec-Ch-Ua": '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"', | |
"Sec-Ch-Ua-Mobile": "?0", | |
"Sec-Ch-Ua-Platform": '"Windows"', | |
"Sec-Fetch-Dest": "empty", | |
"Sec-Fetch-Mode": "cors", | |
"Sec-Fetch-Site": "same-site", | |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", | |
"Uw-Path": "/flow/option_chains", | |
"Uw-Sh": "8lgba0upqzOp4J3C" | |
} | |
# Generate strikes in descending order | |
strikes = sorted((atm_strike + i * 5 for i in range(-5, 6)), reverse=True) | |
expiry_str = expiry.strftime('%y%m%d') | |
# Create columns for calls and puts side by side | |
col_call, col_put = st.columns(2) | |
for strike in strikes: | |
modified_strike = f"0{strike}000" | |
# Fetch and plot for call options | |
call_url = f"https://phx.unusualwhales.com/api/chain_aggregates/{index}{expiry_str}C{modified_strike}/intraday?grouping_minutes=5&market_day_timeframe=1" | |
call_data = fetch_data(call_url, headers) | |
if call_data: | |
df_call = pd.DataFrame(call_data) | |
call_chart = create_chart(df_call, 'Call', strike) | |
with col_call: | |
st.altair_chart(call_chart, use_container_width=True) | |
# Fetch and plot for put options | |
put_url = f"https://phx.unusualwhales.com/api/chain_aggregates/{index}{expiry_str}P{modified_strike}/intraday?grouping_minutes=5&market_day_timeframe=1" | |
put_data = fetch_data(put_url, headers) | |
if put_data: | |
df_put = pd.DataFrame(put_data) | |
put_chart = create_chart(df_put, 'Put', strike) | |
with col_put: | |
st.altair_chart(put_chart, use_container_width=True) | |