algobacktest / app.py
netflypsb's picture
Update app.py
fa62b8c verified
Raw
History Blame Contribute Delete
4.15 kB
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
# Function to load historical data
@st.cache_data
def load_data(ticker):
return yf.download(ticker, start="2000-01-01", end="2023-01-01")
def calculate_performance_metrics(data, initial_capital):
cagr = (data['Portfolio Value'].iloc[-1] / initial_capital) ** (1 / ((data.index[-1] - data.index[0]).days / 365.25)) - 1
sharpe_ratio = data['Portfolio Value'].pct_change().mean() / data['Portfolio Value'].pct_change().std() * np.sqrt(252)
return cagr, sharpe_ratio
def plot_signals(data, ticker, short_window, long_window):
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(data.index, data['Close'], label='Close Price', alpha=0.5)
ax.plot(data.index, data['Short_MA'], label=f'Short MA ({short_window})', alpha=0.75)
ax.plot(data.index, data['Long_MA'], label=f'Long MA ({long_window})', alpha=0.75)
ax.plot(data[data['Position'] == 1].index, data['Short_MA'][data['Position'] == 1], '^', markersize=10, color='g', lw=0, label='Buy Signal')
ax.plot(data[data['Position'] == -1].index, data['Short_MA'][data['Position'] == -1], 'v', markersize=10, color='r', lw=0, label='Sell Signal')
ax.set_title(f"{ticker} Price and Trading Signals")
ax.set_xlabel("Date")
ax.set_ylabel("Price")
ax.legend()
st.pyplot(fig)
# User inputs for strategy parameters
st.title("Algorithmic Trading Strategy Backtesting")
st.markdown("This app allows you to backtest an algorithmic trading strategy using historical stock data.")
ticker = st.text_input("Enter the ticker symbol", "AAPL")
data = load_data(ticker)
# Moving Average Windows
short_window = st.number_input("Short moving average window", 1, 50, 20)
long_window = st.number_input("Long moving average window", 1, 200, 50)
# Initial Capital
initial_capital = st.number_input("Initial Capital", 1000, 1000000, 100000)
# Data Preprocessing
data['Short_MA'] = data['Close'].rolling(window=short_window).mean()
data['Long_MA'] = data['Close'].rolling(window=long_window).mean()
data.dropna(inplace=True)
# Generate Trading Signals
data['Signal'] = 0
data['Signal'][short_window:] = np.where(data['Short_MA'][short_window:] > data['Long_MA'][short_window:], 1, 0)
data['Position'] = data['Signal'].diff()
# Backtesting Engine
data['Portfolio Value'] = initial_capital
data['Portfolio Value'][short_window:] = initial_capital * (1 + data['Signal'][short_window:].shift(1) * data['Close'].pct_change()[short_window:]).cumprod()
# Performance metrics
cagr, sharpe_ratio = calculate_performance_metrics(data, initial_capital)
st.write(f"CAGR: {cagr:.2%}")
st.write(f"Sharpe Ratio: {sharpe_ratio:.2f}")
# Plot strategy performance
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(data.index, data['Portfolio Value'], label='Portfolio Value')
ax.set_title(f"Backtested Performance of {ticker} Strategy")
ax.set_xlabel("Date")
ax.set_ylabel("Portfolio Value")
ax.legend()
st.pyplot(fig)
# Plot trading signals
plot_signals(data, ticker, short_window, long_window)
# Advanced Performance Metrics
st.subheader("Advanced Performance Metrics")
# Maximum Drawdown Calculation
rolling_max = data['Portfolio Value'].cummax()
daily_drawdown = data['Portfolio Value'] / rolling_max - 1.0
max_drawdown = daily_drawdown.cummin().iloc[-1]
st.write(f"Maximum Drawdown: {max_drawdown:.2%}")
# Trade Statistics
st.subheader("Trade Statistics")
num_trades = data['Position'].value_counts().sum()
num_winning_trades = data['Position'][data['Position'] == 1].count()
num_losing_trades = data['Position'][data['Position'] == -1].count()
win_rate = num_winning_trades / num_trades
loss_rate = num_losing_trades / num_trades
st.write(f"Total Trades: {num_trades}")
st.write(f"Winning Trades: {num_winning_trades} ({win_rate:.2%})")
st.write(f"Losing Trades: {num_losing_trades} ({loss_rate:.2%})")
# Add option to upload data
st.subheader("Upload Your Own Data")
uploaded_file = st.file_uploader("Choose a file", type="csv")
if uploaded_file is not None:
user_data = pd.read_csv(uploaded_file)
st.write("Uploaded data:")
st.write(user_data.head())