import streamlit as st import yfinance as yf import numpy as np import pandas as pd from plotly.subplots import make_subplots import plotly.graph_objects as go def analyze_and_visualize_straddle(ticker, strike_call, strike_put, premium_call, premium_put): """ This function is used to analyze a given ticker and visualize the payoffs for both long and short straddle strategies. Parameters: - ticker: Symbol of the underlying asset as is on Yahoo Finance. - strike_call: Strike price for the call option. - strike_put: Strike price for the put option. - premium_call: Premium paid for the call option. - premium_put: Premium paid for the put option. """ ## Downloading historical data df = yf.download(ticker, multi_level_index=False, auto_adjust=False) # Computing returns df['Returns'] = df['Adj Close'].pct_change() # Computing annualized volatility df['Vol'] = df['Returns'].rolling(20).std() * np.sqrt(252) df.dropna(axis = 0, inplace = True) # Removing null values # Generating array of equally-spaced points representing the quantiles to be calculated (from 0% to 100%) quantiles = np.quantile(df['Vol'], np.linspace(0,1,11)) # Using quantilies to categorize and label the annualized volatility values quantile_labels = pd.cut(df['Vol'], bins = quantiles, labels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # Adding categorical labels to the dataframe df['Vol_Rank'] = quantile_labels # Plotting data fig = make_subplots(rows = 3, cols = 1, horizontal_spacing=0.2, row_heights=[.60, .20, .20], shared_xaxes=True) # First row --> Closing Price fig.add_trace(go.Scatter( x = df.index, y = df['Adj Close'], name = 'Closing Price' ), row = 1, col = 1) # Second row --> Annualized Volatility fig.add_trace(go.Scatter( x = df.index, y = df['Vol'], name = 'Annualized Volatility' ), row = 2, col = 1) # Third row --> Volatility rank fig.add_trace(go.Scatter( x = df.index, y = df['Vol_Rank'], name = 'Volatility Rank' ), row = 3, col = 1) # Defining subplots layout fig.update_layout(title = {'text': f'{ticker} Closing Price & Volatility'}, template = 'plotly_white', height = 900, width = 950, showlegend=False, hovermode='x unified') # Defining layout of y-axes across subplots fig.update_yaxes(title_text = 'Closing Price ($)', row = 1) fig.update_yaxes(title_text = 'Annualized Volatility', row = 2) fig.update_yaxes(title_text = 'Volatility Rank', row = 3) # Generating an array of possible prices the underlying asset might fall into stock_prices = np.linspace(0.79 * min(strike_put, strike_call), 1.19 * max(strike_put, strike_call), 100).round(2) # Computing payoffs # Payoffs for holding long call and put options long_call_payoff = np.maximum(stock_prices - strike_call, 0) - premium_call long_put_payoff = np.maximum(strike_put - stock_prices, 0) - premium_put # Payoffs for holding short positions in call and put options short_call_payoff = -long_call_payoff short_put_payoff = -long_put_payoff # Combined payoffs for both long and short positions combined_long_payoff = long_call_payoff + long_put_payoff combined_short_payoff = short_call_payoff + short_put_payoff # Computing profit and loss for long straddle profit_long = np.maximum(combined_long_payoff, 0) loss_long = np.minimum(combined_long_payoff, 0) # Computing profit and loss for short straddle loss_short = np.minimum(combined_short_payoff, 0) profit_short = np.maximum(combined_short_payoff, 0) # Creating subplots fig2 = make_subplots( rows=2, cols=1, horizontal_spacing=0.2, row_heights=[0.5, 0.5], shared_xaxes=False, shared_yaxes=False ) # Adding Long Straddle traces fig2.add_trace( go.Scatter(x=stock_prices, y=long_call_payoff, mode='lines', line=dict(color='grey', dash='dash'), name='Long Call', hovertemplate='%{y:.2f}'), row=1, col=1 ) fig2.add_trace( go.Scatter(x=stock_prices, y=long_put_payoff, mode='lines', line=dict(color='grey', dash='dash'), name='Long Put', hovertemplate='%{y:.2f}'), row=1, col=1 ) # Adding Short Straddle traces fig2.add_trace( go.Scatter(x=stock_prices, y=short_call_payoff, mode='lines', line=dict(color='grey', dash='dash'), name='Short Call', hovertemplate='%{y:.2f}'), row=2, col=1 ) fig2.add_trace( go.Scatter(x=stock_prices, y=short_put_payoff, mode='lines', line=dict(color='grey', dash='dash'), name='Short Put', hovertemplate='%{y:.2f}'), row=2, col=1 ) # Adding the payoff lines for Long Straddle fig2.add_trace( go.Scatter(x=stock_prices, y=profit_long, mode='lines', line=dict(color='black', dash='solid'), name='Profit', hovertemplate='%{y:.2f}', fill='tozeroy', fillcolor='rgba(0, 255, 0, 0.5)'), row=1, col=1 ) fig2.add_trace( go.Scatter(x=stock_prices, y=loss_long, mode='lines', line=dict(color='black', dash='solid'), name='Loss', hovertemplate='%{y:.2f}', fill='tozeroy', fillcolor='rgba(255, 0, 0, 0.5)'), row=1, col=1 ) # Adding the payoff lines for Long Straddle fig2.add_trace( go.Scatter(x=stock_prices, y=loss_short, mode='lines', line=dict(color='black', dash='solid'), name = 'Loss', hovertemplate='%{y:.2f}', fill='tozeroy', fillcolor='rgba(255, 0, 0, 0.5)'), row=2, col=1 ) fig2.add_trace( go.Scatter(x=stock_prices, y=profit_short, mode='lines', line=dict(color='black', dash='solid'), name = 'Profit', hovertemplate='%{y:.2f}', fill='tozeroy', fillcolor='rgba(0, 255, 0, 0.5)'), row=2, col=1 ) # Defining layout fig2.update_layout( title={'text': f'{ticker} Long & Short Straddle'}, template='plotly_white', height=1000, width=750, showlegend=False, hovermode='x unified') # Defining y-axes and x-axes tiles across rows fig2.update_yaxes(title_text='Long Payoff ($)', row=1) fig2.update_yaxes(title_text='Short Payoff ($)', row=2) fig2.update_xaxes(title_text = 'Underlying Asset Price at Expiration', row=1) fig2.update_xaxes(title_text = 'Underlying Asset Price at Expiration', row=2) # Displaying plots return fig, fig2 st.set_page_config(page_title="Long and Short Straddle", page_icon=":chart_with_upwards_trend", layout="wide", initial_sidebar_state="expanded", #theme={"base":"light"} ) title = '

Options Trading: Long & Short Straddle

' st.markdown(title, unsafe_allow_html=True) st.markdown(""" This app helps you compute the payoffs for long and short straddles for options trading. It will also plot the historical closing prices for the underlying asset, its annualized volatility, and its volatility rank.""") st.markdown(""" Annualized volatility is computed by multiplying the standard deviation of the last 20 trading days by the square root of 252. The volatility rank is computed by breaking down the annualized volatility into ten equally-sized bins, and it ranges from 1 to 10, where 1 represents low volatility, and 10 represents high volatility.""") st.markdown('For more information about options and straddles, you can see my Kaggle Notebook, [Options Trading: Long & Short Straddle 📈](https://www.kaggle.com/code/lusfernandotorres/options-trading-long-short-straddle), where I describe the process of building this demo app.') st.write(f"""**Parameters:**""") st.write(f"""**• Ticker:** The asset symbol as it is on Yahoo Finance.""") st.write(f"""**• Strike Price (Call):** Strike price for the call option.""") st.write(f"""**• Strike Price (Put):** Strike price for the put option.""") st.write(f"""**• Premium (Call):** Premium paid for the call option.""") st.write(f"""**• Premium (Put):** Premium paid for the put option.""") ticker = st.text_input("Ticker", placeholder="Enter the symbol for the underlying asset.") strike_call = st.number_input("Strike Price (Call)", min_value=0.0, format="%f") strike_put = st.number_input("Strike Price (Put)", min_value=0.0, format="%f") premium_call = st.number_input("Premium (Call)", min_value=0.0, format="%f") premium_put = st.number_input("Premium (Put)", min_value=0.0, format="%f") # Button to trigger the analysis and visualization if st.button('Analyze and Visualize Straddle'): # Check if all required inputs are provided if not ticker: st.error("Please enter a ticker symbol to proceed.") elif strike_call <= 0: st.error("Please enter a valid strike price for the call option.") elif strike_put <= 0: st.error("Please enter a valid strike price for the put option.") elif premium_call <= 0: st.error("Please enter a valid premium for the call option.") elif premium_put <= 0: st.error("Please enter a valid premium for the put option.") else: # All inputs are valid, proceed with the function call fig, fig2 = analyze_and_visualize_straddle(ticker, strike_call, strike_put, premium_call, premium_put) st.plotly_chart(fig) # Display the figure in the app st.plotly_chart(fig2) # Display the figure in the app signature_html = """
Luis Fernando Torres, 2024

Let's connect!🔗
LinkedIn • Medium • Kaggle

Like my content? Feel free to Buy Me a Coffee ☕
https://luuisotorres.github.io/
""" st.markdown(signature_html, unsafe_allow_html=True)