eagle0504's picture
Update utils/ui_helper.py
2672a77 verified
raw
history blame
6.18 kB
# app.py
from datetime import datetime
import streamlit as st
import plotly.graph_objects as go
import pandas as pd
from utils.helper import *
def main_algo_trader():
# Front-end Design
st.set_page_config(layout="wide")
st.write("# Welcome to Algorithmic Trading! A Quick Implementation👋")
with st.sidebar:
with st.expander("Expand/Collapse"):
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):",
"MSFT, AAPL, NVDA, GOOG, AMZN, META, LLY, AVGO, TSLA, JPM, V, WMT, UNH, MA, PG, HD, JNJ, ORCL, MRK, COST, ABBV, BAC, CRM, AMD, NFLX, ACN, ADBE, DIS, TMO, WFC, MCD, CSCO, ABT, QCOM, INTC, INTU, IBM, AMAT, CMCSA, AXP, PFE, NOW, AMGN, MU, SHOP, DASH, MRVL, TDG, ISRG",
)
start_date = st.sidebar.date_input("Start date", pd.to_datetime("2001-01-01"))
end_date = st.sidebar.date_input("End date", pd.to_datetime(datetime.now().strftime("%Y-%m-%d")))
time_frame = st.sidebar.selectbox(
"Select Time Frame:",
[
"1mo",
"3mo",
],
)
top_n = st.sidebar.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)