eagle0504's picture
Create ui_helper.py
68361fe verified
raw
history blame
5.93 kB
# app.py
import streamlit as st
import plotly.graph_objects as go
import pandas as pd
from helpers.app_helper_algotrader import *
def main_algo_trader():
st.write("# Welcome to Algorithmic Trading! A Toy Implementation👋")
st.sidebar.success("Select a session from the menu of content.")
st.markdown(
r"""
The following app is a simple demonstration of the growth stock strategy. For simplicity, we assume our research team hand over a pool of stocks. Amongst the pool of stocks, we can do the following:
- use `yfinance` library to download stock data live (for the sake of speed, please start with time frame "1mo");
- every period (time frame is a tuning parameter), we balance our portfolio (equal weight) by holding the top n stocks (n can be top quintile/quartile of stocks);
"""
)
# Main inputs
tickers = st.text_input(
"Enter tickers (comma-separated):",
"AXP, AMGN, AAPL, BA, CAT, CSCO, CVX, GS, HD, HON, IBM, INTC, JNJ, KO, JPM, MCD, MMM, MRK, MSFT, NKE, PG, TRV, UNH, CRM, VZ, V, WBA, WMT, DIS, DOW, XOM, WFC, MA, COST, AVGO, ADBE, C, NFLX, PYPL, TSLA, NVDA",
)
start_date = st.date_input("Start date", pd.to_datetime("2001-01-01"))
end_date = st.date_input("End date", pd.to_datetime("2023-12-31"))
time_frame = st.selectbox(
"Select Time Frame:",
[
"1mo",
"3mo",
],
)
top_n = st.number_input("Top n stocks", min_value=1, value=3)
# Process inputs
tickers_list = [ticker.strip() for ticker in tickers.split(",")]
# Run analysis on button click
if st.button("Run Analysis"):
with st.spinner("Downloading data and calculating returns..."):
stock_data = download_stock_data(
tickers_list,
start_date.strftime("%Y-%m-%d"),
end_date.strftime("%Y-%m-%d"),
w=time_frame,
)
returns_data = create_portfolio_and_calculate_returns(stock_data, top_n)
benchmark_sharpe_ratio = (
returns_data["benchmark"].mean() / returns_data["benchmark"].std()
)
portfolio_sharpe_ratio = (
returns_data["portfolio_returns"].mean()
/ returns_data["portfolio_returns"].std()
)
# Data for plotting
df = returns_data[
["rolling_benchmark", "rolling_portfolio_returns", "portfolio_history"]
]
df.index = pd.to_datetime(df.index, unit="ms")
# Create plot
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=df.index,
y=df["rolling_benchmark"],
mode="lines",
name="Rolling Benchmark",
)
)
fig.add_trace(
go.Scatter(
x=df.index,
y=df["rolling_portfolio_returns"],
mode="lines",
name="Rolling Portfolio Returns",
)
)
for date, stocks in df["portfolio_history"].items():
fig.add_shape(
type="line",
x0=date,
y0=0,
x1=date,
y1=0,
line=dict(color="RoyalBlue", width=1),
)
fig.add_annotation(
x=date,
y=0.5,
text=str(stocks),
showarrow=False,
yshift=10,
textangle=-90,
font=dict(size=15), # You can adjust the size as needed
)
# Calculate means and standard deviations
benchmark_mean = returns_data["benchmark"].mean()
benchmark_std = returns_data["benchmark"].std()
portfolio_mean = returns_data["portfolio_returns"].mean()
portfolio_std = returns_data["portfolio_returns"].std()
# Update title text with additional information
if time_frame == '1mo':
some_n_based_on_time_frame = 12
in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
else:
some_n_based_on_time_frame = 4
in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
title_text = (
f"Performance:<br>"
f"Benchmark Sharpe Ratio = {benchmark_sharpe_ratio:.3f}, "
f"Portfolio Sharpe Ratio = {portfolio_sharpe_ratio:.3f}, "
f"based on time frame: {time_frame}<br>"
f"Benchmark => Mean: {benchmark_mean:.4f}, Std: {benchmark_std:.4f}; "
f"Portfolio => Mean: {portfolio_mean:.4f}, Std: {portfolio_std:.4f}<br>"
f"---<br>"
f"This may or may not be a small number, let's check: <br>"
f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame})={in_a_year}, <br>"
f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame}*50)={in_50_years}."
)
curr_max_num = max(
df.rolling_benchmark.max(), df.rolling_portfolio_returns.max()
)
fig.update_layout(
title=title_text,
xaxis_title="Date",
yaxis_title="Value",
yaxis=dict(range=[0, curr_max_num * 1.1]),
legend=dict(
orientation="h", x=0.5, y=-0.4, xanchor="center", yanchor="bottom"
),
)
st.plotly_chart(fig, use_container_width=True)