mgbam commited on
Commit
8cba972
·
verified ·
1 Parent(s): cbdd805

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -5
app.py CHANGED
@@ -1,10 +1,81 @@
1
- # ... (previous code remains the same)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  # Backtesting simulation loop
4
  for i in range(1, len(data)):
5
  today = data.index[i]
6
- price = float(data['Close'].iloc[i]) # Cast to float
7
- rsi_today = float(data['RSI'].iloc[i]) # Cast to float
8
 
9
  # Check for buy signal
10
  macd_today = float(data['MACD'].iloc[i])
@@ -25,7 +96,7 @@ for i in range(1, len(data)):
25
  "entry_price": price,
26
  "allocated": allocation,
27
  "shares": shares_bought,
28
- "highest": price, # Ensure scalar
29
  "trailing_stop": price * (1 - trailing_stop_pct)
30
  })
31
  data.at[today, 'Buy'] = True
@@ -76,4 +147,39 @@ for i in range(1, len(data)):
76
  position_value = sum(pos["shares"] * price for pos in open_positions)
77
  equity_curve.append(cash + position_value)
78
 
79
- # ... (remaining code remains the same)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import yfinance as yf
3
+ import pandas as pd
4
+ import numpy as np
5
+ import matplotlib.pyplot as plt
6
+ from datetime import timedelta
7
+
8
+ # Streamlit App Title and Description
9
+ st.title("Extended MACD-RSI Combo Strategy for SPY")
10
+ st.markdown("""
11
+ This app demonstrates an extended MACD-RSI based trading strategy on SPY with the following features:
12
+ - **Multiple Simultaneous Positions:** Each buy signal creates a new position.
13
+ - **Dynamic Trailing Stop:** Each open position is updated with a trailing stop.
14
+ - **Configurable Parameters:** Adjust strategy parameters via the sidebar.
15
+ - **Buy Rule:**
16
+ Buy a fraction of available cash when:
17
+ - The MACD line crosses above its signal line.
18
+ - RSI is below 50.
19
+ - No buy has been executed in the last few days.
20
+ - **Sell Rule:**
21
+ For each position:
22
+ - **Partial Sell:** Sell a fraction of the position when the price reaches a target multiple of the entry price and RSI is above 50.
23
+ - **Trailing Stop Exit:** If the price falls below the position’s dynamic trailing stop, sell the entire position.
24
+ """)
25
+
26
+ # Sidebar for Strategy Parameters
27
+ st.sidebar.header("Strategy Parameters")
28
+ buy_fraction = st.sidebar.slider("Buy Fraction (of available cash)", 0.05, 0.50, 0.15, 0.05)
29
+ sell_fraction = st.sidebar.slider("Partial Sell Fraction", 0.10, 0.90, 0.40, 0.05)
30
+ target_multiplier = st.sidebar.slider("Target Multiplier", 1.01, 1.20, 1.08, 0.01)
31
+ trailing_stop_pct = st.sidebar.slider("Trailing Stop (%)", 0.01, 0.20, 0.08, 0.01)
32
+ min_days_between_buys = st.sidebar.number_input("Minimum Days Between Buys", min_value=1, max_value=10, value=2)
33
+
34
+ # Load SPY Data
35
+ @st.cache_data
36
+ def load_data(ticker, period="1y"):
37
+ data = yf.download(ticker, period=period)
38
+ data.dropna(inplace=True)
39
+ return data
40
+
41
+ data_load_state = st.text("Loading SPY data...")
42
+ data = load_data("SPY", period="1y")
43
+ data_load_state.text("Loading SPY data...done!")
44
+
45
+ # --- Manual Calculation of Technical Indicators ---
46
+
47
+ # Calculate MACD
48
+ data['EMA12'] = data['Close'].ewm(span=12, adjust=False).mean()
49
+ data['EMA26'] = data['Close'].ewm(span=26, adjust=False).mean()
50
+ data['MACD'] = data['EMA12'] - data['EMA26']
51
+ data['MACD_signal'] = data['MACD'].ewm(span=9, adjust=False).mean()
52
+
53
+ # Calculate RSI
54
+ delta = data['Close'].diff()
55
+ gain = delta.where(delta > 0, 0)
56
+ loss = -delta.where(delta < 0, 0)
57
+ avg_gain = gain.rolling(window=14).mean()
58
+ avg_loss = loss.rolling(window=14).mean()
59
+ rs = avg_gain / avg_loss
60
+ data['RSI'] = 100 - (100 / (1 + rs))
61
+
62
+ # Initialize signal flags for plotting
63
+ data['Buy'] = False
64
+ data['Sell'] = False
65
+
66
+ # Backtesting parameters
67
+ initial_capital = 100000
68
+ cash = initial_capital
69
+ equity_curve = []
70
+ last_buy_date = None
71
+ open_positions = []
72
+ completed_trades = []
73
 
74
  # Backtesting simulation loop
75
  for i in range(1, len(data)):
76
  today = data.index[i]
77
+ price = float(data['Close'].iloc[i]) # Ensure price is a scalar value
78
+ rsi_today = float(data['RSI'].iloc[i]) # Ensure RSI is a scalar value
79
 
80
  # Check for buy signal
81
  macd_today = float(data['MACD'].iloc[i])
 
96
  "entry_price": price,
97
  "allocated": allocation,
98
  "shares": shares_bought,
99
+ "highest": price,
100
  "trailing_stop": price * (1 - trailing_stop_pct)
101
  })
102
  data.at[today, 'Buy'] = True
 
147
  position_value = sum(pos["shares"] * price for pos in open_positions)
148
  equity_curve.append(cash + position_value)
149
 
150
+ # Build performance DataFrame
151
+ performance = pd.DataFrame({
152
+ 'Date': data.index[1:len(equity_curve)+1],
153
+ 'Equity': equity_curve
154
+ }).set_index('Date')
155
+
156
+ # Plot results
157
+ st.subheader("Equity Curve")
158
+ fig, ax = plt.subplots(figsize=(10, 4))
159
+ ax.plot(performance.index, performance['Equity'], label="Total Equity")
160
+ ax.set_xlabel("Date")
161
+ ax.set_ylabel("Equity ($)")
162
+ ax.legend()
163
+ st.pyplot(fig)
164
+
165
+ st.subheader("SPY Price with Buy/Sell Signals")
166
+ fig2, ax2 = plt.subplots(figsize=(10, 4))
167
+ ax2.plot(data.index, data['Close'], label="SPY Close Price", color='black')
168
+ ax2.scatter(data.index[data['Buy']], data['Close'][data['Buy']], marker="^", color="green", label="Buy Signal", s=100)
169
+ ax2.scatter(data.index[data['Sell']], data['Close'][data['Sell']], marker="v", color="red", label="Sell Signal", s=100)
170
+ ax2.set_xlabel("Date")
171
+ ax2.set_ylabel("Price ($)")
172
+ ax2.legend()
173
+ st.pyplot(fig2)
174
+
175
+ # Display performance metrics
176
+ final_equity = equity_curve[-1]
177
+ return_pct = ((final_equity - initial_capital) / initial_capital) * 100
178
+ st.subheader("Strategy Performance Metrics")
179
+ st.write(f"**Initial Capital:** ${initial_capital:,.2f}")
180
+ st.write(f"**Final Equity:** ${final_equity:,.2f}")
181
+ st.write(f"**Return:** {return_pct:.2f}%")
182
+
183
+ st.markdown("""
184
+ *This extended demo is for educational purposes only and does not constitute financial advice. Always test your strategies extensively before trading with real money.*
185
+ """)