diff --git a/vn.trader/ctaAlgo/utilSinaClient.py b/vn.trader/ctaAlgo/utilSinaClient.py new file mode 100644 index 00000000..bd1aed66 --- /dev/null +++ b/vn.trader/ctaAlgo/utilSinaClient.py @@ -0,0 +1,214 @@ +# encoding: UTF-8 + +from __future__ import print_function + +'''一个简单的SINA数据客户端,主要使用requests开发''' +import requests +from time import sleep +import execjs +from datetime import datetime,timedelta +from ctaBase import CtaBarData,CtaTickData + +class UtilSinaClient(object): + + # ---------------------------------------------------------------------- + def __init__(self, strategy): + + self.strategy = strategy + + requests.adapters.DEFAULT_RETRIES = 5 + self.session = requests.session() + self.session.keep_alive = False + + def getTicks(self, symbol, callback): + + # 从sina加载最新的M1数据 + try: + + url = u'http://stock2.finance.sina.com.cn/futures/api/json.php/InnerFuturesService.getInnerFutures5MLine?symbol={0}'.format( + symbol) + self.strategy.writeCtaLog(u'从sina下载{0}Tick数据 {1}'.format(symbol, url)) + responses = execjs.eval(self.session.get(url).content.decode('gbk').split('\n')[-1]) + + datevalue = datetime.now().strftime('%Y-%m-%d') + + for j, day_item in enumerate(responses[str(symbol).upper()]): + for i, item in enumerate(day_item): + + tick = CtaTickData() + tick.vtSymbol = symbol + tick.symbol = symbol + + if len(item) >= 6: + datevalue = item[6] + + tick.date = datevalue + tick.time = item[4] + u':00' + tick.datetime = datetime.strptime(tick.date + ' ' + tick.time, '%Y-%m-%d %H:%M:%S') + + tick.lastPrice = float(item[0]) + tick.volume = int(item[2]) + + if type(item[3]) == type(None): + tick.openInterest = 0 + else: + tick.openInterest = int(item[3]) + + callback(tick) + + return True + + except Exception as e: + self.strategy.writeCtaLog(u'加载sina历史Tick数据失败:' + str(e)) + return False + + + def getMinBars(self, symbol, minute, callback): + """# 从sina加载最新的M5,M15,M30,M60数据""" + + if minute not in {5, 15, 30, 60}: + return False + + sinaBars = [] + try: + + url = u'http://stock2.finance.sina.com.cn/futures/api/json.php/InnerFuturesService.getInnerFutures{0}MinKLine?symbol={1}'.format(minute,symbol) + self.strategy.writeCtaLog(u'从sina下载{0}的{1}分钟数据 {2}'.format(symbol,minute, url)) + responses = execjs.eval(self.session.get(url).content.decode('gbk').split('\n')[-1]) + dayVolume = 0 + + for item in responses: + bar = CtaBarData() + + bar.vtSymbol = symbol + bar.symbol = symbol + # bar的close time + sinaDt = datetime.strptime(item[0], '%Y-%m-%d %H:%M:00') + + if minute in {5, 15} and sinaDt.hour == 10 and sinaDt.minute == 30: + # 这个是sina的bug,它把10:15 ~10:30也包含进来了 + continue + + if minute == 60 and sinaDt.hour in {11,23,1,2} and sinaDt.minute == 30: + bar.datetime = sinaDt - timedelta(seconds=(minute /2)* 60) + else: + bar.datetime = sinaDt - timedelta(seconds=minute * 60) + + bar.date = bar.datetime.strftime('%Y%m%d') + bar.tradingDay = bar.date # todo: 需要修改,晚上21点后,修改为next workingday + bar.time = bar.datetime.strftime('%H:%M:00') + + bar.open = float(item[1]) + bar.high = float(item[2]) + bar.low = float(item[3]) + bar.close = float(item[4]) + bar.volume = int(item[5]) + + # 计算dayvolume + if not sinaBars: + dayVolume = bar.volume + else: + if sinaBars[-1].datetime.hour == 14 and bar.datetime.hour !=14: + dayVolume = bar.volume + else: + dayVolume += bar.volume + + bar.dayVolume = dayVolume + + sinaBars.append(bar) + + if len(sinaBars)>0: + self.strategy.writeCtaLog(u'从sina读取了{0}条{1}分钟数据'.format(len(sinaBars),minute)) + + # 把sina的bar灌入回调函数 + for bar in sinaBars: + callback(bar) + + # 处理完毕,清空 + sinaBars = [] + + return True + else: + self.strategy.writeCtaLog(u'从sina读取{0}分钟数据失败'.format(minute)) + return False + + except Exception as e: + self.strategy.writeCtaLog(u'加载Sina历史分钟数据失败:'+str(e)) + return False + + def getDayBars(self, symbol, callback): + """# 从sina加载最新的Day数据""" + + sinaBars = [] + + try: + + url = u'http://stock.finance.sina.com.cn/futures/api/json.php/InnerFuturesService.getInnerFuturesDailyKLine?symbol={0}'.format(symbol) + self.strategy.writeCtaLog(u'从sina下载{0}的日K数据 {1}'.format(symbol, url)) + responses = execjs.eval(self.session.get(url).content.decode('gbk')) + dayVolume = 0 + + for item in responses: + bar = CtaBarData() + + bar.vtSymbol = symbol + bar.symbol = symbol + # bar的close time + bar.datetime = datetime.strptime(item['date'], '%Y-%m-%d') + bar.date = bar.datetime.strftime('%Y%m%d') + bar.tradingDay = bar.date # todo: 需要修改,晚上21点后,修改为next workingday + bar.time = bar.datetime.strftime('%H:%M:00') + + bar.open = float(item['open']) + bar.high = float(item['high']) + bar.low = float(item['low']) + bar.close = float(item['close']) + bar.volume = int(item['volume']) + bar.dayVolume = bar.volume + + sinaBars.append(bar) + + if len(sinaBars)>0: + self.strategy.writeCtaLog(u'从sina读取了{0}条日线K数据'.format(len(sinaBars))) + + # 把sina的bar灌入回调函数 + for bar in sinaBars: + callback(bar) + + # 处理完毕,清空 + sinaBars = [] + + return True + else: + self.strategy.writeCtaLog(u'从sina读取日线K数据失败') + return False + + except Exception as e: + self.strategy.writeCtaLog(u'加载Sina历史日线数据失败:'+str(e)) + return False + +class TestStrategy(object): + + def __init__(self): + pass + + def addBar(self, bar): + print(u'{0},o:{1},h:{2},l:{3},c:{4},v:{5}'.format(bar.datetime, bar.open, bar.high, bar.low, bar.close, bar.volume)) + + def addTick(self, tick): + print(u'{0},{1},ap:{2},av:{3},bp:{4},bv:{5}'.format(tick.datetime, tick.lastPrice, tick.askPrice1, tick.askVolume1, tick.bidPrice1, tick.bidVolume1)) + + def writeCtaLog(self, content): + print(content) + +if __name__ == '__main__': + t = TestStrategy() + + sina = UtilSinaClient(t) + + #rt=sina.getDayBars(symbol='RB1705', callback=t.addBar) + + #rt = sina.getMinBars(symbol='RB1705',minute = 5, callback=t.addBar) + + rt = sina.getTicks(symbol='RB1705', callback=t.addTick) +