| import os |
| from datetime import datetime, timedelta |
| import ccxt |
| import pandas as pd |
| |
| import calendar |
| |
| from scipy.signal import savgol_filter |
| from pykalman import KalmanFilter |
|
|
|
|
| class HistoricalDataFetcher: |
|
|
| def __init__(self, |
| exchange_name='coinbasepro', |
| symbol='BTC/USD', |
| timeframe='1d', |
| start_date=datetime(2015, 7, 1), |
| end_date=datetime.now()): |
| self.exchange = getattr(ccxt, exchange_name)() |
| self.symbol = symbol |
| self.timeframe = timeframe |
| self.start_date = start_date |
| self.end_date = end_date |
| self.raw_path = f"data/{self.symbol.replace('/','')}" |
| self.clean_path = f"data/clean_{self.symbol.replace('/','')}" |
|
|
| |
| if not os.path.exists(self.raw_path): |
| os.makedirs(self.raw_path) |
| |
| if not os.path.exists(self.clean_path): |
| os.makedirs(self.clean_path) |
|
|
| def fetch_data(self): |
| start_date = self.start_date |
| end_date = self.end_date |
|
|
| while start_date < end_date: |
|
|
| year = start_date.year |
| month = start_date.month |
|
|
| |
| num_days = calendar.monthrange(year, month)[1] |
|
|
| |
| since = self.exchange.parse8601( |
| start_date.strftime('%Y-%m-%d') + 'T00:00:00Z') |
| until = self.exchange.parse8601( |
| (start_date + timedelta(days=num_days)).strftime('%Y-%m-%d') + |
| 'T23:59:59Z') |
|
|
| print(f"Fetching data for {calendar.month_name[month]} {year}") |
|
|
| |
| ohlcv = self.exchange.fetch_ohlcv(self.symbol, |
| self.timeframe, |
| since, |
| limit=None, |
| params={'end': until}) |
|
|
| |
| df = pd.DataFrame( |
| ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) |
|
|
| |
| df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') |
| df.set_index('timestamp', inplace=True) |
|
|
| |
| filename = f"{self.symbol.replace('/','')}_{self.timeframe}_{start_date.strftime('%Y%m')}.csv" |
| file_path = os.path.join(self.raw_path, filename) |
|
|
| df.to_csv(file_path) |
|
|
| print(f"Data saved to {filename}") |
|
|
| |
| start_date = start_date.replace(day=1) + timedelta(days=32) |
| start_date = start_date.replace(day=1) |
|
|
| def get_data(self): |
| |
| data_files = os.listdir(self.raw_path) |
| |
| data_frames = [] |
|
|
| |
| for file_name in data_files: |
| if file_name.endswith(".csv"): |
| file_path = os.path.join(self.raw_path, file_name) |
| data = pd.read_csv(file_path, index_col=0, parse_dates=True) |
| data_frames.append(data) |
|
|
| |
| all_data = pd.concat(data_frames) |
| return all_data |
|
|
| def apply_filters(self, |
| data, |
| window_size=11, |
| polyorder=2, |
| kalman_observation_covariance=0.003, |
| kalman_transition_covariance=0.01, |
| kalman_initial_state_covariance=1000): |
|
|
| |
| alpha = 0.5 |
| data['close_ewm'] = data['close'].ewm(alpha=alpha, adjust=False).mean() |
|
|
| |
| kf = KalmanFilter(observation_covariance=kalman_observation_covariance, |
| transition_covariance=kalman_transition_covariance, |
| initial_state_covariance=kalman_initial_state_covariance, |
| n_dim_obs=1) |
| data['close_kf'], _ = kf.filter(data['close'].values) |
|
|
| |
| data['close_savgol'] = savgol_filter(data['close'], window_size, polyorder) |
|
|
| |
| filename = f"{self.symbol.replace('/','')}_{self.timeframe}_{self.start_date.strftime('%Y%m')}_cleaned.csv" |
| file_path = os.path.join(self.clean_path, filename) |
|
|
| data.to_csv(file_path) |
|
|
| return data |
|
|