File size: 4,528 Bytes
3549379
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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)