[增强功能] linux下策略加密,baostock复权因子,tdx股票数据,gateway增强,回放K线增强

This commit is contained in:
msincenselee 2020-04-29 23:58:06 +08:00
parent d100ff6e57
commit cec5b2f0c0
16 changed files with 426 additions and 148 deletions

View File

@ -1,5 +1,6 @@
# flake8: noqa
# 自动补全期货指数合约renko bar => Mongodb
# 下载的tick数据缓存 => tick_data/tdx/future
import sys, os, copy, csv, signal
vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
@ -23,7 +24,7 @@ if __name__ == "__main__":
setting = {
"host": host,
"db_name": FUTURE_RENKO_DB_NAME,
"cache_folder": os.path.join(vnpy_root, 'ticks', 'tdx', 'future')
"cache_folder": os.path.join(vnpy_root, 'tick_data', 'tdx', 'future')
}
builder = FutureRenkoRebuilder(setting)

View File

@ -17,7 +17,7 @@ ta-lib
ibapi
deap
pyzmq
wmi
QScintilla
pytdx
pykalman
cython

View File

@ -660,6 +660,9 @@ class BackTestingEngine(object):
elif filename.endswith(".pyd"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
elif filename.endswith(".so"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
else:
continue
self.load_strategy_class_from_module(strategy_module_name)

View File

@ -216,8 +216,9 @@ class CtaEngine(BaseEngine):
# 主动获取所有策略得持仓信息
all_strategy_pos = self.get_all_strategy_pos()
# 比对仓位,使用上述获取得持仓信息,不用重复获取
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
if dt.minute % 5 == 0:
# 比对仓位,使用上述获取得持仓信息,不用重复获取
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
# 推送到事件
self.put_all_strategy_pos_event(all_strategy_pos)
@ -1274,6 +1275,9 @@ class CtaEngine(BaseEngine):
elif filename.endswith(".pyd"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
elif filename.endswith(".so"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
else:
continue
self.load_strategy_class_from_module(strategy_module_name)

View File

@ -633,6 +633,9 @@ class BackTestingEngine(object):
elif filename.endswith(".pyd"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
elif filename.endswith(".so"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
else:
continue
self.load_strategy_class_from_module(strategy_module_name)

View File

@ -213,7 +213,7 @@ class CtaEngine(BaseEngine):
all_trading = False
dt = datetime.now()
# 每分钟执行的逻辑
if self.last_minute != dt.minute:
self.last_minute = dt.minute
@ -221,8 +221,10 @@ class CtaEngine(BaseEngine):
# 主动获取所有策略得持仓信息
all_strategy_pos = self.get_all_strategy_pos()
# 比对仓位,使用上述获取得持仓信息,不用重复获取
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
# 每5分钟检查一次
if dt.minute % 5 == 0:
# 比对仓位,使用上述获取得持仓信息,不用重复获取
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
# 推送到事件
self.put_all_strategy_pos_event(all_strategy_pos)
@ -1244,6 +1246,9 @@ class CtaEngine(BaseEngine):
elif filename.endswith(".pyd"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
elif filename.endswith(".so"):
strategy_module_name = ".".join(
[module_name, filename.split(".")[0]])
else:
continue
self.load_strategy_class_from_module(strategy_module_name)
@ -1313,7 +1318,7 @@ class CtaEngine(BaseEngine):
# 兼容处理如果strategy是None通过name获取
if strategy is None:
if name not in self.strategies:
self.write_log(u'getStategyPos 策略实例不存在:' + name)
self.write_log(u'get_strategy_pos 策略实例不存在:' + name)
return []
# 获取策略实例
strategy = self.strategies[name]

View File

@ -63,7 +63,7 @@ class PortfolioTestingEngine(BackTestingEngine):
if vt_symbol in self.bar_df_dict:
return True
if not os.path.exists(bar_file):
if bar_file is None or not os.path.exists(bar_file):
self.write_error(u'回测时,{}对应的csv bar文件{}不存在'.format(vt_symbol, bar_file))
return False

View File

@ -18,14 +18,14 @@ class CtaPosition(CtaComponent):
self.short_pos = 0 # 空仓持仓(负数)
self.pos = 0 # 持仓状态 0:空仓/对空平等; >=1 净多仓 <=-1 净空仓
self.maxPos = sys.maxsize # 最大持仓量(多仓+空仓总量)
self.name = getattr(strategy, 'strategy_name', 'strategy')
def open_pos(self, direction: Direction, volume: float):
"""开、加仓"""
# volume: 正整数
if direction == Direction.LONG: # 加多仓
if (max(self.pos, self.long_pos) + volume) > self.maxPos:
self.write_error(content=f'开仓异常,净:{self.pos},多:{self.long_pos},加多:{volume},超过:{self.maxPos}')
self.write_error(content=f'{self.name} 开仓异常,净:{self.pos},多:{self.long_pos},加多:{volume},超过:{self.maxPos}')
# 更新
pre_long_pos = self.long_pos
@ -34,20 +34,20 @@ class CtaPosition(CtaComponent):
self.pos += volume
self.long_pos = round(self.long_pos, 7)
self.pos = round(self.pos, 7)
self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}')
self.write_log(f'净:{pre_pos}->{self.pos}')
self.write_log(f'{self.name} 多仓:{pre_long_pos}->{self.long_pos}')
self.write_log(f'{self.name} 净:{pre_pos}->{self.pos}')
if direction == Direction.SHORT: # 加空仓
if (min(self.pos, self.short_pos) - volume) < (0 - self.maxPos):
self.write_error(content=f'开仓异常,净:{self.pos},空:{self.short_pos},加空:{volume},超过:{self.maxPos}')
self.write_error(content=f'{self.name} 开仓异常,净:{self.pos},空:{self.short_pos},加空:{volume},超过:{self.maxPos}')
pre_short_pos = self.short_pos
pre_pos = self.pos
self.short_pos -= volume
self.pos -= volume
self.short_pos = round(self.short_pos, 7)
self.pos = round(self.pos, 7)
self.write_log(f'空仓:{pre_short_pos}->{self.short_pos}')
self.write_log(f'净:{pre_pos}->{self.pos}')
self.write_log(f'{self.name} 空仓:{pre_short_pos}->{self.short_pos}')
self.write_log(f'{self.name} 净:{pre_pos}->{self.pos}')
return True
def close_pos(self, direction: Direction, volume: float):
@ -56,7 +56,7 @@ class CtaPosition(CtaComponent):
if direction == Direction.LONG: # 平空仓 Cover
if self.short_pos + volume > 0:
self.write_error(u'平仓异常,超出仓位。净:{0},空:{1},平仓:{2}'.format(self.pos, self.short_pos, volume))
self.write_error(f'{self.name} 平仓异常,超出仓位。净:{self.pos},空:{self.short_pos},平仓:{volume}')
pre_short_pos = self.short_pos
pre_pos = self.pos
@ -64,15 +64,15 @@ class CtaPosition(CtaComponent):
self.pos += volume
self.short_pos = round(self.short_pos, 7)
self.pos = round(self.pos, 7)
self.write_log(f'空仓:{pre_short_pos}->{self.short_pos}')
self.write_log(f'净:{pre_pos}->{self.pos}')
self.write_log(f'{self.name} 空仓:{pre_short_pos}->{self.short_pos}')
self.write_log(f'{self.name} 净:{pre_pos}->{self.pos}')
# 更新上层策略的pos。该方法不推荐使用
self.strategy.pos = self.pos
if direction == Direction.SHORT: # 平多仓
if self.long_pos - volume < 0:
self.write_error(u'平仓异常,超出仓位。净:{0},多:{1},平仓:{2}'.format(self.pos, self.long_pos, volume))
self.write_error(f'{self.name} 平仓异常,超出仓位。净:{self.pos},多:{self.long_pos},平仓:{volume}')
pre_long_pos = self.long_pos
pre_pos = self.pos
@ -81,14 +81,14 @@ class CtaPosition(CtaComponent):
self.long_pos = round(self.long_pos, 7)
self.pos = round(self.pos, 7)
self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}')
self.write_log(f'净:{pre_pos}->{self.pos}')
self.write_log(f'{self.name} 多仓:{pre_long_pos}->{self.long_pos}')
self.write_log(f'{self.name} 净:{pre_pos}->{self.pos}')
return True
def clear(self):
"""清除状态"""
self.write_log(u'清除所有持仓状态')
self.write_log(f'{self.name} 清除所有持仓状态')
self.pos = 0
self.long_pos = 0
self.short_pos = 0

View File

@ -41,6 +41,13 @@ class MongoData(object):
def write_error(self, content):
print(content, file=sys.stderr)
def get_collections(self, db_name):
"""获取所有collection"""
if not self.db_client:
return []
db = self.db_client[db_name]
return db.list_collection_names()
# ----------------------------------------------------------------------
def db_insert(self, db_name, col_name, d):
"""向MongoDB中插入数据d是具体数据"""
@ -308,4 +315,4 @@ class MongoData(object):
if __name__ == "__main__":
m = MongoData(host='localhost', port=27017)
m.db_create_index('FutureRenko_Db', 'AU_5', 'datetime', 1)
m.db_create_index('FutureRenko', 'AU_5', 'datetime', 1)

View File

@ -56,7 +56,7 @@ def get_adjust_factor(vt_symbol: str, stock_name: str = '', need_login: bool = T
print(f'开始获取{stock_name} {bs_code}得复权因子')
rs = bs.query_adjust_factor(
code=bs_code,
start_date='2006-01-01'
start_date='2000-01-01'
)
if rs.error_code != '0':
print(f'证券宝获取沪深A股复权因子数据错误代码:{rs.error_code}, 错误信息:{rs.error_msg}')

View File

@ -12,3 +12,146 @@
1.tdx_stock_data, 股票数据接口
2.tdx_future_data, 期货数据接口
上海交易所
首位代码 产品定义
国债/指数
债券
回购
期货
备用
基金/权证
A股
非交易业务(发行、权益分配)
备用
B股
第一位 第2-3位 业务定义
0 00 上证指数、沪深300指数、中证指数
09 国债(2000年前发行)
10 国债2000年-2009年发行
19 固定收益电子平台交易国债
20 记账式贴现国债
90 新国债质押式回购质押券出入库对应010***国债)
99 新国债质押式回购质押券出入库对应009***国债)
1 00 可转债对应600*)其中1009用于转债回售
04 公司债及国家发改委等核准发行的、登记在证券账户的债券对应122***)出入库
05 105000-105899用于分离债对应126)出入库, 105900-105999用于企业债120、129***)出入库
06 地方政府债出入库对应130***)
07 记账式贴现国债出入库对应020***)
10 可转债对应600***)
12 可转债对应600***)
13 可转债对应601***)
20 企业债
21 资产证券化
22 122000-122499用于公司债122500-122999用于国家发改委等核准发行的、登记在证券账户的债券
26 分离交易的可转换公司债
28 可交换公司债
29 企业债
30 地方政府债
81 可转债转股对应600***),已不再增用
90 可转债转股对应600***
91 可转债转股对应601***
92 可交换公司债转股对应128***
2 01 国债回购(席位托管方式)
02 企业债回购
03 国债买断式回购
04 债券质押式回购(账户托管方式)
05 债券质押式报价回购
3 10 国债期货(暂停交易)
5 00 契约型封闭式基金
10 交易型开放式指数证券投资基金
19 开放式基金申赎
21 开放式基金认购
22 开放式基金跨市场转托管
23 开放式基金分红
24 开放式基金基金转换
80 权证(含股改权证、公司权证)
82 权证行权
6 00 A股证券
01 A股证券
7 00 配股对应600***
02 职工股配股对应600***
04 持股配债
05 基金扩募
06 要约收购
30 申购、增发对应600***
31 持股增发对应600***
33 可转债申购对应600***
35 基金申购
38 网上投票(对应600***)
40 申购款或增发款对应600***
41 申购或增发配号对应600***
43 可转债发债款对应600***
44 可转债配号对应600***
45 基金申购款
46 基金申购配号
51 751000-751199用于国债分销751900-751969用于地方政府债对应130分销751970-751999用于公司债及国家发改委等核准发行的、登记在证券账户的债券对应122分销
60 配股对应601***
62 职工股配股对应601***
80 申购、增发对应601***
81 持股增发对应601***
83 可转债申购对应601***
88 网络投票对应601***
90 申购款或增发款对应601***
91 申购或增发配号对应601***
93 可转债申购款对应601***
94 可转债配号对应601***
99 指定交易含指定交易、撤销指定、回购指定撤销、A股密码服务等
9 00 B股证券
38 网上投票(B股)
39 B股网络投票密码服务现仅用939988
深圳
第一位 第二位 第三位 定义
0 0 0-1 主板 A 股
2-4 中小企业板股票
3 0-2 主板 A 股及中小企业板股票认购权证
6 创业板股权激励计划涉及的员工认股权
7 [037000037499]主板 A 股股权激励计划涉及的员工认股权[037500037999]中小企业板股权激励计划涉及的员工认股权
8-9 主板 A 股及中小企业板股票认沽权证
7 0-1 主板 A 股增发 主板可转换公司债券申购
2-4 中小企业板股票增发 中小企业板可转换公司债券申购
8 0-1 主板 A 股配股优先权 主板可转换公司债券的优先权认购
2-4 中小企业板配股优先权 中小企业板可转换公司债券的优先权认购
1 0 0-7 附息式国债
[101650101699]是债券分销代码区间,分销代码位于[101660 101674]区间时实行投资者适当性管理
8 贴现式国债
9 地方政府债
1 1 企业债
2 公司债
5 可分离交易的可转换公司债券
7 [117000117499]为中小企业可交换私募债
[117500117999]为证券公司短期债
8 [118900118999]为证券公司次级债
[118000118899]为其他中小企业私募债
9 [119000119499]为资产支持证券 ABS
2 0-9 可转换公司债券(已发行的可转换公司债券继续保留原代码)
[123000123999]是创业板可转换公司债券代码区间 [127000127999]是主板可转换公司债券代码区间 [128000128999]是中小企业板可转换公司债券代码区间
3 1 [131800131899]为债券回购交易代码;
131990 为债券回购的标准券代码;
4 0 优先股
5 0-1 分级基金子基金
9 ETF
6 0-9 开放式基金
8 4 封闭式证券投资基金
2 0 0-9 B股
3 8 B 股现金选择权
8 0-9 B 股配股优先权
3 0 0-9 创业板股票
6 0-1 主板股东大会网络投票
2-4 中小企业板股东大会网络投票
5-8 创业板股东大会网络投票证券
9 [369001369499]为基金网络投票
[369501369899]为优先股、债券等网络投票(注 3 369991 用于中国结算网络服务身份认证业务的密码激活/密码重 置 369999 用于深交所身份认证业务的密码激活/密码挂失
7 0-9 创业板股票增发
创业板可转换公司债券申购
8 0-9 创业板配股优先权 创业板可转换公司债券的优先权认购
9 5 成交量统计指标
9 指数

View File

@ -1,10 +1,10 @@
{
"A": {
"underlying_symbol": "A",
"mi_symbol": "a2005",
"full_symbol": "A2005",
"mi_symbol": "a2009",
"full_symbol": "A2009",
"exchange": "DCE",
"margin_rate": 0.06,
"margin_rate": 0.08,
"symbol_size": 10,
"price_tick": 1.0
},
@ -13,14 +13,14 @@
"mi_symbol": "ag2007",
"full_symbol": "AG2007",
"exchange": "SHFE",
"margin_rate": 0.09,
"margin_rate": 0.1,
"symbol_size": 15,
"price_tick": 1.0
},
"AL": {
"underlying_symbol": "AL",
"mi_symbol": "al2004",
"full_symbol": "AL2004",
"mi_symbol": "al2006",
"full_symbol": "AL2006",
"exchange": "SHFE",
"margin_rate": 0.1,
"symbol_size": 5,
@ -28,8 +28,8 @@
},
"AP": {
"underlying_symbol": "AP",
"mi_symbol": "AP005",
"full_symbol": "AP2005",
"mi_symbol": "AP010",
"full_symbol": "AP2010",
"exchange": "CZCE",
"margin_rate": 0.08,
"symbol_size": 10,
@ -46,10 +46,10 @@
},
"B": {
"underlying_symbol": "B",
"mi_symbol": "b2003",
"full_symbol": "B2003",
"mi_symbol": "b2006",
"full_symbol": "B2006",
"exchange": "DCE",
"margin_rate": 0.05,
"margin_rate": 0.08,
"symbol_size": 10,
"price_tick": 1.0
},
@ -73,10 +73,10 @@
},
"C": {
"underlying_symbol": "C",
"mi_symbol": "c2005",
"full_symbol": "C2005",
"mi_symbol": "c2009",
"full_symbol": "C2009",
"exchange": "DCE",
"margin_rate": 0.05,
"margin_rate": 0.06,
"symbol_size": 10,
"price_tick": 1.0
},
@ -91,8 +91,8 @@
},
"CJ": {
"underlying_symbol": "CJ",
"mi_symbol": "CJ005",
"full_symbol": "CJ2005",
"mi_symbol": "CJ009",
"full_symbol": "CJ2009",
"exchange": "CZCE",
"margin_rate": 0.07,
"symbol_size": 5,
@ -100,17 +100,17 @@
},
"CS": {
"underlying_symbol": "CS",
"mi_symbol": "cs2005",
"full_symbol": "CS2005",
"mi_symbol": "cs2009",
"full_symbol": "CS2009",
"exchange": "DCE",
"margin_rate": 0.05,
"margin_rate": 0.06,
"symbol_size": 10,
"price_tick": 1.0
},
"CU": {
"underlying_symbol": "CU",
"mi_symbol": "cu2004",
"full_symbol": "CU2004",
"mi_symbol": "cu2006",
"full_symbol": "CU2006",
"exchange": "SHFE",
"margin_rate": 0.1,
"symbol_size": 5,
@ -118,8 +118,8 @@
},
"CY": {
"underlying_symbol": "CY",
"mi_symbol": "CY005",
"full_symbol": "CY2005",
"mi_symbol": "CY009",
"full_symbol": "CY2009",
"exchange": "CZCE",
"margin_rate": 0.07,
"symbol_size": 5,
@ -127,8 +127,8 @@
},
"EB": {
"underlying_symbol": "EB",
"mi_symbol": "eb2005",
"full_symbol": "EB2005",
"mi_symbol": "eb2009",
"full_symbol": "EB2009",
"exchange": "DCE",
"margin_rate": 0.11,
"symbol_size": 5,
@ -136,8 +136,8 @@
},
"EG": {
"underlying_symbol": "EG",
"mi_symbol": "eg2005",
"full_symbol": "EG2005",
"mi_symbol": "eg2009",
"full_symbol": "EG2009",
"exchange": "DCE",
"margin_rate": 0.11,
"symbol_size": 10,
@ -154,8 +154,8 @@
},
"FG": {
"underlying_symbol": "FG",
"mi_symbol": "FG005",
"full_symbol": "FG2005",
"mi_symbol": "FG009",
"full_symbol": "FG2009",
"exchange": "CZCE",
"margin_rate": 0.05,
"symbol_size": 20,
@ -163,8 +163,8 @@
},
"FU": {
"underlying_symbol": "FU",
"mi_symbol": "fu2005",
"full_symbol": "FU2005",
"mi_symbol": "fu2009",
"full_symbol": "FU2009",
"exchange": "SHFE",
"margin_rate": 0.11,
"symbol_size": 10,
@ -172,8 +172,8 @@
},
"HC": {
"underlying_symbol": "HC",
"mi_symbol": "hc2005",
"full_symbol": "HC2005",
"mi_symbol": "hc2010",
"full_symbol": "HC2010",
"exchange": "SHFE",
"margin_rate": 0.09,
"symbol_size": 10,
@ -181,8 +181,8 @@
},
"I": {
"underlying_symbol": "I",
"mi_symbol": "i2005",
"full_symbol": "I2005",
"mi_symbol": "i2009",
"full_symbol": "I2009",
"exchange": "DCE",
"margin_rate": 0.08,
"symbol_size": 100,
@ -190,10 +190,10 @@
},
"IC": {
"underlying_symbol": "IC",
"mi_symbol": "IC2003",
"full_symbol": "IC2003",
"mi_symbol": "IC2005",
"full_symbol": "IC2005",
"exchange": "CFFEX",
"margin_rate": 0.1,
"margin_rate": 0.12,
"symbol_size": 200,
"price_tick": 0.2
},
@ -217,8 +217,8 @@
},
"J": {
"underlying_symbol": "J",
"mi_symbol": "j2005",
"full_symbol": "J2005",
"mi_symbol": "j2009",
"full_symbol": "J2009",
"exchange": "DCE",
"margin_rate": 0.08,
"symbol_size": 100,
@ -226,17 +226,17 @@
},
"JD": {
"underlying_symbol": "JD",
"mi_symbol": "jd2005",
"full_symbol": "JD2005",
"mi_symbol": "jd2006",
"full_symbol": "JD2006",
"exchange": "DCE",
"margin_rate": 0.09,
"margin_rate": 0.07,
"symbol_size": 10,
"price_tick": 1.0
},
"JM": {
"underlying_symbol": "JM",
"mi_symbol": "jm2005",
"full_symbol": "JM2005",
"mi_symbol": "jm2009",
"full_symbol": "JM2009",
"exchange": "DCE",
"margin_rate": 0.08,
"symbol_size": 60,
@ -253,10 +253,10 @@
},
"L": {
"underlying_symbol": "L",
"mi_symbol": "l2005",
"full_symbol": "L2005",
"mi_symbol": "l2009",
"full_symbol": "L2009",
"exchange": "DCE",
"margin_rate": 0.07,
"margin_rate": 0.08,
"symbol_size": 5,
"price_tick": 5.0
},
@ -271,17 +271,17 @@
},
"M": {
"underlying_symbol": "M",
"mi_symbol": "m2005",
"full_symbol": "M2005",
"mi_symbol": "m2009",
"full_symbol": "M2009",
"exchange": "DCE",
"margin_rate": 0.06,
"margin_rate": 0.08,
"symbol_size": 10,
"price_tick": 1.0
},
"MA": {
"underlying_symbol": "MA",
"mi_symbol": "MA005",
"full_symbol": "MA2005",
"mi_symbol": "MA009",
"full_symbol": "MA2009",
"exchange": "CZCE",
"margin_rate": 0.07,
"symbol_size": 10,
@ -289,8 +289,8 @@
},
"NI": {
"underlying_symbol": "NI",
"mi_symbol": "ni2004",
"full_symbol": "NI2004",
"mi_symbol": "ni2007",
"full_symbol": "NI2007",
"exchange": "SHFE",
"margin_rate": 0.1,
"symbol_size": 1,
@ -298,8 +298,8 @@
},
"NR": {
"underlying_symbol": "NR",
"mi_symbol": "nr2004",
"full_symbol": "NR2004",
"mi_symbol": "nr2006",
"full_symbol": "NR2006",
"exchange": "INE",
"margin_rate": 0.11,
"symbol_size": 10,
@ -307,19 +307,19 @@
},
"OI": {
"underlying_symbol": "OI",
"mi_symbol": "OI005",
"full_symbol": "OI2005",
"mi_symbol": "OI007",
"full_symbol": "OI2007",
"exchange": "CZCE",
"margin_rate": 0.05,
"margin_rate": 0.06,
"symbol_size": 10,
"price_tick": 1.0
},
"P": {
"underlying_symbol": "P",
"mi_symbol": "p2005",
"full_symbol": "P2005",
"mi_symbol": "p2009",
"full_symbol": "P2009",
"exchange": "DCE",
"margin_rate": 0.07,
"margin_rate": 0.08,
"symbol_size": 10,
"price_tick": 2.0
},
@ -343,17 +343,17 @@
},
"PP": {
"underlying_symbol": "PP",
"mi_symbol": "pp2005",
"full_symbol": "PP2005",
"mi_symbol": "pp2009",
"full_symbol": "PP2009",
"exchange": "DCE",
"margin_rate": 0.07,
"margin_rate": 0.11,
"symbol_size": 5,
"price_tick": 1.0
},
"RB": {
"underlying_symbol": "RB",
"mi_symbol": "rb2005",
"full_symbol": "RB2005",
"mi_symbol": "rb2010",
"full_symbol": "RB2010",
"exchange": "SHFE",
"margin_rate": 0.09,
"symbol_size": 10,
@ -370,8 +370,8 @@
},
"RM": {
"underlying_symbol": "RM",
"mi_symbol": "RM005",
"full_symbol": "RM2005",
"mi_symbol": "RM009",
"full_symbol": "RM2009",
"exchange": "CZCE",
"margin_rate": 0.06,
"symbol_size": 10,
@ -379,10 +379,10 @@
},
"RR": {
"underlying_symbol": "RR",
"mi_symbol": "rr2005",
"full_symbol": "RR2005",
"mi_symbol": "rr2009",
"full_symbol": "RR2009",
"exchange": "DCE",
"margin_rate": 0.05,
"margin_rate": 0.06,
"symbol_size": 10,
"price_tick": 1.0
},
@ -397,8 +397,8 @@
},
"RU": {
"underlying_symbol": "RU",
"mi_symbol": "ru2005",
"full_symbol": "RU2005",
"mi_symbol": "ru2009",
"full_symbol": "RU2009",
"exchange": "SHFE",
"margin_rate": 0.11,
"symbol_size": 10,
@ -406,8 +406,8 @@
},
"SA": {
"underlying_symbol": "SA",
"mi_symbol": "SA005",
"full_symbol": "SA2005",
"mi_symbol": "SA009",
"full_symbol": "SA2009",
"exchange": "CZCE",
"margin_rate": 0.05,
"symbol_size": 20,
@ -415,17 +415,17 @@
},
"SC": {
"underlying_symbol": "SC",
"mi_symbol": "sc2004",
"full_symbol": "SC2004",
"mi_symbol": "sc2006",
"full_symbol": "SC2006",
"exchange": "INE",
"margin_rate": 0.2,
"margin_rate": 0.11,
"symbol_size": 1000,
"price_tick": 0.1
},
"SF": {
"underlying_symbol": "SF",
"mi_symbol": "SF005",
"full_symbol": "SF2005",
"mi_symbol": "SF009",
"full_symbol": "SF2009",
"exchange": "CZCE",
"margin_rate": 0.07,
"symbol_size": 5,
@ -433,8 +433,8 @@
},
"SM": {
"underlying_symbol": "SM",
"mi_symbol": "SM005",
"full_symbol": "SM2005",
"mi_symbol": "SM009",
"full_symbol": "SM2009",
"exchange": "CZCE",
"margin_rate": 0.07,
"symbol_size": 5,
@ -451,8 +451,8 @@
},
"SP": {
"underlying_symbol": "SP",
"mi_symbol": "sp2005",
"full_symbol": "SP2005",
"mi_symbol": "sp2009",
"full_symbol": "SP2009",
"exchange": "SHFE",
"margin_rate": 0.08,
"symbol_size": 10,
@ -460,8 +460,8 @@
},
"SR": {
"underlying_symbol": "SR",
"mi_symbol": "SR005",
"full_symbol": "SR2005",
"mi_symbol": "SR009",
"full_symbol": "SR2009",
"exchange": "CZCE",
"margin_rate": 0.05,
"symbol_size": 10,
@ -487,8 +487,8 @@
},
"TA": {
"underlying_symbol": "TA",
"mi_symbol": "TA005",
"full_symbol": "TA2005",
"mi_symbol": "TA009",
"full_symbol": "TA2009",
"exchange": "CZCE",
"margin_rate": 0.07,
"symbol_size": 5,
@ -496,8 +496,8 @@
},
"TF": {
"underlying_symbol": "TF",
"mi_symbol": "TF2004",
"full_symbol": "TF2004",
"mi_symbol": "TF2006",
"full_symbol": "TF2006",
"exchange": "CFFEX",
"margin_rate": 0.012,
"symbol_size": 10000,
@ -514,8 +514,8 @@
},
"UR": {
"underlying_symbol": "UR",
"mi_symbol": "UR005",
"full_symbol": "UR2005",
"mi_symbol": "UR009",
"full_symbol": "UR2009",
"exchange": "CZCE",
"margin_rate": 0.05,
"symbol_size": 20,
@ -523,10 +523,10 @@
},
"V": {
"underlying_symbol": "V",
"mi_symbol": "v2005",
"full_symbol": "V2005",
"mi_symbol": "v2009",
"full_symbol": "V2009",
"exchange": "DCE",
"margin_rate": 0.1,
"margin_rate": 0.08,
"symbol_size": 5,
"price_tick": 5.0
},
@ -550,17 +550,17 @@
},
"Y": {
"underlying_symbol": "Y",
"mi_symbol": "y2005",
"full_symbol": "Y2005",
"mi_symbol": "y2009",
"full_symbol": "Y2009",
"exchange": "DCE",
"margin_rate": 0.06,
"margin_rate": 0.08,
"symbol_size": 10,
"price_tick": 2.0
},
"ZC": {
"underlying_symbol": "ZC",
"mi_symbol": "ZC005",
"full_symbol": "ZC2005",
"mi_symbol": "ZC009",
"full_symbol": "ZC2009",
"exchange": "CZCE",
"margin_rate": 0.06,
"symbol_size": 100,
@ -568,11 +568,38 @@
},
"ZN": {
"underlying_symbol": "ZN",
"mi_symbol": "zn2005",
"full_symbol": "ZN2005",
"mi_symbol": "zn2006",
"full_symbol": "ZN2006",
"exchange": "SHFE",
"margin_rate": 0.1,
"symbol_size": 5,
"price_tick": 5.0
},
"AF": {
"underlying_symbol": "AF",
"mi_symbol": "AF2009",
"full_symbol": "AF2009",
"exchange": "CFFEX"
},
"EF": {
"underlying_symbol": "EF",
"mi_symbol": "EF2009",
"full_symbol": "EF2009",
"exchange": "CFFEX"
},
"TL": {
"underlying_symbol": "TL",
"mi_symbol": "TL2009",
"full_symbol": "TL2009",
"exchange": "CFFEX"
},
"PG": {
"underlying_symbol": "PG",
"mi_symbol": "pg2011",
"full_symbol": "PG2011",
"exchange": "DCE",
"margin_rate": 0.08,
"symbol_size": 20,
"price_tick": 1.0
}
}

View File

@ -15,11 +15,12 @@ import os
import pickle
import bz2
import traceback
import pandas as pd
from datetime import datetime, timedelta
from logging import ERROR
from pytdx.hq import TdxHq_API
from pytdx.params import TDXParams
from pandas import to_datetime
from vnpy.trader.object import BarData
from vnpy.trader.constant import Exchange
@ -268,7 +269,7 @@ class TdxStockData(object):
current_datetime = datetime.now()
data = self.api.to_df(_bars)
data = data.assign(datetime=to_datetime(data['datetime']))
data = data.assign(datetime=pd.to_datetime(data['datetime']))
data = data.assign(ticker=symbol)
data['symbol'] = symbol
data = data.drop(
@ -506,3 +507,63 @@ class TdxStockData(object):
self.write_error(
'exception in get_transaction_data:{},{},{}'.format(symbol, str(ex), traceback.format_exc()))
return False, ret_datas
def get_stock_list(self, types=["stock_cn", "etf_cn", "bond_cn", "cb_cn"]):
"""股票所有的code&name列表"""
if self.api is None:
self.connect()
data = pd.concat(
[pd.concat([self.api.to_df(self.api.get_security_list(j, i * 1000)).assign(sse='sz' if j == 0 else 'sh').set_index(
['code', 'sse'], drop=False) for i in range(int(self.api.get_security_count(j) / 1000) + 1)], axis=0) for j
in range(2)], axis=0)
sz = data.query('sse=="sz"')
sh = data.query('sse=="sh"')
sz = sz.assign(sec=sz.code.apply(get_stock_type))
sh = sh.assign(sec=sh.code.apply(get_stock_type))
temp_df = pd.concat([sz, sh]).query('sec in ["{}"]'.format(types)).sort_index().assign(
name=data['name'].apply(lambda x: str(x)[0:6]))
hq_codelist = []
for i in range(0, len(temp_df)):
row = temp_df.iloc[i]
hq_codelist.append(
{
"code": row['code'],
"exchange": Exchange.SSE.value if row['sse'] == 'sh' else Exchange.SZSE.value,
"market_id": 1 if row['sse'] == 'sh' else 0,
"name": row['name']
}
)
return hq_codelist
def get_security_quotes(self, all_stock, code=None):
"""
支持三种形式的参数
get_security_quotes(market, code )
get_security_quotes((market, code))
get_security_quotes([(market1, code1), (market2, code2)] )
:param all_stock market, code) 的数组
:param code{optional} code to query
:return:
"""
if self.api is None:
self.connect()
return self.api.get_security_quotes(all_stock, code)
def get_stock_quotes_by_type(self, stock_type):
"""根据股票代码类型,获取其最新行情"""
stock_list = [(stock.get('market_id'), stock.get('code')) for stock in self.symbol_dict.values() if stock.get('stock_type') == stock_type]
num_per_count = 60
results = []
for i in range(0, len(stock_list)+1, num_per_count):
cur_results = self.get_security_quotes(stock_list[i:i+num_per_count])
results.extend(cur_results)
return results

View File

@ -708,6 +708,7 @@ class CtpTdApi(TdApi):
order = OrderData(
symbol=symbol,
exchange=exchange,
accountid=self.accountid,
orderid=orderid,
type=order_type,
direction=DIRECTION_CTP2VT[data["Direction"]],

View File

@ -26,35 +26,39 @@ from vnpy.trader.object import (
)
from vnpy.trader.utility import get_folder_path
# 市场id <=> Exchange
MARKET_XTP2VT: Dict[int, Exchange] = {
1: Exchange.SZSE,
2: Exchange.SSE
}
MARKET_VT2XTP: Dict[Exchange, int] = {v: k for k, v in MARKET_XTP2VT.items()}
# 交易所id <=> Exchange
EXCHANGE_XTP2VT: Dict[int, Exchange] = {
1: Exchange.SSE,
2: Exchange.SZSE,
}
EXCHANGE_VT2XTP: Dict[Exchange, int] = {v: k for k, v in EXCHANGE_XTP2VT.items()}
# 方向 <=> Direction, Offset
DIRECTION_STOCK_XTP2VT: Dict[int, Any] = {
1: (Direction.LONG, Offset.NONE),
2: (Direction.SHORT, Offset.NONE),
21: (Direction.LONG, Offset.OPEN),
22: (Direction.SHORT, Offset.OPEN),
24: (Direction.LONG, Offset.CLOSE),
23: (Direction.SHORT, Offset.CLOSE)
1: (Direction.LONG, Offset.NONE), # 买
2: (Direction.SHORT, Offset.NONE), # 卖
21: (Direction.LONG, Offset.OPEN), # 多,开
22: (Direction.SHORT, Offset.OPEN), # 空,开
24: (Direction.LONG, Offset.CLOSE), # 多,平
23: (Direction.SHORT, Offset.CLOSE) # 空, 平
}
DIRECTION_STOCK_VT2XTP: Dict[Any, int] = {v: k for k, v in DIRECTION_STOCK_XTP2VT.items()}
# 期权方向 <=> Direction
DIRECTION_OPTION_XTP2VT: Dict[int, Direction] = {
1: Direction.LONG,
2: Direction.SHORT
}
DIRECTION_OPTION_VT2XTP: Dict[Direction, int] = {v: k for k, v in DIRECTION_OPTION_XTP2VT.items()}
# 持仓方向 <=> Direction
POSITION_DIRECTION_XTP2VT = {
0: Direction.NET,
1: Direction.LONG,
@ -62,17 +66,20 @@ POSITION_DIRECTION_XTP2VT = {
3: Direction.SHORT
}
# 委托单类型
ORDERTYPE_XTP2VT: Dict[int, OrderType] = {
1: OrderType.LIMIT,
2: OrderType.MARKET
}
ORDERTYPE_VT2XTP: Dict[OrderType, int] = {v: k for k, v in ORDERTYPE_XTP2VT.items()}
# 协议类型
PROTOCOL_VT2XTP: Dict[str, int] = {
"TCP": 1,
"UDP": 2
}
# 状态 <=> Status
STATUS_XTP2VT: Dict[int, Status] = {
0: Status.SUBMITTING,
1: Status.ALLTRADED,
@ -84,6 +91,7 @@ STATUS_XTP2VT: Dict[int, Status] = {
7: Status.SUBMITTING
}
# 合约类型 <=> Product
PRODUCT_XTP2VT: Dict[int, Product] = {
0: Product.EQUITY,
1: Product.INDEX,
@ -94,6 +102,7 @@ PRODUCT_XTP2VT: Dict[int, Product] = {
6: Product.OPTION
}
# 开平仓 <=> Offset
OFFSET_VT2XTP: Dict[Offset, int] = {
Offset.NONE: 0,
Offset.OPEN: 1,
@ -103,6 +112,7 @@ OFFSET_VT2XTP: Dict[Offset, int] = {
}
OFFSET_XTP2VT: Dict[int, Offset] = {v: k for k, v in OFFSET_VT2XTP.items()}
# 业务类型 <=> xtp
BUSINESS_VT2XTP: Dict[Any, int] = {
"CASH": 0,
Offset.NONE: 0,
@ -112,7 +122,9 @@ BUSINESS_VT2XTP: Dict[Any, int] = {
"OPTION": 10,
}
# 代码 <=> 中文名称
symbol_name_map: Dict[str, str] = {}
# 代码 <=> 交易所
symbol_exchange_map: Dict[str, Exchange] = {}
@ -130,11 +142,12 @@ class XtpGateway(BaseGateway):
"授权码": ""
}
# 接口支持得交易所清单
exchanges: List[Exchange] = list(EXCHANGE_VT2XTP.keys())
def __init__(self, event_engine: EventEngine):
def __init__(self, event_engine: EventEngine, gateway_name='XTP'):
""""""
super().__init__(event_engine, "XTP")
super().__init__(event_engine, gateway_name=gateway_name)
self.md_api = XtpMdApi(self)
self.td_api = XtpTdApi(self)
@ -258,7 +271,7 @@ class XtpMdApi(MdApi):
pass
def onDepthMarketData(self, data: dict) -> None:
""""""
"""深度行情回报"""
timestamp = str(data["data_time"])
dt = datetime.strptime(timestamp, "%Y%m%d%H%M%S%f")
@ -266,6 +279,9 @@ class XtpMdApi(MdApi):
symbol=data["ticker"],
exchange=EXCHANGE_XTP2VT[data["exchange_id"]],
datetime=dt,
date=dt.strftime('%Y-%m-%d'),
time=dt.strftime('%H:%M:%S.%f'),
trading_day=dt.strftime('%Y-%m-%d'),
volume=data["qty"],
last_price=data["last_price"],
limit_up=data["upper_limit_price"],
@ -334,7 +350,7 @@ class XtpMdApi(MdApi):
pass
def onQueryAllTickers(self, data: dict, error: dict, last: bool) -> None:
""""""
"""合约信息回报"""
contract = ContractData(
symbol=data["ticker"],
exchange=EXCHANGE_XTP2VT[data["exchange_id"]],
@ -347,8 +363,10 @@ class XtpMdApi(MdApi):
)
self.gateway.on_contract(contract)
# 更新 symbol <=> 中文名称映射
symbol_name_map[contract.vt_symbol] = contract.name
# 更新 股票代码 <=> 交易所
if contract.product != Product.INDEX:
symbol_exchange_map[contract.symbol] = contract.exchange
@ -440,7 +458,7 @@ class XtpMdApi(MdApi):
self.subscribeMarketData(req.symbol, 1, xtp_exchange)
def query_contract(self) -> None:
""""""
"""查询合约明细"""
for exchange_id in EXCHANGE_XTP2VT.keys():
self.queryAllTickers(exchange_id)
@ -487,21 +505,24 @@ class XtpTdApi(TdApi):
self.gateway.write_error("交易接口报错", error)
def onOrderEvent(self, data: dict, error: dict, session: int) -> None:
""""""
"""委托回报"""
if error["error_id"]:
self.gateway.write_error("交易委托失败", error)
symbol = data["ticker"]
if len(symbol) == 8:
# 期权
direction = DIRECTION_OPTION_XTP2VT[data["side"]]
offset = OFFSET_XTP2VT[data["position_effect"]]
else:
# 股票
direction, offset = DIRECTION_STOCK_XTP2VT[data["side"]]
order = OrderData(
symbol=symbol,
exchange=MARKET_XTP2VT[data["market"]],
orderid=str(data["order_xtp_id"]),
sys_orderid=str(data["order_xtp_id"]),
type=ORDERTYPE_XTP2VT[data["price_type"]],
direction=direction,
offset=offset,
@ -528,6 +549,7 @@ class XtpTdApi(TdApi):
symbol=symbol,
exchange=MARKET_XTP2VT[data["market"]],
orderid=str(data["order_xtp_id"]),
sys_orderid=str(data["order_xtp_id"]),
tradeid=str(data["exec_id"]),
direction=direction,
offset=offset,
@ -750,7 +772,7 @@ class XtpTdApi(TdApi):
"market": MARKET_VT2XTP[req.exchange],
"price": req.price,
"quantity": int(req.volume),
"side": DIRECTION_STOCK_VT2XTP.get((req.direction, req.offset), ""),
"side": DIRECTION_STOCK_VT2XTP.get((req.direction, Offset.NONE), ""),
"price_type": ORDERTYPE_VT2XTP[req.type],
"business_type": BUSINESS_VT2XTP[req.offset]
}
@ -765,6 +787,7 @@ class XtpTdApi(TdApi):
def cancel_order(self, req: CancelRequest) -> None:
""""""
self.cancelOrder(int(req.orderid), self.session_id)
return True
def query_account(self) -> None:
""""""

View File

@ -1163,12 +1163,12 @@ class KLineWidget(KeyWraper):
price = df_trades['price'].loc[idx]
direction = df_trades['direction'].loc[idx]
if direction.lower() in ['long', 'direction.long']:
if direction.lower() in ['long', 'direction.long', '']:
direction = Direction.LONG
else:
direction = Direction.SHORT
offset = df_trades['offset'].loc[idx]
if offset.lower() in ['open', 'offset.open']:
if offset.lower() in ['open', 'offset.open', '']:
offset = Offset.OPEN
else:
offset = Offset.CLOSE