class tdxApi: def __init__(self): self.ipset = [(v[1], v[2]) for v in hq_hosts] random.shuffle(self.ipset) self.ippool = AvailableIPPool(TdxHq_API, self.ipset) self.primary_ip, _ = self.ippool.sync_get_top_n(2) self.api = TdxHq_API(multithread=True, heartbeat=True, auto_retry=True) def connect(self): self.api.connect(self.primary_ip[0], self.primary_ip[1]) def release(self): self.api.disconnect() def getQuotes(self, stock_list): datas = self.api.get_security_quotes(stock_list) if datas is None: return None else: return self.api.to_df(datas) def getList(self, market, index): df = self.api.to_df(self.api.get_security_list(market, index)) return df def getCount(self, market=0): return self.api.get_security_count(market) def getMinQuotes(self, market, stock_code): datas = self.api.get_minute_time_data(market, stock_code) if datas is None: return None return self.api.to_df(datas) def getMinQuotesHis(self, market, stock_code, date): datas = self.api.get_history_minute_time_data(market, stock_code, date) if datas is None: return None return self.api.to_df(datas)
class TDX(object): ''' This class is tong da xin data source. We can use it to get down the stock datas. Tushare can't get minter line and or year line. TDX can search index of stock and funds. ''' def __init__(self): self.tdx_api = TdxHq_API() self.__ip = '119.147.212.81' #输入IP self.__port = 7709 #端口 self.__code = '600200' self.__market = 1 #市场代码 0:深圳,1:上海 self._startdate = "2017-01-01" self.today = datetime.date.today() self._enddate = datetime.datetime.strftime(self.today, '%Y-%m-%d') self.__mkt_segment = { 'sh': '60', "sz": '00', "cyb": "30", } #segment 当前板块开始字符串 def __str__(self): return 'TDX object (code : %s)' % self.code @property def IP(self): # self.IP return self.__ip @property def PORT(self): return self.__port @property def code(self): #定义stock code 属性 return self.__code @code.setter #设定code def code(self, code_input): """ The setter of the code property """ if not isinstance(code_input, str): #确定是否是字符串 raise ValueError('the code must string!') if not len(code_input) == 6: #确定长度 raise ValueError('the code value error,the len must SIX !') if code_input.startswith('60'): #确定表头 self.__market = 1 elif code_input.startswith('00'): self.__market = 0 elif code_input.startswith('30'): self.__market = 0 else: raise ValueError('this code is not stock code') self.__code = code_input @property def startdate(self): #开始日期 return self._startdate @startdate.setter #设置日期 def startdate(self, date_input): """ The setter of the start date property """ if not isinstance(date_input, str): raise ValueError('the date must string!') if not len(date_input) == 8: raise ValueError( 'the date value error,the date formet must xxxx-xx-xx !') self._startdate = date_input @property #结束日期 def enddate(self): return self._enddate @enddate.setter def enddate(self, date_input): """ The setter of the start date property """ if not isinstance(date_input, str): raise ValueError('the date must string!') if not len(date_input) == 8: raise ValueError( 'the date value error,the date formet must xxxx-xx-xx !') self._enddate = date_input def get_day_data_tdx(self): #获取K line with self.tdx_api.connect(self.IP, self.PORT): data = self.tdx_api.get_k_data(self.code, self.startdate, self.enddate) data = pandas.DataFrame(data) data.date = data.date.apply( lambda x: datetime.datetime.strptime(x, "%Y-%m-%d")) return data #TODO: 现在是用800点进行计数,以后会细化功能 def get_k_data_tdx(self, k_mode=9): """ 获取k 线图,总计800 点 Parameters ---------- k_mode= 0-11 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线 Returns ------- """ with self.tdx_api.connect(self.self.IP, self.self.PORT): data = self.tdx_api.get_security_bars(k_mode, self.__market, self.code, 0, 800) data = pandas.DataFrame(data) #data.date = data.date.apply( # lambda x: datetime.datetime.strptime(x, "%Y-%m-%d")) return data def len_market(self): #市场有多少只股票 with self.tdx_api.connect(self.IP, self.PORT): _len = self.tdx_api.get_security_count(self.__market) return _len def get_page_tdx(self, block=None): if block is None: market = 1 page = [0] elif block in ['sh', 'SH']: market = 1 page = [13, 14] elif block in ['sz', 'SZ']: print('block for shenzhen') market = 0 page = [0, 1] elif block in ['cyb', 'CYB']: print('block for chuang ye ban') market = 0 page = [7, 8] else: pass code_list_df = pandas.DataFrame() with self.tdx_api.connect(self.IP, self.PORT): for pn in page: data = self.tdx_api.get_security_list(market, pn * 1000) data = pandas.DataFrame(data) print(data) code_list_df = code_list_df.append(data, ignore_index=True) return code_list_df def get_base_finace_tdx(self): with self.tdx_api.connect(self.IP, self.PORT): data = self.tdx_api.get_finance_info(0, '000001') data = pandas.Series(data) print(data) def get_min_data(self): from pytdx.params import TDXParams with self.tdx_api.connect(self.IP, self.PORT): data = self.tdx_api.get_history_minute_time_data( TDXParams.MARKET_SH, self.code, 20161209) data = pandas.DataFrame(data) print(data) #TODO: 需要确定 0: buy 1 : sell def get_tick_data(self): """ 历史分笔交易:time 顺序; price ; vol ;buyorsell [1:] [0:]; sh 60 13000-14000 Parameters ---------- Returns ------- """ data = pandas.DataFrame() with self.tdx_api.connect(self.IP, self.PORT): for i in [2000, 0000]: df = self.tdx_api.get_history_transaction_data( TDXParams.MARKET_SH, "600547", i, 2000, 20160308) df = pandas.DataFrame(df) data = data.append(df, ignore_index=True) return data def get_tick_today(self): """ Get every time the each deal for today.每组数最大len 2 k 所以要确定的数据长度 Parameters ---------- self: Returns ------- """ with self.tdx_api.connect(self.IP, self.PORT): data = pandas.DataFrame() for i in [0, 2000]: df = self.tdx_api.get_transaction_data(self.__market, self.code, i, 2000) df = pandas.DataFrame(df) data = data.append(df, ignore_index=True) return data def get_block(self): with self.tdx_api.connect(self.IP, self.PORT): data = self.tdx_api.get_and_parse_block_info("block.dat") data = pandas.DataFrame(data) print(data) def get_market_segment_list(self, mkt): data = self.get_page_tdx(mkt) self.code_list = pandas.DataFrame() pbar = tqdm(total=len(data.code)) mkt_hard = self.mkt_segment[mkt] for idx, __code in enumerate(data.code): pbar.update(1) if __code.startswith(mkt_hard, 0, 2): self.code_list = self.code_list.append(data.loc[idx], ignore_index=True) return self.code_list def get_sh_list(self): return self.get_market_segment_list('sh') def get_sz_list(self): return self.get_market_segment_list('sz') def get_cyb_list(self): return self.get_market_segment_list('cyb')
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("获取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') print(data) print("读取公司信息-最新提示") data = api.get_company_info_content(0, '000001', '000001.txt', 0, 10) print(data) print("读取除权除息信息") data = api.get_xdxr_info(1, '600300')
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
class TDX_GW(object): __lc_min_bar_reader = None __daily_bar_reader = None __tdx_api = None __connected_ip = '119.147.212.81' __connected_port = 7709 def __init__(self): self.__lc_min_bar_reader = lc_min_bar_reader.TdxLCMinBarReader() self.__daily_bar_reader = TdxDailyBarReader() self.__block_reader = block_reader.BlockReader() self.__tdx_api = TdxHq_API() self.__cfg_provider = ConfigProvider.ConfigProvider() def get_local_stock_bars(self, file_path: str, stock_date_type: StockDataType): if stock_date_type == StockDataType.ONE_MIN or \ stock_date_type == StockDataType.FIVE_MINS: # start = time.time() # df = self.__lc_min_bar_reader.get_df(file_path) data = self.__lc_min_bar_reader.parse_data_by_file(file_path) df = pd.DataFrame(data=data) # df = df['date', 'open', 'high', 'low', 'close', 'amount', 'volume'] # print(f"TDX get 1min bar time spent: {(time.time() - start) * 1000} ms") return df[['date', 'open', 'high', 'low', 'close', 'amount', 'volume']] elif stock_date_type == StockDataType.DAILY: data = self.__daily_bar_reader.get_df(file_path).reset_index() data['date'] = data['date'].dt.strftime('%Y-%m-%d') return data[['date', 'open', 'high', 'low', 'close', 'amount', 'volume']] else: raise UnimplementedException def get_local_stock_bars_raw_data(self, file_path: str, stock_date_type: StockDataType): if stock_date_type == StockDataType.ONE_MIN or \ stock_date_type == StockDataType.FIVE_MINS: return self.__lc_min_bar_reader.parse_data_by_file(file_path) elif stock_date_type == StockDataType.DAILY: return self.__daily_bar_reader.parse_data_by_file(file_path) else: raise UnimplementedException def get_local_block(self): file_path = self.__cfg_provider.get_tdx_block_directory_path() return self.__block_reader.get_df(file_path, BlockReader_TYPE_GROUP) def get_realtime_stock_1min_bars(self, market: str, stock_id: str): with self.__tdx_api.connect(self.__connected_ip, self.__connected_port): market_code = self.__get_market_code(market) df = self.__tdx_api.to_df( self.__tdx_api.get_security_bars(8, market_code, stock_id, 0, 10)) # 返回DataFrame return df def get_realtime_stocks_quotes(self, stock_ids: []): stock_list = [] for id in stock_ids: stock_list.append((com_utils.get_stock_market(id), id)) with self.__tdx_api.connect(self.__connected_ip, self.__connected_port): return self.__tdx_api.get_security_quotes(stock_list) def get_history_minute_time_data(self, market: str, stock_id: str, date: int): with self.__tdx_api.connect(self.__connected_ip, self.__connected_port): market_code = self.__get_market_code(market) df = self.__tdx_api.to_df( self.__tdx_api.get_history_minute_time_data(market_code, stock_id, date)) return df def get_xdxr_info(self, market: str, stock_id: str): with self.__tdx_api.connect(self.__connected_ip, self.__connected_port): market_code = self.__get_market_code(market) df = self.__tdx_api.to_df( self.__tdx_api.get_xdxr_info(market_code, stock_id)) return df def test(self): with self.__tdx_api.connect(self.__connected_ip, self.__connected_port): return self.__tdx_api.get_history_minute_time_data(0, '000001', '2019-05-05') def __get_market_code(self, market: str): if market == cfg.MARKET.SHANGHAI: return 1 elif market == cfg.MARKET.SHENZHEN: return 0 else: raise UnimplementedException
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 Stock(): PRICE_TOLERANT = 0.001 PRICE_PRCISION = 0.01 TDX_IP = '119.147.212.81' TDX_PORT = 7709 def __init__(self, code): self.code = str(code) self.market = 2 if code.startswith('002') or code.startswith('300') or code.startswith( '000'): self.market = TDXParams.MARKET_SZ elif code.startswith('60'): self.market = TDXParams.MARKET_SH if self.market == 2: raise Exception('code should be stock code') self.api = TdxHq_API() # stock path self.stock_path = Path.home().joinpath('stocks').joinpath(self.code) self.day_k_path = self.stock_path.joinpath('day_k') self.vpd_path = self.stock_path.joinpath('vpd') if not Path.exists(self.stock_path): os.makedirs(self.stock_path) if not Path.exists(self.day_k_path): os.makedirs(self.day_k_path) if not Path.exists(self.vpd_path): os.makedirs(self.vpd_path) # get xdxr self.xdxr = self.get_xdxr() # get day-k data self.day_k = self.get_all_day_k() self.trading_days = pd.to_datetime( self.day_k.datetime).dt.strftime('%Y%m%d') self.day_k.datetime = self.trading_days # get day minute time data self.vpd = self.get_minute_vpd('20171124') def get_xdxr(self): xdxr_path = self.stock_path.joinpath( 'xdxr_' + str(datetime.datetime.now().date()) + '.csv') if not Path.exists(xdxr_path): with self.api.connect(self.TDX_IP, self.TDX_PORT): xdxr = self.api.to_df( self.api.get_xdxr_info(self.market, self.code)) if xdxr.empty: raise Exception('xdxr empty') xdxr.to_csv(xdxr_path) #pg = xdxr.loc[xdxr['peigu'] > 0] #if not pg.empty: # raise Exception('stock has peigu') return pd.read_csv(xdxr_path, index_col=0) def get_all_day_k(self): day_k_file = self.day_k_path.joinpath( str(datetime.datetime.now().date()) + '.csv') if not Path.exists(day_k_file): day_k = pd.DataFrame() with self.api.connect(self.TDX_IP, self.TDX_PORT): for offset in range(0, 10000, 800): df = self.api.to_df( self.api.get_security_bars(9, self.market, self.code, offset, 800)) if not df.empty: day_k = pd.concat([df, day_k], ignore_index=True) else: break if day_k.size < 10: raise Exception('day_k empty') day_k = day_k[day_k.vol > 0] day_k.reset_index(drop=True, inplace=True) #dt = pd.to_datetime(day_k.datetime) #day_k = day_k.drop(columns=['datetime']) #day_k = day_k.assign(datetime = dt) day_k.to_csv(day_k_file) return pd.read_csv(day_k_file, index_col=0) # day minute time volumn-price-distribution def get_minute_vpd(self, date): vpd_file = self.vpd_path.joinpath(str(date) + '.csv') if not Path.exists(vpd_file): with self.api.connect(self.TDX_IP, self.TDX_PORT): #self.fs = api.get_minute_time_data(self.market, self.code) raw_df = self.api.to_df( self.api.get_history_minute_time_data( self.market, self.code, date)) if raw_df.shape != (240, 2): raise Exception('raw_df wrong size') vpd = pd.DataFrame() vpd = vpd.append(raw_df.sort_values(by=['price']), ignore_index=True) last_price = -1 last_index = -1 drop_index = [] for v in vpd.index: price = vpd.at[v, 'price'] if self.price_equal(price, last_price): vpd.at[last_index, 'vol'] += vpd.at[v, 'vol'] drop_index.append(v) else: last_price = price last_index = v vpd = vpd.drop(drop_index) vpd.reset_index(drop=True, inplace=True) vpd.to_csv(vpd_file) return pd.read_csv(vpd_file, index_col=0) def price_range(self, start, end): while start < (end - self.PRICE_TOLERANT): yield round(start, 2) start += self.PRICE_PRCISION def price_equal(self, a, b): if abs(a - b) < self.PRICE_TOLERANT: return True else: return False def price_higher(self, a, b): if (a - b) > (self.PRICE_PRCISION - self.PRICE_TOLERANT): return True else: return False def price_lower(self, a, b): if (b - a) > (self.PRICE_PRCISION - self.PRICE_TOLERANT): return True else: return False def test_vpd(self): tri_factor = 1 / np.tan(45) chip_hist = [] chip = pd.DataFrame() chip_inc = pd.DataFrame() chip_inc_temp = pd.DataFrame() for day in self.trading_days[0:20]: if datetime.datetime.now().date().strftime('%Y%m%d') == day: continue vpd = self.get_minute_vpd(day) vpd.reset_index(drop=True, inplace=True) #vpd.set_index('price', inplace=True) if chip.empty: chip = pd.DataFrame(vpd, copy=True) chip['vol'] = chip['vol'].astype('float64') chip.drop(chip.index, inplace=True) chip = chip.append({ 'price': 4.79, 'vol': 6000 * 10000 / 100 }, ignore_index=True) chip_inc = pd.DataFrame(chip, copy=True) chip_inc['vol'] = chip_inc['vol'].astype('float64') chip_inc_temp = pd.DataFrame(chip, copy=True) chip_inc_temp['vol'] = chip_inc_temp['vol'].astype('float64') chip_inc['vol'] = np.zeros(chip_inc.shape[0]) for i, p_outer in vpd.iterrows(): chip_inc_temp['vol'] = np.zeros(chip_inc_temp.shape[0]) for j, p_inner in chip.iterrows(): inc = 0 if p_outer.price > chip.iloc[-1].price: inc = (p_outer.price - p_inner.price) * tri_factor else: inc = (chip.iloc[-1].price - p_inner.price) * tri_factor chip_inc_temp.at[j, 'vol'] += inc c = p_outer.vol / chip_inc_temp.sum().vol chip_inc_temp['vol'] = chip_inc_temp['vol'].mul(c) chip_inc['vol'] = chip_inc['vol'].add(chip_inc_temp['vol']) chip['vol'] = chip['vol'].sub(chip_inc['vol']) sum_negative = 0.0 for i, r in chip.iterrows(): if r.vol < 0: sum_negative -= r.vol chip.at[i, 'vol'] = 0.0 for i, r in chip.iterrows(): if r.vol >= sum_negative: chip.at[i, 'vol'] -= sum_negative break else: sum_negative -= chip.at[i, 'vol'] chip.at[i, 'vol'] = 0.0 chip = chip.merge(vpd, how='outer', left_on='price', right_on='price', sort=True, suffixes=['', '_inc']) for i, r in chip.iterrows(): if np.isnan(r.vol): chip.at[i, 'vol'] = 0.0 if not np.isnan(r.vol_inc): chip.at[i, 'vol'] += chip.at[i, 'vol_inc'] chip.drop('vol_inc', axis=1, inplace=True) chip.drop(chip[chip['vol'] == 0].index, inplace=True) chip_inc = pd.DataFrame(chip, copy=True) chip_inc['vol'] = chip_inc['vol'].astype('float64') chip_inc_temp = pd.DataFrame(chip, copy=True) chip_inc_temp['vol'] = chip_inc_temp['vol'].astype('float64') chip_hist.append(pd.DataFrame(chip, copy=True)) print(day) if abs(chip.sum().vol - 600000) > 0.1: raise Exception('vol error')