Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -7,7 +7,32 @@ from sklearn.decomposition import PCA
|
|
7 |
from sklearn.preprocessing import StandardScaler, LabelEncoder
|
8 |
from sklearn.ensemble import RandomForestClassifier
|
9 |
import shap
|
10 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
class DataFetcher:
|
13 |
"""Fetches historical financial data using yfinance."""
|
@@ -147,6 +172,8 @@ class Backtester:
|
|
147 |
position = None
|
148 |
entry_price = None
|
149 |
portfolio_values = []
|
|
|
|
|
150 |
|
151 |
for i in range(1, len(self.data)):
|
152 |
last_row = self.data.iloc[i]
|
@@ -155,11 +182,13 @@ class Backtester:
|
|
155 |
if position != 'Buy':
|
156 |
position = 'Buy'
|
157 |
entry_price = last_row['Close']
|
|
|
158 |
elif (last_row['PCA_Scenario'] == 'Sell' and last_row['PCA_Sell%'] > sell_threshold) or \
|
159 |
(last_row['Scenario'] == 'Sell' and last_row['Sell%'] > sell_threshold):
|
160 |
if position != 'Sell':
|
161 |
position = 'Sell'
|
162 |
entry_price = last_row['Close']
|
|
|
163 |
|
164 |
if position == 'Buy':
|
165 |
portfolio_value *= (last_row['Close'] / entry_price)
|
@@ -168,11 +197,14 @@ class Backtester:
|
|
168 |
|
169 |
portfolio_values.append(portfolio_value)
|
170 |
|
171 |
-
return portfolio_values, position, entry_price
|
172 |
|
173 |
def run_analysis():
|
174 |
"""Runs the complete trading analysis."""
|
175 |
try:
|
|
|
|
|
|
|
176 |
fetcher = DataFetcher(ticker="^DJI", nb_days=50)
|
177 |
data = fetcher.fetch_data()
|
178 |
|
@@ -191,40 +223,44 @@ def run_analysis():
|
|
191 |
buy_threshold, sell_threshold = strategy_builder.refine_thresholds(feature_importance)
|
192 |
|
193 |
backtester = Backtester(processed_data)
|
194 |
-
portfolio_values,
|
195 |
|
196 |
last_row = processed_data.iloc[-1]
|
197 |
|
198 |
# Display results
|
199 |
col1, col2 = st.columns(2)
|
200 |
-
|
201 |
with col1:
|
202 |
st.subheader("Current Position")
|
203 |
-
st.metric("Position",
|
204 |
-
if
|
205 |
-
st.metric("Entry Price", f"${
|
206 |
-
|
207 |
|
208 |
with col2:
|
209 |
st.subheader("Decision Metrics")
|
210 |
st.metric("Buy%", f"{last_row['PCA_Buy%']:.4f}")
|
211 |
st.metric("Sell%", f"{last_row['PCA_Sell%']:.4f}")
|
212 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
return True
|
214 |
|
215 |
except Exception as e:
|
216 |
st.error(f"An error occurred: {str(e)}")
|
217 |
return False
|
218 |
|
219 |
-
# Page configuration
|
220 |
-
st.set_page_config(page_title="DOW JONES Trading Bot", layout="wide")
|
221 |
-
st.title("DOW JONES Trading Bot")
|
222 |
-
|
223 |
-
|
224 |
# Run analysis automatically on page load
|
225 |
run_analysis()
|
226 |
|
227 |
|
|
|
|
|
228 |
# Educational Slides Section
|
229 |
st.header("Educational Slides")
|
230 |
|
|
|
7 |
from sklearn.preprocessing import StandardScaler, LabelEncoder
|
8 |
from sklearn.ensemble import RandomForestClassifier
|
9 |
import shap
|
10 |
+
import requests
|
11 |
+
|
12 |
+
# Google Apps Script Web App URL
|
13 |
+
WEB_APP_URL = "https://script.google.com/macros/s/AKfycbzCLDKHozNB6257wxjPzAMBCqXIpzGUuOPbrzkAGrhaS2ujj7aQaXC0mJeVqPbUlzug/exec"
|
14 |
+
|
15 |
+
# Utility functions for persistent position storage
|
16 |
+
def save_position(position, trade_info, buy_percentage=None, sell_percentage=None):
|
17 |
+
payload = {
|
18 |
+
"action": "save",
|
19 |
+
"position": position,
|
20 |
+
"timestamp": datetime.now().isoformat(),
|
21 |
+
"trade_info": trade_info,
|
22 |
+
"buy_percentage": buy_percentage,
|
23 |
+
"sell_percentage": sell_percentage
|
24 |
+
}
|
25 |
+
response = requests.post(WEB_APP_URL, json=payload)
|
26 |
+
if response.status_code != 200:
|
27 |
+
raise Exception(f"Error saving position: {response.text}")
|
28 |
+
|
29 |
+
def load_position():
|
30 |
+
payload = {"action": "load"}
|
31 |
+
response = requests.post(WEB_APP_URL, json=payload)
|
32 |
+
if response.status_code == 200:
|
33 |
+
return response.json().get("position", None), response.json().get("entry_price", None), response.json().get("buy_percentage", None), response.json().get("sell_percentage", None)
|
34 |
+
else:
|
35 |
+
raise Exception(f"Error loading position: {response.text}")
|
36 |
|
37 |
class DataFetcher:
|
38 |
"""Fetches historical financial data using yfinance."""
|
|
|
172 |
position = None
|
173 |
entry_price = None
|
174 |
portfolio_values = []
|
175 |
+
last_buy_percentage = None
|
176 |
+
last_sell_percentage = None
|
177 |
|
178 |
for i in range(1, len(self.data)):
|
179 |
last_row = self.data.iloc[i]
|
|
|
182 |
if position != 'Buy':
|
183 |
position = 'Buy'
|
184 |
entry_price = last_row['Close']
|
185 |
+
last_buy_percentage = last_row['PCA_Buy%'] if 'PCA_Buy%' in last_row else last_row['Buy%']
|
186 |
elif (last_row['PCA_Scenario'] == 'Sell' and last_row['PCA_Sell%'] > sell_threshold) or \
|
187 |
(last_row['Scenario'] == 'Sell' and last_row['Sell%'] > sell_threshold):
|
188 |
if position != 'Sell':
|
189 |
position = 'Sell'
|
190 |
entry_price = last_row['Close']
|
191 |
+
last_sell_percentage = last_row['PCA_Sell%'] if 'PCA_Sell%' in last_row else last_row['Sell%']
|
192 |
|
193 |
if position == 'Buy':
|
194 |
portfolio_value *= (last_row['Close'] / entry_price)
|
|
|
197 |
|
198 |
portfolio_values.append(portfolio_value)
|
199 |
|
200 |
+
return portfolio_values, position, entry_price, last_buy_percentage, last_sell_percentage
|
201 |
|
202 |
def run_analysis():
|
203 |
"""Runs the complete trading analysis."""
|
204 |
try:
|
205 |
+
# Load previous position
|
206 |
+
current_position, entry_price, current_buy_percentage, current_sell_percentage = load_position()
|
207 |
+
|
208 |
fetcher = DataFetcher(ticker="^DJI", nb_days=50)
|
209 |
data = fetcher.fetch_data()
|
210 |
|
|
|
223 |
buy_threshold, sell_threshold = strategy_builder.refine_thresholds(feature_importance)
|
224 |
|
225 |
backtester = Backtester(processed_data)
|
226 |
+
portfolio_values, new_position, new_entry_price, new_buy_percentage, new_sell_percentage = backtester.backtest(buy_threshold, sell_threshold)
|
227 |
|
228 |
last_row = processed_data.iloc[-1]
|
229 |
|
230 |
# Display results
|
231 |
col1, col2 = st.columns(2)
|
232 |
+
|
233 |
with col1:
|
234 |
st.subheader("Current Position")
|
235 |
+
st.metric("Position", new_position or "No position")
|
236 |
+
if new_position:
|
237 |
+
st.metric("Entry Price", f"${new_entry_price:.2f}")
|
|
|
238 |
|
239 |
with col2:
|
240 |
st.subheader("Decision Metrics")
|
241 |
st.metric("Buy%", f"{last_row['PCA_Buy%']:.4f}")
|
242 |
st.metric("Sell%", f"{last_row['PCA_Sell%']:.4f}")
|
243 |
|
244 |
+
|
245 |
+
# Save new position if changed
|
246 |
+
if new_position != current_position:
|
247 |
+
save_position(new_position, {"entry_price": new_entry_price, "timestamp": datetime.now().isoformat()},
|
248 |
+
buy_percentage=last_row['PCA_Buy%'], sell_percentage=last_row['PCA_Sell%'])
|
249 |
+
|
250 |
+
|
251 |
+
|
252 |
return True
|
253 |
|
254 |
except Exception as e:
|
255 |
st.error(f"An error occurred: {str(e)}")
|
256 |
return False
|
257 |
|
|
|
|
|
|
|
|
|
|
|
258 |
# Run analysis automatically on page load
|
259 |
run_analysis()
|
260 |
|
261 |
|
262 |
+
|
263 |
+
|
264 |
# Educational Slides Section
|
265 |
st.header("Educational Slides")
|
266 |
|