Spaces:
Runtime error
Runtime error
smitathkr1
commited on
Commit
•
3549379
1
Parent(s):
fa24677
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import requests
|
3 |
+
import pandas as pd
|
4 |
+
import altair as alt
|
5 |
+
|
6 |
+
# Function to fetch data from the API
|
7 |
+
def fetch_data(url, headers):
|
8 |
+
response = requests.get(url, headers=headers)
|
9 |
+
if response.status_code == 200:
|
10 |
+
return response.json()['data']
|
11 |
+
else:
|
12 |
+
st.error("Failed to fetch data")
|
13 |
+
return []
|
14 |
+
|
15 |
+
# Altair chart for combined volume and average price
|
16 |
+
def create_chart(df, option_type, strike):
|
17 |
+
# Ensure datetime is correctly parsed and localized
|
18 |
+
df['tape_time'] = pd.to_datetime(df['tape_time']).dt.tz_localize(None)
|
19 |
+
|
20 |
+
# Volume chart with custom colors for bid, ask, and mid volumes
|
21 |
+
volume_chart = alt.Chart(df).transform_fold(
|
22 |
+
fold=['bid_volume', 'ask_volume', 'mid_volume'],
|
23 |
+
as_=['Volume Type', 'Volume']
|
24 |
+
).mark_bar().encode(
|
25 |
+
x='tape_time:T',
|
26 |
+
y=alt.Y('Volume:Q', title='Volume'),
|
27 |
+
color=alt.Color('Volume Type:N', scale=alt.Scale(domain=['bid_volume', 'ask_volume', 'mid_volume'], range=['#ee5365', '#1fb386', '#2448fb'])),
|
28 |
+
tooltip=['tape_time:T', 'bid_volume:Q', 'ask_volume:Q', 'mid_volume:Q']
|
29 |
+
).properties(
|
30 |
+
width=300,
|
31 |
+
height=300
|
32 |
+
)
|
33 |
+
|
34 |
+
# Average price line chart
|
35 |
+
price_chart = alt.Chart(df).mark_line(color='#ffa421').encode(
|
36 |
+
x='tape_time:T',
|
37 |
+
y=alt.Y('avg_price:Q', title='Average Price', scale=alt.Scale(zero=False)),
|
38 |
+
tooltip=['tape_time:T', 'avg_price:Q']
|
39 |
+
)
|
40 |
+
|
41 |
+
# Implied Volatility High line chart
|
42 |
+
iv_high_chart = alt.Chart(df).mark_line(color='purple').encode(
|
43 |
+
x='tape_time:T',
|
44 |
+
y=alt.Y('iv_high:Q', title='IV High', scale=alt.Scale(zero=False)),
|
45 |
+
tooltip=['tape_time:T', 'iv_high:Q']
|
46 |
+
)
|
47 |
+
|
48 |
+
# Combine the charts
|
49 |
+
combined_chart = alt.layer(volume_chart, price_chart, iv_high_chart).resolve_scale(
|
50 |
+
y='independent'
|
51 |
+
).properties(
|
52 |
+
title=f"{option_type} Option Chart for Strike {strike}",
|
53 |
+
width=600,
|
54 |
+
height=300
|
55 |
+
)
|
56 |
+
|
57 |
+
return combined_chart
|
58 |
+
|
59 |
+
|
60 |
+
# Streamlit UI
|
61 |
+
st.title('Stacked Market Data Chart for Calls and Puts')
|
62 |
+
|
63 |
+
|
64 |
+
with st.form(key='data_form'):
|
65 |
+
index = st.text_input('Index (e.g., SPXW)', value='SPXW')
|
66 |
+
expiry = st.date_input('Expiry Date')
|
67 |
+
atm_strike = st.number_input('ATM Strike (e.g., 52350)', value=52350)
|
68 |
+
submit_button = st.form_submit_button('Load Charts')
|
69 |
+
|
70 |
+
if submit_button:
|
71 |
+
headers = {
|
72 |
+
"Accept": "application/json",
|
73 |
+
"Accept-Encoding": "gzip, deflate, br, zstd",
|
74 |
+
"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",
|
75 |
+
"Authorization": "Bearer Qo2zhp0Xf3qI88x81tEvgizT_fH29PlLqhrnRcMHP8gvZ_5OCjWl_r23GdbBzolL",
|
76 |
+
"Content-Type": "application/json",
|
77 |
+
"Origin": "https://unusualwhales.com",
|
78 |
+
"Referer": "https://unusualwhales.com/",
|
79 |
+
"Sec-Ch-Ua": '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
80 |
+
"Sec-Ch-Ua-Mobile": "?0",
|
81 |
+
"Sec-Ch-Ua-Platform": '"Windows"',
|
82 |
+
"Sec-Fetch-Dest": "empty",
|
83 |
+
"Sec-Fetch-Mode": "cors",
|
84 |
+
"Sec-Fetch-Site": "same-site",
|
85 |
+
"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",
|
86 |
+
"Uw-Path": "/flow/option_chains",
|
87 |
+
"Uw-Sh": "8lgba0upqzOp4J3C"
|
88 |
+
}
|
89 |
+
|
90 |
+
|
91 |
+
# Generate strikes in descending order
|
92 |
+
strikes = sorted((atm_strike + i * 5 for i in range(-5, 6)), reverse=True)
|
93 |
+
expiry_str = expiry.strftime('%y%m%d')
|
94 |
+
|
95 |
+
# Create columns for calls and puts side by side
|
96 |
+
col_call, col_put = st.columns(2)
|
97 |
+
|
98 |
+
for strike in strikes:
|
99 |
+
modified_strike = f"0{strike}000"
|
100 |
+
# Fetch and plot for call options
|
101 |
+
call_url = f"https://phx.unusualwhales.com/api/chain_aggregates/{index}{expiry_str}C{modified_strike}/intraday?grouping_minutes=5&market_day_timeframe=1"
|
102 |
+
call_data = fetch_data(call_url, headers)
|
103 |
+
if call_data:
|
104 |
+
df_call = pd.DataFrame(call_data)
|
105 |
+
call_chart = create_chart(df_call, 'Call', strike)
|
106 |
+
with col_call:
|
107 |
+
st.altair_chart(call_chart, use_container_width=True)
|
108 |
+
|
109 |
+
# Fetch and plot for put options
|
110 |
+
put_url = f"https://phx.unusualwhales.com/api/chain_aggregates/{index}{expiry_str}P{modified_strike}/intraday?grouping_minutes=5&market_day_timeframe=1"
|
111 |
+
put_data = fetch_data(put_url, headers)
|
112 |
+
if put_data:
|
113 |
+
df_put = pd.DataFrame(put_data)
|
114 |
+
put_chart = create_chart(df_put, 'Put', strike)
|
115 |
+
with col_put:
|
116 |
+
st.altair_chart(put_chart, use_container_width=True)
|
117 |
+
|