NandanData commited on
Commit
a210c50
·
verified ·
1 Parent(s): c6f6cbb

dim error fixed

Browse files
Files changed (1) hide show
  1. model.py +883 -710
model.py CHANGED
@@ -1,710 +1,883 @@
1
-
2
- import yfinance as yf
3
- import pandas as pd
4
- import ta
5
- from sklearn.model_selection import train_test_split
6
- from sklearn.linear_model import LinearRegression
7
- from sklearn.tree import DecisionTreeRegressor
8
- from sklearn.ensemble import RandomForestRegressor
9
- from sklearn.metrics import mean_absolute_error, r2_score
10
- import xgboost as xgb
11
- from catboost import CatBoostRegressor
12
- import numpy as np
13
- from tensorflow.keras.models import Sequential
14
- from tensorflow.keras.layers import LSTM, Dense
15
- from sklearn.preprocessing import MinMaxScaler
16
- from statsmodels.tsa.arima.model import ARIMA
17
- from statsmodels.tsa.statespace.sarimax import SARIMAX
18
-
19
-
20
- from logger import get_logger
21
-
22
- logger = get_logger(__name__)
23
- # logger.setLevel(logging.DEBUG)
24
- # handler = logging.StreamHandler()
25
- # handler.setLevel(logging.DEBUG)
26
- # formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
27
- # handler.setFormatter(formatter)
28
- # logger.addHandler(handler)
29
-
30
- # # Example usage of logger
31
- # logger.info("This is an info message")
32
-
33
- # Fetch historical data
34
- def fetch_data(ticker, start_date, end_date):
35
- logger.info(f"Fetching data for {ticker} from {start_date} to {end_date}")
36
- data = yf.download(ticker, start=start_date, end=end_date)
37
- if data.empty:
38
- logger.warning(f"No data returned for {ticker}.")
39
- return None
40
-
41
- # Reset index to ensure Date is a column
42
- data.reset_index(inplace=True)
43
- logger.info(f"Data fetched successfully for {ticker}.")
44
- return data
45
-
46
- def calculate_indicators(data: pd.DataFrame) -> pd.DataFrame:
47
- logger.info("Calculating indicators with fixed parameters.")
48
-
49
- # Check if required columns are present
50
- required_columns = ['Close', 'High', 'Low', 'Volume']
51
- missing_columns = [col for col in required_columns if col not in data.columns]
52
- if missing_columns:
53
- logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
54
- raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
55
-
56
- # Calculate fixed moving averages
57
- ma_period = 50 # Fixed period for moving averages
58
- try:
59
- data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
60
- data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
61
- except Exception as e:
62
- logger.error(f"Error calculating moving averages: {e}")
63
- raise
64
-
65
- # Calculate other indicators
66
- try:
67
- data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
68
- macd = ta.trend.MACD(data['Close'])
69
- data['MACD'] = macd.macd()
70
- data['MACD_Signal'] = macd.macd_signal()
71
- bollinger = ta.volatility.BollingerBands(data['Close'])
72
- data['Bollinger_High'] = bollinger.bollinger_hband()
73
- data['Bollinger_Low'] = bollinger.bollinger_lband()
74
- data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
75
- data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
76
- except Exception as e:
77
- logger.error(f"Error calculating other indicators: {e}")
78
- raise
79
-
80
- # Debugging line to check the columns
81
- logger.debug("Columns after calculating indicators: %s", data.columns)
82
-
83
- data = data.dropna()
84
- logger.info("Indicators calculated successfully.")
85
- return data
86
-
87
-
88
- # def calculate_indicators(data: pd.DataFrame, ma_type='SMA', ma_period=50) -> pd.DataFrame:
89
- # logger.info(f"Calculating indicators with {ma_type} of period {ma_period}.")
90
-
91
- # # Check if required columns are present
92
- # required_columns = ['Close', 'High', 'Low', 'Volume']
93
- # missing_columns = [col for col in required_columns if col not in data.columns]
94
- # if missing_columns:
95
- # logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
96
- # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
97
-
98
- # # Calculate moving averages
99
- # if ma_type == 'SMA':
100
- # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
101
- # elif ma_type == 'EMA':
102
- # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
103
- # else:
104
- # logger.error(f"Unknown moving average type: {ma_type}")
105
- # raise ValueError(f"Unknown moving average type: {ma_type}")
106
-
107
- # # Calculate other indicators
108
- # try:
109
- # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
110
- # macd = ta.trend.MACD(data['Close'])
111
- # data['MACD'] = macd.macd()
112
- # data['MACD_Signal'] = macd.macd_signal()
113
- # bollinger = ta.volatility.BollingerBands(data['Close'])
114
- # data['Bollinger_High'] = bollinger.bollinger_hband()
115
- # data['Bollinger_Low'] = bollinger.bollinger_lband()
116
- # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
117
- # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
118
- # except Exception as e:
119
- # logger.error(f"Error calculating indicators: {e}")
120
- # raise
121
-
122
- # Debugging line to check the columns
123
- logger.debug("Columns after calculating indicators: %s", data.columns)
124
-
125
- data = data.dropna()
126
- logger.info("Indicators calculated successfully.")
127
- return data
128
-
129
-
130
- # # Calculate technical indicators
131
- # def calculate_indicators(data, ma_type='SMA', ma_period=50):
132
- # logger.info(f"Calculating indicators with {ma_type} of period {ma_period}.")
133
-
134
- # if ma_type == 'SMA':
135
- # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
136
- # elif ma_type == 'EMA':
137
- # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
138
-
139
- # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
140
- # macd = ta.trend.MACD(data['Close'])
141
- # data['MACD'] = macd.macd()
142
- # data['MACD_Signal'] = macd.macd_signal()
143
- # bollinger = ta.volatility.BollingerBands(data['Close'])
144
- # data['Bollinger_High'] = bollinger.bollinger_hband()
145
- # data['Bollinger_Low'] = bollinger.bollinger_lband()
146
- # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
147
- # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
148
-
149
- # # Debugging line to check the columns
150
- # logger.debug("Columns after calculating indicators: %s", data.columns)
151
-
152
- # data = data.dropna()
153
- # logger.info("Indicators calculated successfully.")
154
- # return data
155
-
156
- # Calculate support and resistance levels
157
- def calculate_support_resistance(data, window=30):
158
- logger.info(f"Calculating support and resistance with a window of {window}.")
159
-
160
- recent_data = data.tail(window)
161
- rolling_max = data['Close'].rolling(window=window).max()
162
- rolling_min = data['Close'].rolling(window=window).min()
163
- recent_max = recent_data['Close'].max()
164
- recent_min = recent_data['Close'].min()
165
-
166
- support = min(rolling_min.iloc[-1], recent_min)
167
- resistance = max(rolling_max.iloc[-1], recent_max)
168
-
169
- logger.debug("Support: %f, Resistance: %f", support, resistance)
170
- return support, resistance
171
-
172
- # Prepare data for LSTM model
173
- def prepare_lstm_data(data):
174
- logger.info("Preparing data for LSTM model.")
175
-
176
- features = data[['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']].values
177
- target = data['Close'].values
178
- scaler = MinMaxScaler()
179
- features = scaler.fit_transform(features)
180
-
181
- X, y = [], []
182
- for i in range(len(features) - 60):
183
- X.append(features[i:i+60])
184
- y.append(target[i+60])
185
-
186
- logger.info("Data preparation for LSTM completed.")
187
- return np.array(X), np.array(y)
188
-
189
-
190
- def predict_future_prices(data, algorithm, days=10):
191
- logger.info(f"Predicting future prices using {algorithm}.")
192
-
193
- # Check if required columns are present
194
- required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
195
- missing_columns = [col for col in required_columns if col not in data.columns]
196
-
197
- if missing_columns:
198
- logger.error("Missing columns in data: %s", ', '.join(missing_columns))
199
- raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
200
-
201
- features = data[required_columns]
202
- target = data['Close']
203
-
204
- X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
205
-
206
- mae, r2 = None, None # Initialize variables for metrics
207
-
208
- if algorithm == 'Linear Regression':
209
- model = LinearRegression()
210
-
211
- elif algorithm == 'Decision Tree':
212
- model = DecisionTreeRegressor()
213
-
214
- elif algorithm == 'Random Forest':
215
- model = RandomForestRegressor(n_estimators=100)
216
-
217
- elif algorithm == 'XGBoost':
218
- model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
219
-
220
- elif algorithm == 'CatBoost':
221
- model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
222
-
223
- elif algorithm == 'LSTM':
224
- X, y = prepare_lstm_data(data)
225
- model = Sequential()
226
- model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
227
- model.add(LSTM(50))
228
- model.add(Dense(1))
229
- model.compile(optimizer='adam', loss='mean_squared_error')
230
- model.fit(X, y, epochs=10, batch_size=32, verbose=0)
231
- last_data_point = np.expand_dims(X[-1], axis=0)
232
- future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
233
- logger.info("Future prices predicted using LSTM model.")
234
- return future_prices, None, None, None, None
235
-
236
- elif algorithm == 'ARIMA':
237
- model = ARIMA(data['Close'], order=(5, 1, 0))
238
- model_fit = model.fit()
239
- future_prices = model_fit.forecast(steps=days)
240
-
241
- elif algorithm == 'SARIMA':
242
- model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
243
- model_fit = model.fit()
244
- future_prices = model_fit.forecast(steps=days)
245
-
246
- else:
247
- logger.error("Algorithm not recognized: %s", algorithm)
248
- return None, None, None, None, None
249
-
250
- if algorithm in ['Linear Regression', 'Decision Tree', 'Random Forest', 'XGBoost', 'CatBoost']:
251
- model.fit(X_train, y_train)
252
- predictions = model.predict(X_test)
253
- mae = mean_absolute_error(y_test, predictions)
254
- r2 = r2_score(y_test, predictions)
255
-
256
- future_prices = []
257
- last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
258
-
259
- for _ in range(days):
260
- future_price = model.predict(last_data_point)[0]
261
- future_prices.append(future_price)
262
- last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
263
-
264
- logger.info("Future prices predicted using %s model.", algorithm)
265
- return future_prices, mae, r2, None, None
266
-
267
-
268
-
269
- # def predict_future_prices(data, algorithm, days=10):
270
- # logger.info(f"Predicting future prices using {algorithm}.")
271
-
272
- # # Check if required columns are present
273
- # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
274
- # missing_columns = [col for col in required_columns if col not in data.columns]
275
-
276
- # if missing_columns:
277
- # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
278
- # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
279
-
280
- # features = data[required_columns]
281
- # target = data['Close']
282
-
283
- # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
284
-
285
- # if algorithm == 'Linear Regression':
286
- # model = LinearRegression()
287
-
288
- # elif algorithm == 'Decision Tree':
289
- # model = DecisionTreeRegressor()
290
-
291
- # elif algorithm == 'Random Forest':
292
- # model = RandomForestRegressor(n_estimators=100)
293
-
294
- # elif algorithm == 'XGBoost':
295
- # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
296
-
297
- # elif algorithm == 'CatBoost':
298
- # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
299
-
300
- # elif algorithm == 'LSTM':
301
- # X, y = prepare_lstm_data(data)
302
- # model = Sequential()
303
- # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
304
- # model.add(LSTM(50))
305
- # model.add(Dense(1))
306
- # model.compile(optimizer='adam', loss='mean_squared_error')
307
- # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
308
- # last_data_point = np.expand_dims(X[-1], axis=0)
309
- # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
310
- # logger.info("Future prices predicted using LSTM model.")
311
- # return future_prices, None, None, None, None
312
-
313
- # elif algorithm == 'ARIMA':
314
- # model = ARIMA(data['Close'], order=(5, 1, 0))
315
- # model_fit = model.fit()
316
- # future_prices = model_fit.forecast(steps=days)
317
-
318
- # elif algorithm == 'SARIMA':
319
- # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
320
- # model_fit = model.fit()
321
- # future_prices = model_fit.forecast(steps=days)
322
-
323
- # else:
324
- # logger.error("Algorithm not recognized: %s", algorithm)
325
- # return None, None, None, None, None
326
-
327
- # if algorithm in ['Linear Regression', 'Decision Tree', 'Random Forest', 'XGBoost', 'CatBoost']:
328
- # model.fit(X_train, y_train)
329
- # predictions = model.predict(X_test)
330
- # mae = mean_absolute_error(y_test, predictions)
331
- # r2 = r2_score(y_test, predictions)
332
-
333
- # future_prices = []
334
- # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
335
-
336
- # for _ in range(days):
337
- # future_price = model.predict(last_data_point)[0]
338
- # future_prices.append(future_price)
339
- # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
340
-
341
- # logger.info("Future prices predicted using %s model.", algorithm)
342
- # return future_prices, mae, r2, None, None
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
- # # Predict future prices using the selected algorithm
356
- # def predict_future_prices(data, algorithm, days=10):
357
- # logger.info(f"Predicting future prices using {algorithm}.")
358
-
359
- # # Check if required columns are present
360
- # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
361
- # missing_columns = [col for col in required_columns if col not in data.columns]
362
-
363
- # if missing_columns:
364
- # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
365
- # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
366
-
367
- # features = data[required_columns]
368
- # target = data['Close']
369
-
370
- # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
371
-
372
- # if algorithm == 'Linear Regression':
373
- # model = LinearRegression()
374
- # elif algorithm == 'Decision Tree':
375
- # model = DecisionTreeRegressor()
376
- # elif algorithm == 'Random Forest':
377
- # model = RandomForestRegressor(n_estimators=100)
378
- # elif algorithm == 'XGBoost':
379
- # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
380
- # elif algorithm == 'CatBoost':
381
- # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
382
- # elif algorithm == 'LSTM':
383
-
384
- # X, y = prepare_lstm_data(data)
385
- # model = Sequential()
386
- # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
387
- # model.add(LSTM(50))
388
- # model.add(Dense(1))
389
- # model.compile(optimizer='adam', loss='mean_squared_error')
390
- # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
391
- # last_data_point = np.expand_dims(X[-1], axis=0)
392
- # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
393
-
394
- # elif algorithm == 'ARIMA':
395
- # model = ARIMA(data['Close'], order=(5, 1, 0))
396
- # model_fit = model.fit()
397
- # future_prices = model_fit.forecast(steps=10)
398
-
399
- # elif algorithm == 'SARIMA':
400
- # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
401
- # model_fit = model.fit()
402
- # forecast = model_fit.forecast(steps=10)
403
-
404
- # logger.info("Future prices predicted using LSTM model.")
405
- # return future_prices, None, None, None, None
406
- # else:
407
- # logger.error("Algorithm not recognized: %s", algorithm)
408
- # return None, None, None, None, None
409
-
410
- # model.fit(X_train, y_train)
411
-
412
- # predictions = model.predict(X_test)
413
- # mae = mean_absolute_error(y_test, predictions)
414
- # r2 = r2_score(y_test, predictions)
415
-
416
- # future_prices = []
417
- # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
418
-
419
- # for _ in range(days):
420
- # future_price = model.predict(last_data_point)[0]
421
- # future_prices.append(future_price)
422
- # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
423
-
424
- # logger.info("Future prices predicted using %s model.", algorithm)
425
- # return future_prices, mae, r2, None, None
426
-
427
- # import pandas as pd
428
- # import numpy as np
429
- # import yfinance as yf
430
- # import ta
431
- # from sklearn.model_selection import train_test_split
432
- # from sklearn.linear_model import LinearRegression
433
- # from sklearn.tree import DecisionTreeRegressor
434
- # from sklearn.ensemble import RandomForestRegressor
435
- # from sklearn.metrics import mean_absolute_error, r2_score
436
- # import xgboost as xgb
437
- # from catboost import CatBoostRegressor
438
- # from tensorflow.keras.models import Sequential
439
- # from tensorflow.keras.layers import LSTM, Dense
440
- # from sklearn.preprocessing import MinMaxScaler
441
- # from statsmodels.tsa.arima_model import ARIMA
442
- # from statsmodels.tsa.statespace.sarimax import SARIMAX
443
-
444
- # from logger import get_logger
445
-
446
- # logger = get_logger(__name__)
447
-
448
- # # Fetch historical data
449
- # def fetch_data(ticker, start_date, end_date):
450
- # logger.info(f"Fetching data for {ticker} from {start_date} to {end_date}")
451
- # data = yf.download(ticker, start=start_date, end=end_date)
452
- # if data.empty:
453
- # logger.warning(f"No data returned for {ticker}.")
454
- # return None
455
-
456
- # # Reset index to ensure Date is a column
457
- # data.reset_index(inplace=True)
458
- # logger.info(f"Data fetched successfully for {ticker}.")
459
- # return data
460
-
461
- # def calculate_indicators(data: pd.DataFrame) -> pd.DataFrame:
462
- # logger.info("Calculating indicators with fixed parameters.")
463
-
464
- # # Check if required columns are present
465
- # required_columns = ['Close', 'High', 'Low', 'Volume']
466
- # missing_columns = [col for col in required_columns if col not in data.columns]
467
- # if missing_columns:
468
- # logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
469
- # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
470
-
471
- # # Calculate fixed moving averages
472
- # ma_period = 50 # Fixed period for moving averages
473
- # try:
474
- # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
475
- # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
476
- # except Exception as e:
477
- # logger.error(f"Error calculating moving averages: {e}")
478
- # raise
479
-
480
- # # Calculate other indicators
481
- # try:
482
- # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
483
- # macd = ta.trend.MACD(data['Close'])
484
- # data['MACD'] = macd.macd()
485
- # data['MACD_Signal'] = macd.macd_signal()
486
- # bollinger = ta.volatility.BollingerBands(data['Close'])
487
- # data['Bollinger_High'] = bollinger.bollinger_hband()
488
- # data['Bollinger_Low'] = bollinger.bollinger_lband()
489
- # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
490
- # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
491
- # except Exception as e:
492
- # logger.error(f"Error calculating other indicators: {e}")
493
- # raise
494
-
495
- # # Debugging line to check the columns
496
- # logger.debug("Columns after calculating indicators: %s", data.columns)
497
-
498
- # data = data.dropna()
499
- # logger.info("Indicators calculated successfully.")
500
- # return data
501
-
502
- # # Calculate support and resistance levels
503
- # def calculate_support_resistance(data, window=30):
504
- # logger.info(f"Calculating support and resistance with a window of {window}.")
505
-
506
- # recent_data = data.tail(window)
507
- # rolling_max = data['Close'].rolling(window=window).max()
508
- # rolling_min = data['Close'].rolling(window=window).min()
509
- # recent_max = recent_data['Close'].max()
510
- # recent_min = recent_data['Close'].min()
511
-
512
- # support = min(rolling_min.iloc[-1], recent_min)
513
- # resistance = max(rolling_max.iloc[-1], recent_max)
514
-
515
- # logger.debug("Support: %f, Resistance: %f", support, resistance)
516
- # return support, resistance
517
-
518
- # # Prepare data for LSTM model
519
- # def prepare_lstm_data(data):
520
- # logger.info("Preparing data for LSTM model.")
521
-
522
- # features = data[['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']].values
523
- # target = data['Close'].values
524
- # scaler = MinMaxScaler()
525
- # features = scaler.fit_transform(features)
526
-
527
- # X, y = [], []
528
- # for i in range(len(features) - 60):
529
- # X.append(features[i:i+60])
530
- # y.append(target[i+60])
531
-
532
- # logger.info("Data preparation for LSTM completed.")
533
- # return np.array(X), np.array(y)
534
-
535
- # # Predict future prices using the selected algorithm
536
- # def predict_future_prices(data, algorithm, days=10):
537
- # logger.info(f"Predicting future prices using {algorithm}.")
538
-
539
- # # Check if required columns are present
540
- # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
541
- # missing_columns = [col for col in required_columns if col not in data.columns]
542
-
543
- # if missing_columns:
544
- # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
545
- # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
546
-
547
- # features = data[required_columns]
548
- # target = data['Close']
549
-
550
- # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
551
-
552
- # if algorithm == 'Linear Regression':
553
- # model = LinearRegression()
554
- # elif algorithm == 'Decision Tree':
555
- # model = DecisionTreeRegressor()
556
- # elif algorithm == 'Random Forest':
557
- # model = RandomForestRegressor(n_estimators=100)
558
- # elif algorithm == 'XGBoost':
559
- # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
560
- # elif algorithm == 'CatBoost':
561
- # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
562
- # elif algorithm == 'LSTM':
563
- # X, y = prepare_lstm_data(data)
564
- # model = Sequential()
565
- # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
566
- # model.add(LSTM(50))
567
- # model.add(Dense(1))
568
- # model.compile(optimizer='adam', loss='mean_squared_error')
569
- # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
570
- # last_data_point = np.expand_dims(X[-1], axis=0)
571
- # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
572
-
573
- # logger.info("Future prices predicted using LSTM model.")
574
- # return future_prices, None, None, None, None
575
- # elif algorithm == 'ARIMA':
576
- # model = ARIMA(data['Close'], order=(5, 1, 0))
577
- # model_fit = model.fit(disp=0)
578
- # forecast = model_fit.forecast(steps=days)[0]
579
-
580
- # mae = mean_absolute_error(target[-days:], forecast[:days])
581
- # r2 = r2_score(target[-days:], forecast[:days])
582
-
583
- # logger.info("Future prices predicted using ARIMA model.")
584
- # return forecast.tolist(), mae, r2, None, None
585
- # elif algorithm == 'SARIMA':
586
- # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
587
- # model_fit = model.fit(disp=0)
588
- # forecast = model_fit.forecast(steps=days)
589
-
590
- # mae = mean_absolute_error(target[-days:], forecast[:days])
591
- # r2 = r2_score(target[-days:], forecast[:days])
592
-
593
- # logger.info("Future prices predicted using SARIMA model.")
594
- # return forecast.tolist(), mae, r2, None, None
595
- # else:
596
- # logger.error("Algorithm not recognized: %s", algorithm)
597
- # return None, None, None, None, None
598
-
599
- # model.fit(X_train, y_train)
600
-
601
- # predictions = model.predict(X_test)
602
- # mae = mean_absolute_error(y_test, predictions)
603
- # r2 = r2_score(y_test, predictions)
604
-
605
- # future_prices = []
606
- # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
607
-
608
- # for _ in range(days):
609
- # future_price = model.predict(last_data_point)[0]
610
- # future_prices.append(future_price)
611
- # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
612
-
613
- # logger.info("Future prices predicted using %s model.", algorithm)
614
- # return future_prices, mae, r2, predictions, y_test
615
-
616
-
617
-
618
-
619
- # # model.py
620
-
621
- # import pandas as pd
622
- # import numpy as np
623
- # import yfinance as yf
624
- # import statsmodels.api as sm
625
- # from statsmodels.tsa.arima.model import ARIMA
626
- # from statsmodels.tsa.statespace.sarimax import SARIMAX
627
- # from sklearn.metrics import mean_absolute_error, r2_score
628
-
629
- # def fetch_data(ticker, start_date, end_date):
630
- # try:
631
- # df = yf.download(ticker, start=start_date, end=end_date)
632
- # return df
633
- # except Exception as e:
634
- # print(f"An error occurred while fetching data: {e}")
635
- # return None
636
-
637
- # def calculate_indicators(data):
638
- # # Example indicators - these should be tailored to your requirements
639
- # data['SMA_50'] = data['Close'].rolling(window=50).mean()
640
- # data['EMA_50'] = data['Close'].ewm(span=50, adjust=False).mean()
641
- # data['RSI'] = calculate_rsi(data['Close'])
642
- # data['MACD'], data['MACD_Signal'] = calculate_macd(data['Close'])
643
- # data['Bollinger_High'], data['Bollinger_Low'] = calculate_bollinger_bands(data['Close'])
644
- # data['ATR'] = calculate_atr(data)
645
- # data['OBV'] = calculate_obv(data)
646
- # return data
647
-
648
- # def calculate_rsi(series, period=14):
649
- # delta = series.diff()
650
- # gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
651
- # loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
652
- # rs = gain / loss
653
- # return 100 - (100 / (1 + rs))
654
-
655
- # def calculate_macd(series):
656
- # macd = series.ewm(span=12, adjust=False).mean() - series.ewm(span=26, adjust=False).mean()
657
- # macd_signal = macd.ewm(span=9, adjust=False).mean()
658
- # return macd, macd_signal
659
-
660
- # def calculate_bollinger_bands(series, window=20):
661
- # rolling_mean = series.rolling(window=window).mean()
662
- # rolling_std = series.rolling(window=window).std()
663
- # high = rolling_mean + (rolling_std * 2)
664
- # low = rolling_mean - (rolling_std * 2)
665
- # return high, low
666
-
667
- # def calculate_atr(data, window=14):
668
- # high_low = data['High'] - data['Low']
669
- # high_close = np.abs(data['High'] - data['Close'].shift())
670
- # low_close = np.abs(data['Low'] - data['Close'].shift())
671
- # tr = np.max(np.array([high_low, high_close, low_close]), axis=0)
672
- # atr = tr.rolling(window=window).mean()
673
- # return atr
674
-
675
- # def calculate_obv(data):
676
- # obv = (data['Volume'] * np.sign(data['Close'].diff())).fillna(0).cumsum()
677
- # return obv
678
-
679
- # def calculate_support_resistance(data):
680
- # # Example calculation - you may need to refine this based on your requirements
681
- # support = data['Close'].min()
682
- # resistance = data['Close'].max()
683
- # return support, resistance
684
-
685
- # def predict_future_prices(data, model_type='ARIMA'):
686
- # try:
687
- # # Use ARIMA
688
- # if model_type == 'ARIMA':
689
- # model = ARIMA(data['Close'], order=(5, 1, 0))
690
- # model_fit = model.fit()
691
- # forecast = model_fit.forecast(steps=10)
692
- # # Use SARIMA
693
- # elif model_type == 'SARIMA':
694
- # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
695
- # model_fit = model.fit()
696
- # forecast = model_fit.forecast(steps=10)
697
- # else:
698
- # raise ValueError("Unsupported model type. Use 'ARIMA' or 'SARIMA'.")
699
-
700
- # # Calculate MAE and R2 for evaluation
701
- # y_true = data['Close'][-10:] # last 10 days as true values for comparison
702
- # mae = mean_absolute_error(y_true, forecast[:len(y_true)])
703
- # r2 = r2_score(y_true, forecast[:len(y_true)])
704
-
705
- # # Return results
706
- # return forecast, mae, r2
707
- # except Exception as e:
708
- # print(f"An error occurred while predicting future prices: {e}")
709
- # return None, None, None
710
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import yfinance as yf
3
+ import pandas as pd
4
+ import ta
5
+ from sklearn.model_selection import train_test_split
6
+ from sklearn.linear_model import LinearRegression
7
+ from sklearn.tree import DecisionTreeRegressor
8
+ from sklearn.ensemble import RandomForestRegressor
9
+ from sklearn.metrics import mean_absolute_error, r2_score
10
+ import xgboost as xgb
11
+ from catboost import CatBoostRegressor
12
+ import numpy as np
13
+ from tensorflow.keras.models import Sequential
14
+ from tensorflow.keras.layers import LSTM, Dense
15
+ from sklearn.preprocessing import MinMaxScaler
16
+ from statsmodels.tsa.arima.model import ARIMA
17
+ from statsmodels.tsa.statespace.sarimax import SARIMAX
18
+
19
+
20
+ from logger import get_logger
21
+
22
+ logger = get_logger(__name__)
23
+ # logger.setLevel(logging.DEBUG)
24
+ # handler = logging.StreamHandler()
25
+ # handler.setLevel(logging.DEBUG)
26
+ # formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
27
+ # handler.setFormatter(formatter)
28
+ # logger.addHandler(handler)
29
+
30
+ # # Example usage of logger
31
+ # logger.info("This is an info message")
32
+
33
+ # Fetch historical data
34
+ # def fetch_data(ticker, start_date, end_date):
35
+ # logger.info(f"Fetching data for {ticker} from {start_date} to {end_date}")
36
+ # data = yf.download(ticker, start=start_date, end=end_date)
37
+ # if data.empty:
38
+ # logger.warning(f"No data returned for {ticker}.")
39
+ # return None
40
+
41
+ # # Reset index to ensure Date is a column
42
+ # data.reset_index(inplace=True)
43
+ # logger.info(f"Data fetched successfully for {ticker}.")
44
+ # return data
45
+
46
+
47
+
48
+ def fetch_data(ticker, start_date, end_date):
49
+ logger.info(f"Fetching data for {ticker} from {start_date} to {end_date}")
50
+ data = yf.download(ticker, start=start_date, end=end_date)
51
+
52
+ if data.empty:
53
+ logger.warning(f"No data returned for {ticker}.")
54
+ return None
55
+
56
+ # Reset index to ensure Date is a column
57
+ data.reset_index(inplace=True)
58
+
59
+ # 🔑 Flatten MultiIndex columns if present
60
+ if isinstance(data.columns, pd.MultiIndex):
61
+ data.columns = [col[0] if col[0] != '' else col[1] for col in data.columns]
62
+
63
+ # Ensure "Date" is named correctly
64
+ if 'Date' not in data.columns:
65
+ data.rename(columns={data.columns[0]: 'Date'}, inplace=True)
66
+
67
+ logger.info(f"Data fetched successfully for {ticker}.")
68
+ return data
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+ # def calculate_indicators(data: pd.DataFrame) -> pd.DataFrame:
84
+ # logger.info("Calculating indicators with fixed parameters.")
85
+
86
+ # # Check if required columns are present
87
+ # required_columns = ['Close', 'High', 'Low', 'Volume']
88
+ # missing_columns = [col for col in required_columns if col not in data.columns]
89
+ # if missing_columns:
90
+ # logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
91
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
92
+
93
+ # # Calculate fixed moving averages
94
+ # ma_period = 50 # Fixed period for moving averages
95
+ # try:
96
+ # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
97
+ # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
98
+ # except Exception as e:
99
+ # logger.error(f"Error calculating moving averages: {e}")
100
+ # raise
101
+
102
+ # # Calculate other indicators
103
+ # try:
104
+ # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
105
+ # macd = ta.trend.MACD(data['Close'])
106
+ # data['MACD'] = macd.macd()
107
+ # data['MACD_Signal'] = macd.macd_signal()
108
+ # bollinger = ta.volatility.BollingerBands(data['Close'])
109
+ # data['Bollinger_High'] = bollinger.bollinger_hband()
110
+ # data['Bollinger_Low'] = bollinger.bollinger_lband()
111
+ # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
112
+ # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
113
+ # except Exception as e:
114
+ # logger.error(f"Error calculating other indicators: {e}")
115
+ # raise
116
+
117
+ # # Debugging line to check the columns
118
+ # logger.debug("Columns after calculating indicators: %s", data.columns)
119
+
120
+ # data = data.dropna()
121
+ # logger.info("Indicators calculated successfully.")
122
+ # return data
123
+
124
+ def calculate_indicators(data: pd.DataFrame) -> pd.DataFrame:
125
+ logger.info("Calculating indicators with fixed parameters.")
126
+
127
+ required_columns = ['Close', 'High', 'Low', 'Volume']
128
+ missing_columns = [col for col in required_columns if col not in data.columns]
129
+ if missing_columns:
130
+ logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
131
+ raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
132
+
133
+ # Ensure Series are 1D
134
+ close = pd.Series(data['Close'].values.flatten(), index=data.index)
135
+ high = pd.Series(data['High'].values.flatten(), index=data.index)
136
+ low = pd.Series(data['Low'].values.flatten(), index=data.index)
137
+ volume = pd.Series(data['Volume'].values.flatten(), index=data.index)
138
+
139
+ ma_period = 50
140
+ try:
141
+ data[f'SMA_{ma_period}'] = close.rolling(window=ma_period).mean()
142
+ data[f'EMA_{ma_period}'] = close.ewm(span=ma_period, adjust=False).mean()
143
+ except Exception as e:
144
+ logger.error(f"Error calculating moving averages: {e}")
145
+ raise
146
+
147
+ try:
148
+ data['RSI'] = ta.momentum.RSIIndicator(close).rsi()
149
+
150
+ macd = ta.trend.MACD(close)
151
+ data['MACD'] = macd.macd()
152
+ data['MACD_Signal'] = macd.macd_signal()
153
+
154
+ bollinger = ta.volatility.BollingerBands(close)
155
+ data['Bollinger_High'] = bollinger.bollinger_hband()
156
+ data['Bollinger_Low'] = bollinger.bollinger_lband()
157
+
158
+ atr = ta.volatility.AverageTrueRange(high, low, close)
159
+ data['ATR'] = atr.average_true_range()
160
+
161
+ obv = ta.volume.OnBalanceVolumeIndicator(close, volume)
162
+ data['OBV'] = obv.on_balance_volume()
163
+ except Exception as e:
164
+ logger.error(f"Error calculating other indicators: {e}")
165
+ raise
166
+
167
+ data = data.dropna()
168
+ logger.info("Indicators calculated successfully.")
169
+ return data
170
+
171
+
172
+
173
+ # def calculate_indicators(data: pd.DataFrame, ma_type='SMA', ma_period=50) -> pd.DataFrame:
174
+ # logger.info(f"Calculating indicators with {ma_type} of period {ma_period}.")
175
+
176
+ # # Check if required columns are present
177
+ # required_columns = ['Close', 'High', 'Low', 'Volume']
178
+ # missing_columns = [col for col in required_columns if col not in data.columns]
179
+ # if missing_columns:
180
+ # logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
181
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
182
+
183
+ # # Calculate moving averages
184
+ # if ma_type == 'SMA':
185
+ # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
186
+ # elif ma_type == 'EMA':
187
+ # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
188
+ # else:
189
+ # logger.error(f"Unknown moving average type: {ma_type}")
190
+ # raise ValueError(f"Unknown moving average type: {ma_type}")
191
+
192
+ # # Calculate other indicators
193
+ # try:
194
+ # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
195
+ # macd = ta.trend.MACD(data['Close'])
196
+ # data['MACD'] = macd.macd()
197
+ # data['MACD_Signal'] = macd.macd_signal()
198
+ # bollinger = ta.volatility.BollingerBands(data['Close'])
199
+ # data['Bollinger_High'] = bollinger.bollinger_hband()
200
+ # data['Bollinger_Low'] = bollinger.bollinger_lband()
201
+ # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
202
+ # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
203
+ # except Exception as e:
204
+ # logger.error(f"Error calculating indicators: {e}")
205
+ # raise
206
+
207
+ # Debugging line to check the columns
208
+ logger.debug("Columns after calculating indicators: %s", data.columns)
209
+
210
+ data = data.dropna()
211
+ logger.info("Indicators calculated successfully.")
212
+ return data
213
+
214
+
215
+ # # Calculate technical indicators
216
+ # def calculate_indicators(data, ma_type='SMA', ma_period=50):
217
+ # logger.info(f"Calculating indicators with {ma_type} of period {ma_period}.")
218
+
219
+ # if ma_type == 'SMA':
220
+ # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
221
+ # elif ma_type == 'EMA':
222
+ # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
223
+
224
+ # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
225
+ # macd = ta.trend.MACD(data['Close'])
226
+ # data['MACD'] = macd.macd()
227
+ # data['MACD_Signal'] = macd.macd_signal()
228
+ # bollinger = ta.volatility.BollingerBands(data['Close'])
229
+ # data['Bollinger_High'] = bollinger.bollinger_hband()
230
+ # data['Bollinger_Low'] = bollinger.bollinger_lband()
231
+ # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
232
+ # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
233
+
234
+ # # Debugging line to check the columns
235
+ # logger.debug("Columns after calculating indicators: %s", data.columns)
236
+
237
+ # data = data.dropna()
238
+ # logger.info("Indicators calculated successfully.")
239
+ # return data
240
+
241
+ # Calculate support and resistance levels
242
+ def calculate_support_resistance(data, window=30):
243
+ logger.info(f"Calculating support and resistance with a window of {window}.")
244
+
245
+ recent_data = data.tail(window)
246
+ rolling_max = data['Close'].rolling(window=window).max()
247
+ rolling_min = data['Close'].rolling(window=window).min()
248
+ recent_max = recent_data['Close'].max()
249
+ recent_min = recent_data['Close'].min()
250
+
251
+ support = min(rolling_min.iloc[-1], recent_min)
252
+ resistance = max(rolling_max.iloc[-1], recent_max)
253
+
254
+ logger.debug("Support: %f, Resistance: %f", support, resistance)
255
+ return support, resistance
256
+
257
+ # Prepare data for LSTM model
258
+ def prepare_lstm_data(data):
259
+ logger.info("Preparing data for LSTM model.")
260
+
261
+ features = data[['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']].values
262
+ target = data['Close'].values
263
+ scaler = MinMaxScaler()
264
+ features = scaler.fit_transform(features)
265
+
266
+ X, y = [], []
267
+ for i in range(len(features) - 60):
268
+ X.append(features[i:i+60])
269
+ y.append(target[i+60])
270
+
271
+ logger.info("Data preparation for LSTM completed.")
272
+ return np.array(X), np.array(y)
273
+
274
+
275
+ # def predict_future_prices(data, algorithm, days=10):
276
+ # logger.info(f"Predicting future prices using {algorithm}.")
277
+
278
+ # # Check if required columns are present
279
+ # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
280
+ # missing_columns = [col for col in required_columns if col not in data.columns]
281
+
282
+ # if missing_columns:
283
+ # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
284
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
285
+
286
+ # features = data[required_columns]
287
+ # target = data['Close']
288
+
289
+ # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
290
+
291
+ # mae, r2 = None, None # Initialize variables for metrics
292
+
293
+ # if algorithm == 'Linear Regression':
294
+ # model = LinearRegression()
295
+
296
+ # elif algorithm == 'Decision Tree':
297
+ # model = DecisionTreeRegressor()
298
+
299
+ # elif algorithm == 'Random Forest':
300
+ # model = RandomForestRegressor(n_estimators=100)
301
+
302
+ # elif algorithm == 'XGBoost':
303
+ # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
304
+
305
+ # elif algorithm == 'CatBoost':
306
+ # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
307
+
308
+ # elif algorithm == 'LSTM':
309
+ # X, y = prepare_lstm_data(data)
310
+ # model = Sequential()
311
+ # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
312
+ # model.add(LSTM(50))
313
+ # model.add(Dense(1))
314
+ # model.compile(optimizer='adam', loss='mean_squared_error')
315
+ # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
316
+ # last_data_point = np.expand_dims(X[-1], axis=0)
317
+ # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
318
+ # logger.info("Future prices predicted using LSTM model.")
319
+ # return future_prices, None, None, None, None
320
+
321
+ # elif algorithm == 'ARIMA':
322
+ # model = ARIMA(data['Close'], order=(5, 1, 0))
323
+ # model_fit = model.fit()
324
+ # future_prices = model_fit.forecast(steps=days)
325
+
326
+ # elif algorithm == 'SARIMA':
327
+ # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
328
+ # model_fit = model.fit()
329
+ # future_prices = model_fit.forecast(steps=days)
330
+
331
+ # else:
332
+ # logger.error("Algorithm not recognized: %s", algorithm)
333
+ # return None, None, None, None, None
334
+
335
+ # if algorithm in ['Linear Regression', 'Decision Tree', 'Random Forest', 'XGBoost', 'CatBoost']:
336
+ # model.fit(X_train, y_train)
337
+ # predictions = model.predict(X_test)
338
+ # mae = mean_absolute_error(y_test, predictions)
339
+ # r2 = r2_score(y_test, predictions)
340
+
341
+ # future_prices = []
342
+ # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
343
+
344
+ # for _ in range(days):
345
+ # future_price = model.predict(last_data_point)[0]
346
+ # future_prices.append(future_price)
347
+ # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
348
+
349
+ # logger.info("Future prices predicted using %s model.", algorithm)
350
+ # return future_prices, mae, r2, None, None
351
+
352
+ def predict_future_prices(data, algorithm, days=10):
353
+ logger.info(f"Predicting future prices using {algorithm}.")
354
+
355
+ required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD',
356
+ 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low',
357
+ 'ATR', 'OBV']
358
+ missing_columns = [col for col in required_columns if col not in data.columns]
359
+ if missing_columns:
360
+ logger.error("Missing columns in data: %s", ', '.join(missing_columns))
361
+ raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
362
+
363
+ features = data[required_columns]
364
+ target = data['Close']
365
+
366
+ X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
367
+
368
+ mae, r2 = None, None
369
+
370
+ # ---------------- Classical ML ----------------
371
+ if algorithm == 'Linear Regression':
372
+ model = LinearRegression()
373
+ elif algorithm == 'Decision Tree':
374
+ model = DecisionTreeRegressor()
375
+ elif algorithm == 'Random Forest':
376
+ model = RandomForestRegressor(n_estimators=100)
377
+ elif algorithm == 'XGBoost':
378
+ model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
379
+ elif algorithm == 'CatBoost':
380
+ model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
381
+ # ---------------- Deep Learning ----------------
382
+ elif algorithm == 'LSTM':
383
+ X, y = prepare_lstm_data(data)
384
+ model = Sequential()
385
+ model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
386
+ model.add(LSTM(50))
387
+ model.add(Dense(1))
388
+ model.compile(optimizer='adam', loss='mean_squared_error')
389
+ model.fit(X, y, epochs=10, batch_size=32, verbose=0)
390
+ last_data_point = np.expand_dims(X[-1], axis=0)
391
+ future_prices = []
392
+ for _ in range(days):
393
+ pred = model.predict(last_data_point, verbose=0)[0][0]
394
+ future_prices.append(pred)
395
+ # append pred to sequence (sliding window)
396
+ last_data_point = np.roll(last_data_point, -1, axis=1)
397
+ last_data_point[0, -1, 0] = pred
398
+ return future_prices, None, None, None, None
399
+ # ---------------- Time Series ----------------
400
+ elif algorithm == 'ARIMA':
401
+ model = ARIMA(target, order=(5, 1, 0))
402
+ model_fit = model.fit()
403
+ forecast = model_fit.forecast(steps=days)
404
+ mae = mean_absolute_error(target[-days:], forecast[:len(target[-days:])])
405
+ r2 = r2_score(target[-days:], forecast[:len(target[-days:])])
406
+ return forecast.tolist(), mae, r2, None, None
407
+ elif algorithm == 'SARIMA':
408
+ model = SARIMAX(target, order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
409
+ model_fit = model.fit()
410
+ forecast = model_fit.forecast(steps=days)
411
+ mae = mean_absolute_error(target[-days:], forecast[:len(target[-days:])])
412
+ r2 = r2_score(target[-days:], forecast[:len(target[-days:])])
413
+ return forecast.tolist(), mae, r2, None, None
414
+ else:
415
+ logger.error("Algorithm not recognized: %s", algorithm)
416
+ return None, None, None, None, None
417
+
418
+ # ---------------- Train classical models ----------------
419
+ model.fit(X_train, y_train)
420
+ predictions = model.predict(X_test)
421
+ mae = mean_absolute_error(y_test, predictions)
422
+ r2 = r2_score(y_test, predictions)
423
+
424
+ # Generate simple future predictions using last row
425
+ future_prices = []
426
+ last_data_point = features.iloc[-1].values.reshape(1, -1)
427
+ for _ in range(days):
428
+ pred = model.predict(last_data_point)[0]
429
+ future_prices.append(pred)
430
+ # (⚠️ currently not updating indicators — just repeating last row with new Close)
431
+ last_data_point[0, 0] = pred # replace "Open" or "Close"-proxy with prediction
432
+
433
+ logger.info("Future prices predicted using %s model.", algorithm)
434
+ return future_prices, mae, r2, predictions, y_test
435
+
436
+
437
+ # def predict_future_prices(data, algorithm, days=10):
438
+ # logger.info(f"Predicting future prices using {algorithm}.")
439
+
440
+ # # Check if required columns are present
441
+ # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
442
+ # missing_columns = [col for col in required_columns if col not in data.columns]
443
+
444
+ # if missing_columns:
445
+ # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
446
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
447
+
448
+ # features = data[required_columns]
449
+ # target = data['Close']
450
+
451
+ # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
452
+
453
+ # if algorithm == 'Linear Regression':
454
+ # model = LinearRegression()
455
+
456
+ # elif algorithm == 'Decision Tree':
457
+ # model = DecisionTreeRegressor()
458
+
459
+ # elif algorithm == 'Random Forest':
460
+ # model = RandomForestRegressor(n_estimators=100)
461
+
462
+ # elif algorithm == 'XGBoost':
463
+ # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
464
+
465
+ # elif algorithm == 'CatBoost':
466
+ # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
467
+
468
+ # elif algorithm == 'LSTM':
469
+ # X, y = prepare_lstm_data(data)
470
+ # model = Sequential()
471
+ # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
472
+ # model.add(LSTM(50))
473
+ # model.add(Dense(1))
474
+ # model.compile(optimizer='adam', loss='mean_squared_error')
475
+ # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
476
+ # last_data_point = np.expand_dims(X[-1], axis=0)
477
+ # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
478
+ # logger.info("Future prices predicted using LSTM model.")
479
+ # return future_prices, None, None, None, None
480
+
481
+ # elif algorithm == 'ARIMA':
482
+ # model = ARIMA(data['Close'], order=(5, 1, 0))
483
+ # model_fit = model.fit()
484
+ # future_prices = model_fit.forecast(steps=days)
485
+
486
+ # elif algorithm == 'SARIMA':
487
+ # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
488
+ # model_fit = model.fit()
489
+ # future_prices = model_fit.forecast(steps=days)
490
+
491
+ # else:
492
+ # logger.error("Algorithm not recognized: %s", algorithm)
493
+ # return None, None, None, None, None
494
+
495
+ # if algorithm in ['Linear Regression', 'Decision Tree', 'Random Forest', 'XGBoost', 'CatBoost']:
496
+ # model.fit(X_train, y_train)
497
+ # predictions = model.predict(X_test)
498
+ # mae = mean_absolute_error(y_test, predictions)
499
+ # r2 = r2_score(y_test, predictions)
500
+
501
+ # future_prices = []
502
+ # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
503
+
504
+ # for _ in range(days):
505
+ # future_price = model.predict(last_data_point)[0]
506
+ # future_prices.append(future_price)
507
+ # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
508
+
509
+ # logger.info("Future prices predicted using %s model.", algorithm)
510
+ # return future_prices, mae, r2, None, None
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+ # # Predict future prices using the selected algorithm
524
+ # def predict_future_prices(data, algorithm, days=10):
525
+ # logger.info(f"Predicting future prices using {algorithm}.")
526
+
527
+ # # Check if required columns are present
528
+ # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
529
+ # missing_columns = [col for col in required_columns if col not in data.columns]
530
+
531
+ # if missing_columns:
532
+ # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
533
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
534
+
535
+ # features = data[required_columns]
536
+ # target = data['Close']
537
+
538
+ # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
539
+
540
+ # if algorithm == 'Linear Regression':
541
+ # model = LinearRegression()
542
+ # elif algorithm == 'Decision Tree':
543
+ # model = DecisionTreeRegressor()
544
+ # elif algorithm == 'Random Forest':
545
+ # model = RandomForestRegressor(n_estimators=100)
546
+ # elif algorithm == 'XGBoost':
547
+ # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
548
+ # elif algorithm == 'CatBoost':
549
+ # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
550
+ # elif algorithm == 'LSTM':
551
+
552
+ # X, y = prepare_lstm_data(data)
553
+ # model = Sequential()
554
+ # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
555
+ # model.add(LSTM(50))
556
+ # model.add(Dense(1))
557
+ # model.compile(optimizer='adam', loss='mean_squared_error')
558
+ # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
559
+ # last_data_point = np.expand_dims(X[-1], axis=0)
560
+ # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
561
+
562
+ # elif algorithm == 'ARIMA':
563
+ # model = ARIMA(data['Close'], order=(5, 1, 0))
564
+ # model_fit = model.fit()
565
+ # future_prices = model_fit.forecast(steps=10)
566
+
567
+ # elif algorithm == 'SARIMA':
568
+ # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
569
+ # model_fit = model.fit()
570
+ # forecast = model_fit.forecast(steps=10)
571
+
572
+ # logger.info("Future prices predicted using LSTM model.")
573
+ # return future_prices, None, None, None, None
574
+ # else:
575
+ # logger.error("Algorithm not recognized: %s", algorithm)
576
+ # return None, None, None, None, None
577
+
578
+ # model.fit(X_train, y_train)
579
+
580
+ # predictions = model.predict(X_test)
581
+ # mae = mean_absolute_error(y_test, predictions)
582
+ # r2 = r2_score(y_test, predictions)
583
+
584
+ # future_prices = []
585
+ # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
586
+
587
+ # for _ in range(days):
588
+ # future_price = model.predict(last_data_point)[0]
589
+ # future_prices.append(future_price)
590
+ # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
591
+
592
+ # logger.info("Future prices predicted using %s model.", algorithm)
593
+ # return future_prices, mae, r2, None, None
594
+
595
+ # import pandas as pd
596
+ # import numpy as np
597
+ # import yfinance as yf
598
+ # import ta
599
+ # from sklearn.model_selection import train_test_split
600
+ # from sklearn.linear_model import LinearRegression
601
+ # from sklearn.tree import DecisionTreeRegressor
602
+ # from sklearn.ensemble import RandomForestRegressor
603
+ # from sklearn.metrics import mean_absolute_error, r2_score
604
+ # import xgboost as xgb
605
+ # from catboost import CatBoostRegressor
606
+ # from tensorflow.keras.models import Sequential
607
+ # from tensorflow.keras.layers import LSTM, Dense
608
+ # from sklearn.preprocessing import MinMaxScaler
609
+ # from statsmodels.tsa.arima_model import ARIMA
610
+ # from statsmodels.tsa.statespace.sarimax import SARIMAX
611
+
612
+ # from logger import get_logger
613
+
614
+ # logger = get_logger(__name__)
615
+
616
+ # # Fetch historical data
617
+ # def fetch_data(ticker, start_date, end_date):
618
+ # logger.info(f"Fetching data for {ticker} from {start_date} to {end_date}")
619
+ # data = yf.download(ticker, start=start_date, end=end_date)
620
+ # if data.empty:
621
+ # logger.warning(f"No data returned for {ticker}.")
622
+ # return None
623
+
624
+ # # Reset index to ensure Date is a column
625
+ # data.reset_index(inplace=True)
626
+ # logger.info(f"Data fetched successfully for {ticker}.")
627
+ # return data
628
+
629
+ # def calculate_indicators(data: pd.DataFrame) -> pd.DataFrame:
630
+ # logger.info("Calculating indicators with fixed parameters.")
631
+
632
+ # # Check if required columns are present
633
+ # required_columns = ['Close', 'High', 'Low', 'Volume']
634
+ # missing_columns = [col for col in required_columns if col not in data.columns]
635
+ # if missing_columns:
636
+ # logger.error(f"Missing columns in data: {', '.join(missing_columns)}")
637
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
638
+
639
+ # # Calculate fixed moving averages
640
+ # ma_period = 50 # Fixed period for moving averages
641
+ # try:
642
+ # data[f'SMA_{ma_period}'] = data['Close'].rolling(window=ma_period).mean()
643
+ # data[f'EMA_{ma_period}'] = data['Close'].ewm(span=ma_period, adjust=False).mean()
644
+ # except Exception as e:
645
+ # logger.error(f"Error calculating moving averages: {e}")
646
+ # raise
647
+
648
+ # # Calculate other indicators
649
+ # try:
650
+ # data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
651
+ # macd = ta.trend.MACD(data['Close'])
652
+ # data['MACD'] = macd.macd()
653
+ # data['MACD_Signal'] = macd.macd_signal()
654
+ # bollinger = ta.volatility.BollingerBands(data['Close'])
655
+ # data['Bollinger_High'] = bollinger.bollinger_hband()
656
+ # data['Bollinger_Low'] = bollinger.bollinger_lband()
657
+ # data['ATR'] = ta.volatility.AverageTrueRange(data['High'], data['Low'], data['Close']).average_true_range()
658
+ # data['OBV'] = ta.volume.OnBalanceVolumeIndicator(data['Close'], data['Volume']).on_balance_volume()
659
+ # except Exception as e:
660
+ # logger.error(f"Error calculating other indicators: {e}")
661
+ # raise
662
+
663
+ # # Debugging line to check the columns
664
+ # logger.debug("Columns after calculating indicators: %s", data.columns)
665
+
666
+ # data = data.dropna()
667
+ # logger.info("Indicators calculated successfully.")
668
+ # return data
669
+
670
+ # # Calculate support and resistance levels
671
+ # def calculate_support_resistance(data, window=30):
672
+ # logger.info(f"Calculating support and resistance with a window of {window}.")
673
+
674
+ # recent_data = data.tail(window)
675
+ # rolling_max = data['Close'].rolling(window=window).max()
676
+ # rolling_min = data['Close'].rolling(window=window).min()
677
+ # recent_max = recent_data['Close'].max()
678
+ # recent_min = recent_data['Close'].min()
679
+
680
+ # support = min(rolling_min.iloc[-1], recent_min)
681
+ # resistance = max(rolling_max.iloc[-1], recent_max)
682
+
683
+ # logger.debug("Support: %f, Resistance: %f", support, resistance)
684
+ # return support, resistance
685
+
686
+ # # Prepare data for LSTM model
687
+ # def prepare_lstm_data(data):
688
+ # logger.info("Preparing data for LSTM model.")
689
+
690
+ # features = data[['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']].values
691
+ # target = data['Close'].values
692
+ # scaler = MinMaxScaler()
693
+ # features = scaler.fit_transform(features)
694
+
695
+ # X, y = [], []
696
+ # for i in range(len(features) - 60):
697
+ # X.append(features[i:i+60])
698
+ # y.append(target[i+60])
699
+
700
+ # logger.info("Data preparation for LSTM completed.")
701
+ # return np.array(X), np.array(y)
702
+
703
+ # # Predict future prices using the selected algorithm
704
+ # def predict_future_prices(data, algorithm, days=10):
705
+ # logger.info(f"Predicting future prices using {algorithm}.")
706
+
707
+ # # Check if required columns are present
708
+ # required_columns = ['Open', 'SMA_50', 'EMA_50', 'RSI', 'MACD', 'MACD_Signal', 'Bollinger_High', 'Bollinger_Low', 'ATR', 'OBV']
709
+ # missing_columns = [col for col in required_columns if col not in data.columns]
710
+
711
+ # if missing_columns:
712
+ # logger.error("Missing columns in data: %s", ', '.join(missing_columns))
713
+ # raise KeyError(f"Missing columns in data: {', '.join(missing_columns)}")
714
+
715
+ # features = data[required_columns]
716
+ # target = data['Close']
717
+
718
+ # X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)
719
+
720
+ # if algorithm == 'Linear Regression':
721
+ # model = LinearRegression()
722
+ # elif algorithm == 'Decision Tree':
723
+ # model = DecisionTreeRegressor()
724
+ # elif algorithm == 'Random Forest':
725
+ # model = RandomForestRegressor(n_estimators=100)
726
+ # elif algorithm == 'XGBoost':
727
+ # model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse')
728
+ # elif algorithm == 'CatBoost':
729
+ # model = CatBoostRegressor(learning_rate=0.1, depth=6, iterations=500, verbose=0)
730
+ # elif algorithm == 'LSTM':
731
+ # X, y = prepare_lstm_data(data)
732
+ # model = Sequential()
733
+ # model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
734
+ # model.add(LSTM(50))
735
+ # model.add(Dense(1))
736
+ # model.compile(optimizer='adam', loss='mean_squared_error')
737
+ # model.fit(X, y, epochs=10, batch_size=32, verbose=0)
738
+ # last_data_point = np.expand_dims(X[-1], axis=0)
739
+ # future_prices = [model.predict(last_data_point)[0][0] for _ in range(days)]
740
+
741
+ # logger.info("Future prices predicted using LSTM model.")
742
+ # return future_prices, None, None, None, None
743
+ # elif algorithm == 'ARIMA':
744
+ # model = ARIMA(data['Close'], order=(5, 1, 0))
745
+ # model_fit = model.fit(disp=0)
746
+ # forecast = model_fit.forecast(steps=days)[0]
747
+
748
+ # mae = mean_absolute_error(target[-days:], forecast[:days])
749
+ # r2 = r2_score(target[-days:], forecast[:days])
750
+
751
+ # logger.info("Future prices predicted using ARIMA model.")
752
+ # return forecast.tolist(), mae, r2, None, None
753
+ # elif algorithm == 'SARIMA':
754
+ # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
755
+ # model_fit = model.fit(disp=0)
756
+ # forecast = model_fit.forecast(steps=days)
757
+
758
+ # mae = mean_absolute_error(target[-days:], forecast[:days])
759
+ # r2 = r2_score(target[-days:], forecast[:days])
760
+
761
+ # logger.info("Future prices predicted using SARIMA model.")
762
+ # return forecast.tolist(), mae, r2, None, None
763
+ # else:
764
+ # logger.error("Algorithm not recognized: %s", algorithm)
765
+ # return None, None, None, None, None
766
+
767
+ # model.fit(X_train, y_train)
768
+
769
+ # predictions = model.predict(X_test)
770
+ # mae = mean_absolute_error(y_test, predictions)
771
+ # r2 = r2_score(y_test, predictions)
772
+
773
+ # future_prices = []
774
+ # last_data_point = features.iloc[-1].values.reshape(1, -1) # Ensure it's 2D
775
+
776
+ # for _ in range(days):
777
+ # future_price = model.predict(last_data_point)[0]
778
+ # future_prices.append(future_price)
779
+ # last_data_point = last_data_point + 1 # Update last data point (simplified, better methods should be used)
780
+
781
+ # logger.info("Future prices predicted using %s model.", algorithm)
782
+ # return future_prices, mae, r2, predictions, y_test
783
+
784
+
785
+
786
+
787
+ # # model.py
788
+
789
+ # import pandas as pd
790
+ # import numpy as np
791
+ # import yfinance as yf
792
+ # import statsmodels.api as sm
793
+ # from statsmodels.tsa.arima.model import ARIMA
794
+ # from statsmodels.tsa.statespace.sarimax import SARIMAX
795
+ # from sklearn.metrics import mean_absolute_error, r2_score
796
+
797
+ # def fetch_data(ticker, start_date, end_date):
798
+ # try:
799
+ # df = yf.download(ticker, start=start_date, end=end_date)
800
+ # return df
801
+ # except Exception as e:
802
+ # print(f"An error occurred while fetching data: {e}")
803
+ # return None
804
+
805
+ # def calculate_indicators(data):
806
+ # # Example indicators - these should be tailored to your requirements
807
+ # data['SMA_50'] = data['Close'].rolling(window=50).mean()
808
+ # data['EMA_50'] = data['Close'].ewm(span=50, adjust=False).mean()
809
+ # data['RSI'] = calculate_rsi(data['Close'])
810
+ # data['MACD'], data['MACD_Signal'] = calculate_macd(data['Close'])
811
+ # data['Bollinger_High'], data['Bollinger_Low'] = calculate_bollinger_bands(data['Close'])
812
+ # data['ATR'] = calculate_atr(data)
813
+ # data['OBV'] = calculate_obv(data)
814
+ # return data
815
+
816
+ # def calculate_rsi(series, period=14):
817
+ # delta = series.diff()
818
+ # gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
819
+ # loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
820
+ # rs = gain / loss
821
+ # return 100 - (100 / (1 + rs))
822
+
823
+ # def calculate_macd(series):
824
+ # macd = series.ewm(span=12, adjust=False).mean() - series.ewm(span=26, adjust=False).mean()
825
+ # macd_signal = macd.ewm(span=9, adjust=False).mean()
826
+ # return macd, macd_signal
827
+
828
+ # def calculate_bollinger_bands(series, window=20):
829
+ # rolling_mean = series.rolling(window=window).mean()
830
+ # rolling_std = series.rolling(window=window).std()
831
+ # high = rolling_mean + (rolling_std * 2)
832
+ # low = rolling_mean - (rolling_std * 2)
833
+ # return high, low
834
+
835
+ # def calculate_atr(data, window=14):
836
+ # high_low = data['High'] - data['Low']
837
+ # high_close = np.abs(data['High'] - data['Close'].shift())
838
+ # low_close = np.abs(data['Low'] - data['Close'].shift())
839
+ # tr = np.max(np.array([high_low, high_close, low_close]), axis=0)
840
+ # atr = tr.rolling(window=window).mean()
841
+ # return atr
842
+
843
+ # def calculate_obv(data):
844
+ # obv = (data['Volume'] * np.sign(data['Close'].diff())).fillna(0).cumsum()
845
+ # return obv
846
+
847
+ # def calculate_support_resistance(data):
848
+ # # Example calculation - you may need to refine this based on your requirements
849
+ # support = data['Close'].min()
850
+ # resistance = data['Close'].max()
851
+ # return support, resistance
852
+
853
+ # def predict_future_prices(data, model_type='ARIMA'):
854
+ # try:
855
+ # # Use ARIMA
856
+ # if model_type == 'ARIMA':
857
+ # model = ARIMA(data['Close'], order=(5, 1, 0))
858
+ # model_fit = model.fit()
859
+ # forecast = model_fit.forecast(steps=10)
860
+ # # Use SARIMA
861
+ # elif model_type == 'SARIMA':
862
+ # model = SARIMAX(data['Close'], order=(5, 1, 0), seasonal_order=(1, 1, 0, 12))
863
+ # model_fit = model.fit()
864
+ # forecast = model_fit.forecast(steps=10)
865
+ # else:
866
+ # raise ValueError("Unsupported model type. Use 'ARIMA' or 'SARIMA'.")
867
+
868
+ # # Calculate MAE and R2 for evaluation
869
+ # y_true = data['Close'][-10:] # last 10 days as true values for comparison
870
+ # mae = mean_absolute_error(y_true, forecast[:len(y_true)])
871
+ # r2 = r2_score(y_true, forecast[:len(y_true)])
872
+
873
+ # # Return results
874
+ # return forecast, mae, r2
875
+ # except Exception as e:
876
+ # print(f"An error occurred while predicting future prices: {e}")
877
+ # return None, None, None
878
+
879
+
880
+
881
+
882
+
883
+