Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -45,86 +45,29 @@ class AdvancedMLModels:
|
|
| 45 |
Dropout(0.2),
|
| 46 |
LSTM(50, return_sequences=False),
|
| 47 |
Dropout(0.2),
|
| 48 |
-
Dense(25),
|
| 49 |
Dense(1)
|
| 50 |
])
|
| 51 |
model.compile(optimizer='adam', loss='mse')
|
| 52 |
return model
|
| 53 |
|
| 54 |
def prepare_lstm_data(self, X, y, look_back=60):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
X_lstm = []
|
| 56 |
y_lstm = []
|
| 57 |
for i in range(look_back, len(X)):
|
| 58 |
X_lstm.append(X[i-look_back:i])
|
| 59 |
y_lstm.append(y[i])
|
| 60 |
-
return np.array(X_lstm), np.array(y_lstm)
|
| 61 |
-
|
| 62 |
-
class PortfolioOptimizer:
|
| 63 |
-
def __init__(self, assets, returns):
|
| 64 |
-
self.assets = assets
|
| 65 |
-
self.returns = returns
|
| 66 |
-
|
| 67 |
-
def portfolio_performance(self, weights):
|
| 68 |
-
returns = np.sum(self.returns.mean() * weights) * 252
|
| 69 |
-
volatility = np.sqrt(np.dot(weights.T, np.dot(self.returns.cov() * 252, weights)))
|
| 70 |
-
sharpe = returns / volatility
|
| 71 |
-
return returns, volatility, sharpe
|
| 72 |
-
|
| 73 |
-
def optimize_portfolio(self, risk_free_rate=0.01):
|
| 74 |
-
num_assets = len(self.assets)
|
| 75 |
-
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
|
| 76 |
-
bounds = tuple((0, 1) for _ in range(num_assets))
|
| 77 |
-
|
| 78 |
-
def objective(weights):
|
| 79 |
-
returns, volatility, sharpe = self.portfolio_performance(weights)
|
| 80 |
-
return -sharpe # Maximize Sharpe ratio
|
| 81 |
-
|
| 82 |
-
initial_weights = np.array([1/num_assets] * num_assets)
|
| 83 |
-
result = minimize(objective, initial_weights, method='SLSQP',
|
| 84 |
-
bounds=bounds, constraints=constraints)
|
| 85 |
|
| 86 |
-
return
|
| 87 |
-
|
| 88 |
-
class AlertSystem:
|
| 89 |
-
def __init__(self):
|
| 90 |
-
self.alert_types = {
|
| 91 |
-
'price_threshold': self.check_price_threshold,
|
| 92 |
-
'rsi_extreme': self.check_rsi_extreme,
|
| 93 |
-
'volume_spike': self.check_volume_spike,
|
| 94 |
-
'trend_reversal': self.check_trend_reversal
|
| 95 |
-
}
|
| 96 |
-
|
| 97 |
-
def check_price_threshold(self, data, params):
|
| 98 |
-
current_price = data['Close'].iloc[-1]
|
| 99 |
-
if current_price >= params['upper']:
|
| 100 |
-
return f"Price above upper threshold: ${current_price:,.2f}"
|
| 101 |
-
elif current_price <= params['lower']:
|
| 102 |
-
return f"Price below lower threshold: ${current_price:,.2f}"
|
| 103 |
-
return None
|
| 104 |
-
|
| 105 |
-
def check_rsi_extreme(self, data, params):
|
| 106 |
-
current_rsi = data['RSI'].iloc[-1]
|
| 107 |
-
if current_rsi >= 70:
|
| 108 |
-
return f"RSI in overbought territory: {current_rsi:.2f}"
|
| 109 |
-
elif current_rsi <= 30:
|
| 110 |
-
return f"RSI in oversold territory: {current_rsi:.2f}"
|
| 111 |
-
return None
|
| 112 |
-
|
| 113 |
-
def check_volume_spike(self, data, params):
|
| 114 |
-
current_volume = data['Volume'].iloc[-1]
|
| 115 |
-
avg_volume = data['Volume'].rolling(window=20).mean().iloc[-1]
|
| 116 |
-
if current_volume > avg_volume * params['threshold']:
|
| 117 |
-
return f"Volume spike detected: {current_volume:,.0f}"
|
| 118 |
-
return None
|
| 119 |
-
|
| 120 |
-
def check_trend_reversal(self, data, params):
|
| 121 |
-
if data['SMA20'].iloc[-1] < data['SMA50'].iloc[-1] and \
|
| 122 |
-
data['SMA20'].iloc[-2] > data['SMA50'].iloc[-2]:
|
| 123 |
-
return "Potential downward trend reversal detected"
|
| 124 |
-
elif data['SMA20'].iloc[-1] > data['SMA50'].iloc[-1] and \
|
| 125 |
-
data['SMA20'].iloc[-2] < data['SMA50'].iloc[-2]:
|
| 126 |
-
return "Potential upward trend reversal detected"
|
| 127 |
-
return None
|
| 128 |
|
| 129 |
class CryptoAnalyzer:
|
| 130 |
def __init__(self, symbol, period='1y'):
|
|
@@ -133,7 +76,6 @@ class CryptoAnalyzer:
|
|
| 133 |
self.data = self.fetch_data()
|
| 134 |
self.preprocess_data()
|
| 135 |
self.ml_models = AdvancedMLModels()
|
| 136 |
-
self.alert_system = AlertSystem()
|
| 137 |
|
| 138 |
def fetch_data(self):
|
| 139 |
return yf.download(self.symbol, period=self.period, interval='1d')
|
|
@@ -142,38 +84,34 @@ class CryptoAnalyzer:
|
|
| 142 |
# Add technical indicators
|
| 143 |
df = self.data.copy()
|
| 144 |
|
|
|
|
| 145 |
df['RSI'] = ta.momentum.RSIIndicator(df['Close']).rsi()
|
| 146 |
macd = ta.trend.MACD(df['Close'])
|
| 147 |
df['MACD'] = macd.macd()
|
| 148 |
-
df['MFI'] = ta.volume.MFIIndicator(df['High'], df['Low'], df['Close'], df['Volume']).money_flow_index()
|
| 149 |
-
df['ATR'] = ta.volatility.AverageTrueRange(df['High'], df['Low'], df['Close']).average_true_range()
|
| 150 |
-
df['OBV'] = ta.volume.OnBalanceVolumeIndicator(df['Close'], df['Volume']).on_balance_volume()
|
| 151 |
|
| 152 |
-
|
| 153 |
-
|
|
|
|
| 154 |
|
| 155 |
-
#
|
| 156 |
-
|
| 157 |
-
df['BB_upper'] = bb.bollinger_hband()
|
| 158 |
-
df['BB_lower'] = bb.bollinger_lband()
|
| 159 |
|
| 160 |
self.data = df
|
| 161 |
|
| 162 |
def train_prediction_model(self):
|
| 163 |
df = self.data.copy()
|
| 164 |
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
'SMA20', 'SMA50', 'BB_upper', 'BB_lower',
|
| 168 |
-
'Volume'
|
| 169 |
-
]
|
| 170 |
|
| 171 |
# Prepare features and target
|
| 172 |
-
X = df[feature_columns].
|
| 173 |
-
y = df['Close'].
|
| 174 |
|
| 175 |
-
#
|
| 176 |
-
|
|
|
|
|
|
|
| 177 |
|
| 178 |
# Train-test split
|
| 179 |
train_size = int(len(X) * (backtesting_split / 100))
|
|
@@ -185,43 +123,25 @@ class CryptoAnalyzer:
|
|
| 185 |
X_train_scaled = scaler.fit_transform(X_train)
|
| 186 |
X_test_scaled = scaler.transform(X_test)
|
| 187 |
|
| 188 |
-
#
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
if name == 'lstm':
|
| 192 |
-
# Prepare LSTM data
|
| 193 |
-
X_lstm_train, y_lstm_train = self.ml_models.prepare_lstm_data(X_train_scaled, y_train)
|
| 194 |
-
X_lstm_test, y_lstm_test = self.ml_models.prepare_lstm_data(X_test_scaled, y_test)
|
| 195 |
-
|
| 196 |
-
# Create and train LSTM model
|
| 197 |
-
model = self.ml_models.create_lstm_model((X_lstm_train.shape[1], X_lstm_train.shape[2]))
|
| 198 |
-
model.fit(X_lstm_train, y_lstm_train, epochs=50, batch_size=32, verbose=0)
|
| 199 |
-
predictions[name] = model.predict(X_lstm_test)
|
| 200 |
-
else:
|
| 201 |
-
model.fit(X_train_scaled, y_train)
|
| 202 |
-
predictions[name] = model.predict(X_test_scaled)
|
| 203 |
|
| 204 |
-
#
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
'gradient_boost': 0.3,
|
| 208 |
-
'ada_boost': 0.2,
|
| 209 |
-
'lstm': 0.2
|
| 210 |
-
}
|
| 211 |
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
final_predictions += pred.flatten() * weights[name]
|
| 215 |
|
| 216 |
-
return
|
| 217 |
|
| 218 |
def main():
|
| 219 |
-
st.set_page_config(page_title="
|
| 220 |
-
st.title("
|
| 221 |
|
| 222 |
-
#
|
| 223 |
-
st.
|
| 224 |
-
selected_crypto = st.sidebar.selectbox(
|
| 225 |
"Select Cryptocurrency",
|
| 226 |
list(TRADING_PAIRS.keys()),
|
| 227 |
index=0
|
|
@@ -232,6 +152,7 @@ def main():
|
|
| 232 |
|
| 233 |
# Initialize Crypto Analyzer
|
| 234 |
try:
|
|
|
|
| 235 |
analyzer = CryptoAnalyzer(symbol)
|
| 236 |
df = analyzer.data
|
| 237 |
|
|
@@ -246,68 +167,35 @@ def main():
|
|
| 246 |
)])
|
| 247 |
st.plotly_chart(fig)
|
| 248 |
|
| 249 |
-
# Portfolio Optimization
|
| 250 |
-
st.subheader("Portfolio Optimization")
|
| 251 |
-
selected_assets = st.multiselect(
|
| 252 |
-
"Select assets for portfolio",
|
| 253 |
-
list(TRADING_PAIRS.keys()),
|
| 254 |
-
default=[selected_crypto]
|
| 255 |
-
)
|
| 256 |
-
|
| 257 |
-
if len(selected_assets) > 1:
|
| 258 |
-
# Fetch historical data for selected assets
|
| 259 |
-
portfolio_data = {}
|
| 260 |
-
for asset in selected_assets:
|
| 261 |
-
symbol = TRADING_PAIRS[asset]
|
| 262 |
-
data = yf.download(symbol, period='1y', interval='1d')
|
| 263 |
-
portfolio_data[asset] = data['Close'].pct_change().dropna()
|
| 264 |
-
|
| 265 |
-
# Create returns DataFrame
|
| 266 |
-
returns_df = pd.DataFrame(portfolio_data)
|
| 267 |
-
|
| 268 |
-
# Optimize portfolio
|
| 269 |
-
optimizer = PortfolioOptimizer(selected_assets, returns_df)
|
| 270 |
-
optimal_weights = optimizer.optimize_portfolio()
|
| 271 |
-
|
| 272 |
-
# Display optimal allocation
|
| 273 |
-
st.write("Optimal Portfolio Allocation:")
|
| 274 |
-
for asset, weight in zip(selected_assets, optimal_weights):
|
| 275 |
-
st.write(f"{asset}: {weight:.2%}")
|
| 276 |
-
|
| 277 |
-
# Real-time Alerts
|
| 278 |
-
st.subheader("Real-time Alerts")
|
| 279 |
-
alert_settings = {}
|
| 280 |
-
|
| 281 |
-
with st.expander("Configure Alerts"):
|
| 282 |
-
alert_settings['price_threshold'] = {
|
| 283 |
-
'upper': st.number_input("Upper Price Threshold", value=float(df['Close'].iloc[-1] * 1.1)),
|
| 284 |
-
'lower': st.number_input("Lower Price Threshold", value=float(df['Close'].iloc[-1] * 0.9))
|
| 285 |
-
}
|
| 286 |
-
alert_settings['volume_spike'] = {
|
| 287 |
-
'threshold': st.slider("Volume Spike Threshold", 1.5, 5.0, 2.0)
|
| 288 |
-
}
|
| 289 |
-
|
| 290 |
-
# Check for alerts
|
| 291 |
-
current_alerts = []
|
| 292 |
-
for alert_type, check_func in analyzer.alert_system.alert_types.items():
|
| 293 |
-
if alert_type in alert_settings:
|
| 294 |
-
alert = check_func(df, alert_settings[alert_type])
|
| 295 |
-
if alert:
|
| 296 |
-
current_alerts.append(alert)
|
| 297 |
-
|
| 298 |
-
if current_alerts:
|
| 299 |
-
for alert in current_alerts:
|
| 300 |
-
st.warning(alert)
|
| 301 |
-
|
| 302 |
# Price Prediction
|
| 303 |
st.subheader("Price Prediction")
|
| 304 |
try:
|
| 305 |
predictions, actual = analyzer.train_prediction_model()
|
|
|
|
|
|
|
| 306 |
pred_df = pd.DataFrame({
|
| 307 |
'Predicted Price': predictions,
|
| 308 |
'Actual Price': actual
|
| 309 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
st.dataframe(pred_df)
|
|
|
|
| 311 |
except Exception as pred_error:
|
| 312 |
st.error(f"Prediction error: {pred_error}")
|
| 313 |
|
|
|
|
| 45 |
Dropout(0.2),
|
| 46 |
LSTM(50, return_sequences=False),
|
| 47 |
Dropout(0.2),
|
| 48 |
+
Dense(25, activation='relu'),
|
| 49 |
Dense(1)
|
| 50 |
])
|
| 51 |
model.compile(optimizer='adam', loss='mse')
|
| 52 |
return model
|
| 53 |
|
| 54 |
def prepare_lstm_data(self, X, y, look_back=60):
|
| 55 |
+
# Ensure X and y are numpy arrays
|
| 56 |
+
X = np.array(X)
|
| 57 |
+
y = np.array(y)
|
| 58 |
+
|
| 59 |
+
# Reshape X to be 3D for LSTM (samples, timesteps, features)
|
| 60 |
+
if len(X.shape) == 2:
|
| 61 |
+
X = X.reshape((X.shape[0], 1, X.shape[1]))
|
| 62 |
+
|
| 63 |
+
# Prepare sequences
|
| 64 |
X_lstm = []
|
| 65 |
y_lstm = []
|
| 66 |
for i in range(look_back, len(X)):
|
| 67 |
X_lstm.append(X[i-look_back:i])
|
| 68 |
y_lstm.append(y[i])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
+
return np.array(X_lstm), np.array(y_lstm)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
class CryptoAnalyzer:
|
| 73 |
def __init__(self, symbol, period='1y'):
|
|
|
|
| 76 |
self.data = self.fetch_data()
|
| 77 |
self.preprocess_data()
|
| 78 |
self.ml_models = AdvancedMLModels()
|
|
|
|
| 79 |
|
| 80 |
def fetch_data(self):
|
| 81 |
return yf.download(self.symbol, period=self.period, interval='1d')
|
|
|
|
| 84 |
# Add technical indicators
|
| 85 |
df = self.data.copy()
|
| 86 |
|
| 87 |
+
# Add technical indicators
|
| 88 |
df['RSI'] = ta.momentum.RSIIndicator(df['Close']).rsi()
|
| 89 |
macd = ta.trend.MACD(df['Close'])
|
| 90 |
df['MACD'] = macd.macd()
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
+
# Ensure all columns are numeric and handle potential NaNs
|
| 93 |
+
numeric_columns = ['Close', 'Open', 'High', 'Low', 'Volume', 'RSI', 'MACD']
|
| 94 |
+
df[numeric_columns] = df[numeric_columns].apply(pd.to_numeric, errors='coerce')
|
| 95 |
|
| 96 |
+
# Fill NaN values
|
| 97 |
+
df.fillna(method='ffill', inplace=True)
|
|
|
|
|
|
|
| 98 |
|
| 99 |
self.data = df
|
| 100 |
|
| 101 |
def train_prediction_model(self):
|
| 102 |
df = self.data.copy()
|
| 103 |
|
| 104 |
+
# Select and prepare features
|
| 105 |
+
feature_columns = ['Close', 'Volume', 'RSI', 'MACD']
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
# Prepare features and target
|
| 108 |
+
X = df[feature_columns].values
|
| 109 |
+
y = df['Close'].values
|
| 110 |
|
| 111 |
+
# Remove NaN values
|
| 112 |
+
mask = ~np.isnan(X).any(axis=1) & ~np.isnan(y)
|
| 113 |
+
X = X[mask]
|
| 114 |
+
y = y[mask]
|
| 115 |
|
| 116 |
# Train-test split
|
| 117 |
train_size = int(len(X) * (backtesting_split / 100))
|
|
|
|
| 123 |
X_train_scaled = scaler.fit_transform(X_train)
|
| 124 |
X_test_scaled = scaler.transform(X_test)
|
| 125 |
|
| 126 |
+
# Prepare LSTM data
|
| 127 |
+
X_lstm_train, y_lstm_train = self.ml_models.prepare_lstm_data(X_train_scaled, y_train)
|
| 128 |
+
X_lstm_test, y_lstm_test = self.ml_models.prepare_lstm_data(X_test_scaled, y_test)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
+
# Create and train LSTM model
|
| 131 |
+
lstm_model = self.ml_models.create_lstm_model((X_lstm_train.shape[2], X_lstm_train.shape[1]))
|
| 132 |
+
lstm_model.fit(X_lstm_train, y_lstm_train, epochs=50, batch_size=32, verbose=0)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
+
# Make predictions
|
| 135 |
+
lstm_predictions = lstm_model.predict(X_lstm_test).flatten()
|
|
|
|
| 136 |
|
| 137 |
+
return lstm_predictions, y_lstm_test
|
| 138 |
|
| 139 |
def main():
|
| 140 |
+
st.set_page_config(page_title="Crypto Price Prediction", layout="wide")
|
| 141 |
+
st.title("Cryptocurrency Price Prediction")
|
| 142 |
|
| 143 |
+
# Cryptocurrency selection
|
| 144 |
+
selected_crypto = st.selectbox(
|
|
|
|
| 145 |
"Select Cryptocurrency",
|
| 146 |
list(TRADING_PAIRS.keys()),
|
| 147 |
index=0
|
|
|
|
| 152 |
|
| 153 |
# Initialize Crypto Analyzer
|
| 154 |
try:
|
| 155 |
+
# Fetch and analyze data
|
| 156 |
analyzer = CryptoAnalyzer(symbol)
|
| 157 |
df = analyzer.data
|
| 158 |
|
|
|
|
| 167 |
)])
|
| 168 |
st.plotly_chart(fig)
|
| 169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
# Price Prediction
|
| 171 |
st.subheader("Price Prediction")
|
| 172 |
try:
|
| 173 |
predictions, actual = analyzer.train_prediction_model()
|
| 174 |
+
|
| 175 |
+
# Create DataFrame for comparison
|
| 176 |
pred_df = pd.DataFrame({
|
| 177 |
'Predicted Price': predictions,
|
| 178 |
'Actual Price': actual
|
| 179 |
})
|
| 180 |
+
|
| 181 |
+
# Plotting predictions vs actual
|
| 182 |
+
fig_pred = go.Figure()
|
| 183 |
+
fig_pred.add_trace(go.Scatter(
|
| 184 |
+
x=list(range(len(predictions))),
|
| 185 |
+
y=predictions,
|
| 186 |
+
mode='lines',
|
| 187 |
+
name='Predicted Price'
|
| 188 |
+
))
|
| 189 |
+
fig_pred.add_trace(go.Scatter(
|
| 190 |
+
x=list(range(len(actual))),
|
| 191 |
+
y=actual,
|
| 192 |
+
mode='lines',
|
| 193 |
+
name='Actual Price'
|
| 194 |
+
))
|
| 195 |
+
|
| 196 |
+
st.plotly_chart(fig_pred)
|
| 197 |
st.dataframe(pred_df)
|
| 198 |
+
|
| 199 |
except Exception as pred_error:
|
| 200 |
st.error(f"Prediction error: {pred_error}")
|
| 201 |
|