options / app.py
smitathkr1's picture
Create app.py
3549379 verified
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)