Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
|
2 |
-
import
|
3 |
from datetime import datetime, timedelta
|
|
|
4 |
import numpy as np
|
5 |
import pandas as pd
|
6 |
from sklearn.decomposition import PCA
|
@@ -11,7 +12,7 @@ import matplotlib.pyplot as plt
|
|
11 |
|
12 |
class DataFetcher:
|
13 |
"""Fetches historical financial data using yfinance."""
|
14 |
-
def __init__(self, ticker, nb_days):
|
15 |
self.ticker = ticker
|
16 |
self.nb_days = nb_days
|
17 |
self.data = None
|
@@ -21,7 +22,6 @@ class DataFetcher:
|
|
21 |
end_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
22 |
start_date = end_date - timedelta(days=self.nb_days)
|
23 |
end_date = end_date + timedelta(days=1)
|
24 |
-
print(f"Fetching data from {start_date} to {end_date}")
|
25 |
self.data = yf.download(self.ticker, start=start_date, end=end_date, interval="1h")
|
26 |
|
27 |
class FinancialDataProcessor:
|
@@ -111,9 +111,9 @@ class StrategyBuilder:
|
|
111 |
def analyze_feature_importance(self, shap_values, feature_names):
|
112 |
"""Analyzes feature importance based on SHAP values."""
|
113 |
if isinstance(shap_values, list):
|
114 |
-
shap_values = shap_values[1]
|
115 |
|
116 |
-
if len(shap_values.shape) == 3:
|
117 |
shap_values = shap_values[:, :, 1]
|
118 |
|
119 |
mean_abs_shap = np.mean(np.abs(shap_values), axis=0)
|
@@ -126,8 +126,6 @@ class StrategyBuilder:
|
|
126 |
'Mean_Abs_SHAP': mean_abs_shap
|
127 |
}).sort_values(by='Mean_Abs_SHAP', ascending=False)
|
128 |
|
129 |
-
print("Feature Importance based on Shapley Values:")
|
130 |
-
print(feature_importance)
|
131 |
return feature_importance
|
132 |
|
133 |
def refine_thresholds(self, feature_importance, buy_threshold=0.5, sell_threshold=0.5):
|
@@ -149,9 +147,14 @@ class Backtester:
|
|
149 |
position = None
|
150 |
entry_price = None
|
151 |
portfolio_values = []
|
|
|
|
|
152 |
|
153 |
for i in range(1, len(self.data)):
|
154 |
last_row = self.data.iloc[i]
|
|
|
|
|
|
|
155 |
if (last_row['PCA_Scenario'] == 'Buy' and last_row['PCA_Buy%'] > buy_threshold) or \
|
156 |
(last_row['Scenario'] == 'Buy' and last_row['Buy%'] > buy_threshold):
|
157 |
if position != 'Buy':
|
@@ -169,12 +172,19 @@ class Backtester:
|
|
169 |
portfolio_value *= (entry_price / last_row['Close'])
|
170 |
|
171 |
portfolio_values.append(portfolio_value)
|
|
|
|
|
|
|
|
|
172 |
|
173 |
-
|
|
|
|
|
174 |
|
175 |
-
def
|
176 |
try:
|
177 |
-
|
|
|
178 |
fetcher.fetch_data()
|
179 |
|
180 |
processor = FinancialDataProcessor(fetcher.data)
|
@@ -192,33 +202,53 @@ def main():
|
|
192 |
buy_threshold, sell_threshold = strategy_builder.refine_thresholds(feature_importance)
|
193 |
|
194 |
backtester = Backtester(processed_data)
|
195 |
-
portfolio_values,
|
196 |
|
197 |
last_row = processed_data.iloc[-1]
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
|
218 |
except Exception as e:
|
219 |
-
|
220 |
-
|
221 |
-
|
|
|
222 |
|
223 |
-
|
224 |
-
|
|
|
|
|
|
|
|
1 |
|
2 |
+
import streamlit as st
|
3 |
from datetime import datetime, timedelta
|
4 |
+
import yfinance as yf
|
5 |
import numpy as np
|
6 |
import pandas as pd
|
7 |
from sklearn.decomposition import PCA
|
|
|
12 |
|
13 |
class DataFetcher:
|
14 |
"""Fetches historical financial data using yfinance."""
|
15 |
+
def __init__(self, ticker, nb_days=50):
|
16 |
self.ticker = ticker
|
17 |
self.nb_days = nb_days
|
18 |
self.data = None
|
|
|
22 |
end_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
23 |
start_date = end_date - timedelta(days=self.nb_days)
|
24 |
end_date = end_date + timedelta(days=1)
|
|
|
25 |
self.data = yf.download(self.ticker, start=start_date, end=end_date, interval="1h")
|
26 |
|
27 |
class FinancialDataProcessor:
|
|
|
111 |
def analyze_feature_importance(self, shap_values, feature_names):
|
112 |
"""Analyzes feature importance based on SHAP values."""
|
113 |
if isinstance(shap_values, list):
|
114 |
+
shap_values = shap_values[1]
|
115 |
|
116 |
+
if len(shap_values.shape) == 3:
|
117 |
shap_values = shap_values[:, :, 1]
|
118 |
|
119 |
mean_abs_shap = np.mean(np.abs(shap_values), axis=0)
|
|
|
126 |
'Mean_Abs_SHAP': mean_abs_shap
|
127 |
}).sort_values(by='Mean_Abs_SHAP', ascending=False)
|
128 |
|
|
|
|
|
129 |
return feature_importance
|
130 |
|
131 |
def refine_thresholds(self, feature_importance, buy_threshold=0.5, sell_threshold=0.5):
|
|
|
147 |
position = None
|
148 |
entry_price = None
|
149 |
portfolio_values = []
|
150 |
+
positions = []
|
151 |
+
entry_prices = []
|
152 |
|
153 |
for i in range(1, len(self.data)):
|
154 |
last_row = self.data.iloc[i]
|
155 |
+
prev_position = position
|
156 |
+
prev_entry_price = entry_price
|
157 |
+
|
158 |
if (last_row['PCA_Scenario'] == 'Buy' and last_row['PCA_Buy%'] > buy_threshold) or \
|
159 |
(last_row['Scenario'] == 'Buy' and last_row['Buy%'] > buy_threshold):
|
160 |
if position != 'Buy':
|
|
|
172 |
portfolio_value *= (entry_price / last_row['Close'])
|
173 |
|
174 |
portfolio_values.append(portfolio_value)
|
175 |
+
positions.append(prev_position)
|
176 |
+
entry_prices.append(prev_entry_price)
|
177 |
+
|
178 |
+
return portfolio_values, position, entry_price, positions[-1], entry_prices[-1]
|
179 |
|
180 |
+
# Streamlit interface
|
181 |
+
st.set_page_config(page_title="Crypto Trading Bot", layout="wide")
|
182 |
+
st.title("Real-Time Crypto Trading Analysis")
|
183 |
|
184 |
+
def run_analysis():
|
185 |
try:
|
186 |
+
ticker = "BTC-USD" # Fixed to BTC-USD
|
187 |
+
fetcher = DataFetcher(ticker=ticker)
|
188 |
fetcher.fetch_data()
|
189 |
|
190 |
processor = FinancialDataProcessor(fetcher.data)
|
|
|
202 |
buy_threshold, sell_threshold = strategy_builder.refine_thresholds(feature_importance)
|
203 |
|
204 |
backtester = Backtester(processed_data)
|
205 |
+
portfolio_values, current_position, current_entry, prev_position, prev_entry = backtester.backtest(buy_threshold, sell_threshold)
|
206 |
|
207 |
last_row = processed_data.iloc[-1]
|
208 |
+
prev_row = processed_data.iloc[-2]
|
209 |
+
|
210 |
+
# Display current status
|
211 |
+
st.header("Current Status")
|
212 |
+
col1, col2, col3 = st.columns(3)
|
213 |
+
|
214 |
+
with col1:
|
215 |
+
st.subheader("Position Info")
|
216 |
+
st.metric("Current Position", current_position or "No position")
|
217 |
+
st.metric("Previous Position", prev_position or "No position")
|
218 |
+
if current_entry:
|
219 |
+
st.metric("Current Entry Price", f"${current_entry:.2f}")
|
220 |
+
if prev_entry:
|
221 |
+
st.metric("Previous Entry Price", f"${prev_entry:.2f}")
|
222 |
+
|
223 |
+
with col2:
|
224 |
+
st.subheader("Current Bar")
|
225 |
+
st.metric("Close Price", f"${last_row['Close']:.2f}")
|
226 |
+
st.metric("Buy Signal", f"{last_row['Buy%']:.4f}")
|
227 |
+
st.metric("Sell Signal", f"{last_row['Sell%']:.4f}")
|
228 |
+
|
229 |
+
with col3:
|
230 |
+
st.subheader("Previous Bar")
|
231 |
+
st.metric("Close Price", f"${prev_row['Close']:.2f}")
|
232 |
+
st.metric("Buy Signal", f"{prev_row['Buy%']:.4f}")
|
233 |
+
st.metric("Sell Signal", f"{prev_row['Sell%']:.4f}")
|
234 |
+
|
235 |
+
# Portfolio Performance
|
236 |
+
st.header("Portfolio Performance")
|
237 |
+
st.metric("Current Portfolio Value", f"${portfolio_values[-1]:.2f}")
|
238 |
+
st.metric("Return", f"{((portfolio_values[-1] - 10000) / 10000 * 100):.2f}%")
|
239 |
+
|
240 |
+
# Feature importance
|
241 |
+
st.header("Strategy Analysis")
|
242 |
+
st.dataframe(feature_importance)
|
243 |
|
244 |
except Exception as e:
|
245 |
+
st.error(f"An error occurred: {str(e)}")
|
246 |
+
|
247 |
+
# Run analysis automatically on page load
|
248 |
+
run_analysis()
|
249 |
|
250 |
+
# Auto-refresh every 5 minutes
|
251 |
+
st.empty()
|
252 |
+
st.markdown("*Data updates automatically every 5 minutes*")
|
253 |
+
if st.button("Refresh Now"):
|
254 |
+
run_analysis()
|