From e7b56439f93548a291d71258e0d03c74062e86dd Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 5 Dec 2017 12:48:25 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=E6=96=B0=E5=A2=9EQuantosDataService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/QuantosDataService/README.md | 3 + examples/QuantosDataService/config.json | 10 ++ examples/QuantosDataService/dataService.py | 121 ++++++++++++++++++++ examples/QuantosDataService/downloadData.py | 22 ++++ examples/QuantosDataService/runService.py | 39 +++++++ examples/README.md | 6 +- 6 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 examples/QuantosDataService/README.md create mode 100644 examples/QuantosDataService/config.json create mode 100644 examples/QuantosDataService/dataService.py create mode 100644 examples/QuantosDataService/downloadData.py create mode 100644 examples/QuantosDataService/runService.py diff --git a/examples/QuantosDataService/README.md b/examples/QuantosDataService/README.md new file mode 100644 index 00000000..18d119e0 --- /dev/null +++ b/examples/QuantosDataService/README.md @@ -0,0 +1,3 @@ +# quantOS历史行情服务 + +请在[www.quantos.org](www.quantos.org)注册后,将用户名和TOKEN输入到配置文件config.json中,即可使用该服务。 \ No newline at end of file diff --git a/examples/QuantosDataService/config.json b/examples/QuantosDataService/config.json new file mode 100644 index 00000000..c046ab3f --- /dev/null +++ b/examples/QuantosDataService/config.json @@ -0,0 +1,10 @@ +{ + "MONGO_HOST": "localhost", + "MONGO_PORT": 27017, + + "DATA_SERVER": "tcp://data.tushare.org:8910", + "USERNAME": "", + "TOKEN": "", + + "SYMBOLS": ["510050.SSE", "510300.SSE"] +} \ No newline at end of file diff --git a/examples/QuantosDataService/dataService.py b/examples/QuantosDataService/dataService.py new file mode 100644 index 00000000..0d76fc70 --- /dev/null +++ b/examples/QuantosDataService/dataService.py @@ -0,0 +1,121 @@ +# encoding: UTF-8 + +import sys +import json +from datetime import datetime, timedelta +from time import time, sleep + +from pymongo import MongoClient, ASCENDING + +from vnpy.trader.vtObject import VtBarData +from vnpy.trader.app.ctaStrategy.ctaBase import MINUTE_DB_NAME +from vnpy.trader.gateway.tkproGateway.DataApi import DataApi + + +# 交易所类型映射 +exchangeMap = {} +exchangeMap['CFFEX'] = 'CFE' +exchangeMap['SHFE'] = 'SHF' +exchangeMap['CZCE'] = 'CZC' +exchangeMap['DCE'] = 'DCE' +exchangeMap['SSE'] = 'SH' +exchangeMap['SZSE'] = 'SZ' +exchangeMapReverse = {v:k for k,v in exchangeMap.items()} + +# 加载配置 +config = open('config.json') +setting = json.load(config) +config.close() + +MONGO_HOST = setting['MONGO_HOST'] +MONGO_PORT = setting['MONGO_PORT'] +SYMBOLS = setting['SYMBOLS'] +USERNAME = setting['USERNAME'] +TOKEN = setting['TOKEN'] +DATA_SERVER = setting['DATA_SERVER'] + +# 创建API对象 +mc = MongoClient(MONGO_HOST, MONGO_PORT) # Mongo连接 +db = mc[MINUTE_DB_NAME] # 数据库 + + +#---------------------------------------------------------------------- +def generateVtBar(row): + """生成K线""" + bar = VtBarData() + + symbol, exchange = row['symbol'].split('.') + + bar.symbol = symbol + bar.exchange = exchangeMapReverse[exchange] + bar.vtSymbol = '.'.join([bar.symbol, bar.exchange]) + bar.open = row['open'] + bar.high = row['high'] + bar.low = row['low'] + bar.close = row['close'] + bar.volume = row['volume'] + + bar.date = str(row['trade_date']) + bar.time = str(row['time']) + bar.datetime = datetime.strptime(' '.join([bar.date, bar.time]), '%Y%m%d %H%M%S') + + return bar + +#---------------------------------------------------------------------- +def downMinuteBarBySymbol(api, vtSymbol, startDate): + """下载某一合约的分钟线数据""" + start = time() + + cl = db[vtSymbol] + cl.ensure_index([('datetime', ASCENDING)], unique=True) # 添加索引 + + dt = datetime.strptime(startDate, '%Y%m%d') + today = datetime.now() + delta = timedelta(1) + + code, exchange = vtSymbol.split('.') + symbol = '.'.join([code, exchangeMap[exchange]]) + + while dt <= today: + d = int(dt.strftime('%Y%m%d')) + df, msg = api.bar(symbol, freq='1M', trade_date=d) + dt += delta + + if df is None: + continue + + for ix, row in df.iterrows(): + bar = generateVtBar(row) + d = bar.__dict__ + flt = {'datetime': bar.datetime} + cl.replace_one(flt, d, True) + + + end = time() + cost = (end - start) * 1000 + + print u'合约%s数据下载完成%s - %s,耗时%s毫秒' %(vtSymbol, startDate, today.strftime('%Y%m%d'), cost) + + +#---------------------------------------------------------------------- +def downloadAllMinuteBar(api): + """下载所有配置中的合约的分钟线数据""" + print '-' * 50 + print u'开始下载合约分钟线数据' + print '-' * 50 + + startDt = datetime.today() - 10 * timedelta(1) + startDate = startDt.strftime('%Y%m%d') + + # 添加下载任务 + for symbol in SYMBOLS: + downMinuteBarBySymbol(api, str(symbol), startDate) + + print '-' * 50 + print u'合约分钟线数据下载完成' + print '-' * 50 + + +if __name__ == '__main__': + downloadAllMinuteBar() + \ No newline at end of file diff --git a/examples/QuantosDataService/downloadData.py b/examples/QuantosDataService/downloadData.py new file mode 100644 index 00000000..5ed97326 --- /dev/null +++ b/examples/QuantosDataService/downloadData.py @@ -0,0 +1,22 @@ +# encoding: UTF-8 + +""" +立即下载数据到数据库中,用于手动执行更新操作。 +""" + +import json + +from vnpy.trader.gateway.tkproGateway.DataApi import DataApi +from dataService import * + + +if __name__ == '__main__': + # 创建API对象 + api = DataApi(DATA_SERVER) + info, msg = api.login(USERNAME, TOKEN) + + if not info: + print u'数据服务器登录失败,原因:%s' %msg + + # 下载数据 + downloadAllMinuteBar(api) \ No newline at end of file diff --git a/examples/QuantosDataService/runService.py b/examples/QuantosDataService/runService.py new file mode 100644 index 00000000..34132e33 --- /dev/null +++ b/examples/QuantosDataService/runService.py @@ -0,0 +1,39 @@ +# encoding: UTF-8 + +""" +定时服务,可无人值守运行,实现每日自动下载更新历史行情数据到数据库中。 +""" + +import datetime as ddt + +from dataService import * + + +if __name__ == '__main__': + taskCompletedDate = None + + # 生成一个随机的任务下载时间,用于避免所有用户在同一时间访问数据服务器 + taskTime = ddt.time(hour=17, minute=0) + + # 进入主循环 + while True: + t = ddt.datetime.now() + + # 每天到达任务下载时间后,执行数据下载的操作 + if t.time() > taskTime and (taskCompletedDate is None or t.date() != taskCompletedDate): + # 创建API对象 + api = DataApi(DATA_SERVER) + info, msg = api.login(USERNAME, TOKEN) + + if not info: + print u'数据服务器登录失败,原因:%s' %msg + + # 下载数据 + downloadAllMinuteBar(api) + + # 更新任务完成的日期 + taskCompletedDate = t.date() + else: + print u'当前时间%s,任务定时%s' %(t, taskTime) + + sleep(60) \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index 10befbda..cb7a61bf 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,6 +4,8 @@ * VnTrader:最常用的vn.py图形交易界面 +* OptionMaster: 期权量化交易系统 + * DataRecording:全自动行情记录工具(无需用户每日定时重启) * CtaTrading:无图形界面模式的CTA策略交易 @@ -18,4 +20,6 @@ * TushareDataService:TuShare历史行情服务(A股) -* FutuDataService:富途证券历史行情服务(美股、港股) \ No newline at end of file +* FutuDataService:富途证券历史行情服务(美股、港股) + +* QuantosDataService: quantOS历史行情服务(A股、期货) \ No newline at end of file