├── BitfinexDataToLocalMSQ ├── DB_Local_utils_Get.py ├── DB_Local_utils_load.py ├── GlobalObjects.py ├── database_fresh.py ├── database_update.py ├── print_all_symbols.py └── print_coins_picked_by_amt.py ├── README.md ├── 创建_更新.png └── 说明文档.png /BitfinexDataToLocalMSQ/DB_Local_utils_Get.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from sqlalchemy import create_engine, inspect 3 | 4 | pd.set_option('expand_frame_repr', False) 5 | pd.set_option('max_rows', 20) 6 | 7 | 8 | def DB_get_one_field_all(db_name='cc_bitfinex_hd_1d', field='close', indextostr=True, indextostrdigits=10): 9 | engine = create_engine(f'mysql://root:123456@localhost/{db_name}') 10 | inspector = inspect(engine) 11 | list_table = inspector.get_table_names() 12 | list_table.sort() 13 | list_coin = [i.split('_')[0] for i in list_table] 14 | result_DF = pd.DataFrame() 15 | for table, coin in zip(list_table, list_coin): 16 | data = pd.read_sql_table(table_name=table, con=engine) 17 | data.index = data['time'] 18 | result = data[field] 19 | result.name = coin 20 | result_DF = pd.concat([result_DF, result], axis=1, sort=False) 21 | if indextostr: 22 | result_DF.index = pd.Series(result_DF.index).apply(lambda x: str(x)[:indextostrdigits]) 23 | return result_DF 24 | 25 | 26 | def DB_get_one_field_forList(db_name, field, coin_list, indextostr=True, indextostrdigits=10): 27 | engine = create_engine(f'mysql://root:123456@localhost/{db_name}') 28 | inspector = inspect(engine) 29 | list_table = inspector.get_table_names() 30 | list_table.sort() 31 | list_coin = [i.split('_')[0] for i in list_table] 32 | result_DF = pd.DataFrame() 33 | for table, coin in zip(list_table, list_coin): 34 | if coin in coin_list: 35 | data = pd.read_sql_table(table_name=table, con=engine) 36 | data.index = data['time'] 37 | result = data[field] 38 | result.name = coin 39 | result_DF = pd.concat([result_DF, result], axis=1, sort=False) 40 | if indextostr: 41 | result_DF.index = pd.Series(result_DF.index).apply(lambda x: str(x)[:indextostrdigits]) 42 | return result_DF 43 | 44 | 45 | def DB_get_usd_AMT_all(db_name='cc_bitfinex_hd_1d', indextostr=True, indextostrdigits=10): 46 | engine = create_engine(f'mysql://root:123456@localhost/{db_name}') 47 | inspector = inspect(engine) 48 | list_table = inspector.get_table_names() 49 | list_table.sort() 50 | list_coin = [i.split('_')[0] for i in list_table] 51 | result_DF = pd.DataFrame() 52 | for table, coin in zip(list_table, list_coin): 53 | data = pd.read_sql_table(table_name=table, con=engine) 54 | data['avgp'] = data[['open', 'high', 'low', 'close']].mean(axis=1) 55 | data['amt'] = data['avgp'] * data['volume'] 56 | data.index = data['time'] 57 | result = data['amt'] 58 | result.name = coin 59 | result_DF = pd.concat([result_DF, result], axis=1, sort=False) 60 | if indextostr: 61 | result_DF.index = pd.Series(result_DF.index).apply(lambda x: str(x)[:indextostrdigits]) 62 | return result_DF 63 | 64 | 65 | def DB_get_usd_AMT_forList(db_name, coin_list, indextostr=True, indextostrdigits=10): 66 | engine = create_engine(f'mysql://root:123456@localhost/{db_name}') 67 | inspector = inspect(engine) 68 | list_table = inspector.get_table_names() 69 | list_table.sort() 70 | list_coin = [i.split('_')[0] for i in list_table] 71 | result_DF = pd.DataFrame() 72 | for table, coin in zip(list_table, list_coin): 73 | if coin in coin_list: 74 | data = pd.read_sql_table(table_name=table, con=engine) 75 | data['avgp'] = data[['open', 'high', 'low', 'close']].mean(axis=1) 76 | data['amt'] = data['avgp'] * data['volume'] 77 | data.index = data['time'] 78 | result = data['amt'] 79 | result.name = coin 80 | result_DF = pd.concat([result_DF, result], axis=1, sort=False) 81 | if indextostr: 82 | result_DF.index = pd.Series(result_DF.index).apply(lambda x: str(x)[:indextostrdigits]) 83 | return result_DF 84 | -------------------------------------------------------------------------------- /BitfinexDataToLocalMSQ/DB_Local_utils_load.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | import pandas as pd 3 | import datetime 4 | import time 5 | 6 | 7 | def local_db_exists(db_name): 8 | ''' 9 | 检测本地mysql数据库是否含有数据库 db_name 10 | :param db_name: str 11 | :return: bool 12 | ''' 13 | check_engine = create_engine('mysql://root:123456@localhost') 14 | try: 15 | check_engine.execute(f"use {db_name}") 16 | return True 17 | except: 18 | return False 19 | 20 | 21 | def local_fresh_db_con(db_name_title): 22 | ''' 23 | 在本地mysql数据库新建一个数据库,数据库名为 db_name_title 加上当天日期字符串 24 | :param db_name_title: str 25 | :return: [一个指向新建好的数据库的 sqlalchemy 链接,新数据名字字符串] 26 | ''' 27 | db_name = db_name_title + '_' + str(datetime.datetime.now())[:10].replace('-', '_') 28 | engine = create_engine('mysql://root:123456@localhost') 29 | if local_db_exists(db_name=db_name): 30 | engine.execute(f"drop database {db_name}") 31 | engine.execute(f"create database {db_name}") 32 | else: 33 | engine.execute(f"create database {db_name}") 34 | engine.execute(f"use {db_name}") 35 | return [engine, db_name] 36 | 37 | 38 | def cal_time_delta(timeframe): 39 | ''' 40 | 将字符串时间间隔转换成pandas.Timedelta对象 41 | ''' 42 | frame = timeframe[-1] 43 | unit = int(timeframe[:-1]) 44 | if frame == 'm': 45 | return pd.Timedelta(minutes=unit) 46 | elif frame == 'h': 47 | return pd.Timedelta(hours=unit) 48 | elif frame == 'd': 49 | return pd.Timedelta(days=unit) 50 | else: 51 | return None 52 | 53 | 54 | def ccxt_fetch_start_k_data(exchange, symbol, timeframe, limit, time_sh_utc_hours_diff): 55 | ''' 56 | 获取exchange交易所内symbol交易对最初的limit根timeframe K线数据 57 | :param exchange: ccxt的exchange对象 58 | :param symbol: 字符串,例如"BTC/USD" 59 | :param timeframe: 字符串,例如"5m"、"1d" 60 | :param limit: 整形,例如1000 61 | :param time_sh_utc_hours_diff: int,当地时间与utc时间的小时差,例如在上海就选择8 62 | :return: pandas.DataFrame,其中的时间(time)为当地时间 63 | ''' 64 | data = exchange.fetch_ohlcv(symbol=symbol, timeframe=timeframe, limit=limit, since=0) 65 | result = pd.DataFrame(data) 66 | result.columns = ['time', 'open', 'high', 'low', 'close', 'volume'] 67 | if timeframe[-1] != 'd': 68 | result['time'] = pd.to_datetime(result['time'], unit='ms') + pd.Timedelta(hours=time_sh_utc_hours_diff) 69 | result['time'] = pd.to_datetime(result['time'], unit='ms') 70 | result.drop_duplicates(subset=['time'], inplace=True) 71 | result.sort_values(by=['time'], ascending=True, inplace=True) 72 | result = result.iloc[:-1, :] 73 | return result 74 | 75 | 76 | def ccxt_fetch_continue_k_data(exchange, symbol, timeframe, start_time_str, time_sh_utc_hours_diff, limit): 77 | ''' 78 | 获取exchange交易所内symbol交易对从当地时间start_time_str开始的limit根timeframe K线数据 79 | :param exchange: ccxt的exchange对象 80 | :param symbol: 字符串,例如"BTC/USD" 81 | :param timeframe: 字符串,例如"5m"、"1d" 82 | :param start_time_str: 字符串,例如"2019-01-01" 83 | :param time_sh_utc_hours_diff: int,当地时间与utc时间的小时差,例如在上海就选择8 84 | :param limit: 整形,例如1000 85 | :return: pandas.DataFrame,其中的时间(time)为当地时间 86 | ''' 87 | local_timestamp = pd.to_datetime(start_time_str).timestamp() 88 | utc_timestamp = local_timestamp - time_sh_utc_hours_diff * 60 * 60 89 | data = exchange.fetch_ohlcv(symbol=symbol, timeframe=timeframe, limit=limit, since=utc_timestamp * 1000) 90 | result = pd.DataFrame(data) 91 | result.columns = ['time', 'open', 'high', 'low', 'close', 'volume'] 92 | if timeframe[-1] != 'd': 93 | result['time'] = pd.to_datetime(result['time'], unit='ms') + pd.Timedelta(hours=time_sh_utc_hours_diff) 94 | result['time'] = pd.to_datetime(result['time'], unit='ms') 95 | result.drop_duplicates(subset=['time'], inplace=True) 96 | result.sort_values(by=['time'], ascending=True, inplace=True) 97 | result = result.iloc[:-1, :] 98 | return result 99 | 100 | 101 | def local_table_fresh(exchange, symbol, timeframe, db_con, time_sh_utc_hours_diff): 102 | ''' 103 | 在db_con指向的本地mysql数据库中下载exchange交易所symbol交易对的timeframe K线数据 104 | :param exchange: ccxt的exchange对象 105 | :param symbol: 字符串,例如"BTC/USD" 106 | :param timeframe: 字符串,例如"5m"、"1d" 107 | :param db_con: sqlalchemy.create_engine()创建的链接 108 | :param time_sh_utc_hours_diff: int,当地时间与utc时间的小时差,例如在上海就选择8 109 | :return: 此函数会将symbol交易对在当前时间前两天之前的所有历史数据全部下载到本地的mysql数据库,直到出现网络异常或者下载完全之后停止。 110 | ''' 111 | name_table = ('_'.join(symbol.split('/')) + '_' + timeframe).lower() 112 | db_date = str(datetime.datetime.now() - pd.Timedelta(days=2))[:10] 113 | df_first = run_function_till_success(function=lambda: ccxt_fetch_start_k_data(exchange=exchange, symbol=symbol, timeframe=timeframe, limit=1000, time_sh_utc_hours_diff=time_sh_utc_hours_diff), tryTimes=5, sleepTimes=1)[0] 114 | df_first.to_sql(name=name_table, if_exists='replace', con=db_con, index=False) 115 | stop = 0 116 | while True: 117 | if stop >= 2: 118 | break 119 | try: 120 | query = f'select * from {name_table} order by time desc limit 5' 121 | record_last = pd.read_sql(sql=query, con=db_con).sort_values(by=['time'], ascending=True) 122 | time_last = str(record_last['time'].iloc[-1]) 123 | print(f'loading {symbol} {timeframe} {time_last}') 124 | if time_last[:10] >= db_date: 125 | break 126 | time_delta = cal_time_delta(timeframe=timeframe) 127 | data_new = run_function_till_success(function=lambda: ccxt_fetch_continue_k_data(exchange=exchange, symbol=symbol, timeframe=timeframe, start_time_str=str(pd.to_datetime(time_last) + time_delta), time_sh_utc_hours_diff=time_sh_utc_hours_diff, limit=1000), tryTimes=5, sleepTimes=1)[0] 128 | if data_new.empty: 129 | break 130 | else: 131 | data_new.to_sql(name=name_table, con=db_con, if_exists='append', index=False) 132 | except: 133 | stop += 1 134 | else: 135 | time.sleep(3) 136 | 137 | 138 | def local_table_update(exchange, symbol, timeframe, db_name, time_sh_utc_hours_diff): 139 | ''' 140 | 更新db_name数据库中exchange交易所symbol交易对的timeframe K线数据 141 | :param exchange: ccxt的exchange对象 142 | :param symbol: 字符串,例如"BTC/USD" 143 | :param timeframe: 字符串,例如"5m"、"1d" 144 | :param db_name: str,数据库名字 145 | :param time_sh_utc_hours_diff: int,当地时间与utc时间的小时差,例如在上海就选择8 146 | :return: 此函数会将symbol交易对在当前时间前两天之前的所有历史数据进行更新,即下载目前未下载到的数据并且保存到本地的mysql数据库,直到出现网络异常或者下载完全之后停止。 147 | ''' 148 | name_table = ('_'.join(symbol.split('/')) + '_' + timeframe).lower() 149 | engine = create_engine('mysql://root:123456@localhost') 150 | engine.execute(f"use {db_name}") 151 | db_date = str(datetime.datetime.now() - pd.Timedelta(days=2))[:10] 152 | stop = 0 153 | while True: 154 | if stop >= 2: 155 | break 156 | try: 157 | query = f'select * from {name_table} order by time desc limit 5' 158 | record_last = pd.read_sql(sql=query, con=engine).sort_values(by=['time'], ascending=True) 159 | time_last = str(record_last['time'].iloc[-1]) 160 | print(f'loading {symbol} {timeframe} {time_last}') 161 | if time_last[:10] >= db_date: 162 | break 163 | time_delta = cal_time_delta(timeframe=timeframe) 164 | data_new = run_function_till_success(function=lambda: ccxt_fetch_continue_k_data(exchange=exchange, symbol=symbol, timeframe=timeframe, start_time_str=str(pd.to_datetime(time_last) + time_delta), time_sh_utc_hours_diff=time_sh_utc_hours_diff, limit=1000), tryTimes=5, sleepTimes=1)[0] 165 | if data_new.empty: 166 | break 167 | else: 168 | data_new.to_sql(name=name_table, con=engine, if_exists='append', index=False) 169 | except: 170 | stop += 1 171 | else: 172 | time.sleep(3) 173 | 174 | 175 | def run_function_till_success(function, tryTimes, sleepTimes): 176 | retry = 0 177 | while True: 178 | if retry > tryTimes: 179 | return False 180 | try: 181 | result = function() 182 | return [result, retry] 183 | except: 184 | retry += 1 185 | time.sleep(sleepTimes) 186 | 187 | 188 | def revert_dict(dict_original): 189 | assert len(set(dict_original.values())) == len(dict_original), 'original dict values must be different' 190 | return {v: k for k, v in dict_original.items()} 191 | 192 | 193 | def list_dict_values(dict_original): 194 | return list(dict_original.values()) 195 | 196 | 197 | def list_dict_keys(dict_original): 198 | return list(dict_original.keys()) 199 | 200 | 201 | def dict_extract_by_keys(dict_the, list_the): 202 | return {k: dict_the.get(k) for k in list_the if k in list_dict_keys(dict_the)} 203 | 204 | 205 | def run_function_list(object_list): 206 | wait_obj_list = object_list.copy() 207 | stop = 0 208 | while wait_obj_list and stop < 2: 209 | prenum = len(wait_obj_list) 210 | do_list = wait_obj_list.copy() 211 | wait_obj_list = [] 212 | for obj in do_list: 213 | try: 214 | obj.call_run_function_list() 215 | print('completed', obj.symbol, sep='\t') 216 | except: 217 | wait_obj_list.append(obj) 218 | print(obj.symbol, '-' * 100) 219 | if prenum == len(wait_obj_list): 220 | stop += 1 221 | elif prenum > len(wait_obj_list): 222 | stop = 0 223 | print('this loop remain: ', '-' * 100) 224 | print([i.symbol for i in wait_obj_list]) 225 | print('finally remain: ', '-' * 100) 226 | print([i.symbol for i in wait_obj_list]) 227 | return wait_obj_list 228 | 229 | 230 | class CallTableFresh: 231 | def __init__(self, symbol, exchange, timeframe, time_sh_utc_hours_diff, db_con): 232 | self.symbol = symbol 233 | self.exchange = exchange 234 | self.timeframe = timeframe 235 | self.time_sh_utc_hours_diff = time_sh_utc_hours_diff 236 | self.db_con = db_con 237 | 238 | def call_run_function_list(self): 239 | local_table_fresh(exchange=self.exchange, symbol=self.symbol, timeframe=self.timeframe, db_con=self.db_con, time_sh_utc_hours_diff=self.time_sh_utc_hours_diff) 240 | 241 | 242 | class CallTableUpdate: 243 | def __init__(self, symbol, exchange, timeframe, db_name, time_sh_utc_hours_diff): 244 | self.symbol = symbol 245 | self.exchange = exchange 246 | self.timeframe = timeframe 247 | self.db_name = db_name 248 | self.time_sh_utc_hours_diff = time_sh_utc_hours_diff 249 | 250 | def call_run_function_list(self): 251 | local_table_update(exchange=self.exchange, symbol=self.symbol, timeframe=self.timeframe, db_name=self.db_name, time_sh_utc_hours_diff=self.time_sh_utc_hours_diff) 252 | -------------------------------------------------------------------------------- /BitfinexDataToLocalMSQ/GlobalObjects.py: -------------------------------------------------------------------------------- 1 | # symbols_usd, coins_picked的生成见print_all_symbols.py和print_coins_picked_by_amt.py 2 | 3 | symbols_usd = ['ABYSS/USD', 'AGI/USD', 'AID/USD', 'AION/USD', 'ANT/USD', 'ATMI/USD', 'AUC/USD', 'AVT/USD', 'BAT/USD', 'BBN/USD', 'BCHABC/USD', 'BCHSV/USD', 'BCI/USD', 'BFT/USD', 'BNT/USD', 'BOX/USD', 'BTC/USD', 'BTG/USD', 'CBT/USD', 'CFI/USD', 'CND/USD', 'CNN/USD', 'CSX/USD', 'CTXC/USD', 'DADI/USD', 'DAI/USD', 'DASH/USD', 'DATA/USD', 'DGB/USD', 'DGX/USD', 'DRN/USD', 'DTA/USD', 'DTH/USD', 'EDO/USD', 'ELF/USD', 'ENJ/USD', 'EOS/USD', 'ESS/USD', 'ETC/USD', 'ETH/USD', 'ETP/USD', 'EUT/USD', 'FSN/USD', 'FUN/USD', 'GNT/USD', 'GOT/USD', 'GSD/USD', 'INT/USD', 'IOST/USD', 'IOTA/USD','IQ/USD', 'KNC/USD', 'LRC/USD', 'LTC/USD', 'LYM/USD', 'MAN/USD', 'MANA/USD', 'MGO/USD', 'MITH/USD', 'MKR/USD', 'MLN/USD', 'MTN/USD', 'NCASH/USD', 'NEO/USD', 'NIO/USD', 'ODE/USD', 'OMG/USD', 'OMN/USD', 'ONL/USD', 'PAI/USD', 'PAX/USD', 'PNK/USD', 'POA/USD', 'POLY/USD', 'QASH/USD', 'QTUM/USD', 'RBT/USD', 'RCN/USD', 'RDN/USD', 'REP/USD', 'REQ/USD', 'RLC/USD', 'RRT/USD', 'RTE/USD', 'SAN/USD', 'SEER/USD', 'SEN/USD', 'SNGLS/USD', 'SNT/USD', 'SPANK/USD', 'STORJ/USD', 'TKN/USD', 'TNB/USD', 'TRX/USD', 'TSD/USD', 'UDC/USD', 'UST/USD', 'UTK/USD', 'UTNP/USD', 'VEE/USD','VET/USD', 'VLD/USD', 'WAX/USD', 'WLO/USD', 'WPR/USD', 'WTC/USD', 'XLM/USD', 'XMR/USD', 'XRA/USD', 'XRP/USD', 'XTZ/USD', 'XVG/USD', 'YGG/USD', 'YOYOW/USD', 'ZCN/USD', 'ZEC/USD', 'ZIL/USD', 'ZRX/USD'] 4 | 5 | coins_picked = ['btc','eth','eos','xrp','ltc','neo','etc','iota','bchabc','dash','bchsv','xmr','zec','omg','mgo','trx','btg','zrx','etp','xlm'] 6 | 7 | def print_list(inputList): 8 | print("'", end='') 9 | for item in inputList[:-1]: 10 | print(item, "','", sep='', end='') 11 | print(inputList[-1], "'", sep='') 12 | -------------------------------------------------------------------------------- /BitfinexDataToLocalMSQ/database_fresh.py: -------------------------------------------------------------------------------- 1 | import ccxt 2 | from DB_Local_utils_load import * 3 | from GlobalObjects import symbols_usd, coins_picked 4 | 5 | fresh_symbols = [i for i in symbols_usd if i.split('/')[0].lower() in coins_picked[:10]] 6 | 7 | pd.set_option('expand_frame_repr', False) 8 | pd.set_option('max_rows', 20) 9 | 10 | bitfinex = ccxt.bitfinex({'timeout': 1000}) 11 | 12 | db_title = 'cc_bitfinex_top10_hd' 13 | timeframe = '1h' 14 | db_name = '_'.join([db_title, timeframe]) 15 | db_con, db_name_new = local_fresh_db_con(db_name_title=db_name) 16 | time_sh_utc_hours_diff = 8 17 | 18 | list_obj_tablefresh = [CallTableFresh(symbol=i, exchange=bitfinex, timeframe=timeframe, time_sh_utc_hours_diff=time_sh_utc_hours_diff, db_con=db_con) for i in fresh_symbols] 19 | 20 | list_obj_tablefresh_remain = run_function_list(object_list=list_obj_tablefresh) 21 | 22 | print('=' * 100) 23 | print([i.symbol for i in list_obj_tablefresh_remain]) 24 | -------------------------------------------------------------------------------- /BitfinexDataToLocalMSQ/database_update.py: -------------------------------------------------------------------------------- 1 | import ccxt 2 | from DB_Local_utils_load import * 3 | from GlobalObjects import symbols_usd 4 | 5 | update_symbols = symbols_usd 6 | 7 | pd.set_option('expand_frame_repr', False) 8 | pd.set_option('max_rows', 20) 9 | 10 | bitfinex = ccxt.bitfinex({'timeout': 1000}) 11 | 12 | timeframe = '1d' 13 | db_name_update = 'cc_bitfinex_hd_1d' 14 | time_sh_utc_hours_diff = 8 15 | 16 | list_obj_tableupdate = [CallTableUpdate(symbol=i, exchange=bitfinex, timeframe=timeframe, time_sh_utc_hours_diff=time_sh_utc_hours_diff, db_name=db_name_update) for i in update_symbols] 17 | list_obj_tableupdate_remain = run_function_list(object_list=list_obj_tableupdate) 18 | 19 | print('=' * 100) 20 | print([i.symbol for i in list_obj_tableupdate_remain]) 21 | -------------------------------------------------------------------------------- /BitfinexDataToLocalMSQ/print_all_symbols.py: -------------------------------------------------------------------------------- 1 | import ccxt 2 | import pandas as pd 3 | import time 4 | from GlobalObjects import print_list 5 | 6 | pd.set_option('expand_frame_repr', False) 7 | pd.set_option('max_rows', 20) 8 | 9 | bitfinex = ccxt.bitfinex({'timeout': 1000}) 10 | 11 | bitfinex.load_markets() 12 | symbols = bitfinex.symbols 13 | symbols_usd=[i for i in symbols if i[-3:]=='USD'] 14 | 15 | print_list(symbols) 16 | print('\n'+'-'*100+'\n') 17 | print_list(symbols_usd) 18 | -------------------------------------------------------------------------------- /BitfinexDataToLocalMSQ/print_coins_picked_by_amt.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from DB_Local_utils_Get import * 3 | from GlobalObjects import print_list 4 | 5 | pd.set_option('expand_frame_repr', False) 6 | pd.set_option('max_rows', 20) 7 | 8 | db_name = 'cc_bitfinex_hd_1d' 9 | DF_amt = DB_get_usd_AMT_all(db_name=db_name, indextostr=True, indextostrdigits=10) 10 | DF_amt = DF_amt[DF_amt.index >= '2018-12-01'] 11 | 12 | amt_avg = DF_amt.mean(skipna=True).sort_values(ascending=False) 13 | coins_picked = amt_avg[amt_avg >= 1 * 1e5].index.tolist() 14 | 15 | print_list(coins_picked) 16 | print() 17 | print(len(coins_picked)) 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bitfinex-Data-To-Local-MySQL 2 | 下载以及更新bitfinex所有交易对历史K线数据到本地mysql数据库的方案 3 | 4 | 目的:为bitfinex数字货币策略回测提供数据支持,本方案充分利用了MySQL储存数据占用空间小、存取速度快的优点,以及pandas库与sqlalchemy库对MySQL数据库的完美支持。 5 | 6 | 准备工作: 7 | 1,安装MySQL数据库到本地,并且打开MySQL服务,示例代码中我的MySQL数据库账号信息为(账户名:root,密码:123456,主机地址:localhost),在代码中将其内容依次替换成你自己的账号信息即可。 8 | 2,安装2019年1月份最新版本的pandas、ccxt、sqlalchemy库,如果已经有这几个库那就更新到2019年1月份的最新版本。 9 | 3,科学上网环境,如果是本机下载数据,请调成全局代理模式。 10 | 11 | 如果您没有耐心,可以直接跳过以下两条虚线内的介绍说明内容: 12 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 13 | sqlalchemy库中建立本地MySQL数据库连接的方法,可参考sqlalchemy的文档或者: 14 | https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_sql_table.html#pandas.read_sql_table 15 | 等pandas的文档,建立本地MySQL数据库连接的示例脚本如下: 16 | from sqlalchemy import create_engine 17 | # 例如账号信息为:(账户名:root,密码:123456,主机地址:由于登陆本地的mysql,所以填localhost) 18 | # 实际情况中可根据自己的账户密码填写。 19 | engine = create_engine('mysql://root:123456@localhost') 20 | 21 | GlobalObjects.py中的symbols_usd是bitfinex交易所所有以USD为计价单位的交易对列表,coins_picked是这些交易对在2018年12月之后至今的一段时间内按照USD交易额由大到小排名的前20位币种列表。 22 | symbols_usd, coins_picked的生成见print_all_symbols.py和print_coins_picked_by_amt.py 23 | 24 | 数据库命名规范:无强制命名规范 25 | 示例中使用cc_bitfinex_hd_timeframe的格式,例如bitfinex中选定的交易对的5分钟K线数据会存入数据库cc_bitfinex_hd_5m中,其中不同的交易对历史数据分别存入不同表中。表的命名规范如下: 26 | 数据表命名规范:格式为base_quote_timeframe 27 | 例如对于5分钟的BTC/USD交易对k线数据,将其存入数据表btc_usd_5m中。 28 | 29 | 方案设计思路: 30 | database_fresh.py会创建一个新的数据库,后缀为K线周期,然后将需要下载数据的交易对的历史数据下载到这个数据库中,这些交易对名称存在列表变量fresh_symbols中,每个交易对的K线数据在一张表中,表的命名规范见上一条,为了不让新创建的数据库覆盖掉之前的数据库,新库库名后面会加上当日的字符串(库创建好之后库名可以修改)。 31 | database_update.py会在本地MySQL的指定数据库db_name_update中将需要更新的交易对数据进行更新,其中需要更新的交易对存放在列表变量update_symbols中,对于其中的每一个交易对,程序会找到最后一条K线时间点,然后从这里接着下载接下来的数据并将其接入这张表中。 32 | 例如最后一张图中我在2019-01-16使用database_fresh.py创建了新的日K线数据库,然后在2019-02-14日使用database_update.py将这个库进行了更新。 33 | 34 | 使用database_fresh.py下载数据时会将所有的交易对数据进行下载,对于没有下载到的数据程序会在下一次循环时尝试再次下载,直到3次都没有结果就放弃这个交易对的数据,这个思路写在DB_Local_utils_load.py中的函数run_function_list中。 35 | 36 | 脚本套件介绍: 37 | GlobalObjects.py 中定义了常用的一些全局对象 38 | DB_Local_utils_load.py 中定义了下载数据所用的所有对象 39 | DB_Local_utils_Get.py 中定义了从下载好的数据库中批量提取数据的对象(数据库中已有数据的情况下才可使用) 40 | database_fresh.py 用来创建一个新的数据库,并将fresh_symbols中的交易对数据存放入这个数据库中 41 | database_update.py 用来将本地MySQL的指定数据库db_name_update中需要更新的交易对数据进行更新,更新的交易对存放在列表变量update_symbols中(数据库中已有数据的情况下才可使用) 42 | print_all_symbols.py 生成symbols_usd 43 | print_coins_picked_by_amt.py 生成coins_picked(数据库中已有日K线数据的情况下才可使用) 44 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 45 | 准备工作完成之后可以直接运行database_fresh.py脚本将交易额排名前10位的交易对1小时K线数据下载到新的数据库中,如果需要下载所有交易对的数据,那么将fresh_symbols赋值为GlobalObjects.py中的symbols_usd即可(或者自己修改)。 46 | 一段时间后若想更新数据库,注意定义好变量db_name_update、update_symbols、timeframe,然后使用database_update.py进行更新。 47 | 若需要批量提取数据字段,使用DB_Local_utils_Get.py中定义的对象即可。 48 | 49 | -------------------------------------------------------------------------------- /创建_更新.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArthurAnanda/Bitfinex-Data-To-Local-MySQL/89ec471439aed6ceeb692c19d8020a12c155c5c6/创建_更新.png -------------------------------------------------------------------------------- /说明文档.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArthurAnanda/Bitfinex-Data-To-Local-MySQL/89ec471439aed6ceeb692c19d8020a12c155c5c6/说明文档.png --------------------------------------------------------------------------------