xtquant.xtdata
取行情、财务等数据的相关接口
1# coding=utf-8 2""" 3取行情、财务等数据的相关接口 4""" 5 6import os, sys 7import time 8import traceback 9import json 10 11from . import xtbson as bson 12from . import xtdata_config 13 14from .IPythonApiClient import IPythonApiClient as RPCClient 15 16__all__ = [ 17 'subscribe_quote' 18 , 'subscribe_whole_quote' 19 , 'unsubscribe_quote' 20 , 'run' 21 , 'get_market_data' 22 , 'get_local_data' 23 , 'get_full_tick' 24 , 'get_divid_factors' 25 , 'get_l2_quote' 26 , 'get_l2_order' 27 , 'get_l2_transaction' 28 , 'download_history_data' 29 , 'get_financial_data' 30 , 'download_financial_data' 31 , 'get_instrument_detail' 32 , 'get_instrument_type' 33 , 'get_trading_dates' 34 , 'get_sector_list' 35 , 'get_stock_list_in_sector' 36 , 'download_sector_data' 37 , 'add_sector' 38 , 'remove_sector' 39 , 'get_index_weight' 40 , 'download_index_weight' 41 , 'get_holidays' 42 , 'get_trading_calendar' 43 , 'get_trade_times' 44 #, 'get_industry' 45 #, 'get_etf_info' 46 #, 'get_main_contract' 47 #, 'download_history_contracts' 48 , 'download_cb_data' 49 , 'get_cb_info' 50] 51 52def try_except(func): 53 def wrapper(*args, **kwargs): 54 try: 55 return func(*args, **kwargs) 56 except Exception: 57 exc_type, exc_instance, exc_traceback = sys.exc_info() 58 formatted_traceback = ''.join(traceback.format_tb(exc_traceback)) 59 message = '\n{0} raise {1}:{2}'.format( 60 formatted_traceback, 61 exc_type.__name__, 62 exc_instance 63 ) 64 # raise exc_type(message) 65 print(message) 66 return None 67 68 return wrapper 69 70 71CLIENT = None 72 73from os.path import abspath, dirname 74__curdir = dirname(abspath(__file__)) 75 76__rpc_config = __curdir + '/xtdata.ini' 77__xtdata_config = __curdir + '/xtdata.ini' 78 79from .IPythonApiClient import rpc_init 80__rpc_init_status = rpc_init(__rpc_config) 81if __rpc_init_status < 0: 82 print(f'rpc初始化失败,配置文件:{__rpc_config}') 83 84def load_global_config(): 85 res = {} 86 87 base_path = os.path.join(os.environ["USERPROFILE"], ".xtquant") 88 if xtdata_config.client_guid: 89 full_path = os.path.join(base_path, xtdata_config.client_guid) 90 if os.path.isfile(os.path.join(full_path, "xtdata.cfg")): 91 config = json.load(open(os.path.join(full_path, "xtdata.cfg"), "r", encoding = "utf-8")) 92 res[config.get('port', 58610)] = config 93 else: 94 for file in os.listdir(base_path): 95 full_path = os.path.join(base_path, file) 96 97 try: 98 os.remove(os.path.join(full_path, "running_status")) 99 except PermissionError: 100 if os.path.isfile(os.path.join(full_path, "xtdata.cfg")): 101 config = json.load(open(os.path.join(full_path, "xtdata.cfg"), "r", encoding = "utf-8")) 102 res[config.get('port', 58610)] = config 103 except Exception as e: 104 pass 105 return res 106 107def get_client(): 108 global CLIENT 109 if not CLIENT: 110 CLIENT = RPCClient('client_xtdata', __xtdata_config) 111 112 try: 113 configs = load_global_config() 114 configs = sorted(configs.items(), key = lambda x:x[0]) 115 for port, config in configs: 116 CLIENT.set_remote_addr('localhost', port) 117 CLIENT.reset() 118 succ, errmsg = CLIENT.connect_ex() 119 if succ: 120 init_data_dir() 121 break 122 except Exception as e: 123 pass 124 125 if not CLIENT.is_connected(): 126 CLIENT.load_config(__xtdata_config) 127 CLIENT.reset() 128 129 if not CLIENT.is_connected(): 130 succ, errmsg = CLIENT.connect_ex() 131 if succ: 132 init_data_dir() 133 else: 134 raise Exception("无法连接行情服务!") 135 return CLIENT 136 137def reconnect(ip = 'localhost', port = None): 138 global CLIENT 139 CLIENT = None 140 if not CLIENT: 141 if port == None: 142 CLIENT = get_client() 143 else: 144 CLIENT = RPCClient('client_xtdata', __xtdata_config) 145 CLIENT.set_remote_addr(ip, port) 146 CLIENT.reset() 147 succ, errmsg = CLIENT.connect_ex() 148 if succ: 149 init_data_dir() 150 151 if not CLIENT.is_connected(): 152 succ, errmsg = CLIENT.connect_ex() 153 if succ: 154 init_data_dir() 155 else: 156 raise Exception("无法连接行情服务!") 157 return 158 159default_data_dir = '../userdata_mini/datadir' 160data_dir = default_data_dir 161 162def init_data_dir(): 163 global data_dir 164 165 try: 166 client = get_client() 167 data_dir = client.get_data_dir() 168 169 if data_dir == "": 170 data_dir = os.path.join(client.get_app_dir(), default_data_dir) 171 172 if data_dir != default_data_dir: 173 data_dir = os.path.abspath(data_dir) 174 except Exception as e: 175 pass 176 177 return data_dir 178 179debug_mode = 0 180 181def create_array(shape, dtype_tuple, capsule, size): 182 import numpy as np 183 import ctypes 184 185 ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.POINTER(ctypes.c_char) 186 ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p] 187 buff = ctypes.pythonapi.PyCapsule_GetPointer(capsule, None) 188 base_type = size * buff._type_ 189 190 for dim in shape[::-1]: 191 base_type = dim * base_type 192 p_arr_type = ctypes.POINTER(base_type) 193 obj = ctypes.cast(buff, p_arr_type).contents 194 obj._base = capsule 195 return np.ndarray(shape = shape, dtype = np.dtype(dtype_tuple), buffer = obj) 196 197from .IPythonApiClient import register_create_nparray 198register_create_nparray(create_array) 199 200def get_industry(industry_name): 201 ''' 202 获取行业成份股,支持申万行业和证监会行业 203 :param industry_name: (str)行业名称 204 :return: list 205 ''' 206 client = get_client() 207 return client.get_industry(industry_name) 208 209 210def get_stock_list_in_sector(sector_name): 211 ''' 212 获取板块成份股,支持客户端左侧板块列表中任意的板块,包括自定义板块 213 :param sector_name: (str)板块名称 214 :return: list 215 ''' 216 client = get_client() 217 return client.get_stock_list_in_sector(sector_name, 0) 218 219 220def get_index_weight(index_code): 221 ''' 222 获取某只股票在某指数中的绝对权重 223 :param index_code: (str)指数名称 224 :return: dict 225 ''' 226 client = get_client() 227 return client.get_weight_in_index(index_code) 228 229 230def get_financial_data(stock_list, table_list=[], start_time='', end_time='', report_type='report_time'): 231 ''' 232 获取财务数据 233 :param stock_list: (list)合约代码列表 234 :param table_list: (list)报表名称列表 235 :param start_time: (str)起始时间 236 :param end_time: (str)结束时间 237 :param report_type: (str) 时段筛选方式 'announce_time' / 'report_time' 238 :return: 239 field: list[str] 240 date: list[int] 241 stock: list[str] 242 value: list[list[float]] 243 ''' 244 client = get_client() 245 all_table = { 246 'Balance' : 'ASHAREBALANCESHEET' 247 , 'Income' : 'ASHAREINCOME' 248 , 'CashFlow' : 'ASHARECASHFLOW' 249 , 'Capital' : 'CAPITALSTRUCTURE' 250 , 'HolderNum' : 'SHAREHOLDER' 251 , 'Top10Holder' : 'TOP10HOLDER' 252 , 'Top10FlowHolder' : 'TOP10FLOWHOLDER' 253 , 'PershareIndex' : 'PERSHAREINDEX' 254 } 255 256 if not table_list: 257 table_list = list(all_table.keys()) 258 259 all_table_upper = {table.upper() : all_table[table] for table in all_table} 260 req_list = [] 261 names = {} 262 for table in table_list: 263 req_table = all_table_upper.get(table.upper(), table) 264 req_list.append(req_table) 265 names[req_table] = table 266 267 data = {} 268 sl_len = 20 269 stock_list2 = [stock_list[i : i + sl_len] for i in range(0, len(stock_list), sl_len)] 270 for sl in stock_list2: 271 data2 = client.get_financial_data(sl, req_list, start_time, end_time, report_type) 272 for s in data2: 273 data[s] = data2[s] 274 275 import time 276 import math 277 def conv_date(data, key, key2): 278 if key in data: 279 tmp_data = data[key] 280 if math.isnan(tmp_data): 281 if key2 not in data or math.isnan(data[key2]): 282 data[key] = '' 283 else: 284 tmp_data = data[key2] 285 data[key] = time.strftime('%Y%m%d', time.localtime(tmp_data / 1000)) 286 return 287 288 result = {} 289 import pandas as pd 290 for stock in data: 291 stock_data = data[stock] 292 result[stock] = {} 293 for table in stock_data: 294 table_data = stock_data[table] 295 for row_data in table_data: 296 conv_date(row_data, 'm_anntime', 'm_timetag') 297 conv_date(row_data, 'm_timetag', '') 298 conv_date(row_data, 'declareDate', '') 299 conv_date(row_data, 'endDate', '') 300 result[stock][names[table]] = pd.DataFrame(table_data) 301 return result 302 303 304def get_market_data_ori( 305 field_list = [], stock_list = [], period = '1d' 306 , start_time = '', end_time = '', count = -1 307 , dividend_type = 'none', fill_data = True 308): 309 client = get_client() 310 enable_read_from_local = period in {'1m', '5m', '15m', '30m', '1h', '1d'} 311 global debug_mode 312 return client.get_market_data3(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data, 'v2', enable_read_from_local, debug_mode) 313 314 315def get_market_data( 316 field_list = [], stock_list = [], period = '1d' 317 , start_time = '', end_time = '', count = -1 318 , dividend_type = 'none', fill_data = True 319): 320 ''' 321 获取历史行情数据 322 :param field_list: 行情数据字段列表,[]为全部字段 323 K线可选字段: 324 "time" #时间戳 325 "open" #开盘价 326 "high" #最高价 327 "low" #最低价 328 "close" #收盘价 329 "volume" #成交量 330 "amount" #成交额 331 "settle" #今结算 332 "openInterest" #持仓量 333 分笔可选字段: 334 "time" #时间戳 335 "lastPrice" #最新价 336 "open" #开盘价 337 "high" #最高价 338 "low" #最低价 339 "lastClose" #前收盘价 340 "amount" #成交总额 341 "volume" #成交总量 342 "pvolume" #原始成交总量 343 "stockStatus" #证券状态 344 "openInt" #持仓量 345 "lastSettlementPrice" #前结算 346 "askPrice1", "askPrice2", "askPrice3", "askPrice4", "askPrice5" #卖一价~卖五价 347 "bidPrice1", "bidPrice2", "bidPrice3", "bidPrice4", "bidPrice5" #买一价~买五价 348 "askVol1", "askVol2", "askVol3", "askVol4", "askVol5" #卖一量~卖五量 349 "bidVol1", "bidVol2", "bidVol3", "bidVol4", "bidVol5" #买一量~买五量 350 :param stock_list: 股票代码 "000001.SZ" 351 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 352 :param start_time: 起始时间 "20200101" "20200101093000" 353 :param end_time: 结束时间 "20201231" "20201231150000" 354 :param count: 数量 -1全部/n: 从结束时间向前数n个 355 :param dividend_type: 除权类型"none" "front" "back" "front_ratio" "back_ratio" 356 :param fill_data: 对齐时间戳时是否填充数据,仅对K线有效,分笔周期不对齐时间戳 357 为True时,以缺失数据的前一条数据填充 358 open、high、low、close 为前一条数据的close 359 amount、volume为0 360 settle、openInterest 和前一条数据相同 361 为False时,缺失数据所有字段填NaN 362 :return: 数据集,分笔数据和K线数据格式不同 363 period为'tick'时:{stock1 : value1, stock2 : value2, ...} 364 stock1, stock2, ... : 合约代码 365 value1, value2, ... : np.ndarray 数据列表,按time增序排列 366 period为其他K线周期时:{field1 : value1, field2 : value2, ...} 367 field1, field2, ... : 数据字段 368 value1, value2, ... : pd.DataFrame 字段对应的数据,各字段维度相同,index为stock_list,columns为time_list 369 ''' 370 if period in {'1m', '5m', '15m', '30m', '1h', '1d'}: 371 import pandas as pd 372 index, data = get_market_data_ori(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 373 result = {} 374 for field in data: 375 result[field] = pd.DataFrame(data[field], index = index[0], columns = index[1]) 376 return result 377 378 return get_market_data_ori(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 379 380 381def get_market_data_ex_ori( 382 field_list = [], stock_list = [], period = '1d' 383 , start_time = '', end_time = '', count = -1 384 , dividend_type = 'none', fill_data = True 385): 386 client = get_client() 387 enable_read_from_local = period in {'1m', '5m', '15m', '30m', '1h', '1d'} 388 global debug_mode 389 return client.get_market_data3(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data, 'v3', enable_read_from_local, debug_mode) 390 391 392def get_market_data_ex( 393 field_list = [], stock_list = [], period = '1d' 394 , start_time = '', end_time = '', count = -1 395 , dividend_type = 'none', fill_data = True 396): 397 ''' 398 获取历史行情数据 399 :param field_list: 行情数据字段列表,[]为全部字段 400 K线可选字段: 401 "time" #时间戳 402 "open" #开盘价 403 "high" #最高价 404 "low" #最低价 405 "close" #收盘价 406 "volume" #成交量 407 "amount" #成交额 408 "settle" #今结算 409 "openInterest" #持仓量 410 分笔可选字段: 411 "time" #时间戳 412 "lastPrice" #最新价 413 "open" #开盘价 414 "high" #最高价 415 "low" #最低价 416 "lastClose" #前收盘价 417 "amount" #成交总额 418 "volume" #成交总量 419 "pvolume" #原始成交总量 420 "stockStatus" #证券状态 421 "openInt" #持仓量 422 "lastSettlementPrice" #前结算 423 "askPrice1", "askPrice2", "askPrice3", "askPrice4", "askPrice5" #卖一价~卖五价 424 "bidPrice1", "bidPrice2", "bidPrice3", "bidPrice4", "bidPrice5" #买一价~买五价 425 "askVol1", "askVol2", "askVol3", "askVol4", "askVol5" #卖一量~卖五量 426 "bidVol1", "bidVol2", "bidVol3", "bidVol4", "bidVol5" #买一量~买五量 427 :param stock_list: 股票代码 "000001.SZ" 428 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 429 :param start_time: 起始时间 "20200101" "20200101093000" 430 :param end_time: 结束时间 "20201231" "20201231150000" 431 :param count: 数量 -1全部/n: 从结束时间向前数n个 432 :param dividend_type: 除权类型"none" "front" "back" "front_ratio" "back_ratio" 433 :param fill_data: 对齐时间戳时是否填充数据,仅对K线有效,分笔周期不对齐时间戳 434 为True时,以缺失数据的前一条数据填充 435 open、high、low、close 为前一条数据的close 436 amount、volume为0 437 settle、openInterest 和前一条数据相同 438 为False时,缺失数据所有字段填NaN 439 :return: 数据集,分笔数据和K线数据格式不同 440 period为'tick'时:{stock1 : value1, stock2 : value2, ...} 441 stock1, stock2, ... : 合约代码 442 value1, value2, ... : np.ndarray 数据列表,按time增序排列 443 period为其他K线周期时:{field1 : value1, field2 : value2, ...} 444 field1, field2, ... : 数据字段 445 value1, value2, ... : pd.DataFrame 字段对应的数据,各字段维度相同,index为stock_list,columns为time_list 446 ''' 447 448 if period in {'1m', '5m', '15m', '30m', '1h', '1d'}: 449 ifield = 'time' 450 query_field_list = field_list if (not field_list) or (ifield in field_list) else [ifield] + field_list 451 ori_data = _get_market_data_ex_ori_221207(query_field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 452 453 import pandas as pd 454 result = {} 455 456 if not ori_data: 457 return result 458 stime_fmt = '%Y%m%d' if period == '1d' else '%Y%m%d%H%M%S' 459 for s, data in ori_data.items(): 460 cols = field_list if field_list else list(data.dtype.names) 461 sdata = pd.DataFrame(data, columns = cols) 462 sdata.index = [timetag_to_datetime(t, stime_fmt) for t in data['time']] 463 result[s] = sdata 464 465 return result 466 467 import pandas as pd 468 result = {} 469 470 ifield = 'time' 471 query_field_list = field_list if (not field_list) or (ifield in field_list) else [ifield] + field_list 472 ori_data = get_market_data_ex_ori(query_field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 473 474 fl = field_list 475 stime_fmt = '%Y%m%d' if period == '1d' else '%Y%m%d%H%M%S' 476 if fl: 477 fl2 = fl if ifield in fl else [ifield] + fl 478 for s in ori_data: 479 sdata = pd.DataFrame(ori_data[s], columns = fl2) 480 sdata2 = sdata[fl] 481 sdata2.index = sdata[ifield] 482 sdata2.index.name = 'stime' 483 result[s] = sdata2 484 else: 485 for s in ori_data: 486 sdata = pd.DataFrame(ori_data[s]) 487 sdata.index = [timetag_to_datetime(t, stime_fmt) for t in sdata[ifield]] 488 sdata.index.name = 'stime' 489 result[s] = sdata 490 491 return result 492 493 494def _get_market_data_ex_ori_221207( 495 field_list = [], stock_list = [], period = '1d' 496 , start_time = '', end_time = '', count = -1 497 , dividend_type = 'none', fill_data = True 498): 499 client = get_client() 500 enable_read_from_local = period in {'1m', '5m', '15m', '30m', '1h', '1d'} 501 global debug_mode 502 503 fi, sdl = client.get_market_data3(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data, 'v4', enable_read_from_local, debug_mode) 504 505 import numpy as np 506 return {s: np.frombuffer(b, fi) for s, b in sdl} 507 508 509def _get_market_data_ex_221207( 510 field_list = [], stock_list = [], period = '1d' 511 , start_time = '', end_time = '', count = -1 512 , dividend_type = 'none', fill_data = True 513): 514 ifield = 'time' 515 query_field_list = field_list if (not field_list) or (ifield in field_list) else [ifield] + field_list 516 517 if period in {'1m', '5m', '15m', '30m', '1h', '1d'}: 518 ori_data = _get_market_data_ex_ori_221207(query_field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 519 else: 520 ori_data = get_market_data_ex_ori(query_field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 521 522 import pandas as pd 523 result = {} 524 525 for s, data in ori_data.items(): 526 cols = field_list if field_list else list(data.dtype.names) 527 sdata = pd.DataFrame(data, columns = cols) 528 sdata.index = pd.to_datetime((data['time'] + 28800000) * 1000000) 529 result[s] = sdata 530 531 return result 532 533 534get_market_data3 = _get_market_data_ex_221207 535 536 537def get_local_data(field_list=[], stock_code=[], period='1d', start_time='', end_time='', count=-1, 538 dividend_type='none', fill_data=True, data_dir=data_dir): 539 return None 540 541 542def get_l2_quote(field_list=[], stock_code='', start_time='', end_time='', count=-1): 543 ''' 544 level2实时行情 545 ''' 546 client = get_client() 547 datas = client.get_market_data3(field_list, [stock_code], 'l2quote', start_time, end_time, count, 'none', False, '', False, False) 548 if datas: 549 return datas[stock_code] 550 return None 551 552 553def get_l2_order(field_list=[], stock_code='', start_time='', end_time='', count=-1): 554 ''' 555 level2逐笔委托 556 ''' 557 client = get_client() 558 datas = client.get_market_data3(field_list, [stock_code], 'l2order', start_time, end_time, count, 'none', False, '', False, False) 559 if datas: 560 return datas[stock_code] 561 return None 562 563 564def get_l2_transaction(field_list=[], stock_code='', start_time='', end_time='', count=-1): 565 ''' 566 level2逐笔成交 567 ''' 568 client = get_client() 569 datas = client.get_market_data3(field_list, [stock_code], 'l2transaction', start_time, end_time, count, 'none', False, '', False, False) 570 if datas: 571 return datas[stock_code] 572 return None 573 574 575def get_divid_factors(stock_code, start_time='', end_time=''): 576 ''' 577 获取除权除息日及对应的权息 578 :param stock_code: (str)股票代码 579 :param date: (str)日期 580 :return: pd.DataFrame 数据集 581 ''' 582 client = get_client() 583 datas = client.get_divid_factors(stock_code, start_time, end_time) 584 import pandas as pd 585 datas = pd.DataFrame(datas).T 586 return datas 587 588 589@try_except 590def getDividFactors(stock_code, date): 591 client = get_client() 592 resData = client.get_divid_factors(stock_code, date) 593 res = {resData[i]: [resData[i + 1][j] for j in 594 range(0, len(resData[i + 1]), 1)] for i in range(0, len(resData), 2)} 595 if isinstance(res, dict): 596 for k, v in res.items(): 597 if isinstance(v, list) and len(v) > 5: 598 v[5] = int(v[5]) 599 return res 600 601 602def get_main_contract(code_market): 603 ''' 604 获取当前期货主力合约 605 :param code_market: (str)股票代码 606 :return: str 607 ''' 608 client = get_client() 609 return client.get_main_contract(code_market) 610 611def datetime_to_timetag(datetime, format = "%Y%m%d%H%M%S"): 612 if len(datetime) == 8: 613 format = "%Y%m%d" 614 timetag = time.mktime(time.strptime(datetime, format)) 615 return timetag * 1000 616 617def timetag_to_datetime(timetag, format): 618 ''' 619 将毫秒时间转换成日期时间 620 :param timetag: (int)时间戳毫秒数 621 :param format: (str)时间格式 622 :return: str 623 ''' 624 return timetagToDateTime(timetag, format) 625 626 627@try_except 628def timetagToDateTime(timetag, format): 629 import time 630 timetag = timetag / 1000 631 time_local = time.localtime(timetag) 632 return time.strftime(format, time_local) 633 634 635def get_trading_dates(market, start_time='', end_time='', count=-1): 636 ''' 637 根据市场获取交易日列表 638 : param market: 市场代码 e.g. 'SH','SZ','IF','DF','SF','ZF'等 639 : param start_time: 起始时间 '20200101' 640 : param end_time: 结束时间 '20201231' 641 : param count: 数据个数,-1为全部数据 642 :return list(long) 毫秒数的时间戳列表 643 ''' 644 client = get_client() 645 datas = client.get_trading_dates_by_market(market, start_time, end_time, count) 646 return list(datas.values()) 647 648 649def get_full_tick(code_list): 650 ''' 651 获取盘口tick数据 652 :param code_list: (list)stock.market组成的股票代码列表 653 :return: dict 654 {'stock.market': {dict}} 655 ''' 656 client = get_client() 657 resp_json = client.get_full_tick(code_list) 658 return json.loads(resp_json) 659 660 661def subscribe_callback_wrapper(callback): 662 import traceback 663 def subscribe_callback(datas): 664 try: 665 if type(datas) == bytes: 666 datas = bson.BSON.decode(datas) 667 callback(datas) 668 except: 669 print('subscribe_quote callback error:', callback) 670 traceback.print_exc() 671 return subscribe_callback 672 673 674def subscribe_quote(stock_code, period='1d', start_time='', end_time='', count=0, callback=None): 675 ''' 676 订阅股票行情数据 677 :param stock_code: 股票代码 e.g. "000001.SZ" 678 :param start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 679 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000" 680 :param end_time: 结束时间 同“开始时间” 681 :param count: 数量 -1全部/n: 从结束时间向前数n个 682 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 683 :param callback: 684 订阅回调函数onSubscribe(datas) 685 :param datas: {stock : [data1, data2, ...]} 数据字典 686 :return: int 订阅序号 687 ''' 688 if callback: 689 callback = subscribe_callback_wrapper(callback) 690 691 meta = {'stockCode': stock_code, 'period': period} 692 region = {'startTime': start_time, 'endTime': end_time, 'count': count} 693 694 client = get_client() 695 return client.subscribe_quote(bson.BSON.encode(meta), bson.BSON.encode(region), callback) 696 697 698def subscribe_l2thousand(stock_code, gear_num = 0, callback = None): 699 ''' 700 订阅千档盘口 701 ''' 702 if callback: 703 callback = subscribe_callback_wrapper(callback) 704 705 meta = {'stockCode': stock_code, 'period': 'l2thousand'} 706 region = {'thousandGearNum': gear_num, 'thousandDetailGear': 0, 'thousandDetailNum': 0} 707 708 client = get_client() 709 return client.subscribe_quote(bson.BSON.encode(meta), bson.BSON.encode(region), callback) 710 711 712def subscribe_whole_quote(code_list, callback=None): 713 ''' 714 订阅全推数据 715 :param code_list: 市场代码列表 ["SH", "SZ"] 716 :param callback: 717 订阅回调函数onSubscribe(datas) 718 :param datas: {stock1 : data1, stock2 : data2, ...} 数据字典 719 :return: int 订阅序号 720 ''' 721 if callback: 722 callback = subscribe_callback_wrapper(callback) 723 724 client = get_client() 725 return client.subscribe_whole_quote(code_list, callback) 726 727 728def unsubscribe_quote(seq): 729 ''' 730 :param seq: 订阅接口subscribe_quote返回的订阅号 731 :return: 732 ''' 733 client = get_client() 734 return client.unsubscribe_quote(seq) 735 736 737def run(): 738 '''阻塞线程接收行情回调''' 739 import time 740 client = get_client() 741 while True: 742 time.sleep(3) 743 if not client.is_connected(): 744 raise Exception('行情服务连接断开') 745 break 746 return 747 748 749def get_sector_list(): 750 ''' 751 获取板块列表 752 :return: (list[str]) 753 ''' 754 client = get_client() 755 return client.get_sector_list() 756 757 758def add_sector(sector_name, stock_list): 759 ''' 760 增加自定义板块 761 :param sector_name: 板块名称 e.g. "我的自选" 762 :param stock_list: (list)stock.market组成的股票代码列表 763 ''' 764 client = get_client() 765 return client.add_sector(sector_name, stock_list, 1) 766 767 768def remove_sector(sector_name): 769 ''' 770 删除自定义板块 771 :param sector_name: 板块名称 e.g. "我的自选" 772 ''' 773 client = get_client() 774 return client.add_sector(sector_name, [], -1) 775 776 777def get_instrument_detail(stock_code): 778 ''' 779 获取合约信息 780 :param stock_code: 股票代码 e.g. "600000.SH" 781 :return: dict 782 ExchangeID(str):合约市场代码, InstrumentID(str):合约代码, InstrumentName(str):合约名称, ProductID(str):合约的品种ID(期货), ProductName(str)合约的品种名称(期货), 783 CreateDate(int):上市日期(期货), OpenDate(int):IPO日期(股票), ExpireDate(int):退市日或者到期日, PreClose(double):前收盘价格, SettlementPrice(double):前结算价格, 784 UpStopPrice(double):当日涨停价, DownStopPrice(double):当日跌停价, FloatVolume(double):流通股本, TotalVolume(double):总股本, LongMarginRatio(double):多头保证金率, 785 ShortMarginRatio(double):空头保证金率, PriceTick(double):最小变价单位, VolumeMultiple(int):合约乘数(对期货以外的品种,默认是1), 786 MainContract(int):主力合约标记,1、2、3分别表示第一主力合约,第二主力合约,第三主力合约, LastVolume(int):昨日持仓量, InstrumentStatus(int):合约停牌状态, 787 IsTrading(bool):合约是否可交易, IsRecent(bool):是否是近月合约, 788 ''' 789 client = get_client() 790 inst = client.get_instrument_detail(stock_code) 791 if not inst: 792 return None 793 field_list = [ 794 'ExchangeID' 795 , 'InstrumentID' 796 , 'InstrumentName' 797 , 'ProductID' 798 , 'ProductName' 799 , 'CreateDate' 800 , 'OpenDate' 801 , 'ExpireDate' 802 , 'PreClose' 803 , 'SettlementPrice' 804 , 'UpStopPrice' 805 , 'DownStopPrice' 806 , 'FloatVolume' 807 , 'TotalVolume' 808 , 'LongMarginRatio' 809 , 'ShortMarginRatio' 810 , 'PriceTick' 811 , 'VolumeMultiple' 812 , 'MainContract' 813 , 'LastVolume' 814 , 'InstrumentStatus' 815 , 'IsTrading' 816 , 'IsRecent' 817 ] 818 ret = {} 819 for field in field_list: 820 ret[field] = inst.get(field) 821 822 exfield_list = [ 823 'ProductTradeQuota' 824 , 'ContractTradeQuota' 825 , 'ProductOpenInterestQuota' 826 , 'ContractOpenInterestQuota' 827 ] 828 inst_ex = inst.get('ExtendInfo', {}) 829 for field in exfield_list: 830 ret[field] = inst_ex.get(field) 831 832 def convNum2Str(field): 833 if field in ret and isinstance(ret[field], int): 834 ret[field] = str(ret[field]) 835 convNum2Str('CreateDate') 836 convNum2Str('OpenDate') 837 return ret 838 839 840def get_etf_info(stockCode): 841 ''' 842 获取etf申赎清单 843 :param stockCode: ETF代码 e.g. "159811.SZ" 844 :return: dict 845 etfCode(str):ETF代码, etfExchID(str):ETF市场, prCode(str):基金申赎代码, 846 stocks(dict):成分股 847 key: 成分股代码 e.g. "000063.SZ" 848 value: dict 849 componentExchID(str):成份股市场代码, componentCode(str):成份股代码, componentName(str):成份股名称, componentVolume(int):成份股数量 850 ''' 851 client = get_client() 852 return client.get_etf_info(stockCode) 853 854 855def download_index_weight(): 856 ''' 857 下载指数权重数据 858 ''' 859 client = get_client() 860 client.down_index_weight() 861 862 863def download_history_contracts(): 864 ''' 865 下载过期合约数据 866 ''' 867 client = get_client() 868 client.down_history_contracts() 869 870 871class TimeListBuilder: 872 def __init__(self): 873 # param 874 self.period = 3600000 875 self.open_list = None # [['093000', '113000'], ['130000', '150000']] 876 877 # build up 878 self.cur_date = 0 879 self.date_offset = 3600000 * 8 880 self.day_time_list = [] 881 self.cur_index = 0 882 883 def init(self): 884 if not self.open_list: return False 885 if self.period <= 0: return False 886 887 for scope in self.open_list: 888 hour, minute, second = self.parse_time(scope[0]) 889 start = (((hour * 60) + minute) * 60 + second) * 1000 890 hour, minute, second = self.parse_time(scope[1]) 891 end = (((hour * 60) + minute) * 60 + second) * 1000 892 t = start + self.period 893 while t <= end: 894 self.day_time_list.append(t) 895 t += self.period 896 self.cur_index = 0 897 898 if not self.day_time_list: return False 899 return True 900 901 def parse_time(self, ft): 902 ft = int(ft) 903 second = ft % 100 904 ft = int((ft - second) / 100) 905 minute = ft % 100 906 ft = int((ft - minute) / 100) 907 hour = ft % 100 908 return hour, minute, second 909 910 def get(self): 911 if self.day_time_list: 912 return self.cur_date + self.day_time_list[self.cur_index] 913 else: 914 return self.cur_date 915 916 def next(self): 917 self.cur_index += 1 918 if self.cur_index >= len(self.day_time_list): 919 self.cur_date += 86400000 920 self.cur_index = 0 921 922 def locate(self, t): 923 day_time = t % 86400000 924 self.cur_date = t - day_time - self.date_offset 925 self.cur_index = 0 926 for i in range(len(self.day_time_list)): 927 te = self.day_time_list[i] 928 if t < te: 929 self.cur_index = i 930 break 931 932 933class MergeData: 934 def __init__(self): 935 # param 936 self.period = 3600000 937 self.open_list = None # [['093000', '113000'], ['130000', '150000']] 938 self.merge_func = None 939 940 # build up 941 self.timer = None 942 943 # result 944 self.time_list = [] 945 self.data_list = [] 946 947 def init(self): 948 self.timer = TimeListBuilder() 949 self.timer.open_list = self.open_list 950 self.timer.period = self.period 951 self.timer.init() 952 953 def push(self, t, data): 954 if self.time_list: 955 te = self.time_list[-1] 956 if t <= te: 957 self.data_list[-1] = self.merge_func(self.data_list[-1], data) 958 else: 959 self.timer.next() 960 te = self.timer.get() 961 self.time_list.append(te) 962 self.data_list.append(data) 963 else: 964 self.timer.locate(t) 965 966 te = self.timer.get() 967 self.time_list.append(te) 968 self.data_list.append(data) 969 970 971def merge_data_sum(data1, data2): 972 return data1 + data2 973 974 975def merge_data_max(data1, data2): 976 return max(data1, data2) 977 978 979def merge_data_min(data1, data2): 980 return min(data1, data2) 981 982 983def merge_data_first(data1, data2): 984 return data1 985 986 987def merge_data_last(data1, data2): 988 return data2 989 990 991def merge_data(time_list, data_list, period, open_list, field): 992 merge_func = {} 993 merge_func['open'] = merge_data_first 994 merge_func['high'] = merge_data_max 995 merge_func['low'] = merge_data_min 996 merge_func['close'] = merge_data_last 997 merge_func['volume'] = merge_data_sum 998 merge_func['amount'] = merge_data_sum 999 1000 md = MergeData() 1001 md.period = period 1002 md.open_list = open_list 1003 md.merge_func = merge_func[field.lower()] 1004 md.init() 1005 1006 for i in range(len(time_list)): 1007 md.push(time_list[i], data_list[i]) 1008 1009 return md.time_list, md.data_list 1010 1011 1012def download_history_data(stock_code, period, start_time='', end_time=''): 1013 ''' 1014 :param stock_code: 股票代码 e.g. "000001.SZ" 1015 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 1016 :param start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 1017 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000" 1018 :param end_time: 结束时间 同上,若是未来某时刻会被视作当前时间 1019 :return: bool 是否成功 1020 ''' 1021 client = get_client() 1022 client.supply_history_data(stock_code, period, start_time, end_time) 1023 1024 1025supply_history_data = download_history_data 1026 1027 1028def download_history_data2(stock_list, period, start_time='', end_time='', callback=None): 1029 ''' 1030 :param stock_code: 股票代码 e.g. "000001.SZ" 1031 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 1032 :param start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 1033 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000" 1034 :param end_time: 结束时间 同上,若是未来某时刻会被视作当前时间 1035 :return: bool 是否成功 1036 ''' 1037 client = get_client() 1038 1039 status = [False, 0, 1, ''] 1040 def on_progress(data): 1041 try: 1042 finished = data['finished'] 1043 total = data['total'] 1044 done = (finished >= total) 1045 status[0] = done 1046 status[1] = finished 1047 status[2] = total 1048 1049 try: 1050 callback(data) 1051 except: 1052 pass 1053 1054 return done 1055 except: 1056 status[0] = True 1057 status[3] = 'exception' 1058 return True 1059 1060 client.supply_history_data2(stock_list, period, start_time, end_time, on_progress) 1061 1062 import time 1063 try: 1064 while not status[0] and client.is_connected(): 1065 time.sleep(0.1) 1066 except: 1067 if status[1] < status[2]: 1068 client.stop_supply_history_data2() 1069 traceback.print_exc() 1070 if not client.is_connected(): 1071 raise Exception('行情服务连接断开') 1072 if status[3]: 1073 raise Exception('下载数据失败:' + status[3]) 1074 return 1075 1076 1077def download_financial_data(stock_list, table_list=[], start_time='', end_time=''): 1078 ''' 1079 :param stock_list: 股票代码列表 1080 :param table_list: 财务数据表名列表,[]为全部表 1081 可选范围:['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare'] 1082 :param start_time: 开始时间,格式YYYYMMDD,e.g."20200427" 1083 :param end_time: 结束时间 同上,若是未来某时刻会被视作当前时间 1084 ''' 1085 client = get_client() 1086 if not table_list: 1087 table_list = ['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare'] 1088 1089 for stock_code in stock_list: 1090 for table in table_list: 1091 client.supply_history_data(stock_code, table, start_time, end_time) 1092 1093 1094def download_financial_data2(stock_list, table_list=[], start_time='', end_time='', callback=None): 1095 ''' 1096 :param stock_list: 股票代码列表 1097 :param table_list: 财务数据表名列表,[]为全部表 1098 可选范围:['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare'] 1099 :param start_time: 开始时间,格式YYYYMMDD,e.g."20200427" 1100 :param end_time: 结束时间 同上,若是未来某时刻会被视作当前时间 1101 ''' 1102 client = get_client() 1103 if not table_list: 1104 table_list = ['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare'] 1105 1106 data = {} 1107 data['total'] = len(table_list) * len(stock_list) 1108 finish = 0 1109 for stock_code in stock_list: 1110 for table in table_list: 1111 client.supply_history_data(stock_code, table, start_time, end_time) 1112 1113 finish = finish + 1 1114 try: 1115 data['finished'] = finish 1116 callback(data) 1117 except: 1118 pass 1119 1120 if not client.is_connected(): 1121 raise Exception('行情服务连接断开') 1122 break 1123 1124 1125def get_instrument_type(stock_code): 1126 ''' 1127 判断证券类型 1128 :param stock_code: 股票代码 e.g. "600000.SH" 1129 :return: dict{str : bool} {类型名:是否属于该类型} 1130 ''' 1131 client = get_client() 1132 return client.get_stock_type(stock_code) 1133 1134get_stock_type = get_instrument_type 1135 1136 1137def download_sector_data(): 1138 ''' 1139 下载行业板块数据 1140 ''' 1141 client = get_client() 1142 client.down_all_sector_data() 1143 1144def get_holidays(): 1145 ''' 1146 获取节假日列表 1147 :return: 8位int型日期 1148 ''' 1149 client = get_client() 1150 return [str(d) for d in client.get_holidays()] 1151 1152def get_trading_calendar(market, start_time = '', end_time = '', tradetimes = False): 1153 ''' 1154 获取指定市场交易日历 1155 :param market: str 市场 1156 :param start_time: str 起始时间 '20200101' 1157 :param end_time: str 结束时间 '20201231' 1158 :param tradetimes: bool 是否包含日内交易时段 1159 :return: 1160 ''' 1161 holidays_list = get_holidays() # 19900101格式的数字 1162 import datetime 1163 now = datetime.datetime.combine(datetime.date.today(), datetime.time()) 1164 last = datetime.datetime(now.year + 1, 1, 1) 1165 1166 client = get_client() 1167 trading_list = list(client.get_trading_dates_by_market(market, start_time, end_time, -1).keys()) 1168 1169 if start_time == '' and trading_list: 1170 start_time = trading_list[0] 1171 start = datetime.datetime.strptime(start_time, "%Y%m%d") 1172 1173 if end_time == '': 1174 end_time = now.strftime("%Y%m%d") 1175 end = min(datetime.datetime.strptime(end_time, "%Y%m%d"), last) 1176 1177 # 时间戳毫秒 1178 if not trading_list: 1179 return [] 1180 1181 if not tradetimes: 1182 ret_list = trading_list 1183 while now < end: 1184 now += datetime.timedelta(days=1) 1185 if datetime.datetime.isoweekday(now) not in [6, 7]: 1186 ft = (now.strftime("%Y%m%d")) 1187 if ft not in holidays_list: 1188 ret_list.append(ft) 1189 return ret_list 1190 else: 1191 ret_map = {} 1192 trading_times = get_trade_times(market) 1193 new_trading_times_prev = [] #21-24 1194 new_trading_times_mid = [] #0-3 1195 new_trading_times_next = [] #9-15 1196 1197 for tt in trading_times: 1198 t0 = tt[0] 1199 t1 = tt[1] 1200 t2 = tt[2] 1201 try: 1202 if t1 <= 0: 1203 new_trading_times_prev.append([t0 + 86400, t1 + 86400, t2]) 1204 elif 0 <= t0 and t1 <= 10800: 1205 new_trading_times_mid.append(tt) 1206 elif t0 <= 0 and t1 <= 10800: 1207 new_trading_times_prev.append([t0 + 86400, 86400, t2]) 1208 new_trading_times_mid.append([0, t1, t2]) 1209 else: 1210 new_trading_times_next.append(tt) 1211 except: 1212 pass 1213 1214 end = end + datetime.timedelta(days=1) 1215 import copy 1216 prev_open_flag = False 1217 while start < end: 1218 weekday = datetime.datetime.isoweekday(start) 1219 ft = start.strftime("%Y%m%d") 1220 if weekday not in [6, 7]: 1221 if ft not in holidays_list: 1222 ret_map[ft] = [] 1223 if prev_open_flag: 1224 ret_map[ft].extend(new_trading_times_mid) # 早盘 1225 ret_map[ft].extend(new_trading_times_next) 1226 if weekday != 5: 1227 if (start + datetime.timedelta(days=1)).strftime("%Y%m%d") not in holidays_list: 1228 ret_map[ft].extend(new_trading_times_prev) 1229 else: 1230 if (start + datetime.timedelta(days=3)).strftime("%Y%m%d") not in holidays_list: 1231 ret_map[ft].extend(new_trading_times_prev) 1232 prev_open_flag = True 1233 else: 1234 prev_open_flag = False 1235 start += datetime.timedelta(days=1) 1236 return ret_map 1237 1238def get_trade_times(stockcode): 1239 ''' 1240 返回指定市场或者指定股票的交易时段 1241 :param stockcode: 市场或者代码.市场 例如 'SH' 或者 '600000.SH' 1242 :return: 返回交易时段列表,第一位是开始时间,第二位结束时间,第三位交易类型 (2 - 开盘竞价, 3 - 连续交易, 8 - 收盘竞价, 9 - 盘后定价) 1243 ''' 1244 stockcode_split = stockcode.split('.') 1245 if len(stockcode_split) == 2: 1246 ins_dl = get_instrument_detail(stockcode) 1247 product = ins_dl['ProductID'] 1248 stock = stockcode_split[0] 1249 market = stockcode_split[1] 1250 default = 0 1251 else: 1252 market = stockcode 1253 product = "" 1254 stock = "" 1255 default = 1 1256 1257 trader_time = {} 1258 try: 1259 with open(os.path.join(data_dir, '..', 'config', 'tradetimeconfig2.json'), 'r') as f: 1260 trader_time = json.loads(f.read()) 1261 except: 1262 pass 1263 1264 ret = [] 1265 import re 1266 for tdm in trader_time: 1267 if tdm['default'] == default and tdm['market'] == market: 1268 if tdm['product'] == [] and tdm['type'] == "": 1269 ret = tdm['tradetime'] #默认为product为空的 默认值 1270 if tdm['type'] != "" and re.match(tdm['type'], stock): 1271 ret = tdm['tradetime'] 1272 break 1273 if product != "" and product in tdm['product']: 1274 ret = tdm['tradetime'] 1275 break 1276 1277 import datetime 1278 def convert(t): 1279 if t == "240000" or t == "-240000": 1280 return 0 1281 if t[0] == '-': 1282 parc = datetime.datetime.strptime(t, "-%H%M%S") 1283 t = datetime.timedelta(hours=-parc.hour, minutes=-parc.minute) 1284 else: 1285 parc = datetime.datetime.strptime(t, "%H%M%S") 1286 t = datetime.timedelta(hours=parc.hour, minutes=parc.minute) 1287 return int(t.total_seconds()) 1288 ret = [[convert(timepair[0]), convert(timepair[1]), int(timepair[2])] for timepair in ret] 1289 return ret 1290 1291def is_stock_type(stock, tag): 1292 client = get_client() 1293 return client.is_stock_type(stock, tag) 1294 1295def download_cb_data(): 1296 client = get_client() 1297 return client.down_cb_data() 1298 1299def get_cb_info(stockcode): 1300 client = get_client() 1301 return client.get_cb_info(stockcode) 1302 1303gmd = get_market_data 1304gmd2 = get_market_data_ex 1305gmd3 = get_market_data3 1306gld = get_local_data 1307t2d = timetag_to_datetime 1308gsl = get_stock_list_in_sector
675def subscribe_quote(stock_code, period='1d', start_time='', end_time='', count=0, callback=None): 676 ''' 677 订阅股票行情数据 678 :param stock_code: 股票代码 e.g. "000001.SZ" 679 :param start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 680 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000" 681 :param end_time: 结束时间 同“开始时间” 682 :param count: 数量 -1全部/n: 从结束时间向前数n个 683 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 684 :param callback: 685 订阅回调函数onSubscribe(datas) 686 :param datas: {stock : [data1, data2, ...]} 数据字典 687 :return: int 订阅序号 688 ''' 689 if callback: 690 callback = subscribe_callback_wrapper(callback) 691 692 meta = {'stockCode': stock_code, 'period': period} 693 region = {'startTime': start_time, 'endTime': end_time, 'count': count} 694 695 client = get_client() 696 return client.subscribe_quote(bson.BSON.encode(meta), bson.BSON.encode(region), callback)
订阅股票行情数据
Parameters
- stock_code: 股票代码 e.g. "000001.SZ"
- start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000"
- end_time: 结束时间 同“开始时间”
- count: 数量 -1全部/n: 从结束时间向前数n个
- period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d"
- callback: 订阅回调函数onSubscribe(datas) :param datas: {stock : [data1, data2, ...]} 数据字典
Returns
int 订阅序号
713def subscribe_whole_quote(code_list, callback=None): 714 ''' 715 订阅全推数据 716 :param code_list: 市场代码列表 ["SH", "SZ"] 717 :param callback: 718 订阅回调函数onSubscribe(datas) 719 :param datas: {stock1 : data1, stock2 : data2, ...} 数据字典 720 :return: int 订阅序号 721 ''' 722 if callback: 723 callback = subscribe_callback_wrapper(callback) 724 725 client = get_client() 726 return client.subscribe_whole_quote(code_list, callback)
订阅全推数据
Parameters
- code_list: 市场代码列表 ["SH", "SZ"]
- callback: 订阅回调函数onSubscribe(datas) :param datas: {stock1 : data1, stock2 : data2, ...} 数据字典
Returns
int 订阅序号
729def unsubscribe_quote(seq): 730 ''' 731 :param seq: 订阅接口subscribe_quote返回的订阅号 732 :return: 733 ''' 734 client = get_client() 735 return client.unsubscribe_quote(seq)
Parameters
- seq: 订阅接口subscribe_quote返回的订阅号
Returns
738def run(): 739 '''阻塞线程接收行情回调''' 740 import time 741 client = get_client() 742 while True: 743 time.sleep(3) 744 if not client.is_connected(): 745 raise Exception('行情服务连接断开') 746 break 747 return
阻塞线程接收行情回调
316def get_market_data( 317 field_list = [], stock_list = [], period = '1d' 318 , start_time = '', end_time = '', count = -1 319 , dividend_type = 'none', fill_data = True 320): 321 ''' 322 获取历史行情数据 323 :param field_list: 行情数据字段列表,[]为全部字段 324 K线可选字段: 325 "time" #时间戳 326 "open" #开盘价 327 "high" #最高价 328 "low" #最低价 329 "close" #收盘价 330 "volume" #成交量 331 "amount" #成交额 332 "settle" #今结算 333 "openInterest" #持仓量 334 分笔可选字段: 335 "time" #时间戳 336 "lastPrice" #最新价 337 "open" #开盘价 338 "high" #最高价 339 "low" #最低价 340 "lastClose" #前收盘价 341 "amount" #成交总额 342 "volume" #成交总量 343 "pvolume" #原始成交总量 344 "stockStatus" #证券状态 345 "openInt" #持仓量 346 "lastSettlementPrice" #前结算 347 "askPrice1", "askPrice2", "askPrice3", "askPrice4", "askPrice5" #卖一价~卖五价 348 "bidPrice1", "bidPrice2", "bidPrice3", "bidPrice4", "bidPrice5" #买一价~买五价 349 "askVol1", "askVol2", "askVol3", "askVol4", "askVol5" #卖一量~卖五量 350 "bidVol1", "bidVol2", "bidVol3", "bidVol4", "bidVol5" #买一量~买五量 351 :param stock_list: 股票代码 "000001.SZ" 352 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 353 :param start_time: 起始时间 "20200101" "20200101093000" 354 :param end_time: 结束时间 "20201231" "20201231150000" 355 :param count: 数量 -1全部/n: 从结束时间向前数n个 356 :param dividend_type: 除权类型"none" "front" "back" "front_ratio" "back_ratio" 357 :param fill_data: 对齐时间戳时是否填充数据,仅对K线有效,分笔周期不对齐时间戳 358 为True时,以缺失数据的前一条数据填充 359 open、high、low、close 为前一条数据的close 360 amount、volume为0 361 settle、openInterest 和前一条数据相同 362 为False时,缺失数据所有字段填NaN 363 :return: 数据集,分笔数据和K线数据格式不同 364 period为'tick'时:{stock1 : value1, stock2 : value2, ...} 365 stock1, stock2, ... : 合约代码 366 value1, value2, ... : np.ndarray 数据列表,按time增序排列 367 period为其他K线周期时:{field1 : value1, field2 : value2, ...} 368 field1, field2, ... : 数据字段 369 value1, value2, ... : pd.DataFrame 字段对应的数据,各字段维度相同,index为stock_list,columns为time_list 370 ''' 371 if period in {'1m', '5m', '15m', '30m', '1h', '1d'}: 372 import pandas as pd 373 index, data = get_market_data_ori(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data) 374 result = {} 375 for field in data: 376 result[field] = pd.DataFrame(data[field], index = index[0], columns = index[1]) 377 return result 378 379 return get_market_data_ori(field_list, stock_list, period, start_time, end_time, count, dividend_type, fill_data)
获取历史行情数据
Parameters
- field_list: 行情数据字段列表,[]为全部字段 K线可选字段: "time" #时间戳 "open" #开盘价 "high" #最高价 "low" #最低价 "close" #收盘价 "volume" #成交量 "amount" #成交额 "settle" #今结算 "openInterest" #持仓量 分笔可选字段: "time" #时间戳 "lastPrice" #最新价 "open" #开盘价 "high" #最高价 "low" #最低价 "lastClose" #前收盘价 "amount" #成交总额 "volume" #成交总量 "pvolume" #原始成交总量 "stockStatus" #证券状态 "openInt" #持仓量 "lastSettlementPrice" #前结算 "askPrice1", "askPrice2", "askPrice3", "askPrice4", "askPrice5" #卖一价~卖五价 "bidPrice1", "bidPrice2", "bidPrice3", "bidPrice4", "bidPrice5" #买一价~买五价 "askVol1", "askVol2", "askVol3", "askVol4", "askVol5" #卖一量~卖五量 "bidVol1", "bidVol2", "bidVol3", "bidVol4", "bidVol5" #买一量~买五量
- stock_list: 股票代码 "000001.SZ"
- period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d"
- start_time: 起始时间 "20200101" "20200101093000"
- end_time: 结束时间 "20201231" "20201231150000"
- count: 数量 -1全部/n: 从结束时间向前数n个
- dividend_type: 除权类型"none" "front" "back" "front_ratio" "back_ratio"
- fill_data: 对齐时间戳时是否填充数据,仅对K线有效,分笔周期不对齐时间戳 为True时,以缺失数据的前一条数据填充 open、high、low、close 为前一条数据的close amount、volume为0 settle、openInterest 和前一条数据相同 为False时,缺失数据所有字段填NaN
Returns
数据集,分笔数据和K线数据格式不同 period为'tick'时:{stock1 : value1, stock2 : value2, ...} stock1, stock2, ... : 合约代码 value1, value2, ... : np.ndarray 数据列表,按time增序排列 period为其他K线周期时:{field1 : value1, field2 : value2, ...} field1, field2, ... : 数据字段 value1, value2, ... : pd.DataFrame 字段对应的数据,各字段维度相同,index为stock_list,columns为time_list
650def get_full_tick(code_list): 651 ''' 652 获取盘口tick数据 653 :param code_list: (list)stock.market组成的股票代码列表 654 :return: dict 655 {'stock.market': {dict}} 656 ''' 657 client = get_client() 658 resp_json = client.get_full_tick(code_list) 659 return json.loads(resp_json)
获取盘口tick数据
Parameters
- code_list: (list)stock.market组成的股票代码列表
Returns
dict {'stock.market': {dict}}
576def get_divid_factors(stock_code, start_time='', end_time=''): 577 ''' 578 获取除权除息日及对应的权息 579 :param stock_code: (str)股票代码 580 :param date: (str)日期 581 :return: pd.DataFrame 数据集 582 ''' 583 client = get_client() 584 datas = client.get_divid_factors(stock_code, start_time, end_time) 585 import pandas as pd 586 datas = pd.DataFrame(datas).T 587 return datas
获取除权除息日及对应的权息
Parameters
- stock_code: (str)股票代码
- date: (str)日期
Returns
pd.DataFrame 数据集
543def get_l2_quote(field_list=[], stock_code='', start_time='', end_time='', count=-1): 544 ''' 545 level2实时行情 546 ''' 547 client = get_client() 548 datas = client.get_market_data3(field_list, [stock_code], 'l2quote', start_time, end_time, count, 'none', False, '', False, False) 549 if datas: 550 return datas[stock_code] 551 return None
level2实时行情
554def get_l2_order(field_list=[], stock_code='', start_time='', end_time='', count=-1): 555 ''' 556 level2逐笔委托 557 ''' 558 client = get_client() 559 datas = client.get_market_data3(field_list, [stock_code], 'l2order', start_time, end_time, count, 'none', False, '', False, False) 560 if datas: 561 return datas[stock_code] 562 return None
level2逐笔委托
565def get_l2_transaction(field_list=[], stock_code='', start_time='', end_time='', count=-1): 566 ''' 567 level2逐笔成交 568 ''' 569 client = get_client() 570 datas = client.get_market_data3(field_list, [stock_code], 'l2transaction', start_time, end_time, count, 'none', False, '', False, False) 571 if datas: 572 return datas[stock_code] 573 return None
level2逐笔成交
1013def download_history_data(stock_code, period, start_time='', end_time=''): 1014 ''' 1015 :param stock_code: 股票代码 e.g. "000001.SZ" 1016 :param period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d" 1017 :param start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 1018 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000" 1019 :param end_time: 结束时间 同上,若是未来某时刻会被视作当前时间 1020 :return: bool 是否成功 1021 ''' 1022 client = get_client() 1023 client.supply_history_data(stock_code, period, start_time, end_time)
Parameters
- stock_code: 股票代码 e.g. "000001.SZ"
- period: 周期 分笔"tick" 分钟线"1m"/"5m" 日线"1d"
- start_time: 开始时间,格式YYYYMMDD/YYYYMMDDhhmmss/YYYYMMDDhhmmss.milli,e.g."20200427" "20200427093000" "20200427093000.000" 若取某日全量历史数据,时间需要具体到秒,e.g."20200427093000"
- end_time: 结束时间 同上,若是未来某时刻会被视作当前时间
Returns
bool 是否成功
231def get_financial_data(stock_list, table_list=[], start_time='', end_time='', report_type='report_time'): 232 ''' 233 获取财务数据 234 :param stock_list: (list)合约代码列表 235 :param table_list: (list)报表名称列表 236 :param start_time: (str)起始时间 237 :param end_time: (str)结束时间 238 :param report_type: (str) 时段筛选方式 'announce_time' / 'report_time' 239 :return: 240 field: list[str] 241 date: list[int] 242 stock: list[str] 243 value: list[list[float]] 244 ''' 245 client = get_client() 246 all_table = { 247 'Balance' : 'ASHAREBALANCESHEET' 248 , 'Income' : 'ASHAREINCOME' 249 , 'CashFlow' : 'ASHARECASHFLOW' 250 , 'Capital' : 'CAPITALSTRUCTURE' 251 , 'HolderNum' : 'SHAREHOLDER' 252 , 'Top10Holder' : 'TOP10HOLDER' 253 , 'Top10FlowHolder' : 'TOP10FLOWHOLDER' 254 , 'PershareIndex' : 'PERSHAREINDEX' 255 } 256 257 if not table_list: 258 table_list = list(all_table.keys()) 259 260 all_table_upper = {table.upper() : all_table[table] for table in all_table} 261 req_list = [] 262 names = {} 263 for table in table_list: 264 req_table = all_table_upper.get(table.upper(), table) 265 req_list.append(req_table) 266 names[req_table] = table 267 268 data = {} 269 sl_len = 20 270 stock_list2 = [stock_list[i : i + sl_len] for i in range(0, len(stock_list), sl_len)] 271 for sl in stock_list2: 272 data2 = client.get_financial_data(sl, req_list, start_time, end_time, report_type) 273 for s in data2: 274 data[s] = data2[s] 275 276 import time 277 import math 278 def conv_date(data, key, key2): 279 if key in data: 280 tmp_data = data[key] 281 if math.isnan(tmp_data): 282 if key2 not in data or math.isnan(data[key2]): 283 data[key] = '' 284 else: 285 tmp_data = data[key2] 286 data[key] = time.strftime('%Y%m%d', time.localtime(tmp_data / 1000)) 287 return 288 289 result = {} 290 import pandas as pd 291 for stock in data: 292 stock_data = data[stock] 293 result[stock] = {} 294 for table in stock_data: 295 table_data = stock_data[table] 296 for row_data in table_data: 297 conv_date(row_data, 'm_anntime', 'm_timetag') 298 conv_date(row_data, 'm_timetag', '') 299 conv_date(row_data, 'declareDate', '') 300 conv_date(row_data, 'endDate', '') 301 result[stock][names[table]] = pd.DataFrame(table_data) 302 return result
获取财务数据
Parameters
- stock_list: (list)合约代码列表
- table_list: (list)报表名称列表
- start_time: (str)起始时间
- end_time: (str)结束时间
- report_type: (str) 时段筛选方式 'announce_time' / 'report_time'
Returns
field: list[str] date: list[int] stock: list[str] value: list[list[float]]
1078def download_financial_data(stock_list, table_list=[], start_time='', end_time=''): 1079 ''' 1080 :param stock_list: 股票代码列表 1081 :param table_list: 财务数据表名列表,[]为全部表 1082 可选范围:['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare'] 1083 :param start_time: 开始时间,格式YYYYMMDD,e.g."20200427" 1084 :param end_time: 结束时间 同上,若是未来某时刻会被视作当前时间 1085 ''' 1086 client = get_client() 1087 if not table_list: 1088 table_list = ['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare'] 1089 1090 for stock_code in stock_list: 1091 for table in table_list: 1092 client.supply_history_data(stock_code, table, start_time, end_time)
Parameters
- stock_list: 股票代码列表
- table_list: 财务数据表名列表,[]为全部表 可选范围:['Balance','Income','CashFlow','Capital','Top10FlowHolder','Top10Holder','HolderNum','PershareIndex', 'PerShare']
- start_time: 开始时间,格式YYYYMMDD,e.g."20200427"
- end_time: 结束时间 同上,若是未来某时刻会被视作当前时间
778def get_instrument_detail(stock_code): 779 ''' 780 获取合约信息 781 :param stock_code: 股票代码 e.g. "600000.SH" 782 :return: dict 783 ExchangeID(str):合约市场代码, InstrumentID(str):合约代码, InstrumentName(str):合约名称, ProductID(str):合约的品种ID(期货), ProductName(str)合约的品种名称(期货), 784 CreateDate(int):上市日期(期货), OpenDate(int):IPO日期(股票), ExpireDate(int):退市日或者到期日, PreClose(double):前收盘价格, SettlementPrice(double):前结算价格, 785 UpStopPrice(double):当日涨停价, DownStopPrice(double):当日跌停价, FloatVolume(double):流通股本, TotalVolume(double):总股本, LongMarginRatio(double):多头保证金率, 786 ShortMarginRatio(double):空头保证金率, PriceTick(double):最小变价单位, VolumeMultiple(int):合约乘数(对期货以外的品种,默认是1), 787 MainContract(int):主力合约标记,1、2、3分别表示第一主力合约,第二主力合约,第三主力合约, LastVolume(int):昨日持仓量, InstrumentStatus(int):合约停牌状态, 788 IsTrading(bool):合约是否可交易, IsRecent(bool):是否是近月合约, 789 ''' 790 client = get_client() 791 inst = client.get_instrument_detail(stock_code) 792 if not inst: 793 return None 794 field_list = [ 795 'ExchangeID' 796 , 'InstrumentID' 797 , 'InstrumentName' 798 , 'ProductID' 799 , 'ProductName' 800 , 'CreateDate' 801 , 'OpenDate' 802 , 'ExpireDate' 803 , 'PreClose' 804 , 'SettlementPrice' 805 , 'UpStopPrice' 806 , 'DownStopPrice' 807 , 'FloatVolume' 808 , 'TotalVolume' 809 , 'LongMarginRatio' 810 , 'ShortMarginRatio' 811 , 'PriceTick' 812 , 'VolumeMultiple' 813 , 'MainContract' 814 , 'LastVolume' 815 , 'InstrumentStatus' 816 , 'IsTrading' 817 , 'IsRecent' 818 ] 819 ret = {} 820 for field in field_list: 821 ret[field] = inst.get(field) 822 823 exfield_list = [ 824 'ProductTradeQuota' 825 , 'ContractTradeQuota' 826 , 'ProductOpenInterestQuota' 827 , 'ContractOpenInterestQuota' 828 ] 829 inst_ex = inst.get('ExtendInfo', {}) 830 for field in exfield_list: 831 ret[field] = inst_ex.get(field) 832 833 def convNum2Str(field): 834 if field in ret and isinstance(ret[field], int): 835 ret[field] = str(ret[field]) 836 convNum2Str('CreateDate') 837 convNum2Str('OpenDate') 838 return ret
获取合约信息
Parameters
- stock_code: 股票代码 e.g. "600000.SH"
Returns
dict ExchangeID(str):合约市场代码, InstrumentID(str):合约代码, InstrumentName(str):合约名称, ProductID(str):合约的品种ID(期货), ProductName(str)合约的品种名称(期货), CreateDate(int):上市日期(期货), OpenDate(int):IPO日期(股票), ExpireDate(int):退市日或者到期日, PreClose(double):前收盘价格, SettlementPrice(double):前结算价格, UpStopPrice(double):当日涨停价, DownStopPrice(double):当日跌停价, FloatVolume(double):流通股本, TotalVolume(double):总股本, LongMarginRatio(double):多头保证金率, ShortMarginRatio(double):空头保证金率, PriceTick(double):最小变价单位, VolumeMultiple(int):合约乘数(对期货以外的品种,默认是1), MainContract(int):主力合约标记,1、2、3分别表示第一主力合约,第二主力合约,第三主力合约, LastVolume(int):昨日持仓量, InstrumentStatus(int):合约停牌状态, IsTrading(bool):合约是否可交易, IsRecent(bool):是否是近月合约,
1126def get_instrument_type(stock_code): 1127 ''' 1128 判断证券类型 1129 :param stock_code: 股票代码 e.g. "600000.SH" 1130 :return: dict{str : bool} {类型名:是否属于该类型} 1131 ''' 1132 client = get_client() 1133 return client.get_stock_type(stock_code)
判断证券类型
Parameters
- stock_code: 股票代码 e.g. "600000.SH"
Returns
dict{str : bool} {类型名:是否属于该类型}
636def get_trading_dates(market, start_time='', end_time='', count=-1): 637 ''' 638 根据市场获取交易日列表 639 : param market: 市场代码 e.g. 'SH','SZ','IF','DF','SF','ZF'等 640 : param start_time: 起始时间 '20200101' 641 : param end_time: 结束时间 '20201231' 642 : param count: 数据个数,-1为全部数据 643 :return list(long) 毫秒数的时间戳列表 644 ''' 645 client = get_client() 646 datas = client.get_trading_dates_by_market(market, start_time, end_time, count) 647 return list(datas.values())
根据市场获取交易日列表 : param market: 市场代码 e.g. 'SH','SZ','IF','DF','SF','ZF'等 : param start_time: 起始时间 '20200101' : param end_time: 结束时间 '20201231' : param count: 数据个数,-1为全部数据 :return list(long) 毫秒数的时间戳列表
750def get_sector_list(): 751 ''' 752 获取板块列表 753 :return: (list[str]) 754 ''' 755 client = get_client() 756 return client.get_sector_list()
获取板块列表
Returns
(list[str])
211def get_stock_list_in_sector(sector_name): 212 ''' 213 获取板块成份股,支持客户端左侧板块列表中任意的板块,包括自定义板块 214 :param sector_name: (str)板块名称 215 :return: list 216 ''' 217 client = get_client() 218 return client.get_stock_list_in_sector(sector_name, 0)
获取板块成份股,支持客户端左侧板块列表中任意的板块,包括自定义板块
Parameters
- sector_name: (str)板块名称
Returns
list
1138def download_sector_data(): 1139 ''' 1140 下载行业板块数据 1141 ''' 1142 client = get_client() 1143 client.down_all_sector_data()
下载行业板块数据
759def add_sector(sector_name, stock_list): 760 ''' 761 增加自定义板块 762 :param sector_name: 板块名称 e.g. "我的自选" 763 :param stock_list: (list)stock.market组成的股票代码列表 764 ''' 765 client = get_client() 766 return client.add_sector(sector_name, stock_list, 1)
增加自定义板块
Parameters
- sector_name: 板块名称 e.g. "我的自选"
- stock_list: (list)stock.market组成的股票代码列表
769def remove_sector(sector_name): 770 ''' 771 删除自定义板块 772 :param sector_name: 板块名称 e.g. "我的自选" 773 ''' 774 client = get_client() 775 return client.add_sector(sector_name, [], -1)
删除自定义板块
Parameters
- sector_name: 板块名称 e.g. "我的自选"
221def get_index_weight(index_code): 222 ''' 223 获取某只股票在某指数中的绝对权重 224 :param index_code: (str)指数名称 225 :return: dict 226 ''' 227 client = get_client() 228 return client.get_weight_in_index(index_code)
获取某只股票在某指数中的绝对权重
Parameters
- index_code: (str)指数名称
Returns
dict
856def download_index_weight(): 857 ''' 858 下载指数权重数据 859 ''' 860 client = get_client() 861 client.down_index_weight()
下载指数权重数据
1145def get_holidays(): 1146 ''' 1147 获取节假日列表 1148 :return: 8位int型日期 1149 ''' 1150 client = get_client() 1151 return [str(d) for d in client.get_holidays()]
获取节假日列表
Returns
8位int型日期
1153def get_trading_calendar(market, start_time = '', end_time = '', tradetimes = False): 1154 ''' 1155 获取指定市场交易日历 1156 :param market: str 市场 1157 :param start_time: str 起始时间 '20200101' 1158 :param end_time: str 结束时间 '20201231' 1159 :param tradetimes: bool 是否包含日内交易时段 1160 :return: 1161 ''' 1162 holidays_list = get_holidays() # 19900101格式的数字 1163 import datetime 1164 now = datetime.datetime.combine(datetime.date.today(), datetime.time()) 1165 last = datetime.datetime(now.year + 1, 1, 1) 1166 1167 client = get_client() 1168 trading_list = list(client.get_trading_dates_by_market(market, start_time, end_time, -1).keys()) 1169 1170 if start_time == '' and trading_list: 1171 start_time = trading_list[0] 1172 start = datetime.datetime.strptime(start_time, "%Y%m%d") 1173 1174 if end_time == '': 1175 end_time = now.strftime("%Y%m%d") 1176 end = min(datetime.datetime.strptime(end_time, "%Y%m%d"), last) 1177 1178 # 时间戳毫秒 1179 if not trading_list: 1180 return [] 1181 1182 if not tradetimes: 1183 ret_list = trading_list 1184 while now < end: 1185 now += datetime.timedelta(days=1) 1186 if datetime.datetime.isoweekday(now) not in [6, 7]: 1187 ft = (now.strftime("%Y%m%d")) 1188 if ft not in holidays_list: 1189 ret_list.append(ft) 1190 return ret_list 1191 else: 1192 ret_map = {} 1193 trading_times = get_trade_times(market) 1194 new_trading_times_prev = [] #21-24 1195 new_trading_times_mid = [] #0-3 1196 new_trading_times_next = [] #9-15 1197 1198 for tt in trading_times: 1199 t0 = tt[0] 1200 t1 = tt[1] 1201 t2 = tt[2] 1202 try: 1203 if t1 <= 0: 1204 new_trading_times_prev.append([t0 + 86400, t1 + 86400, t2]) 1205 elif 0 <= t0 and t1 <= 10800: 1206 new_trading_times_mid.append(tt) 1207 elif t0 <= 0 and t1 <= 10800: 1208 new_trading_times_prev.append([t0 + 86400, 86400, t2]) 1209 new_trading_times_mid.append([0, t1, t2]) 1210 else: 1211 new_trading_times_next.append(tt) 1212 except: 1213 pass 1214 1215 end = end + datetime.timedelta(days=1) 1216 import copy 1217 prev_open_flag = False 1218 while start < end: 1219 weekday = datetime.datetime.isoweekday(start) 1220 ft = start.strftime("%Y%m%d") 1221 if weekday not in [6, 7]: 1222 if ft not in holidays_list: 1223 ret_map[ft] = [] 1224 if prev_open_flag: 1225 ret_map[ft].extend(new_trading_times_mid) # 早盘 1226 ret_map[ft].extend(new_trading_times_next) 1227 if weekday != 5: 1228 if (start + datetime.timedelta(days=1)).strftime("%Y%m%d") not in holidays_list: 1229 ret_map[ft].extend(new_trading_times_prev) 1230 else: 1231 if (start + datetime.timedelta(days=3)).strftime("%Y%m%d") not in holidays_list: 1232 ret_map[ft].extend(new_trading_times_prev) 1233 prev_open_flag = True 1234 else: 1235 prev_open_flag = False 1236 start += datetime.timedelta(days=1) 1237 return ret_map
获取指定市场交易日历
Parameters
- market: str 市场
- start_time: str 起始时间 '20200101'
- end_time: str 结束时间 '20201231'
- tradetimes: bool 是否包含日内交易时段
Returns
1239def get_trade_times(stockcode): 1240 ''' 1241 返回指定市场或者指定股票的交易时段 1242 :param stockcode: 市场或者代码.市场 例如 'SH' 或者 '600000.SH' 1243 :return: 返回交易时段列表,第一位是开始时间,第二位结束时间,第三位交易类型 (2 - 开盘竞价, 3 - 连续交易, 8 - 收盘竞价, 9 - 盘后定价) 1244 ''' 1245 stockcode_split = stockcode.split('.') 1246 if len(stockcode_split) == 2: 1247 ins_dl = get_instrument_detail(stockcode) 1248 product = ins_dl['ProductID'] 1249 stock = stockcode_split[0] 1250 market = stockcode_split[1] 1251 default = 0 1252 else: 1253 market = stockcode 1254 product = "" 1255 stock = "" 1256 default = 1 1257 1258 trader_time = {} 1259 try: 1260 with open(os.path.join(data_dir, '..', 'config', 'tradetimeconfig2.json'), 'r') as f: 1261 trader_time = json.loads(f.read()) 1262 except: 1263 pass 1264 1265 ret = [] 1266 import re 1267 for tdm in trader_time: 1268 if tdm['default'] == default and tdm['market'] == market: 1269 if tdm['product'] == [] and tdm['type'] == "": 1270 ret = tdm['tradetime'] #默认为product为空的 默认值 1271 if tdm['type'] != "" and re.match(tdm['type'], stock): 1272 ret = tdm['tradetime'] 1273 break 1274 if product != "" and product in tdm['product']: 1275 ret = tdm['tradetime'] 1276 break 1277 1278 import datetime 1279 def convert(t): 1280 if t == "240000" or t == "-240000": 1281 return 0 1282 if t[0] == '-': 1283 parc = datetime.datetime.strptime(t, "-%H%M%S") 1284 t = datetime.timedelta(hours=-parc.hour, minutes=-parc.minute) 1285 else: 1286 parc = datetime.datetime.strptime(t, "%H%M%S") 1287 t = datetime.timedelta(hours=parc.hour, minutes=parc.minute) 1288 return int(t.total_seconds()) 1289 ret = [[convert(timepair[0]), convert(timepair[1]), int(timepair[2])] for timepair in ret] 1290 return ret
返回指定市场或者指定股票的交易时段
Parameters
- stockcode: 市场或者代码.市场 例如 'SH' 或者 '600000.SH'
Returns
返回交易时段列表,第一位是开始时间,第二位结束时间,第三位交易类型 (2 - 开盘竞价, 3 - 连续交易, 8 - 收盘竞价, 9 - 盘后定价)