def QA_fetch_get_index_min(code, start, end, level='1min', ip=best_ip, port=7709): '指数分钟线' api = TdxHq_API() type_ = '' if str(level) in ['5', '5m', '5min', 'five']: level, type_ = 0, '5min' elif str(level) in ['1', '1m', '1min', 'one']: level, type_ = 8, '1min' elif str(level) in ['15', '15m', '15min', 'fifteen']: level, type_ = 1, '15min' elif str(level) in ['30', '30m', '30min', 'half']: level, type_ = 2, '30min' elif str(level) in ['60', '60m', '60min', '1h']: level, type_ = 3, '60min' with api.connect(ip, port): if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( level, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (25 - i) * 800, 800)) for i in range(26)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( level, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (25 - i) * 800, 800)) for i in range(26)], axis=0) data = data\ .assign(datetime=pd.to_datetime(data['datetime']), code=str(code))\ .drop(['year', 'month', 'day', 'hour', 'minute'], axis=1, inplace=False)\ .assign(date=data['datetime'].apply(lambda x: str(x)[0:10]))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(x)))\ .assign(time_stamp=data['datetime'].apply(lambda x: QA_util_time_stamp(x)))\ .assign(type=type_).set_index('datetime', drop=False, inplace=False)[start:end] # data return data.assign(datetime=data['datetime'].apply(lambda x: str(x)))
def QA_fetch_get_index_day(code, start_date, end_date, level='day', ip=best_ip, port=7709): '指数日线' api = TdxHq_API() if level in ['day', 'd', 'D', 'DAY', 'Day']: level = 9 elif level in ['w', 'W', 'Week', 'week']: level = 5 elif level in ['month', 'M', 'm', 'Month']: level = 6 elif level in ['Q', 'Quarter', 'q']: level = 10 elif level in ['y', 'Y', 'year', 'Year']: level = 11 with api.connect(ip, port): if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( level, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (25 - i) * 800, 800)) for i in range(26)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( level, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (25 - i) * 800, 800)) for i in range(26)], axis=0) data = data.assign(date=data['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(str(x)[0:10])))\ .set_index('date', drop=False, inplace=False)\ .drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1)[start_date:end_date] return data.assign(date=data['date'].apply(lambda x: str(x)[0:10]))
def _get_bars(self, market, code, ktype): data = [] tdx_market = self._trans_market(market) if tdx_market is None: print("tdx_market == None") return data tdx_ktype = self._trans_ktype(ktype) if tdx_ktype is None: print("tdx_ktype == None") return data try: ip = self.getParam('ip') port = self.getParam('port') except: ip = '119.147.212.81' port = 7709 api = TdxHq_API(raise_exception=True) with api.connect(ip, port): if (market == 'SH' and code[:3] == '000') \ or (market == 'SZ' and code[:2] == '39'): for i in range(self._max[ktype]): data += api.get_index_bars(tdx_ktype, tdx_market, code, (self._max[ktype]-1-i)*800,800) else: for i in range(self._max[ktype]): data += api.get_security_bars(tdx_ktype, tdx_market, code, (self._max[ktype]-1-i)*800,800) return data
def QA_fetch_get_index_day(code, start_date, end_date, frequence='day', ip=best_ip['stock']['ip'], port=best_ip['stock']['port']): '指数日线' api = TdxHq_API() if frequence in ['day', 'd', 'D', 'DAY', 'Day']: frequence = 9 elif frequence in ['w', 'W', 'Week', 'week']: frequence = 5 elif frequence in ['month', 'M', 'm', 'Month']: frequence = 6 elif frequence in ['Q', 'Quarter', 'q']: frequence = 10 elif frequence in ['y', 'Y', 'year', 'Year']: frequence = 11 with api.connect(ip, port): start_date = str(start_date)[0:10] today_ = datetime.date.today() lens = QA_util_get_trade_gap(start_date, today_) if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) data = data.assign(date=data['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(str(x)[0:10])))\ .set_index('date', drop=False, inplace=False)\ .assign(code=code)\ .drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1)[start_date:end_date] return data.assign(date=data['date'].apply(lambda x: str(x)[0:10]))
def QA_fetch_get_index_min(code, start, end, level='1min', ip=best_ip, port=7709): api = TdxHq_API() type_ = '' if str(level) in ['5', '5m', '5min', 'five']: level, type_ = 0, '5min' elif str(level) in ['1', '1m', '1min', 'one']: level, type_ = 8, '1min' elif str(level) in ['15', '15m', '15min', 'fifteen']: level, type_ = 1, '15min' elif str(level) in ['30', '30m', '30min', 'half']: level, type_ = 2, '30min' elif str(level) in ['60', '60m', '60min', '1h']: level, type_ = 3, '60min' with api.connect(ip, port): if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( level, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (25 - i) * 800, 800)) for i in range(26)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( level, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (25 - i) * 800, 800)) for i in range(26)], axis=0) data = data\ .assign(datetime=pd.to_datetime(data['datetime']), code=str(code))\ .drop(['year', 'month', 'day', 'hour', 'minute'], axis=1, inplace=False)\ .assign(date=data['datetime'].apply(lambda x: str(x)[0:10]))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(x)))\ .assign(time_stamp=data['datetime'].apply(lambda x: QA_util_time_stamp(x)))\ .assign(type=type_).set_index('datetime', drop=False, inplace=False)[start:end] # data return data.assign(datetime=data['datetime'].apply(lambda x: str(x)))
def _getKLineData(self): api = TdxHq_API(auto_retry=True) if api.connect('119.147.212.81', 7709): self._KLineData = api.to_df( api.get_index_bars(9, 1, self._stockCode, 0, self._stockOberCount)) # 返回DataFrame # print(self._KLineData) api.disconnect()
def QA_fetch_get_index_min(code, start, end, frequence='1min', ip=None, port=None): '指数分钟线' global best_ip if ip is None and port is None and best_ip['stock']['ip'] is None and best_ip['stock']['port'] is None: best_ip = select_best_ip() ip = best_ip['stock']['ip'] port = best_ip['stock']['port'] elif ip is None and port is None and best_ip['stock']['ip'] is not None and best_ip['stock']['port'] is not None: ip = best_ip['stock']['ip'] port = best_ip['stock']['port'] else: pass api = TdxHq_API() type_ = '' start_date = str(start)[0:10] today_ = datetime.date.today() lens = QA_util_get_trade_gap(start_date, today_) if str(frequence) in ['5', '5m', '5min', 'five']: frequence, type_ = 0, '5min' lens = 48 * lens elif str(frequence) in ['1', '1m', '1min', 'one']: frequence, type_ = 8, '1min' lens = 240 * lens elif str(frequence) in ['15', '15m', '15min', 'fifteen']: frequence, type_ = 1, '15min' lens = 16 * lens elif str(frequence) in ['30', '30m', '30min', 'half']: frequence, type_ = 2, '30min' lens = 8 * lens elif str(frequence) in ['60', '60m', '60min', '1h']: frequence, type_ = 3, '60min' lens = 4 * lens if lens > 20800: lens = 20800 with api.connect(ip, port): if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) data = data\ .assign(datetime=pd.to_datetime(data['datetime']), code=str(code))\ .drop(['year', 'month', 'day', 'hour', 'minute'], axis=1, inplace=False)\ .assign(code=code)\ .assign(date=data['datetime'].apply(lambda x: str(x)[0:10]))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(x)))\ .assign(time_stamp=data['datetime'].apply(lambda x: QA_util_time_stamp(x)))\ .assign(type=type_).set_index('datetime', drop=False, inplace=False)[start:end] # data return data.assign(datetime=data['datetime'].apply(lambda x: str(x)))
def QA_fetch_get_index_day(code, start_date, end_date, ip=best_ip, port=7709): '指数日线' QA_util_log_info(code) api = TdxHq_API() with api.connect(ip, port): data = pd.concat([api.to_df(api.get_index_bars( 9, 1 if str(code)[0] in ['0', '8', '9'] else 0, str(code), (9 - i) * 800, 800)) for i in range(10)], axis=0) data = data.assign(date=data['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(str(x)[0:10])))\ .set_index('date', drop=False, inplace=False)\ .drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1)[start_date:end_date] return data.assign(date=data['date'].apply(lambda x: str(x)[0:10]))
def QA_fetch_get_index_day(code, start_date, end_date, frequence='day', ip=None, port=None): """指数日线 1- sh 0 -sz Arguments: code {[type]} -- [description] start_date {[type]} -- [description] end_date {[type]} -- [description] Keyword Arguments: frequence {str} -- [description] (default: {'day'}) ip {[type]} -- [description] (default: {None}) port {[type]} -- [description] (default: {None}) Returns: [type] -- [description] """ ip, port = get_mainmarket_ip(ip, port) api = TdxHq_API() if frequence in ['day', 'd', 'D', 'DAY', 'Day']: frequence = 9 elif frequence in ['w', 'W', 'Week', 'week']: frequence = 5 elif frequence in ['month', 'M', 'm', 'Month']: frequence = 6 elif frequence in ['Q', 'Quarter', 'q']: frequence = 10 elif frequence in ['y', 'Y', 'year', 'Year']: frequence = 11 with api.connect(ip, port): start_date = str(start_date)[0:10] today_ = datetime.date.today() lens = QA_util_get_trade_gap(start_date, today_) if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) data = data.assign(date=data['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(str(x)[0:10])))\ .set_index('date', drop=False, inplace=False)\ .assign(code=code)\ .drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1)[start_date:end_date] return data.assign(date=data['date'].apply(lambda x: str(x)[0:10]))
def QA_fetch_get_index_day(code, start_date, end_date, frequence='day', ip=None, port=None): '指数日线' global best_ip if ip is None and port is None and best_ip['stock']['ip'] is None and best_ip['stock']['port'] is None: best_ip = select_best_ip() ip = best_ip['stock']['ip'] port = best_ip['stock']['port'] elif ip is None and port is None and best_ip['stock']['ip'] is not None and best_ip['stock']['port'] is not None: ip = best_ip['stock']['ip'] port = best_ip['stock']['port'] else: pass api = TdxHq_API() if frequence in ['day', 'd', 'D', 'DAY', 'Day']: frequence = 9 elif frequence in ['w', 'W', 'Week', 'week']: frequence = 5 elif frequence in ['month', 'M', 'm', 'Month']: frequence = 6 elif frequence in ['Q', 'Quarter', 'q']: frequence = 10 elif frequence in ['y', 'Y', 'year', 'Year']: frequence = 11 with api.connect(ip, port): start_date = str(start_date)[0:10] today_ = datetime.date.today() lens = QA_util_get_trade_gap(start_date, today_) if str(code)[0] in ['5', '1']: # ETF data = pd.concat([api.to_df(api.get_security_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) else: data = pd.concat([api.to_df(api.get_index_bars( frequence, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(lens / 800) - i) * 800, 800)) for i in range(int(lens / 800) + 1)], axis=0) data = data.assign(date=data['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=data['datetime'].apply(lambda x: QA_util_date_stamp(str(x)[0:10])))\ .set_index('date', drop=False, inplace=False)\ .assign(code=code)\ .drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1)[start_date:end_date] return data.assign(date=data['date'].apply(lambda x: str(x)[0:10]))
def QA_fetch_get_index_day(code, start_date, end_date, ip='119.147.212.81', port=7709): api = TdxHq_API() start_date = QA_util_get_real_date(start_date, trade_date_sse, 1) end_date = QA_util_get_real_date(end_date, trade_date_sse, -1) with api.connect(ip, port): data = [] for i in range(10): data += api.get_index_bars(9, 1, code, (9 - i) * 800, 800) data = api.to_df(data) data['date'] = data['datetime'].apply(lambda x: x[0:10]) data['date'] = pd.to_datetime(data['date']) data = data.set_index('date', drop=False) data = data.drop( ['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1) return data[start_date:end_date]
def ping(ip, port=7709, multithread=False): #print(ip, port, multithread) api = TdxHq_API(multithread=multithread) success = False starttime = time.time() try: with api.connect(ip, port, time_out=1): #x = api.get_security_count(0) x = api.get_index_bars(7, 1, '000001', 1, 800) if x: success = True y = api.get_security_bars(7, 0, '000001', 800, 800) if x and y: success = True except Exception as e: success = False #print(e) endtime = time.time() #print(success, endtime - starttime) return (success, endtime - starttime, ip, port)
def download_index_bars(index_code, freq='day', market=None): """获取指数 market -> 市场代码 0:深圳,1:上海 """ if not market: if stock_code[0] == '3': market = 0 else: market = 1 category = FREQUENT[freq] api = TdxHq_API() with api.connect('119.147.212.81', 7709): index = 0 stock_data = [] while True: older_data = api.get_index_bars(category, market, index_code, index * 800, 800) if older_data: stock_data = older_data + stock_data index += 1 else: break stock_df = api.to_df(stock_data) # 返回DataFrame return stock_df[ct.STOCK_COLS]
from pytdx.hq import TdxHq_API import pandas as pd import datetime from Event.Event import EventType from Stock.AnalyseKLine import AnalyseKLine #dd = DIFNewHighLogic() from Stock.KLine import KLine, KLineType api = TdxHq_API(auto_retry=True) if api.connect('119.147.212.81', 7709): data = api.to_df(api.get_index_bars(9, 1, '000905', 0, 500)) # 返回DataFrame start = datetime.datetime.now() ak = KLine(KLineType.LINE_1_D) ak.updateKLineData(data) end = datetime.datetime.now() print(end - start) print("*" * 50) print(ak.getData()) print("*" * 50) api.disconnect() quit()
class TBStockData: __serverList = [] _bestIP = [] __bestIPFile = '' __tdx = None _lastBaseHistList = pd.DataFrame() _xdxrData = None def __init__(self, autoIP = False): self.__serverList = hq_hosts self.__bestIPFile = os.path.dirname(os.path.realpath(__file__)) + '/best.ip' if autoIP: self.getBestIP() else: if os.path.exists(self.__bestIPFile): with open(self.__bestIPFile, 'r') as f: data = f.read() self._bestIP = json.loads(data) def ping(self, ip, port): api = TdxHq_API() time1 = datetime.datetime.now() try: with api.connect(ip, int(port)): if len(api.get_security_list(0, 1)) > 800: return datetime.datetime.now() - time1 else: return datetime.timedelta(9, 9, 0) except: return datetime.timedelta(9, 9, 0) def getBestIP(self): pingTimeList = [self.ping(x[1], x[2]) for x in self.__serverList] self._bestIP = self.__serverList[pingTimeList.index(min(pingTimeList))] with open(self.__bestIPFile, 'w') as f: f.write(json.dumps(self._bestIP)) def showAllIP(self): for item in self.__serverList: print item[0],'\t', item[1], '\t', item[2] def _connect(self): if self.__tdx is None: if not self._bestIP: self.getBestIP() #self.__tdx = TdxHq_API(heartbeat=True, auto_retry=True) self.__tdx = TdxHq_API(auto_retry=True) self.__tdx.connect(self._bestIP[1], int(self._bestIP[2])) #计算量比 def _setVolRaito(self, row): date = row.name histList = self._lastBaseHistList[:date] if len(histList) < 6: return np.nan return round((histList['vol'].values[-1] / 240) / (histList[-6:-1]['vol'].sum() / 1200), 3) #计算各种指标 def getData(self, df = pd.DataFrame(), indexs=['turnover', 'vol', 'ma', 'macd', 'kdj', 'cci', 'bbi', 'sar', 'trix']): indexs = [x.lower() for x in indexs] histList = pd.DataFrame() if not df.empty: histList = df.copy() elif not self._lastBaseHistList.empty: histList = self._lastBaseHistList.copy() if histList.empty: return None dayKStatus = False try: if int(time.mktime(time.strptime(str(histList.index[-1]), "%Y-%m-%d %X"))) - int(time.mktime(time.strptime(str(histList.index[-2]), "%Y-%m-%d %X"))) > 43200: #日线以上行情 dayKStatus = True except: dayKStatus = True #计算涨幅 histList['p_change'] = histList['close'].pct_change().round(5) * 100 #量比 histList['vol_ratio'] = histList.apply(self._setVolRaito, axis=1) #振幅 histList['amp'] = ((histList['high'] - histList['low']) / histList.shift()['close'] * 100).round(3) #计算换手率 if self._xdxrData is None: xdxrData = self.getXdxr(str(histList['code'].values[0])) else: xdxrData = self._xdxrData info = xdxrData[xdxrData['liquidity_after'] > 0][['liquidity_after', 'shares_after']] if dayKStatus: startDate = str(histList.index[0])[0:10] endDate = str(histList.index[-1])[0:10] info1 = info[info.index <= startDate][-1:] info = info1.append(info[info.index >= startDate]).drop_duplicates() info = info.reindex(pd.date_range(info1.index[-1], endDate)) info = info.resample('1D').last().fillna(method='pad')[startDate:endDate] #info['date'] = info.index #info['date'] = info['date'].dt.strftime('%Y-%m-%d') #info = info.set_index('date') circulate = info['liquidity_after'] * 10000 capital = info['shares_after'] * 10000 else: circulate = info['liquidity_after'].values[-1] * 10000 capital = info['shares_after'].values[-1] * 10000 #histList['circulate'] = (circulate / 10000 / 10000).round(4) if 'turnover' in indexs and dayKStatus: histList['turnover'] = (histList['vol'] * 100 / circulate).round(5) * 100 histList['turnover5'] = talib.MA(histList['turnover'].values, timeperiod=5).round(3) #stockstats转换,主要是用来计算KDJ等相关指标 #用talib计算KDJ时会与现有软件偏差大 ss = StockDataFrame.retype(histList[['high','low','open','close']]) #MACD计算 if 'macd' in indexs: difList, deaList, macdList = talib.MACD(histList['close'].values, fastperiod=12, slowperiod=26, signalperiod=9) macdList = macdList * 2 histList['macd_dif'] = difList.round(3) histList['macd_dea'] = deaList.round(3) histList['macd_value'] = macdList.round(3) histList['macd_value_ma'] = 0 try: histList['macd_value_ma'] = talib.MA(histList['macd_value'].values, timeperiod=5).round(3) except: pass histList['macd_cross_status'] = 0 macdPosList = histList['macd_dif'] > histList['macd_dea'] histList.loc[macdPosList[(macdPosList == True) & (macdPosList.shift() == False)].index, 'macd_cross_status'] = 1 histList.loc[macdPosList[(macdPosList == False) & (macdPosList.shift() == True)].index, 'macd_cross_status'] = -1 #histList[['macd_cross_status']] = histList[['macd_cross_status']].fillna(method='pad') #KDJ计算 if 'kdj' in indexs: histList['kdj_k'] = ss['kdjk'].round(3) histList['kdj_d'] = ss['kdjd'].round(3) histList['kdj_j'] = ss['kdjj'].round(3) histList['kdj_cross_status'] = 0 kdjPosList = histList['kdj_k'] >= histList['kdj_d'] histList.loc[kdjPosList[(kdjPosList == True) & (kdjPosList.shift() == False)].index, 'kdj_cross_status'] = 1 histList.loc[kdjPosList[(kdjPosList == False) & (kdjPosList.shift() == True)].index, 'kdj_cross_status'] = -1 #histList[['kdj_cross_status']] = histList[['kdj_cross_status']].fillna(method='pad') #CCI计算 if 'cci' in indexs: histList['cci'] = ss['cci'].round(3) #ma相关计算 if 'ma' in indexs: histList['ma5'] = talib.MA(histList['close'].values, timeperiod=5).round(3) histList['ma10'] = talib.MA(histList['close'].values, timeperiod=10).round(3) histList['ma20'] = talib.MA(histList['close'].values, timeperiod=20).round(3) histList['ma30'] = talib.MA(histList['close'].values, timeperiod=30).round(3) histList['ma60'] = talib.MA(histList['close'].values, timeperiod=60).round(3) histList['ma240'] = talib.MA(histList['close'].values, timeperiod=240).round(3) histList[['ma5', 'ma10', 'ma20', 'ma30', 'ma60', 'ma240']] = histList[['ma5', 'ma10', 'ma20', 'ma30', 'ma60', 'ma240']].fillna(0) #成交量计算 if 'vol' in indexs: histList['vol5'] = talib.MA(histList['vol'].values, timeperiod=5).round(3) histList['vol10'] = talib.MA(histList['vol'].values, timeperiod=10).round(3) histList['vol20'] = talib.MA(histList['vol'].values, timeperiod=20).round(3) histList['vol_zoom'] = (histList['vol'] / histList['vol5'] * 1.0).round(3) histList['vol5_vol10_cross_status'] = 0 volumePosList = histList['vol5'] >= histList['vol10'] histList.loc[volumePosList[(volumePosList == True) & (volumePosList.shift() == False)].index, 'vol5_vol10_cross_status'] = 1 histList.loc[volumePosList[(volumePosList == False) & (volumePosList.shift() == True)].index, 'vol5_vol10_cross_status'] = -1 del volumePosList histList['vol5_vol20_cross_status'] = 0 volumePosList = histList['vol5'] >= histList['vol20'] histList.loc[volumePosList[(volumePosList == True) & (volumePosList.shift() == False)].index, 'vol5_vol20_cross_status'] = 1 histList.loc[volumePosList[(volumePosList == False) & (volumePosList.shift() == True)].index, 'vol5_vol20_cross_status'] = -1 del volumePosList histList['vol10_vol20_cross_status'] = 0 volumePosList = histList['vol10'] >= histList['vol20'] histList.loc[volumePosList[(volumePosList == True) & (volumePosList.shift() == False)].index, 'vol10_vol20_cross_status'] = 1 histList.loc[volumePosList[(volumePosList == False) & (volumePosList.shift() == True)].index, 'vol10_vol20_cross_status'] = -1 #histList[['vol5_vol10_cross_status', 'vol5_vol20_cross_status', 'vol10_vol20_cross_status']] = histList[['vol5_vol10_cross_status', 'vol5_vol20_cross_status', 'vol10_vol20_cross_status']].fillna(method='pad') #bbi计算 if 'bbi' in indexs: ma3 = talib.MA(histList['close'].values, timeperiod=3) ma6 = talib.MA(histList['close'].values, timeperiod=6) ma12 = talib.MA(histList['close'].values, timeperiod=12) ma24 = talib.MA(histList['close'].values, timeperiod=24) histList['bbi'] = (ma3 + ma6 + ma12 + ma24) / 4 histList['bbi'] = histList['bbi'].round(3) #SAR计算 if 'sar' in indexs: sarList = talib.SAR(histList['high'].values, histList['low'].values, acceleration=0.04, maximum=0.2) histList['sar'] = sarList.round(3) histList['sar_cross_status'] = 0 sarPosList = histList['close'] >= histList['sar'] histList.loc[sarPosList[(sarPosList == True) & (sarPosList.shift() == False)].index, 'sar_cross_status'] = 1 histList.loc[sarPosList[(sarPosList == False) & (sarPosList.shift() == True)].index, 'sar_cross_status'] = -1 #计算TRIX if 'trix' in indexs: histList['trix'] = np.nan histList['trma'] = np.nan histList['trix_diff'] = np.nan try: trix = talib.TRIX(histList['close'].values, 12) trma = talib.MA(trix, timeperiod=20) histList['trix'] = trix.round(3) histList['trma'] = trma.round(3) histList['trix_diff'] = histList['trix'] - histList['trma'] histList['trix_cross_status'] = 0 trixPosList = histList['trix'] >= histList['trma'] histList.loc[trixPosList[(trixPosList == True) & (trixPosList.shift() == False)].index, 'trix_cross_status'] = 1 histList.loc[trixPosList[(trixPosList == False) & (trixPosList.shift() == True)].index, 'trix_cross_status'] = -1 #histList[['trix_cross_status']] = histList[['trix_cross_status']].fillna(method='pad') except: pass if 'cyc' in indexs: avePrice = histList['amount'] / (histList['vol'] * 100) histList['cyc5'] = talib.MA(avePrice.values, timeperiod=5).round(3) histList['cyc13'] = talib.MA(avePrice.values, timeperiod=13).round(3) histList['cyc34'] = talib.MA(avePrice.values, timeperiod=34).round(3) #histList['cycx'] = talib.EMA(histList['close'].values, timeperiod=histList['vol'].values * 100 / circulate).round(3) histList['cyc5_cyc13_cross_status'] = 0 volumePosList = histList['cyc5'] >= histList['cyc13'] histList.loc[volumePosList[(volumePosList == True) & (volumePosList.shift() == False)].index, 'cyc5_cyc13_cross_status'] = 1 histList.loc[volumePosList[(volumePosList == False) & (volumePosList.shift() == True)].index, 'cyc5_cyc13_cross_status'] = -1 del volumePosList histList['cyc13_cyc34_cross_status'] = 0 volumePosList = histList['cyc13'] >= histList['cyc34'] histList.loc[volumePosList[(volumePosList == True) & (volumePosList.shift() == False)].index, 'cyc13_cyc34_cross_status'] = 1 histList.loc[volumePosList[(volumePosList == False) & (volumePosList.shift() == True)].index, 'cyc13_cyc34_cross_status'] = -1 del volumePosList if 'boll' in indexs: up, mid, low = talib.BBANDS( histList['close'].values, timeperiod=20, # number of non-biased standard deviations from the mean nbdevup=2, nbdevdn=2, # Moving average type: simple moving average here matype=0) histList['boll_up'] = up.round(3) histList['boll_mid'] = mid.round(3) histList['boll_low'] = low.round(3) return histList #整理开始,结束时间,并计算相差天数 def _getDate(self, start, end): if not end: end = time.strftime('%Y-%m-%d',time.localtime()) if not start: t = int(time.mktime(time.strptime(str(end), '%Y-%m-%d'))) - 86400 * 800 start = str(time.strftime('%Y-%m-%d',time.localtime(t))) startTimestamp = int(time.mktime(time.strptime(str(start), '%Y-%m-%d'))) endTimestamp = int(time.mktime(time.strptime(str(end), '%Y-%m-%d'))) diffDayNum = int((time.time() - startTimestamp) / 86400) if diffDayNum <= 0: diffDayNum = 1 return start, end, diffDayNum #得到市场代码 def getMarketCode(self, code): code = str(code) if code[0] in ['5', '6', '9'] or code[:3] in ["009", "126", "110", "201", "202", "203", "204"]: return 1 return 0 #时间整理 def _dateStamp(self, date): datestr = str(date)[0:10] date = time.mktime(time.strptime(datestr, '%Y-%m-%d')) return date #整理时间 def _timeStamp(self, _time): if len(str(_time)) == 10: # yyyy-mm-dd格式 return time.mktime(time.strptime(_time, '%Y-%m-%d')) elif len(str(_time)) == 16: # yyyy-mm-dd hh:mm格式 return time.mktime(time.strptime(_time, '%Y-%m-%d %H:%M')) else: timestr = str(_time)[0:19] return time.mktime(time.strptime(timestr, '%Y-%m-%d %H:%M:%S')) #得到除权信息 def getXdxr(self, code): self._connect() category = { '1': '除权除息', '2': '送配股上市', '3': '非流通股上市', '4': '未知股本变动', '5': '股本变化', '6': '增发新股', '7': '股份回购', '8': '增发新股上市', '9': '转配股上市', '10': '可转债上市', '11': '扩缩股', '12': '非流通股缩股', '13': '送认购权证', '14': '送认沽权证'} data = self.__tdx.to_df(self.__tdx.get_xdxr_info(self.getMarketCode(code), code)) if len(data) >= 1: data = data\ .assign(date=pd.to_datetime(data[['year', 'month', 'day']], format='%Y-%m-%d'))\ .drop(['year', 'month', 'day'], axis=1)\ .assign(category_meaning=data['category'].apply(lambda x: category[str(x)]))\ .assign(code=str(code))\ .rename(index=str, columns={'panhouliutong': 'liquidity_after', 'panqianliutong': 'liquidity_before', 'houzongguben': 'shares_after', 'qianzongguben': 'shares_before'})\ .set_index('date', drop=False, inplace=False) xdxrData = data.assign(date=data['date'].apply(lambda x: str(x)[0:10])) #xdxrData = xdxrData.set_index('date') self._xdxrData = xdxrData return xdxrData else: return None #得到股本 def getGuben(self, code): self._connect() if self._xdxrData is None: xdxrData = self.getXdxr(code) else: xdxrData = self._xdxrData info = xdxrData[xdxrData['liquidity_after'] > 0][['liquidity_after', 'shares_after']] circulate = info['liquidity_after'].values[-1] * 10000 capital = info['shares_after'].values[-1] * 10000 return capital,circulate #按天得到标准数据 ''' ktype = D(天)/W(周)/M(月)/Q(季)/Y(年) autype = bfq(不复权)/hfq(后复权)/qfq(前复权) ''' def getDays(self, code, ktype = 'D', start = '', end = '', autype = 'qfq', indexs = ['turnover', 'vol', 'ma', 'macd', 'kdj', 'cci', 'bbi', 'sar', 'trix']): startDate, endDate, diffDayNum = self._getDate(start, end) self._connect() ktypeCode = 9 if ktype.lower() == 'd': ktypeCode = 9 elif ktype.lower() == 'w': ktypeCode = 5 elif ktype.lower() == 'm': ktypeCode = 6 elif ktype.lower() == 'q': ktypeCode = 10 elif ktype.lower() == 'y': ktypeCode = 11 histList = pd.concat([self.__tdx.to_df(self.__tdx.get_security_bars(ktypeCode, self.getMarketCode(code), code, (int(diffDayNum / 800) - i) * 800, 800)) for i in range(int(diffDayNum / 800) + 1)], axis=0) if histList.empty: return None histList = histList[histList['open'] != 0] histList = histList[histList['vol'] > 1] if not autype or autype == 'bfq': histList = histList.assign(date=histList['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=histList['datetime'].apply(lambda x: self._dateStamp(str(x)[0:10]))) histList = histList.drop(['year', 'month', 'day', 'hour', 'minute', 'datetime', 'date_stamp'], axis=1) histList = histList.set_index('date') histList = histList[startDate:endDate] self._lastBaseHistList = histList histList['p_change'] = histList['close'].pct_change().round(5) * 100 if indexs: return self.getData(indexs=indexs) else: return histList elif autype == 'qfq': bfqData = histList.assign(date=pd.to_datetime(histList['datetime'].apply(lambda x: str(x[0:10])))).assign(code=str(code))\ .assign(date_stamp=histList['datetime'].apply(lambda x: self._dateStamp(str(x)[0:10]))) bfqData = bfqData.set_index('date') bfqData = bfqData.drop( ['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1) xdxrData = self.getXdxr(code) if xdxrData is not None: info = xdxrData[xdxrData['category'] == 1] bfqData['if_trade'] = True data = pd.concat([bfqData, info[['category']] [bfqData.index[0]:]], axis=1) #data['date'] = data.index data['if_trade'].fillna(value=False, inplace=True) data = data.fillna(method='ffill') data = pd.concat([data, info[['fenhong', 'peigu', 'peigujia', 'songzhuangu']][bfqData.index[0]:]], axis=1) data = data.fillna(0) data['preclose'] = (data['close'].shift(1) * 10 - data['fenhong'] + data['peigu'] * data['peigujia']) / (10 + data['peigu'] + data['songzhuangu']) data['adj'] = (data['preclose'].shift(-1) / data['close']).fillna(1)[::-1].cumprod() data['open'] = data['open'] * data['adj'] data['high'] = data['high'] * data['adj'] data['low'] = data['low'] * data['adj'] data['close'] = data['close'] * data['adj'] data['preclose'] = data['preclose'] * data['adj'] data = data[data['if_trade']] histList = data.drop(['fenhong', 'peigu', 'peigujia', 'songzhuangu', 'if_trade', 'category', 'preclose', 'date_stamp', 'adj'], axis=1) histList = histList[startDate:endDate] self._lastBaseHistList = histList histList['p_change'] = histList['close'].pct_change().round(5) * 100 if indexs: return self.getData(indexs=indexs) else: return histList else: bfqData['preclose'] = bfqData['close'].shift(1) bfqData['adj'] = 1 histList = bfqData.drop(['preclose', 'date_stamp', 'adj'], axis=1) histList = histList[startDate:endDate] self._lastBaseHistList = histList if indexs: return self.getData(indexs=indexs) else: return histList elif autype == 'hfq': xdxrData = self.getXdxr(code) info = xdxrData[xdxrData['category'] == 1] bfqData = histList.assign(date=histList['datetime'].apply(lambda x: x[0:10])).assign(code=str(code))\ .assign(date_stamp=histList['datetime'].apply(lambda x: self._dateStamp(str(x)[0:10]))) bfqData = bfqData.set_index('date') bfqData = bfqData.drop( ['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1) bfqData['if_trade'] = True data = pd.concat([bfqData, info[['category']] [bfqData.index[0]:]], axis=1) data['if_trade'].fillna(value=False, inplace=True) data = data.fillna(method='ffill') data = pd.concat([data, info[['fenhong', 'peigu', 'peigujia', 'songzhuangu']][bfqData.index[0]:]], axis=1) data = data.fillna(0) data['preclose'] = (data['close'].shift(1) * 10 - data['fenhong'] + data['peigu'] * data['peigujia']) / (10 + data['peigu'] + data['songzhuangu']) data['adj'] = (data['preclose'].shift(-1) / data['close']).fillna(1).cumprod() data['open'] = data['open'] / data['adj'] data['high'] = data['high'] / data['adj'] data['low'] = data['low'] / data['adj'] data['close'] = data['close'] / data['adj'] data['preclose'] = data['preclose'] / data['adj'] data = data[data['if_trade']] histList = data.drop(['fenhong', 'peigu', 'peigujia', 'songzhuangu', 'if_trade', 'category', 'preclose', 'date_stamp', 'adj'], axis=1) histList = histList[startDate:endDate] self._lastBaseHistList = histList histList['p_change'] = histList['close'].pct_change().round(5) * 100 if indexs: return self.getData(indexs=indexs) else: return histList #按分钟得到标准数据 ''' ktype = 1/5/15/30/60 分钟 ''' def getMins(self, code, ktype = 1, start = '', end = '', indexs=['vol', 'ma', 'macd', 'kdj', 'cci', 'bbi', 'sar', 'trix']): startDate, endDate, diffDayNum = self._getDate(start, end) self._connect() ktypeCode = 8 if int(ktype) == 1: ktypeCode = 8 diffDayNum = 240 * diffDayNum elif int(ktype) == 5: ktypeCode = 0 diffDayNum = 48 * diffDayNum elif int(ktype) == 15: ktypeCode = 1 diffDayNum = 16 * diffDayNum elif int(ktype) == 30: ktypeCode = 2 diffDayNum = 8 * diffDayNum elif int(ktype) == 60: ktypeCode = 3 diffDayNum = 4 * diffDayNum if diffDayNum > 20800: diffDayNum = 20800 histList = pd.concat([self.__tdx.to_df(self.__tdx.get_security_bars(ktypeCode, self.getMarketCode( str(code)), str(code), (int(diffDayNum / 800) - i) * 800, 800)) for i in range(int(diffDayNum / 800) + 1)], axis=0) if histList.empty: return None histList = histList\ .assign(datetime=pd.to_datetime(histList['datetime']), code=str(code))\ .assign(date=histList['datetime'].apply(lambda x: str(x)[0:10]))\ .assign(date_stamp=histList['datetime'].apply(lambda x: self._dateStamp(x)))\ .assign(time_stamp=histList['datetime'].apply(lambda x: self._timeStamp(x))) histList['date'] = histList['datetime'] histList = histList.drop(['year', 'month', 'day', 'hour', 'minute', 'datetime', 'date_stamp', 'time_stamp'], axis=1) histList = histList.set_index('date') histList = histList[startDate:endDate] self._lastBaseHistList = histList histList['p_change'] = histList['close'].pct_change().round(5) * 100 histList['vol'] = histList['vol'] / 100.0 if indexs: return self.getData(indexs=indexs) else: return histList #按天得到指数日k线 ''' ktype = D(天)/W(周)/M(月)/Q(季)/Y(年) ''' def getIndexDays(self, code, ktype = 'D', start = '', end = '', indexs=['turnover', 'vol', 'ma', 'macd', 'kdj', 'cci', 'bbi', 'sar', 'trix']): startDate, endDate, diffDayNum = self._getDate(start, end) self._connect() ktypeCode = 9 if ktype.lower() == 'd': ktypeCode = 9 elif ktype.lower() == 'w': ktypeCode = 5 elif ktype.lower() == 'm': ktypeCode = 6 elif ktype.lower() == 'q': ktypeCode = 10 elif ktype.lower() == 'y': ktypeCode = 11 if str(code)[0] in ['5', '1']: # ETF data = pd.concat([self.__tdx.to_df(self.__tdx.get_security_bars( ktypeCode, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(diffDayNum / 800) - i) * 800, 800)) for i in range(int(diffDayNum / 800) + 1)], axis=0) else: data = pd.concat([self.__tdx.to_df(self.__tdx.get_index_bars( ktypeCode, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(diffDayNum / 800) - i) * 800, 800)) for i in range(int(diffDayNum / 800) + 1)], axis=0) histList = data.assign(date=data['datetime'].apply(lambda x: str(x[0:10]))).assign(code=str(code))\ .assign(date_stamp=data['datetime'].apply(lambda x: self._dateStamp(str(x)[0:10])))\ .assign(code=code) if histList.empty: return None histList = histList.drop(['year', 'month', 'day', 'hour', 'minute', 'datetime', 'date_stamp', 'up_count', 'down_count'], axis=1) histList = histList.set_index('date') histList = histList[startDate:endDate] self._lastBaseHistList = histList histList['p_change'] = histList['close'].pct_change().round(5) * 100 if indexs: return self.getData(indexs=indexs) else: return histList #按分钟得到标准数据 ''' ktype = 1/5/15/30/60 分钟 ''' def getIndexMins(self, code, ktype = 1, start = '', end = '', indexs=['vol', 'ma', 'macd', 'kdj', 'cci', 'bbi', 'sar', 'trix']): startDate, endDate, diffDayNum = self._getDate(start, end) self._connect() ktypeCode = 8 if int(ktype) == 1: ktypeCode = 8 diffDayNum = 240 * diffDayNum elif int(ktype) == 5: ktypeCode = 0 diffDayNum = 48 * diffDayNum elif int(ktype) == 15: ktypeCode = 1 diffDayNum = 16 * diffDayNum elif int(ktype) == 30: ktypeCode = 2 diffDayNum = 8 * diffDayNum elif int(ktype) == 60: ktypeCode = 3 diffDayNum = 4 * diffDayNum if diffDayNum > 20800: diffDayNum = 20800 if str(code)[0] in ['5', '1']: # ETF data = pd.concat([self.__tdx.to_df(self.__tdx.get_security_bars( ktypeCode, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(diffDayNum / 800) - i) * 800, 800)) for i in range(int(diffDayNum / 800) + 1)], axis=0) else: data = pd.concat([self.__tdx.to_df(self.__tdx.get_index_bars( ktypeCode, 1 if str(code)[0] in ['0', '8', '9', '5'] else 0, code, (int(diffDayNum / 800) - i) * 800, 800)) for i in range(int(diffDayNum / 800) + 1)], axis=0) histList = data.assign(datetime=pd.to_datetime(data['datetime']), code=str(code))\ .assign(date=data['datetime'].apply(lambda x: str(x)[0:10]))\ .assign(date_stamp=data['datetime'].apply(lambda x: self._dateStamp(x)))\ .assign(time_stamp=data['datetime'].apply(lambda x: self._timeStamp(x))) if histList.empty: return None histList['date'] = histList['datetime'] histList = histList.drop(['year', 'month', 'day', 'hour', 'minute', 'datetime', 'date_stamp', 'time_stamp', 'up_count', 'down_count'], axis=1) histList = histList.set_index('date') histList = histList[startDate:endDate] self._lastBaseHistList = histList histList['p_change'] = histList['close'].pct_change().round(5) * 100 if indexs: return self.getData(indexs=indexs) else: return histList #实时逐笔 ''' 0买 1卖 2中性 ''' def getRealtimeTransaction(self, code): self._connect() try: data = pd.concat([self.__tdx.to_df(self.__tdx.get_transaction_data( self.getMarketCode(str(code)), code, (2 - i) * 2000, 2000)) for i in range(3)], axis=0) if 'value' in data.columns: data = data.drop(['value'], axis=1) data = data.dropna() day = datetime.date.today() histList = data.assign(date=str(day)).assign(datetime=pd.to_datetime(data['time'].apply(lambda x: str(day) + ' ' + str(x))))\ .assign(code=str(code)).assign(order=range(len(data.index))) histList['money'] = histList['price'] * histList['vol'] * 100 histList['type'] = histList['buyorsell'] histList['type'].replace([0,1,2], ['B','S','N'], inplace = True) histList = histList.drop(['order', 'buyorsell'], axis=1).reset_index() return histList except: return None #历史逐笔 ''' 0买 1卖 2中性 ''' def getHistoryTransaction(self, code, date): self._connect() try: data = pd.concat([self.__tdx.to_df(self.__tdx.get_history_transaction_data( self.getMarketCode(str(code)), code, (2 - i) * 2000, 2000, int(str(date).replace('-', '')))) for i in range(3)], axis=0) if 'value' in data.columns: data = data.drop(['value'], axis=1) data = data.dropna() #day = datetime.date.today() day = date histList = data.assign(date=str(day)).assign(datetime=pd.to_datetime(data['time'].apply(lambda x: str(day) + ' ' + str(x))))\ .assign(code=str(code)).assign(order=range(len(data.index))) histList['money'] = histList['price'] * histList['vol'] * 100 histList['type'] = histList['buyorsell'] histList['type'].replace([0,1,2], ['B','S','N'], inplace = True) histList = histList.drop(['order', 'buyorsell'], axis=1).reset_index() return histList except: return None #实时分时数据 def getRealtimeMinuteTime(self, code): self._connect() date = str(time.strftime('%Y-%m-%d',time.localtime())) morningData = pd.date_range(start=str(date) + ' 09:31', end=str(date) + ' 11:30', freq = 'min') morningDF = pd.DataFrame(index=morningData) afternoonData = pd.date_range(start=str(date) + ' 13:01',end=str(date) + ' 15:00', freq = 'min') afternoonDF = pd.DataFrame(index=afternoonData) timeData = morningDF.append(afternoonDF) histList = self.__tdx.to_df(self.__tdx.get_minute_time_data( self.getMarketCode(str(code)), code)) #非标准均价计算 money = histList['price'] * histList['vol'] * 100 histList['money'] = money.round(2) totalMoney = money.cumsum() totalVol = histList['vol'].cumsum() histList['ave'] = totalMoney / (totalVol * 100) histList['ave'] = histList['ave'].round(3) histList['datetime'] = timeData.index[0:len(histList)] histList['date'] = histList['datetime'].apply(lambda x: x.strftime('%Y-%m-%d')) histList['time'] = histList['datetime'].apply(lambda x: x.strftime('%H:%M')) histList = histList.reset_index() return histList #历史分时数据 def getHistoryMinuteTime(self, code, date): self._connect() morningData = pd.date_range(start=str(date) + ' 09:31', end=str(date) + ' 11:30', freq = 'min') morningDF = pd.DataFrame(index=morningData) afternoonData = pd.date_range(start=str(date) + ' 13:01',end=str(date) + ' 15:00', freq = 'min') afternoonDF = pd.DataFrame(index=afternoonData) timeData = morningDF.append(afternoonDF) histList = self.__tdx.to_df(self.__tdx.get_history_minute_time_data( self.getMarketCode(str(code)), code, int(str(date).replace('-', '')))) #非标准均价计算 money = histList['price'] * histList['vol'] * 100 histList['money'] = money.round(2) totalMoney = money.cumsum() totalVol = histList['vol'].cumsum() histList['ave'] = totalMoney / (totalVol * 100) histList['ave'] = histList['ave'].round(3) histList['datetime'] = timeData.index[0:len(histList)] histList['date'] = histList['datetime'].apply(lambda x: x.strftime('%Y-%m-%d')) histList['time'] = histList['datetime'].apply(lambda x: x.strftime('%H:%M')) histList = histList.reset_index() return histList #实时报价(五档行情) ''' market => 市场 active1 => 活跃度 price => 现价 last_close => 昨收 open => 开盘 high => 最高 low => 最低 reversed_bytes0 => 保留 reversed_bytes1 => 保留 vol => 总量 cur_vol => 现量 amount => 总金额 s_vol => 内盘 b_vol => 外盘 reversed_bytes2 => 保留 reversed_bytes3 => 保留 bid1 => 买一价 ask1 => 卖一价 bid_vol1 => 买一量 ask_vol1 => 卖一量 bid2 => 买二价 ask2 => 卖二价 bid_vol2 => 买二量 ask_vol2 => 卖二量 bid3 => 买三价 ask3 => 卖三价 bid_vol3 => 买三量 ask_vol3 => 卖三量 bid4 => 买四价 ask4 => 卖四价 bid_vol4 => 买四量 ask_vol4 => 卖四量 bid5 => 买五价 ask5 => 卖五价 bid_vol5 => 买五量 ask_vol5 => 卖五量 reversed_bytes4 => 保留 reversed_bytes5 => 保留 reversed_bytes6 => 保留 reversed_bytes7 => 保留 reversed_bytes8 => 保留 reversed_bytes9 => 涨速 active2 => 活跃度 ''' def getRealtimeQuotes(self, codeList): self._connect() itemList = [] for item in codeList: itemList.append((self.getMarketCode(item), item)) histList = self.__tdx.to_df(self.__tdx.get_security_quotes(itemList)) histList = histList.set_index('code') return histList #计算指定日期成交量细节 def getVolAnalysis(self, code, date): self._connect() if str(time.strftime('%Y-%m-%d',time.localtime())) == str(date): if int(time.strftime('%H%M',time.localtime())) > 1600: volList = self.getHistoryTransaction(code, date) else: volList = self.getRealtimeTransaction(code) else: volList = self.getHistoryTransaction(code, date) if volList is None: return None guben,circulate = self.getGuben(code) if not self._lastBaseHistList.empty: histList = self._lastBaseHistList.copy() else: histList = self.getDays(code, end=date, indexs=[]) #涨停单数量 limitVol = round(histList[-5:]['vol'].mean() * 0.0618) #超大单,先转成市值,再转回成手数 superVol = float(circulate) * float(histList['close'].values[-1]) * 0.000618 / float(histList['close'].values[-1]) / 100 #大单 bigVol = round(superVol * 0.518) #中单 middleVol = round(superVol * 0.382) #小单 smallVol = round(superVol * 0.191) #买单统计 buyVolList = volList[volList['type'] == 'B'] totalBuyVolNum = buyVolList['vol'].sum() mainBuyVolNum = buyVolList[buyVolList['vol'] >= bigVol]['vol'].sum() limitBuyVolNum = math.ceil(buyVolList[(buyVolList['vol'] >= limitVol)]['vol'].sum() / limitVol) superBuyVolNum = math.ceil(buyVolList[(buyVolList['vol'] < limitVol) & (buyVolList['vol'] >= superVol)]['vol'].sum() / superVol) bigBuyVolNum = math.ceil(buyVolList[(buyVolList['vol'] < superVol) & (buyVolList['vol'] >= bigVol)]['vol'].sum() / bigVol) middleBuyVolNum = math.ceil(buyVolList[(buyVolList['vol'] < bigVol) & (buyVolList['vol'] >= middleVol)]['vol'].sum() / middleVol) smallBuyVolNum = math.ceil(buyVolList[(buyVolList['vol'] < middleVol) & (buyVolList['vol'] >= smallVol)]['vol'].sum() / smallVol) microBuyVolNum = len(buyVolList[(buyVolList['vol'] < smallVol)]) #print limitBuyVolNum,superBuyVolNum,bigBuyVolNum,middleBuyVolNum,smallBuyVolNum,microBuyVolNum #卖单统计 sellVolList = volList[volList['type'] == 'S'] totalSellVolNum = sellVolList['vol'].sum() mainSellVolNum = sellVolList[sellVolList['vol'] >= bigVol]['vol'].sum() limitSellVolNum = math.ceil(sellVolList[(sellVolList['vol'] >= limitVol)]['vol'].sum() / limitVol) superSellVolNum = math.ceil(sellVolList[(sellVolList['vol'] < limitVol) & (sellVolList['vol'] >= superVol)]['vol'].sum() / superVol) bigSellVolNum = math.ceil(sellVolList[(sellVolList['vol'] < superVol) & (sellVolList['vol'] >= bigVol)]['vol'].sum() / bigVol) middleSellVolNum = math.ceil(sellVolList[(sellVolList['vol'] < bigVol) & (sellVolList['vol'] >= middleVol)]['vol'].sum() / middleVol) smallSellVolNum = math.ceil(sellVolList[(sellVolList['vol'] < middleVol) & (sellVolList['vol'] >= smallVol)]['vol'].sum() / smallVol) microSellVolNum = len(sellVolList[(sellVolList['vol'] < smallVol)]) #print limitSellVolNum,superSellVolNum,bigSellVolNum,middleSellVolNum,smallSellVolNum,microSellVolNum #计算吸筹线 #主力标准吸筹金额 mainBaseMoney = round(histList['close'].values[-1] * circulate * 0.001 / 10000 / 10000, 4) #主力强力吸筹金额 mainBigMoney = round(histList['close'].values[-1] * circulate * 0.003 / 10000 / 10000, 4) #资金统计 totalMoney = round(volList['money'].sum() / 10000 / 10000, 4) totalBuyMoney = round(buyVolList['money'].sum() / 10000 / 10000, 4) totalSellMoney = round(sellVolList['money'].sum() / 10000 / 10000, 4) totalAbsMoney = round(totalBuyMoney - totalSellMoney, 3) mainMoney = round(volList[volList['vol'] >= bigVol]['money'].sum() / 10000 / 10000, 4) mainBuyMoney = round(buyVolList[buyVolList['vol'] >= bigVol]['money'].sum() / 10000 / 10000, 4) mainSellMoney = round(sellVolList[sellVolList['vol'] >= bigVol]['money'].sum() / 10000 / 10000, 4) mainAbsMoney = round(mainBuyMoney - mainSellMoney, 3) mainRate = 0 try: mainRate = round((mainBuyMoney + mainSellMoney) / totalMoney * 100, 2) except: pass mainBuyRate = 0 try: mainBuyRate = round(mainBuyMoney / (mainBuyMoney + mainSellMoney) * 100, 2) except: pass #print totalAbsMoney,mainAbsMoney,totalMoney,totalBuyMoney,totalSellMoney,mainBuyMoney,mainSellMoney,mainRate,mainBuyRate #成交笔数 volNum = len(volList) #平均每笔交易价格 aveTradePrice = round(totalMoney / volNum * 10000 * 10000, 2) #平均每股买价格 avePerShareBuyPrice = 0 try: avePerShareBuyPrice = round(totalBuyMoney * 10000 * 10000 / (totalBuyVolNum * 100), 3) except: pass #主力平均每股买价格 mainAvePerShareBuyPrice = 0 try: mainAvePerShareBuyPrice = round(mainBuyMoney * 10000 * 10000 / (mainBuyVolNum * 100), 3) except: pass #平均每股卖价格 avePerShareSellPrice = 0 try: avePerShareSellPrice = round(totalSellMoney * 10000 * 10000 / (totalSellVolNum * 100), 3) except: pass #主力平均每股卖价格 mainAvePerShareSellPrice = 0 try: mainAvePerShareSellPrice = round(mainSellMoney * 10000 * 10000 / (mainSellVolNum * 100), 3) except: pass #print totalMoney,volNum,aveVolPrice * 10000 * 10000 statData = {} statData['limit_buy_vol_num'] = limitBuyVolNum statData['super_buy_vol_num'] = superBuyVolNum statData['big_buy_vol_num'] = bigBuyVolNum statData['middle_buy_vol_num'] = middleBuyVolNum statData['small_buy_vol_num'] = smallBuyVolNum statData['micro_buy_vol_num'] = microBuyVolNum statData['limit_sell_vol_num'] = limitSellVolNum statData['super_sell_vol_num'] = superSellVolNum statData['big_sell_vol_num'] = bigSellVolNum statData['middle_sell_vol_num'] = middleSellVolNum statData['small_sell_vol_num'] = smallSellVolNum statData['micro_sell_vol_num'] = microSellVolNum statData['total_abs_money'] = totalAbsMoney statData['main_abs_money'] = mainAbsMoney statData['total_money'] = totalMoney statData['total_buy_money'] = totalBuyMoney statData['total_sell_money'] = totalSellMoney statData['main_money'] = mainMoney statData['main_buy_money'] = mainBuyMoney statData['main_sell_money'] = mainSellMoney statData['main_rate'] = mainRate statData['main_buy_rate'] = mainBuyRate statData['trade_num'] = volNum statData['vol_num'] = volList['vol'].sum() statData['ave_trade_price'] = aveTradePrice statData['main_base_money'] = mainBaseMoney statData['main_big_money'] = mainBigMoney statData['ave_per_share_buy_price'] = avePerShareBuyPrice statData['ave_per_share_sell_price'] = avePerShareSellPrice statData['main_ave_per_share_buy_price'] = mainAvePerShareBuyPrice statData['main_ave_per_share_sell_price'] = mainAvePerShareSellPrice statData['circulate_money'] = round(circulate * histList['close'].values[-1] / 10000 / 10000, 4) return statData #输出ebk文件 def outputEbk(self, stockList, ebkPath = ''): if len(ebkPath) <= 0: ebkPath = os.getcwd() + '/' + sys.argv[0][0:-3] + '.' + str(time.strftime('%Y%m%d',time.localtime())) + '.ebk' if not isinstance(stockList,list): return False fp = open(ebkPath, "a") fp.write('\r\n') #ebk第一行为空行 for code in stockList: if self.getMarketCode(code) == 1: fp.write('1' + code) else: fp.write('0' + code) fp.write('\r\n') fp.close() return True #输出sel文件 def outputSel(self, stockList, selPath = ''): import struct if len(selPath) <= 0: selPath = os.getcwd() + '/' + sys.argv[0][0:-3] + '.' + str(time.strftime('%Y%m%d',time.localtime())) + '.sel' if not isinstance(stockList,list): return False stocks = [] for code in stockList: if self.getMarketCode(code) == 1: stocks.append('\x07\x11' + code) else: stocks.append('\x07\x21' + code) with open(selPath, 'ab') as fp: data = struct.pack('H', len(stocks)).decode() + ''.join(stocks) fp.write(data.encode()) return True #ebk to sel def ebk2sel(self, ebkPath): import struct if not os.path.exists(ebkPath): return False selPath = ebkPath.replace('.ebk', '.sel') stocks = [] with open(ebkPath, 'r') as ebkfp: for code in ebkfp: code = code.strip() if len(code) > 0: if self.getMarketCode(code[1:]) == 1: stocks.append('\x07\x11' + code[1:]) else: stocks.append('\x07\x21' + code[1:]) with open(selPath, 'wb') as selfp: data = struct.pack('H', len(stocks)).decode() + ''.join(stocks) selfp.write(data.encode()) return True #sel to ebk def sel2ebk(self, selPath): import struct if not os.path.exists(selPath): return False ebkPath = selPath.replace('.sel', '.ebk') with open(selPath, 'rb') as selfp: ebkfp = open(ebkPath, "a") cnt = struct.unpack('<H', selfp.read(2))[0] for _ in range(cnt): data = selfp.readline(8).decode() exch = '1' if data[1] == '\x11' else '0' code = exch + data[2:] ebkfp.write(code + '\r\n') ebkfp.close() return True
class StdQuotes(object): """股票市场实时行情""" bestip = ('47.103.48.45', 7709) def __init__(self, **kwargs): try: default = settings.get('SERVER').get('HQ')[0] self.bestip = config.get('BESTIP').get('HQ', default) except ValueError: self.config = None self.client = TdxHq_API(**kwargs) def traffic(self): with self.client.connect(*self.bestip): return self.client.get_traffic_stats() def quotes(self, symbol=[]): ''' 获取实时日行情数据 :param symbol: 股票代码 :return: pd.dataFrame or None ''' logger.debug(type(logger)) if type(symbol) is str: symbol = [symbol] with self.client.connect(*self.bestip): symbol = get_stock_markets(symbol) result = self.client.get_security_quotes(symbol) return to_data(result) def bars(self, symbol='000001', frequency='9', start='0', offset='100'): ''' 获取实时日K线数据 :param symbol: 股票代码 :param frequency: 数据类别 :param market: 证券市场 :param start: 开始位置 :param offset: 每次获取条数 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_security_bars(int(frequency), int(market), str(symbol), int(start), int(offset)) return to_data(result) def stock_count(self, market=MARKET_SH): ''' 获取市场股票数量 :param market: 股票市场代码 sh 上海, sz 深圳 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): result = self.client.get_security_count(market=market) return result def stocks(self, market=MARKET_SH): ''' 获取股票列表 :param market: :return: ''' with self.client.connect(*self.bestip): counts = self.client.get_security_count(market=market) stocks = None for start in tqdm(range(0, counts, 1000)): result = self.client.get_security_list(market=market, start=start) stocks = pandas.concat( [stocks, to_data(result)], ignore_index=True) if start > 1 else to_data(result) return stocks def index_bars(self, symbol='000001', frequency='9', start='0', offset='100'): ''' 获取指数k线 :param symbol: :param frequency: :param start: :param offset: :return: ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_index_bars(frequency=frequency, market=market, code=symbol, start=start, count=offset) return to_data(result) def minute(self, symbol=''): ''' 获取实时分时数据 :param market: 证券市场 :param symbol: 股票代码 :return: pd.DataFrame ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_minute_time_data(market=market, code=symbol) return to_data(result) def minutes(self, symbol='', date='20191023'): ''' 分时历史数据 :param market: :param symbol: :param date: :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_history_minute_time_data(market=market, code=symbol, date=date) return to_data(result) def transaction(self, symbol='', start=0, offset=10): ''' 查询分笔成交 :param market: 市场代码 :param symbol: 股票代码 :param start: 起始位置 :param offset: 请求数量 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_transaction_data(int(market), symbol, int(start), int(offset)) return to_data(result) def transactions(self, symbol='', start=0, offset=10, date='20170209'): ''' 查询历史分笔成交 参数:市场代码, 股票代码,起始位置,日期 数量 如: 0,000001,0,10,20170209 :param symbol: 股票代码 :param start: 起始位置 :param offset: 数量 :param date: 日期 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol, string=False) result = self.client.get_history_transaction_data(market=market, code=symbol, start=start, count=offset, date=date) return to_data(result) def F10C(self, symbol=''): ''' 查询公司信息目录 :param market: 市场代码 :param symbol: 股票代码 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_company_info_category(int(market), symbol) return result def F10(self, symbol='', name=''): ''' 读取公司信息详情 :param name: 公司 F10 标题 :param symbol: 股票代码 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): result = {} market = get_stock_market(symbol, string=False) frequency = self.client.get_company_info_category( int(market), symbol) if name: for x in frequency: if x['name'] == name: return self.client.get_company_info_content( market=market, code=symbol, filename=x['filename'], start=x['start'], length=x['length']) for x in frequency: result[x['name']] = self.client.get_company_info_content( market=market, code=symbol, filename=x['filename'], start=x['start'], length=x['length']) else: pass return result def xdxr(self, symbol=''): ''' 读取除权除息信息 :param market: 市场代码 :param symbol: 股票代码 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_xdxr_info(int(market), symbol) return to_data(result) def finance(self, symbol='000001'): ''' 读取财务信息 :param symbol: :return: ''' with self.client.connect(*self.bestip): market = get_stock_market(symbol) result = self.client.get_finance_info(market=market, code=symbol) return to_data(result) def k(self, symbol='', begin=None, end=None): ''' 读取k线信息 :param symbol: :param begin: 开始日期 :param end: 截止日期 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): result = self.client.get_k_data(symbol, begin, end) return to_data(result) def index(self, symbol='000001', market=MARKET_SH, frequency='9', start=1, offset=2): ''' 获取指数k线 K线种类: - 0 5分钟K线 - 1 15分钟K线 - 2 30分钟K线 - 3 1小时K线 - 4 日K线 - 5 周K线 - 6 月K线 - 7 1分钟 - 8 1分钟K线 - 9 日K线 - 10 季K线 - 11 年K线 :param symbol: 股票代码 :param frequency: 数据类别 :param market: 证券市场 :param start: 开始位置 :param offset: 每次获取条数 :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): result = self.client.get_index_bars(int(frequency), int(market), str(symbol), int(start), int(offset)) return to_data(result) def block(self, tofile="block.dat"): ''' 获取证券板块信息 :param tofile: :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): result = self.client.get_and_parse_block_info(tofile) return to_data(result)
def test_all_functions(multithread, heartbeat, auto_retry, raise_exception): api = TdxHq_API(multithread=multithread, heartbeat=heartbeat, auto_retry=auto_retry, raise_exception=raise_exception) with api.connect(time_out=30): log.info("获取股票行情") stocks = api.get_security_quotes([(0, "000001"), (1, "600300")]) assert stocks is not None assert type(stocks) is list # 方法2 stocks = api.get_security_quotes(0, "000001") assert stocks is not None assert type(stocks) is list # 方法3 stocks = api.get_security_quotes((0, "000001")) assert stocks is not None assert type(stocks) is list log.info("获取k线") data = api.get_security_bars(9, 0, '000001', 4, 3) assert data is not None assert type(data) is list assert len(data) == 3 log.info("获取 深市 股票数量") assert api.get_security_count(0) > 0 log.info("获取股票列表") stocks = api.get_security_list(1, 0) assert stocks is not None assert type(stocks) is list assert len(stocks) > 0 log.info("获取指数k线") data = api.get_index_bars(9, 1, '000001', 1, 2) assert data is not None assert type(data) is list assert len(data) == 2 log.info("查询分时行情") data = api.get_minute_time_data(TDXParams.MARKET_SH, '600300') assert data is not None log.info("查询历史分时行情") data = api.get_history_minute_time_data( TDXParams.MARKET_SH, '600300', 20161209) assert data is not None assert type(data) is list assert len(data) > 0 log.info("查询分时成交") data = api.get_transaction_data(TDXParams.MARKET_SZ, '000001', 0, 30) assert data is not None assert type(data) is list log.info("查询历史分时成交") data = api.get_history_transaction_data( TDXParams.MARKET_SZ, '000001', 0, 10, 20170209) assert data is not None assert type(data) is list assert len(data) == 10 log.info("查询公司信息目录") data = api.get_company_info_category(TDXParams.MARKET_SZ, '000001') assert data is not None assert type(data) is list assert len(data) > 0 start = data[0]['start'] length = data[0]['length'] log.info("读取公司信息-最新提示") data = api.get_company_info_content( 0, '000001', '000001.txt', start, length) assert data is not None assert len(data) > 0 log.info("读取除权除息信息") data = api.get_xdxr_info(1, '600300') assert data is not None assert type(data) is list assert len(data) > 0 log.info("读取财务信息") data = api.get_finance_info(0, '000001') assert data is not None assert type(data) is OrderedDict assert len(data) > 0 log.info("日线级别k线获取函数") data = api.get_k_data('000001', '2017-07-01', '2017-07-10') assert type(data) is pd.DataFrame assert len(data) == 6 log.info("获取板块信息") data = api.get_and_parse_block_info(TDXParams.BLOCK_FG) assert data is not None assert type(data) is list assert len(data) > 0
print(data2) print("获取股票行情") stocks = api.get_security_quotes([(0, "000002"), (1, "600300")]) print(stocks) print("获取k线") data = api.get_security_bars(9, 0, '000001', 4, 3) print(data) print("获取 深市 股票数量") print(api.get_security_count(0)) print("获取股票列表") stocks = api.get_security_list(1, 255) print(stocks) print("获取指数k线") data = api.get_index_bars(9, 1, '000001', 1, 2) print(data) print("查询分时行情") data = api.get_minute_time_data(1, '600300') print(data) print("查询历史分时行情") data = api.get_history_minute_time_data(1, '600300', 20161209) print(data) print("查询分时成交") data = api.get_transaction_data(1, '000002', 0, 30) print(data) print("查询历史分时成交") data = api.get_history_transaction_data(2, '600302', 0, 10, 20170209) print(data) print("查询公司信息目录") data = api.get_company_info_category(1, '000003')
class TdxHelper: ip_list = [{ 'ip': '119.147.212.81', 'port': 7709 }, { 'ip': '60.12.136.250', 'port': 7709 }] def __init__(self): #连接tdx接口 self.api = TdxHq_API() if not self.api.connect('60.12.136.250', 7709): print("服务器连接失败!") # pandas数据显示设置 pd.set_option('display.max_columns', None) # 显示所有列 #pd.set_option('display.max_rows', None) # 显示所有行 # mysql对象 self.mysql = mysqlHelper(config.mysql_host, config.mysql_username, bluedothe.mysql_password, config.mysql_dbname) # pandas的mysql对象 self.engine = create_engine( f'mysql+pymysql://{config.mysql_username}:{bluedothe.mysql_password}@{config.mysql_host}/{config.mysql_dbname}?charset=utf8' ) #断开tdx接口连接 def close_connect(self): self.api.disconnect() #获取k线,最后一个参数day,说明需要获取的数量,本接口只获取从最近交易日往前的数据 #输入参数:五个参数分别为:category(k线),市场代码(0:深圳,1:上海),股票代码,开始位置(从最近交易日向前取,0表示最近交易日),返回的记录条数 #K线种类: 0 5分钟K线; 1 15分钟K线; 2 30分钟K线; 3 1小时K线; 4 日K线;5 周K线;6 月K线;7 1分钟;8 1分钟K线; 9 日K线;10 季K线;11 年K线 #返回值:open,close,high,low,vol,amount,year,month,day,hour,minute,datetime # csv格式:code,ts_code,trade_date(缩写),trade_time,time_index,open,high,low,close,amount,volume def get_security_bars(self, category, market, code, start=0, count=240): dict = {0: 'SZ', 1: 'SH'} ts_code = code + "." + dict[market] order = [ 'code', 'ts_code', 'trade_date', 'trade_time', 'time_index', 'open', 'high', 'low', 'close', 'amount', 'volume' ] #df = self.api.get_security_bars(9, 0, '000001', 0, 10) # 返回普通list df = self.api.to_df( self.api.get_security_bars(category, market, code, start, count)) # 返回DataFrame if df.empty: return df df.insert(0, 'ts_code', ts_code) df.insert(0, 'code', code) df['trade_time'] = df['datetime'].apply(lambda x: str(x)[11:19]) df['time_index'] = df['trade_time'].apply( lambda x: datatime_util.stockTradeTime2Index(x)) df['trade_date'] = df['datetime'].apply( lambda x: (str(x)[0:10]).replace('-', '')) df.rename(columns={'vol': 'volume'}, inplace=True) df.drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1, inplace=True) df['volume'] = df['volume'].apply(lambda x: int(x)) #取整 df.loc[df['amount'] == 5.877471754111438e-39, 'amount'] = 0 #列值根据条件筛选后修改为0 df = df[order] filename = config.tdx_csv_minline1_all + ts_code + ".csv" if os.path.isfile(filename): df.to_csv(filename, index=False, mode='a', header=False, sep=',', encoding="utf_8_sig") else: df.to_csv(filename, index=False, mode='w', header=True, sep=',', encoding="utf_8_sig") print("新增加的一分钟all股票数据:", filename) # 获取1分钟k线,最后一个参数说明需要获取的数量,本接口只获取从最近交易日往前的数据 # 输入参数:五个参数分别为:category(k线),市场代码(0:深圳,1:上海),股票代码,开始位置(从最近交易日向前取,0表示最近交易日),返回的记录条数 # K线种类: 0 5分钟K线; 1 15分钟K线; 2 30分钟K线; 3 1小时K线; 4 日K线;5 周K线;6 月K线;7 1分钟;8 1分钟K线; 9 日K线;10 季K线;11 年K线 # 返回值:open,close,high,low,vol,amount,year,month,day,hour,minute,datetime # csv格式:code,ts_code,trade_date(缩写),trade_time,time_index,open,high,low,close,amount,volume def get_security_bars_minute1(self, category, market, code, start, count): dict = {0: 'SZ', 1: 'SH'} ts_code = code + "." + dict[market] order = [ 'code', 'ts_code', 'trade_date', 'trade_time', 'time_index', 'open', 'high', 'low', 'close', 'amount', 'volume' ] # df = self.api.get_security_bars(9, 0, '000001', 0, 10) # 返回普通list df = self.api.to_df( self.api.get_security_bars(category, market, code, start, count)) # 返回DataFrame if df.empty: return df.insert(0, 'ts_code', ts_code) df.insert(0, 'code', code) df['trade_time'] = df['datetime'].apply(lambda x: str(x)[11:19]) df['time_index'] = df['trade_time'].apply( lambda x: datatime_util.stockTradeTime2Index(x)) df['trade_date'] = df['datetime'].apply( lambda x: (str(x)[0:10]).replace('-', '')) df.rename(columns={'vol': 'volume'}, inplace=True) df.drop(['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1, inplace=True) df['volume'] = df['volume'].apply(lambda x: int(x)) # 取整 df.loc[df['amount'] == 5.877471754111438e-39, 'amount'] = 0 # 列值根据条件筛选后修改为0 df = df[order] #过滤掉停牌的数据,在tdx中,停牌股票也能取到数据,价格是前一交易日的收盘价,所以只能用成交量或成交金额为0来判断 #1按日期分组后取出成交量为0的日期;2循环过滤掉成交量为0的日期的数据。 dfg = df.groupby(by='trade_date').mean() #分组 dfg['trade_date'] = dfg.index dfg = dfg[dfg.volume == 0] #条件过滤,保留满足条件的数据 for trade_date in dfg['trade_date'].values: df = df[(df['trade_date'] != trade_date)] # 每个条件要用括号()括起来 return df #可以获取多只股票的行情信息 #返回值:market,code,active1,price,last_close,open,high,low,reversed_bytes0,reversed_bytes1,vol,cur_vol,amount,s_vol, #reversed_bytes2,reversed_bytes3,bid1,ask1,bid_vol1,ask_vol1,bid2,ask2,bid_vol2,ask_vol2,bid3,ask3,bid_vol3,ask_vol3,bid4, #ask4,bid_vol4,ask_vol4,bid5,ask5,bid_vol5,ask_vol5,reversed_bytes4,reversed_bytes5,reversed_bytes6,reversed_bytes7, #reversed_bytes8,reversed_bytes9,active2 def get_security_quotes(self): df = self.api.to_df( self.api.get_security_quotes([(0, '000001'), (1, '600300')])) print(df) # 获取市场股票数量 #返回值:value def get_security_count(self): df = self.api.to_df(self.api.get_security_count(0)) #0 - 深圳, 1 - 上海 print(df) # 获取股票列表,返回值里面除了股票,还有国债等 #返回值:code,volunit,decimal_point,name,pre_close def get_security_list(self): df = self.api.to_df(self.api.get_security_list( 0, 10000)) # 市场代码, 起始位置 如: 0,0 或 1,100 print(df) # 获取指数k线 #输入参数同股票k线接口 # 返回值:open,close,high,low,vol,amount,year,month,day,hour,minute,datetime,up_count down_count def get_index_bars(self): index_dict_cn = { "上证指数": "999999", "深证成指": "399001", "中小板指": "399005", "创业板指": "399006", "深证综指": "399106", "上证50": "000016", "沪深300": "000300" } index_dict = { "sh": "999999", "sz": "399001", "zxb": "399005", "cyb": "399006", "szz": "399106", "sz50": "000016", "hs300": "000300" } for key in index_dict.keys(): df = self.api.to_df( self.api.get_index_bars(9, 1, index_dict[key], 0, 2)) print(df) # 查询分时行情,最近交易日的数据,一分钟一条记录 #返回值:price,vol def get_minute_time_data(self): df = self.api.to_df(self.api.get_minute_time_data( 1, '600300')) #市场代码, 股票代码 print(df) # 查询历史分时行情 # 返回值:price,vol def get_history_minute_time_data(self): df = self.api.to_df( self.api.get_history_minute_time_data(TDXParams.MARKET_SH, '603887', 20200420)) #市场代码, 股票代码,时间 print(df) # 查询分笔成交,最近交易日数据 #返回值:time,price,vol,num,buyorsell def get_transaction_data(self): df = self.api.to_df( self.api.get_transaction_data(TDXParams.MARKET_SZ, '000001', 0, 30)) #市场代码, 股票代码,起始位置, 数量 print(df) # 查询历史分笔成交 #返回值:time,price,vol,buyorsell def get_history_transaction_data(self): df = self.api.to_df( self.api.get_history_transaction_data( TDXParams.MARKET_SZ, '000001', 0, 10, 20170209)) #市场代码, 股票代码,起始位置,日期 数量 print(df) # 查询公司信息目录,返回的不是具体数据 #返回值:name,filename,start,length def get_company_info_category(self): df = self.api.to_df( self.api.get_company_info_category(TDXParams.MARKET_SZ, '000001')) #市场代码, 股票代码 print(df) # 读取公司信息详情 #返回值:value def get_company_info_content(self): df = self.api.to_df( self.api.get_company_info_content( 0, '000001', '000001.txt', 0, 1000)) #市场代码, 股票代码, 文件名, 起始位置, 数量 print(df) # 读取除权除息信息 #返回值:year,month,day,category,name,fenhong,peigujia,songzhuangu,peigu def get_xdxr_info(self): df = self.api.to_df(self.api.get_xdxr_info(1, '600300')) #市场代码, 股票代码 print(df) # 读取财务信息 #返回值:market,code,liutongguben,province,industry,updated_date,ipo_date,zongguben,guojiagu,faqirenfarengu,farengu,bgu,hgu,zhigonggu, #zongzichan,liudongzichan,gudingzichan,wuxingzichan,gudongrenshu,liudongfuzhai,changqifuzhai,zibengongjijin,jingzichan,zhuyingshouru, #zhuyinglirun,yingshouzhangkuan,yingyelirun,touzishouyu,jingyingxianjinliu,zongxianjinliu,cunhuo,lirunzonghe,shuihoulirun,jinglirun,weifenlirun,baoliu1,baoliu2 def get_finance_info(self): df = self.api.to_df(self.api.get_finance_info(1, '600300')) #市场代码, 股票代码 print(df) # 读取k线信息 # 返回值:value def get_k_data(self): df = self.api.to_df( self.api.get_k_data('600300', '2017-07-03', '2017-07-10')) #股票代码, 开始时间, 结束时间 print(df) # 读取板块信息 #返回值:blockname, block_type, code_index, code """ BLOCK_SZ = "block_zs.dat";BLOCK_FG = "block_fg.dat";BLOCK_GN = "block_gn.dat";BLOCK_DEFAULT = "block.dat" """ def get_and_parse_block_info(self): ##指数板块 风格板块 概念板块 一般板块 block_filename = [ "block_zs.dat", "block_fg.dat", "block_gn.dat", "block.dat" ] for block in block_filename: df = self.api.to_df( self.api.get_and_parse_block_info(block)) #板块文件名称 filename = config.tdx_csv_block + block[0:-4] + ".csv" if os.path.isfile(filename): os.remove(filename) df.to_csv(filename, index=False, mode='w', header=True, sep=',', encoding="utf_8_sig") else: df.to_csv(filename, index=False, mode='w', header=True, sep=',', encoding="utf_8_sig") # 读取板块信息,多个类型封装到一个df对象中返回 # 返回值:data_source, block_category, block_type, block_name, block_code, ts_code, create_time def update_block_member(self): ##指数板块 风格板块 概念板块 一般板块 #block_filename = ["block_zs.dat", "block_fg.dat", "block_gn.dat", "block.dat"] block_filename = ["block_zs.dat", "block_fg.dat", "block_gn.dat"] #block.dat中的数据都包含在其他版块里了,这个可以去掉 data_source = "tdx" dfall = None for block in block_filename: df = self.api.to_df( self.api.get_and_parse_block_info(block)) # 板块文件名称 df['data_source'] = data_source if block == "block.dat": df['block_category'] = data_source + ".yb" else: df['block_category'] = data_source + "." + block[6:8] df['block_type'] = df['block_type'].map(lambda x: str(x)) df['block_type'] = df['block_category'].str.cat( df['block_type'], sep=".") #, sep = "." df['block_code'] = "" #使用pd直接插入到数据库时,字段不能是None值 df['ts_code'] = df['code'].apply(lambda x: x + ".SH" if x[0:1] == "6" else x + ".SZ") if (dfall is not None) and (not dfall.empty): dfall = dfall.append(df, ignore_index=True) else: dfall = df if (dfall is None) or (dfall.empty): return None dfall.rename(columns={'blockname': 'block_name'}, inplace=True) dfall['create_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) dfall = dfall[[ 'data_source', 'block_category', 'block_type', 'block_name', 'block_code', 'ts_code', 'create_time' ]] #列重排序 #分组统计 dfg = dfall.groupby(by=[ 'data_source', 'block_category', 'block_type', 'block_name', 'block_code' ], as_index=False).count() # 分组求每组数量 dfg.rename(columns={'ts_code': 'member_count'}, inplace=True) #ts_code列数值为汇总值,需要重命名 dfg['create_time'] = time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(time.time())) #create_time列数值为汇总值,需要重新赋值 delete_condition = f"data_source = '{data_source}'" mysql_script.df2db_update(delete_condition=delete_condition, block_basic_df=dfg, block_member_df=dfall) return (len(dfg), len(dfall)) #获取一段时间的1分钟数据,因为每次调用接口只能返回3天的分钟数据(240*3),需要分多次调用 #返回值:0没有提取到数据;1提取到数据 def get_minute1_data(self, category, market, code, start_date, end_date): init_start_date = start_date.replace('-', '') init_end_date = end_date.replace('-', '') day = datatime_util.diffrentPeriod(datatime_util.DAILY, start_date, end_date) df = self.get_security_bars_minute1(category, market, code, 0, 240 * 3) # 返回DataFrame if df is None or df.empty: print('{0}没有交易数据'.format(code)) return 0 print(market, '--', code, '--', start_date, '--', end_date) #print("最大值:",df.groupby('datetime').max()) #print(df.describe()) #df数据统计 data_start_date = df.min()['trade_date'] data_end_date = df.max()['trade_date'] start_date = start_date.replace('-', '') end_date = end_date.replace('-', '') if data_end_date < start_date or end_date < data_start_date: print("采集时间在数据范围之外,退出函数") return 0 elif end_date > data_end_date: end_date = data_end_date if start_date < data_start_date: #最近三天的数据中,去掉无用的数据后即是最终数据 #需要取的数据还有三天前的数据,需要继续向前取 n = (day - 3) // 3 m = (day - 3) % 3 for i in range(0, n): dfn = self.get_security_bars_minute1(category, market, code, 240 * 3 * (i + 1), 240 * 3) # 返回DataFrame if (dfn is not None) and (not dfn.empty): df = dfn.append(df, ignore_index=True) if m > 0: dfn = self.get_security_bars_minute1(category, market, code, 240 * 3 * (n + 1), 240 * m) if (dfn is not None) and (not dfn.empty): df = dfn.append(df, ignore_index=True) df = df.sort_values(by=['trade_date', 'time_index'], axis=0, ascending=True) #过滤掉start_date, end_date之外的数据 df = df[(df['trade_date'] >= str(init_start_date)) & (df['trade_date'] <= str(init_end_date))] #每个条件要用括号()括起来 dict = {0: 'SZ', 1: 'SH'} ts_code = code + "." + dict[market] filename = config.tdx_csv_minline1_all + ts_code + ".csv" if os.path.isfile(filename): df.to_csv(filename, index=False, mode='a', header=False, sep=',', encoding="utf_8_sig") print("更新一分钟all股票数据:", filename) else: df.to_csv(filename, index=False, mode='w', header=True, sep=',', encoding="utf_8_sig") print("新增加的一分钟all股票数据:", filename)
class SP(object): def __init__(self,userid="account4",rate=1.2,products="1",limit=2,total=1000000,mock=True,server="http://192.168.118.1:65000"): if products == "1": self.products = {'880414': {'args': (3, 12, 90), 'stocklst': {}}, '880456': {'args': (6, 28, 40), 'stocklst': {}}, '880476': {'args': (5, 20, 90), 'stocklst': {}}, '880440': {'args': (4, 8, 85), 'stocklst': {}}, '880424': {'args': (4, 16, 110),'stocklst': {}}, '880448': {'args': (3, 14, 60), 'stocklst': {}}, '880454': {'args': (4, 8, 85), 'stocklst': {}}, '880493': {'args': (3, 24, 55), 'stocklst': {}}, '880344': {'args': (4, 4, 30), 'stocklst': {}}, '880301': {'args': (6, 20, 30), 'stocklst': {}}, '880464': {'args': (4, 14, 50), 'stocklst': {}}, '880459': {'args': (3, 16, 80), 'stocklst': {}}, '880380': {'args': (5, 22, 70), 'stocklst': {}}, '880472': {'args': (3, 32, 170),'stocklst': {}}, '880421': {'args': (3, 16, 45), 'stocklst': {}}, '880471': {'args': (4, 12, 40), 'stocklst': {}}, '880453': {'args': (6, 14, 30), 'stocklst': {}}, '880350': {'args': (4, 26, 30), 'stocklst': {}}, '880447': {'args': (5, 20, 170),'stocklst': {}}, '880351': {'args': (3, 6, 65), 'stocklst': {}}, '880390': {'args': (3, 14, 65), 'stocklst': {}}, '880406': {'args': (4, 16, 50), 'stocklst': {}}, '880305': {'args': (3, 14, 95), 'stocklst': {}}, '880492': {'args': (3, 30, 105),'stocklst': {}}, '880387': {'args': (5, 20, 70), 'stocklst': {}}, '880418': {'args': (4, 16, 100),'stocklst': {}}, '880367': {'args': (5, 14, 110),'stocklst': {}}, '880398': {'args': (5, 26, 100),'stocklst': {}}, '880437': {'args': (4, 8, 85), 'stocklst': {}}, '880474': {'args': (4, 24, 45), 'stocklst': {}}, '880324': {'args': (6, 22, 75), 'stocklst': {}}, '880335': {'args': (3, 12, 75), 'stocklst': {}}, '880372': {'args': (6, 20, 105),'stocklst': {}}, '880491': {'args': (4, 16, 20), 'stocklst': {}}, '880490': {'args': (3, 26, 110),'stocklst': {}}, '880431': {'args': (7, 12, 40), 'stocklst': {}}, '880432': {'args': (3, 10, 110),'stocklst': {}}, '880318': {'args': (4, 20, 90), 'stocklst': {}}, '880497': {'args': (3, 8, 40), 'stocklst': {}}, '880494': {'args': (3, 30, 110),'stocklst': {}}, '880400': {'args': (3, 10, 90), 'stocklst': {}}, '880360': {'args': (3, 16, 70), 'stocklst': {}}, '880310': {'args': (3, 12, 20), 'stocklst': {}}, '880423': {'args': (5, 16, 30), 'stocklst': {}}, '880430': {'args': (7, 12, 25), 'stocklst': {}}, '880422': {'args': (6, 8, 35), 'stocklst': {}}, '880465': {'args': (4, 12, 95), 'stocklst': {}}, '880482': {'args': (3, 20, 180),'stocklst': {}}, '880355': {'args': (3, 18, 45), 'stocklst': {}}, '880473': {'args': (3, 6, 40), 'stocklst': {}}, '880446': {'args': (3, 8, 45), 'stocklst': {}}, '880452': {'args': (3, 32, 90), 'stocklst': {}}, '880455': {'args': (5, 6, 20), 'stocklst': {}}, '880399': {'args': (3, 8, 85), 'stocklst': {}}, '880330': {'args': (5, 12, 80), 'stocklst': {}}, '880489': {'args': (3, 18, 190),'stocklst': {}}} elif products == "2": #资金比较少是,选择配置部分行业 self.products = {'880414': {'args': (3, 12, 90), 'stocklst': {}}, '880456': {'args': (6, 28, 40), 'stocklst': {}}, '880476': {'args': (5, 20, 90), 'stocklst': {}}, '880440': {'args': (4, 8, 85), 'stocklst': {}}, '880424': {'args': (4, 16, 110),'stocklst': {}}, '880448': {'args': (3, 14, 60), 'stocklst': {}}, '880454': {'args': (4, 8, 85), 'stocklst': {}}, '880493': {'args': (3, 24, 55), 'stocklst': {}}, '880344': {'args': (4, 4, 30), 'stocklst': {}}, '880301': {'args': (6, 20, 30), 'stocklst': {}}, '880464': {'args': (4, 14, 50), 'stocklst': {}}, '880459': {'args': (3, 16, 80), 'stocklst': {}}, '880380': {'args': (5, 22, 70), 'stocklst': {}}, '880472': {'args': (3, 32, 170),'stocklst': {}}, '880421': {'args': (3, 16, 45), 'stocklst': {}}, '880471': {'args': (4, 12, 40), 'stocklst': {}}, '880453': {'args': (6, 14, 30), 'stocklst': {}}, '880350': {'args': (4, 26, 30), 'stocklst': {}}, '880447': {'args': (5, 20, 170),'stocklst': {}}, '880351': {'args': (3, 6, 65), 'stocklst': {}}, '880390': {'args': (3, 14, 65), 'stocklst': {}}, '880406': {'args': (4, 16, 50), 'stocklst': {}}, '880305': {'args': (3, 14, 95), 'stocklst': {}}, '880492': {'args': (3, 30, 105),'stocklst': {}}, '880387': {'args': (5, 20, 70), 'stocklst': {}}, '880418': {'args': (4, 16, 100),'stocklst': {}}, } self.server = server self.datatype = 1 self.userid = userid self.limit = limit self.api = TdxHq_API(heartbeat=True) self.trader = None self.trading = False self.mock = mock self.rate = rate #持仓杠杆率 self.total = total #默认持仓资金 self.TDX_IP_SETS = STOCK_IP_SETS self.file_incon = FILE_INCON self.file_tdxhy = FILE_TDXHY self.file_tdxzs = FILE_TDXZS def connect(self): for ip in self.TDX_IP_SETS: try: if self.api.connect(ip, 7709): return except: pass def getdata(self,product,market=1,number=5000,pn=400): data = [] for i in range(int(number/pn)+1): temp = self.api.get_index_bars(self.datatype, market, product, (int(number/pn)-i)*pn,pn) if not temp or len(temp)<pn: self.connect() for _ in range(2): temp = self.api.get_index_bars(self.datatype, market, product, (int(number/pn)-i)*pn,pn) if not temp or len(temp)<pn: logger.info("record not reach the limit!") else: break data += temp df = self.api.to_df(data)[["open","close","high","low","datetime"]] df.set_index("datetime",inplace=True,drop=False) return df def disconnect(self): logger.info("[DISCONNECT]:statrt disconnect!!!!!") if self.istradeday: self.api.disconnect() logger.info("[DISCONNECT]:disconnect finished!!!!!") def updatetotal(self): '''更新总资金 ''' accountinfo,holdlists = self.trader.position() nhg = holdlists[holdlists[u"证券代码"].map(lambda x:x in ["SZRQ88","SHRQ88"])][u"最新市值"].sum() self.total = accountinfo.ix["总资产"]["人民币"]-nhg return self.total def set_permoney(self): '''单个品种资金上限 ''' self.permoney = self.total * self.rate /len(self.products) return self.permoney def _get_incon(self,): '''获取行业分类代码 ''' f= open(self.file_incon, "rb") data = f.read() strings = data.decode("gbk", 'ignore').rstrip("\x00").replace("\r\n","\n") data = strings.split("######") rst = {} for hystr in data: key = re.findall(r'#.*',hystr) if key == ['#TDXNHY']: hylst = hystr.replace("#TDXNHY","").strip("\n").split("\n") for item in hylst: k,v = item.split("|") rst[k] = [v] return rst def _get_tdxhy(self,islocal=True): '''获取股票和行业对应列表 ''' if islocal: stocklist = HY_WEIGHT.keys() else: stocklist = list(ts.get_stock_basics().index) #获取全市场股票代码 rst = self._get_incon() f= open(self.file_tdxhy, "rb") data = f.read().decode("gbk", 'ignore').rstrip("\x00").replace("\r\n","\n").strip("\n").split("\n") for i in data: _,code,tdxhy,_,_ = i.split("|") if tdxhy != "T00" and code in stocklist: rst[tdxhy].append(code) return rst def _get_tdxzs(self,islocal=True): '''生成通达性版块代码对应股票列表 ''' dct = {} rst = self._get_tdxhy(islocal=islocal) f= open(self.file_tdxzs, "rb") data = f.read().decode("gbk", 'ignore').rstrip("\x00").replace("\r\n","\n").strip("\n").split("\n") for i in data: name,code,_,_,_,hy = i.split("|") code = int(code) if 880301<=code and 880497>=code and hy in rst.keys() : k = hy[:5] if not dct.__contains__(k): dct[k] = {"name":"","code":"","stocklist":[]} if k==hy: dct[k]["name"] = name dct[k]["code"] = code dct[k]["stocklist"].extend(rst[hy][1:]) return dct def get_tdxhy_list(self,islocal=True): '''获取通达信行业板块指数对应的股票列表 ''' return self._get_tdxzs(islocal) def get_weight(self,htlist={},islocal=True): '''获取行业板块个股权重,流动市值为权重系数 备注:回测是为方便处理,以最后一天的权重系数作为历史上的权重 ''' if islocal: self.weight = HY_WEIGHT else: if not htlist: htlist = self.get_tdxhy_list(islocal) tasks = [] for v in htlist.values(): tasks.append(gevent.spawn(self.get_latest_ltsz,v["stocklist"])) gevent.joinall(tasks) return self.weight def get_latest_ltsz(self,stocks=[]): '''获取最新流通市值,千万为单位,取整 ''' unit = 10000000 for code in stocks: mk = self._select_market_code(code) print(mk,code) try: ltgb = self.api.get_finance_info(mk,code)["liutongguben"] price = self.api.get_security_bars(4,mk,code,0,1)[0]["close"] ltsz = int(ltgb*price/unit) self.weight[code] = ltsz except: print("*****",code) return def set_instrument(self): '''设置交易股票 ''' func = lambda x :1 if x.startswith("6") else 0 weight = self.get_weight() for v in self.get_tdxhy_list().values(): code = str(v["code"]) if not self.products.__contains__(code):continue stocks = [(i,weight[i]) for i in v["stocklist"]] limit_stocks = sorted(stocks,key=lambda x:x[1],reverse=True)[:self.limit] total = sum([i[1] for i in limit_stocks]) for i in limit_stocks: market = func(i[0]) price = self.api.get_security_bars(4,market,i[0],0,1)[0]["close"] number = int(self.permoney*i[1]/total/price/100)*100 self.products[code]["stocklst"][i[0]] = number return self.products def judgetradeday(self,): today = datetime.datetime.today().date().strftime('%Y-%m-%d') df = ts.trade_cal() return df[(df["calendarDate"]==today)].isOpen.values[0] @property def istradeday(self): if not hasattr(self, "_istradeday"): self._istradeday = self.judgetradeday() return self._istradeday def initial(self): '''每天初始化设置 ''' logger.info("[INITIAL]:start initial !!!!!!") if not self.istradeday: self.trading = False return self.trading = True logger.info("[INITIAL]:try to create connect... ") self.connect() self.trader = trade(UserID=self.userid,api=self.api,mock=self.mock,server=self.server) logger.info("[INITIAL]:connect successful!") logger.info("[INITIAL]:initial account info...") self.updatetotal() #更新账户总资金 self.set_permoney() #设置单个品种资金上限 logger.info("[INITIAL]:set per product money limit:{}".format(self.permoney)) self.set_instrument() #设置交易股票和手数 logger.info("[INITIAL]:set stock list succcessful !!!") logger.info("[INITIAL]:initial finished!!!!!!") def handledata(self,df,args=[]): df.loc[:,"number"] = range(df.shape[0]) s,m,l = args for i in args:#5 15 60 D key = str(5*i) df.loc[:,key+"high"] = df["high"].rolling(i).max() df.loc[:,key+"low"] = df["low"].rolling(i).min() df.loc[:,key+"atr"] = (df[key+"high"]-df[key+"low"]).rolling(10*i).mean() df.loc[:,key+"med"] = (df[key+"high"]+df[key+"low"])/2 df.loc[:,key+"HH"] = df[key+"med"] + 1.5*df[key+"atr"] df.loc[:,key+"LL"] = df[key+"med"] - 1.5*df[key+"atr"] df.loc[:,key+'HHmax'] = df[key+'HH'].rolling(10*i).max() df.loc[:,key+'LLmin'] = df[key+'LL'].rolling(10*i).min() df.loc[df[key+'HH']>=df[key+'HHmax'],key+'hmark'] = df["number"] df.loc[df[key+'LL']<=df[key+'LLmin'],key+'lmark'] = df["number"] df[key+'hmark'].fillna(method="ffill",inplace=True) df[key+'hmark'].fillna(0,inplace=True) df[key+'lmark'].fillna(method="ffill",inplace=True) df[key+'lmark'].fillna(0,inplace=True) df.loc[:,key+'UP'] = df[key+'hmark'] >= df[key+'lmark'] # debuginfo.append({key+'hmark':df.iloc[-1][key+'hmark'],key+'lmark':df.iloc[-1][key+'lmark']}) df.fillna(method="ffill",inplace=True) df.dropna(inplace=True) # logger.info("trademessage:{}".format(debuginfo)) result = (df.iloc[-1][str(5*l)+"UP"] >0)&(df.iloc[-1][str(5*s)+"UP"]>0) result |= (df.iloc[-1][str(5*l)+"UP"]>0)&(df.iloc[-1][str(5*m)+"UP"]>0) result |= (df.iloc[-1][str(5*l)+"UP"]<=0)&(df.iloc[-1][str(5*m)+"UP"]>0)&(df.iloc[-1][str(5*s)+"UP"]>0) return result def sync(self,idx,director=True): stocks = self.products[idx]["stocklst"] for stock,number in stocks.items(): if not director: number = 0 #空信号,清仓 #判断现有持仓 try: code = stock h_number = self.hd_df.ix[code]["证券数量"] except: h_number = 0 logger.info("[RUN]:{},{},{}".format(stock,h_number,number)) #补仓差 cangcha = int((number-h_number)/100)*100 if h_number>0 and abs(cangcha)/h_number<0.2: #如果有持仓,同时仓差小于10% 不进行更改,为了处理频繁加减仓达到问题 continue if cangcha>0: logger.info("[RUN]:buy code:{}, number:{}".format(stock,number-h_number)) self.buy(stock,cangcha) elif cangcha<0: couldsell = self.hd_df.ix[code]["可卖数量"] logger.info("[RUN]:sell code:{}, number:{},couldsell:{}".format(stock,h_number-number,couldsell)) if couldsell >0: self.sell(stock,min(-cangcha,couldsell)) # def buy(self,stock,number): self.trader.buy(stock, number) def sell(self,stock,number): self.trader.sell(stock, number) def check_position(self,status): '''检查仓位情况 ''' self.handleposition() handlelist = [] for ins,v in status.items(): if ins not in self.g_df.index : handlelist.append(ins) elif self.g_df.ix[ins]["Position"] != v["number"]: handlelist.append(ins) return handlelist def handleposition(self): '''计算多仓,空仓,以及昨仓和今仓 ''' self.trader.cancelorder() #先尝试撤单 _,holdlists = self.trader.position() self.hd_df = holdlists if holdlists.shape[0]>0: self.hd_df.set_index("证券代码",inplace=True) self.hd_df.index = self.hd_df.index.astype(np.str).map(lambda x:x if len(x)>=6 else "0"*(6-len(x))+x) return self.hd_df def run(self): logger.info("[RUN]:start run !!!!!") if not self.trading: return self.handleposition() rst = {} for idx in list(self.products.keys()): director = self.handledata(self.getdata(idx,market=1),self.products[idx]["args"]) #用指数出信号 logger.info("[RUN]:trademessage: block:{}, director:{}".format(idx,director)) self.sync(idx,director) rst[idx] = {"up":director,"number":self.products[idx]["stocklst"],"product":idx} logger.info("[RUN]:lastest position status:{}".format(rst)) logger.info("[RUN]:run finished !!!!!")
class SP(object): def __init__(self, userid="account1", number=2, mock=True, server="http://192.168.118.1:65000"): ''' 根据实际账户资金,以股指1手为基本对冲单位进行配置。 ''' self.products = { '000905': { 'args': (3, 6, 65), 'stocklst': { "510500": 0 } } } self.datatype = 0 self.userid = userid self.api = TdxHq_API(heartbeat=True) self.trader = None self.trading = False self.mock = mock self.permoney = 200 #指数一个点对应的金额 self.number = number #指数的倍数 self.server = server self.TDX_IP_SETS = STOCK_IP_SETS if mock: self.judgerate = 100 else: self.judgerate = 10 def connect(self): for ip in self.TDX_IP_SETS: try: if self.api.connect(ip, 7709): return except: pass def getdata(self, product, market=1, number=10000, pn=400): data = [] for i in range(int(number / pn) + 1): temp = self.api.get_index_bars(self.datatype, market, product, (int(number / pn) - i) * pn, pn) if not temp or len(temp) < pn: for _ in range(2): temp = self.api.get_index_bars(self.datatype, market, product, (int(number / pn) - i) * pn, pn) if not temp or len(temp) < pn: logger.info("record not reach the limit!") else: break try: data += temp except: self.connect() df = self.api.to_df(data)[["open", "close", "high", "low", "datetime"]] df.set_index("datetime", inplace=True, drop=False) return df def disconnect(self): logger.info("[DISCONNECT]:statrt disconnect!!!!!") if self.istradeday: self.api.disconnect() logger.info("[DISCONNECT]:disconnect finished!!!!!") def set_number(self): '''设置日内交易的单次手数 ''' price = self.api.get_security_quotes([(1, '510500')])[0]["last_close"] index_price = self.api.get_security_quotes([(1, '000905') ])[0]["last_close"] self.products["000905"]["stocklst"]["510500"] = int( index_price * self.number * self.permoney / price / self.judgerate) * 100 def judgetradeday(self, ): today = datetime.datetime.today().date().strftime('%Y-%m-%d') df = ts.trade_cal() return df[(df["calendarDate"] == today)].isOpen.values[0] @property def istradeday(self): if not hasattr(self, "_istradeday"): self._istradeday = self.judgetradeday() return self._istradeday def initial(self): '''每天初始化设置 ''' logger.info("[INITIAL]:start initial !!!!") if not self.istradeday: self.trading = False return self.trading = True logger.info("[INITIAL]:try to create connect... ") self.connect() self.trader = trade(UserID=self.userid, api=self.api, mock=self.mock, server=self.server) logger.info("[INITIAL]:connect successful!") self.set_number() #设置手数 logger.info("[INITIAL]:initial finished !!!!!") def handledata(self, df, args=[]): df.loc[:, "number"] = range(df.shape[0]) s, m, l = args for i in args: #5 15 60 D key = str(5 * i) df.loc[:, key + "high"] = df["high"].rolling(i).max() df.loc[:, key + "low"] = df["low"].rolling(i).min() df.loc[:, key + "atr"] = (df[key + "high"] - df[key + "low"]).rolling(10 * i).mean() df.loc[:, key + "med"] = (df[key + "high"] + df[key + "low"]) / 2 df.loc[:, key + "HH"] = df[key + "med"] + 1.5 * df[key + "atr"] df.loc[:, key + "LL"] = df[key + "med"] - 1.5 * df[key + "atr"] df.loc[:, key + 'HHmax'] = df[key + 'HH'].rolling(10 * i).max() df.loc[:, key + 'LLmin'] = df[key + 'LL'].rolling(10 * i).min() df.loc[df[key + 'HH'] >= df[key + 'HHmax'], key + 'hmark'] = df["number"] df.loc[df[key + 'LL'] <= df[key + 'LLmin'], key + 'lmark'] = df["number"] df[key + 'hmark'].fillna(method="ffill", inplace=True) df[key + 'hmark'].fillna(0, inplace=True) df[key + 'lmark'].fillna(method="ffill", inplace=True) df[key + 'lmark'].fillna(0, inplace=True) df.loc[:, key + 'UP'] = df[key + 'hmark'] >= df[key + 'lmark'] # debuginfo.append({key+'hmark':df.iloc[-1][key+'hmark'],key+'lmark':df.iloc[-1][key+'lmark']}) df.fillna(method="ffill", inplace=True) df.dropna(inplace=True) # logger.info("trademessage:{}".format(debuginfo)) result = (df.iloc[-1][str(5 * l) + "UP"] > 0) & (df.iloc[-1][str(5 * s) + "UP"] > 0) result |= (df.iloc[-1][str(5 * l) + "UP"] > 0) & (df.iloc[-1][str(5 * m) + "UP"] > 0) result |= (df.iloc[-1][str(5 * l) + "UP"] <= 0) & (df.iloc[-1][ str(5 * m) + "UP"] > 0) & (df.iloc[-1][str(5 * s) + "UP"] > 0) return result def sync(self, idx, director=True): stocks = self.products[idx]["stocklst"] for stock, number in stocks.items(): if not director: number = 2 * number #空信号,清仓 else: number = 4 * number #判断现有持仓 try: h_number = self.hd_df.ix[stock]["证券数量"] except: h_number = 0 #补仓差 cangcha = int((number - h_number) / 100) * 100 if h_number > 0 and abs( cangcha ) / number < 0.05: #如果有持仓,同时仓差小于5% 不进行更改,为了处理频繁加减仓达到问题 return if cangcha > 0: logger.info("[RUN]:buy code:{}, number:{}".format( stock, number - h_number)) self.buy(stock, cangcha) elif cangcha < 0: logger.info("[RUN]:sell code:{}, number:{}".format( stock, h_number - number)) lastholdnumber = self.hd_df.ix[stock]["可卖数量"] self.sell(stock, min(-cangcha, lastholdnumber)) def buy(self, stock, number, jump=0.02): self.trader.buy(stock, number, jump=jump) def sell(self, stock, number, jump=0.02): self.trader.sell(stock, number, jump=jump) def check_position(self, status): '''检查仓位情况 ''' self.handleposition() handlelist = [] for ins, v in status.items(): if ins not in self.g_df.index: handlelist.append(ins) elif self.g_df.ix[ins]["Position"] != v["number"]: handlelist.append(ins) return handlelist def handleposition(self): '''计算多仓,空仓,以及昨仓和今仓 ''' self.trader.cancelorder() #先尝试撤单 _, holdlists = self.trader.position() self.hd_df = holdlists if holdlists.shape[0] > 0: self.hd_df.set_index("证券代码", inplace=True) self.hd_df.index = self.hd_df.index.astype(np.str) return self.hd_df def run(self): logger.info("[RUN]:start run !!!!!") if not self.trading: return self.handleposition() rst = {} for idx in list(self.products.keys()): director = self.handledata(self.getdata(idx, market=1), self.products[idx]["args"]) #用指数出信号 logger.info("[RUN]:trademessage: block:{}, director:{}".format( idx, director)) self.sync(idx, director) rst[idx] = { "up": director, "number": self.products[idx]["stocklst"], "product": idx } logger.info("[RUN]:lastest position status:{}".format(rst)) logger.info("[RUN]:run finished !!!!!") def nhg(self): '''尾盘自动进行逆回购 ''' if not self.mock: self.trader.autobuy()
class TdxData: def __init__(self): self.api = TdxHq_API(heartbeat=True) self.dbUtil = DBUtil.getInstance() def get_security_quotes(self, code, type): return self.api.get_security_quotes([(type, code)]) # 支持板块及个股 def days(self, code, type, bk=False, all=False, day=5): category = int(config.getByKey('TDX_CATEGORY')) try: with self.api.connect(TDX_IP, TDX_PORT): data = [] if all: if bk: for i in range(10): data += self.api.get_index_bars( category, type, code, (9 - i) * 800, 800) else: for i in range(10): data += self.api.get_security_bars( category, type, code, (9 - i) * 800, 800) if len(data) > 0: df = self.api.to_df(data).drop([ 'amount', 'year', 'month', 'day', 'hour', 'minute' ], axis=1) df['trade_date'] = df['datetime'].apply( lambda x: x[0:10].replace('-', '')) df = df.drop(['datetime'], axis=1) df = df.sort_values(by=['trade_date'], axis=0, ascending=False) return df else: return self.api.to_df(data) else: if bk: data = self.api.get_index_bars(category, type, code, 0, day) # 返回DataFrame else: data = self.api.get_security_bars( category, type, code, 0, day) if len(data) > 0: df = self.api.to_df(data).drop([ 'amount', 'year', 'month', 'day', 'hour', 'minute' ], axis=1) df['trade_date'] = df['datetime'].apply( lambda x: x[0:10].replace('-', '')) df = df.drop(['datetime'], axis=1) df = df.sort_values(by=['trade_date'], axis=0, ascending=False) return df else: return self.api.to_df(data) except Exception as e: logging.info("暂不支持类型,代码:%s:%s" % (code, e)) return self.api.to_df([]) # F10 查询公司信息目录 def get_company_info_category(self, code, type): with self.api.connect(TDX_IP, TDX_PORT): df = pd.DataFrame(self.api.get_company_info_category(type, code)) df['txt'] = None return df return [] def get_company_info_content(self, code, type, df): with self.api.connect(TDX_IP, TDX_PORT): return self.api.get_company_info_content(type, code, df['filename'].values[0], df['start'].values[0], df['length'].values[0]) return "" # 查询财务数据 def get_finance_info(self, code, type): with self.api.connect(TDX_IP, TDX_PORT): return self.api.get_finance_info(type, code) return '' # 每年更新一次,板块个股关系 def updateBk(self): with self.api.connect(TDX_IP, TDX_PORT): """ # 获取股票所属板块信息 # 板块相关参数 BLOCK_SZ = "block_zs.dat" BLOCK_FG = "block_fg.dat" BLOCK_GN = "block_gn.dat" BLOCK_DEFAULT = "block.dat" """ bk_zs = self.api.to_df( self.api.get_and_parse_block_info("block_zs.dat")) #指数板块 bk_fg = self.api.to_df( self.api.get_and_parse_block_info("block_fg.dat")) #风格板块 bk_gn = self.api.to_df( self.api.get_and_parse_block_info("block_gn.dat")) #概念板块 bk_default = self.api.to_df( self.api.get_and_parse_block_info("block.dat")) # 默认 self.dbUtil.to_sql(bk_gn, 'stock_bk_gn', if_exists='replace', index=False, dtype=STOCK_BK_DTYPE) self.dbUtil.to_sql(bk_fg, 'stock_bk_fg', if_exists='replace', index=False, dtype=STOCK_BK_DTYPE) self.dbUtil.to_sql(bk_zs, 'stock_bk_zs', if_exists='replace', index=False, dtype=STOCK_BK_DTYPE) self.dbUtil.to_sql(bk_default, 'stock_bk_default', if_exists='replace', index=False, dtype=STOCK_BK_DTYPE) # 获取股票列表 tmp1 = self.api.to_df(self.api.get_security_list(0, 0)) # 深圳 tmp1['type'] = 0 tmp2 = self.api.to_df(self.api.get_security_list(1, 0)) # 上海 tmp2['type'] = 1 tmp = tmp1.append(tmp2) self.dbUtil.to_sql(tmp, 'stock_bk', if_exists='replace', index=False, dtype=STOCK_BK) def updateGD(self, code, type): url = 'http://emweb.securities.eastmoney.com/PC_HSF10/ShareholderResearch/ShareholderResearchAjax?code=%s%s' % ( type.lower(), code) html = urllib.request.urlopen(url).read() # 将字符串转换成字典 data = json.loads(html.decode('utf-8')) # gdrs 股东人数,sdgd 十大股东 ,sdltgd 十大流通股东 df_gdrs = pd.DataFrame(data['gdrs']) df_gdrs['code'] = code try: db_df_gdrs = self.dbUtil.read_sql( "select * from stock_gdrs where code ='%s'" % code) # 数据合并 df_gdrs = df_gdrs.append(db_df_gdrs).drop_duplicates( subset=['code', 'rq', 'gdmc'], keep='last') except Exception as e: pass self.dbUtil.to_sql(df_gdrs, 'stock_gdrs', if_exists='append', index=False, dtype=STOCK_GDRS_DTYPE) sdgd = [] for i in range(len(data['sdgd'])): sdgd += data['sdgd'][i]['sdgd'] df_sdgd = pd.DataFrame(sdgd) df_sdgd['code'] = code try: db_df_sdgd = self.dbUtil.read_sql( "select * from stock_sdgd where code ='%s'" % code) df_sdgd = df_sdgd.append(db_df_sdgd).drop_duplicates( subset=['code', 'rq', 'gdmc'], keep='last') except Exception as e: pass self.dbUtil.to_sql(df_sdgd, 'stock_sdgd', if_exists='append', index=False, dtype=STOCK_SDGD_DTYPE) sdltgd = [] for i in range(len(data['sdltgd'])): sdltgd += data['sdltgd'][i]['sdltgd'] df_sdltgd = pd.DataFrame(sdltgd) df_sdltgd['code'] = code # 获取后与数据库中的数据进行merge,首次表不存在,会抛异常 try: db_df_sdltgd = self.dbUtil.read_sql( "select * from stock_sdltgd where code ='%s'" % code) df_sdltgd = df_sdltgd.append(db_df_sdltgd).drop_duplicates( subset=['code', 'rq', 'gdmc'], keep='last') except Exception as e: pass self.dbUtil.to_sql(df_sdltgd, 'stock_sdltgd', if_exists='append', index=False, dtype=STOCK_SDGD_DTYPE) # 没季度更新一次 def updateGDs(self): codes = self.dbUtil.read_sql("select ts_code from stock_basic") tmp = codes['ts_code'].str.split('.', expand=True) for index, row in tmp.iterrows(): try: self.updateGD(row[0], row[1]) logging.info('%s更新结束,当前索引%s' % (row[0], index)) except Exception as e: logging.info('%s更新失败,当前索引%s' % (row[0], index)) # 分红 # 分红地址http://data.eastmoney.com/yjfp/201812.html def updateFh(self, rq): url = 'http://data.eastmoney.com/DataCenter_V3/yjfp/getlist.ashx?filter=(ReportingPeriod=^%s^)' % rq html = requests.get(url) # 将字符串转换成字典 data = json.loads(html.text)['data'] if len(data) == 0: return 0 df = pd.DataFrame(data) df['ReportingPeriod'] = df['ReportingPeriod'].apply(lambda x: x[0:10]) # 首次需要将df_fh制空,因为表还不存在 if self.dbUtil.is_exist("stock_fh"): db_fh = self.dbUtil.read_sql( "select * from stock_fh where ReportingPeriod = '%s'" % df['ReportingPeriod'][0]) if db_fh.empty: # 不存在当前日期的分红信息,进行拼接 self.dbUtil.to_sql(df, 'stock_fh', if_exists='append', index=False) return 1 else: pass else: self.dbUtil.to_sql(df, 'stock_fh', if_exists='append', index=False) return 1 # 更新历年分红 def updateFhYears(self): now = int(time.strftime("%Y", time.localtime())) + 1 lastYear = int(self._getFhMaxYear()) for i in range(lastYear, now): #初始化时开启 type = self.updateFh('%s-06-30' % i) logging.info('%s-06-30%s' % (i, '成功' if type == 1 else '失败')) self.updateFh('%s-12-31' % i) logging.info('%s-12-31%s' % (i, '成功' if type == 1 else '失败')) def _getFhMaxYear(self): if self.dbUtil.is_exist('stock_fh'): try: df = self.dbUtil.read_sql( 'select substr(max(t.ReportingPeriod ),0,5) year from stock_fh t' ) return df['year'][0].values except Exception as e: pass return 1991 @classmethod def getInstance(cls): if not hasattr(TdxData, "_instance"): TdxData._instance = TdxData() return TdxData._instance
class StdQuotes(object): """股票市场实时行情""" # __slots__ = def __init__(self, **kwargs): self.config = None try: self.config = json.loads( os.path.join(os.environ['HOME'], '.mootdx/config.josn')) except Exception as e: self.config = None self.client = TdxHq_API(**kwargs) if not self.config: self.bestip = os.environ.setdefault("MOOTDX_SERVER", '202.108.253.131:7709') self.bestip = self.bestip.split(':') self.bestip[1] = int(self.bestip[1]) else: self.bestip = self.config.get('SERVER') # K线 def bars(self, symbol='000001', category='9', start='0', offset='100'): ''' 获取实时日K线数据 :param symbol: 股票代码 :param category: 数据类别 :param market: 证券市场 :param start: 开始位置 :param offset: 每次获取条数 :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_security_bars(int(category), int(market), str(symbol), int(start), int(offset)) return self.client.to_df(data) # 分时数据 def minute(self, symbol=''): ''' 获取实时分时数据 :param market: 证券市场 :param symbol: 股票代码 :return: pd.DataFrame ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_minute_time_data(int(market), symbol) return self.client.to_df(data) # 分时历史数据 def minute_his(self, symbol='', datetime='20161209'): ''' 分时历史数据 :param market: :param symbol: :param datetime: :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_history_minute_time_data( int(market), symbol, datetime) return self.client.to_df(data) def trans(self, symbol='', start=0, offset=10): ''' 查询分笔成交 :param market: 市场代码 :param symbol: 股票代码 :param start: 起始位置 :param offset: 请求数量 :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_transaction_data(int(market), symbol, int(start), int(market)) return self.client.to_df(data) def trans_his(self, symbol='', start=0, offset=10, date=''): ''' 查询历史分笔成交 :param market: 市场代码 :param symbol: 股票代码 :param start: 起始位置 :param offset: 数量 :param date: 日期 :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_history_transaction_data( int(market), symbol, int(start), int(offset), date) return self.client.to_df(data) def company(self, symbol='', detail='category', *args, **kwargs): ''' 企业信息获取 :param symbol: :param detail: :param args: :param kwargs: :return: ''' pass def company_category(self, symbol=''): ''' 查询公司信息目录 :param market: 市场代码 :param symbol: 股票代码 :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_company_info_category(int(market), symbol) return self.client.to_df(data) def company_content(self, symbol='', file='', start=0, offset=10): ''' 读取公司信息详情 :param market: 市场代码 :param symbol: 股票代码 :param file: 文件名 :param start: 起始位置 :param offset: 数量 :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_company_info_content( int(market), symbol, file, int(start), int(offset)) return self.client.to_df(data) def xdxr(self, symbol=''): ''' 读取除权除息信息 :param market: 市场代码 :param symbol: 股票代码 :return: pd.dataFrame or None ''' market = get_stock_market(symbol) with self.client.connect(*self.bestip): data = self.client.get_xdxr_info(int(market), symbol) return self.client.to_df(data) def k(self, symbol='', begin=None, end=None): ''' 读取k线信息 :param symbol: :param begin: :param end: :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): data = self.client.get_k_data(symbol, begin, end) return data def index(self, symbol='000001', market='sh', category='9', start='0', offset='100'): ''' 获取指数k线 K线种类: - 0 5分钟K线 - 1 15分钟K线 - 2 30分钟K线 - 3 1小时K线 - 4 日K线 - 5 周K线 - 6 月K线 - 7 1分钟 - 8 1分钟K线 - 9 日K线 - 10 季K线 - 11 年K线 :param symbol: 股票代码 :param category: 数据类别 :param market: 证券市场 :param start: 开始位置 :param offset: 每次获取条数 :return: pd.dataFrame or None ''' market = 1 if market == 'sh' else 0 with self.client.connect(*self.bestip): data = self.client.get_index_bars(int(category), int(market), str(symbol), int(start), int(offset)) return self.client.to_df(data) def block(self, tofile="block.dat"): ''' 获取证券板块信息 :param tofile: :return: pd.dataFrame or None ''' with self.client.connect(*self.bestip): data = self.client.get_and_parse_block_info(tofile) return self.client.to_df(data) def batch(self, method='', offset=100, *args, **kwargs): ''' 批量下载相关数据 :param method: :param offset: :return: ''' pass