[增强功能] 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 # flake8: noqa
# 自动补全期货指数合约renko bar => Mongodb
# 下载的tick数据缓存 => tick_data/tdx/future
import sys, os, copy, csv, signal import sys, os, copy, csv, signal
vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
@ -23,7 +24,7 @@ if __name__ == "__main__":
setting = { setting = {
"host": host, "host": host,
"db_name": FUTURE_RENKO_DB_NAME, "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) builder = FutureRenkoRebuilder(setting)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ class PortfolioTestingEngine(BackTestingEngine):
if vt_symbol in self.bar_df_dict: if vt_symbol in self.bar_df_dict:
return True 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)) self.write_error(u'回测时,{}对应的csv bar文件{}不存在'.format(vt_symbol, bar_file))
return False return False

View File

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

View File

@ -41,6 +41,13 @@ class MongoData(object):
def write_error(self, content): def write_error(self, content):
print(content, file=sys.stderr) 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): def db_insert(self, db_name, col_name, d):
"""向MongoDB中插入数据d是具体数据""" """向MongoDB中插入数据d是具体数据"""
@ -308,4 +315,4 @@ class MongoData(object):
if __name__ == "__main__": if __name__ == "__main__":
m = MongoData(host='localhost', port=27017) 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}得复权因子') print(f'开始获取{stock_name} {bs_code}得复权因子')
rs = bs.query_adjust_factor( rs = bs.query_adjust_factor(
code=bs_code, code=bs_code,
start_date='2006-01-01' start_date='2000-01-01'
) )
if rs.error_code != '0': if rs.error_code != '0':
print(f'证券宝获取沪深A股复权因子数据错误代码:{rs.error_code}, 错误信息:{rs.error_msg}') print(f'证券宝获取沪深A股复权因子数据错误代码:{rs.error_code}, 错误信息:{rs.error_msg}')

View File

@ -12,3 +12,146 @@
1.tdx_stock_data, 股票数据接口 1.tdx_stock_data, 股票数据接口
2.tdx_future_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": { "A": {
"underlying_symbol": "A", "underlying_symbol": "A",
"mi_symbol": "a2005", "mi_symbol": "a2009",
"full_symbol": "A2005", "full_symbol": "A2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.06, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
@ -13,14 +13,14 @@
"mi_symbol": "ag2007", "mi_symbol": "ag2007",
"full_symbol": "AG2007", "full_symbol": "AG2007",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.09, "margin_rate": 0.1,
"symbol_size": 15, "symbol_size": 15,
"price_tick": 1.0 "price_tick": 1.0
}, },
"AL": { "AL": {
"underlying_symbol": "AL", "underlying_symbol": "AL",
"mi_symbol": "al2004", "mi_symbol": "al2006",
"full_symbol": "AL2004", "full_symbol": "AL2006",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.1, "margin_rate": 0.1,
"symbol_size": 5, "symbol_size": 5,
@ -28,8 +28,8 @@
}, },
"AP": { "AP": {
"underlying_symbol": "AP", "underlying_symbol": "AP",
"mi_symbol": "AP005", "mi_symbol": "AP010",
"full_symbol": "AP2005", "full_symbol": "AP2010",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.08, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
@ -46,10 +46,10 @@
}, },
"B": { "B": {
"underlying_symbol": "B", "underlying_symbol": "B",
"mi_symbol": "b2003", "mi_symbol": "b2006",
"full_symbol": "B2003", "full_symbol": "B2006",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.05, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
@ -73,10 +73,10 @@
}, },
"C": { "C": {
"underlying_symbol": "C", "underlying_symbol": "C",
"mi_symbol": "c2005", "mi_symbol": "c2009",
"full_symbol": "C2005", "full_symbol": "C2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.05, "margin_rate": 0.06,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
@ -91,8 +91,8 @@
}, },
"CJ": { "CJ": {
"underlying_symbol": "CJ", "underlying_symbol": "CJ",
"mi_symbol": "CJ005", "mi_symbol": "CJ009",
"full_symbol": "CJ2005", "full_symbol": "CJ2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.07, "margin_rate": 0.07,
"symbol_size": 5, "symbol_size": 5,
@ -100,17 +100,17 @@
}, },
"CS": { "CS": {
"underlying_symbol": "CS", "underlying_symbol": "CS",
"mi_symbol": "cs2005", "mi_symbol": "cs2009",
"full_symbol": "CS2005", "full_symbol": "CS2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.05, "margin_rate": 0.06,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
"CU": { "CU": {
"underlying_symbol": "CU", "underlying_symbol": "CU",
"mi_symbol": "cu2004", "mi_symbol": "cu2006",
"full_symbol": "CU2004", "full_symbol": "CU2006",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.1, "margin_rate": 0.1,
"symbol_size": 5, "symbol_size": 5,
@ -118,8 +118,8 @@
}, },
"CY": { "CY": {
"underlying_symbol": "CY", "underlying_symbol": "CY",
"mi_symbol": "CY005", "mi_symbol": "CY009",
"full_symbol": "CY2005", "full_symbol": "CY2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.07, "margin_rate": 0.07,
"symbol_size": 5, "symbol_size": 5,
@ -127,8 +127,8 @@
}, },
"EB": { "EB": {
"underlying_symbol": "EB", "underlying_symbol": "EB",
"mi_symbol": "eb2005", "mi_symbol": "eb2009",
"full_symbol": "EB2005", "full_symbol": "EB2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.11, "margin_rate": 0.11,
"symbol_size": 5, "symbol_size": 5,
@ -136,8 +136,8 @@
}, },
"EG": { "EG": {
"underlying_symbol": "EG", "underlying_symbol": "EG",
"mi_symbol": "eg2005", "mi_symbol": "eg2009",
"full_symbol": "EG2005", "full_symbol": "EG2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.11, "margin_rate": 0.11,
"symbol_size": 10, "symbol_size": 10,
@ -154,8 +154,8 @@
}, },
"FG": { "FG": {
"underlying_symbol": "FG", "underlying_symbol": "FG",
"mi_symbol": "FG005", "mi_symbol": "FG009",
"full_symbol": "FG2005", "full_symbol": "FG2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.05, "margin_rate": 0.05,
"symbol_size": 20, "symbol_size": 20,
@ -163,8 +163,8 @@
}, },
"FU": { "FU": {
"underlying_symbol": "FU", "underlying_symbol": "FU",
"mi_symbol": "fu2005", "mi_symbol": "fu2009",
"full_symbol": "FU2005", "full_symbol": "FU2009",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.11, "margin_rate": 0.11,
"symbol_size": 10, "symbol_size": 10,
@ -172,8 +172,8 @@
}, },
"HC": { "HC": {
"underlying_symbol": "HC", "underlying_symbol": "HC",
"mi_symbol": "hc2005", "mi_symbol": "hc2010",
"full_symbol": "HC2005", "full_symbol": "HC2010",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.09, "margin_rate": 0.09,
"symbol_size": 10, "symbol_size": 10,
@ -181,8 +181,8 @@
}, },
"I": { "I": {
"underlying_symbol": "I", "underlying_symbol": "I",
"mi_symbol": "i2005", "mi_symbol": "i2009",
"full_symbol": "I2005", "full_symbol": "I2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.08, "margin_rate": 0.08,
"symbol_size": 100, "symbol_size": 100,
@ -190,10 +190,10 @@
}, },
"IC": { "IC": {
"underlying_symbol": "IC", "underlying_symbol": "IC",
"mi_symbol": "IC2003", "mi_symbol": "IC2005",
"full_symbol": "IC2003", "full_symbol": "IC2005",
"exchange": "CFFEX", "exchange": "CFFEX",
"margin_rate": 0.1, "margin_rate": 0.12,
"symbol_size": 200, "symbol_size": 200,
"price_tick": 0.2 "price_tick": 0.2
}, },
@ -217,8 +217,8 @@
}, },
"J": { "J": {
"underlying_symbol": "J", "underlying_symbol": "J",
"mi_symbol": "j2005", "mi_symbol": "j2009",
"full_symbol": "J2005", "full_symbol": "J2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.08, "margin_rate": 0.08,
"symbol_size": 100, "symbol_size": 100,
@ -226,17 +226,17 @@
}, },
"JD": { "JD": {
"underlying_symbol": "JD", "underlying_symbol": "JD",
"mi_symbol": "jd2005", "mi_symbol": "jd2006",
"full_symbol": "JD2005", "full_symbol": "JD2006",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.09, "margin_rate": 0.07,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
"JM": { "JM": {
"underlying_symbol": "JM", "underlying_symbol": "JM",
"mi_symbol": "jm2005", "mi_symbol": "jm2009",
"full_symbol": "JM2005", "full_symbol": "JM2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.08, "margin_rate": 0.08,
"symbol_size": 60, "symbol_size": 60,
@ -253,10 +253,10 @@
}, },
"L": { "L": {
"underlying_symbol": "L", "underlying_symbol": "L",
"mi_symbol": "l2005", "mi_symbol": "l2009",
"full_symbol": "L2005", "full_symbol": "L2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.07, "margin_rate": 0.08,
"symbol_size": 5, "symbol_size": 5,
"price_tick": 5.0 "price_tick": 5.0
}, },
@ -271,17 +271,17 @@
}, },
"M": { "M": {
"underlying_symbol": "M", "underlying_symbol": "M",
"mi_symbol": "m2005", "mi_symbol": "m2009",
"full_symbol": "M2005", "full_symbol": "M2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.06, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
"MA": { "MA": {
"underlying_symbol": "MA", "underlying_symbol": "MA",
"mi_symbol": "MA005", "mi_symbol": "MA009",
"full_symbol": "MA2005", "full_symbol": "MA2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.07, "margin_rate": 0.07,
"symbol_size": 10, "symbol_size": 10,
@ -289,8 +289,8 @@
}, },
"NI": { "NI": {
"underlying_symbol": "NI", "underlying_symbol": "NI",
"mi_symbol": "ni2004", "mi_symbol": "ni2007",
"full_symbol": "NI2004", "full_symbol": "NI2007",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.1, "margin_rate": 0.1,
"symbol_size": 1, "symbol_size": 1,
@ -298,8 +298,8 @@
}, },
"NR": { "NR": {
"underlying_symbol": "NR", "underlying_symbol": "NR",
"mi_symbol": "nr2004", "mi_symbol": "nr2006",
"full_symbol": "NR2004", "full_symbol": "NR2006",
"exchange": "INE", "exchange": "INE",
"margin_rate": 0.11, "margin_rate": 0.11,
"symbol_size": 10, "symbol_size": 10,
@ -307,19 +307,19 @@
}, },
"OI": { "OI": {
"underlying_symbol": "OI", "underlying_symbol": "OI",
"mi_symbol": "OI005", "mi_symbol": "OI007",
"full_symbol": "OI2005", "full_symbol": "OI2007",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.05, "margin_rate": 0.06,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
"P": { "P": {
"underlying_symbol": "P", "underlying_symbol": "P",
"mi_symbol": "p2005", "mi_symbol": "p2009",
"full_symbol": "P2005", "full_symbol": "P2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.07, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 2.0 "price_tick": 2.0
}, },
@ -343,17 +343,17 @@
}, },
"PP": { "PP": {
"underlying_symbol": "PP", "underlying_symbol": "PP",
"mi_symbol": "pp2005", "mi_symbol": "pp2009",
"full_symbol": "PP2005", "full_symbol": "PP2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.07, "margin_rate": 0.11,
"symbol_size": 5, "symbol_size": 5,
"price_tick": 1.0 "price_tick": 1.0
}, },
"RB": { "RB": {
"underlying_symbol": "RB", "underlying_symbol": "RB",
"mi_symbol": "rb2005", "mi_symbol": "rb2010",
"full_symbol": "RB2005", "full_symbol": "RB2010",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.09, "margin_rate": 0.09,
"symbol_size": 10, "symbol_size": 10,
@ -370,8 +370,8 @@
}, },
"RM": { "RM": {
"underlying_symbol": "RM", "underlying_symbol": "RM",
"mi_symbol": "RM005", "mi_symbol": "RM009",
"full_symbol": "RM2005", "full_symbol": "RM2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.06, "margin_rate": 0.06,
"symbol_size": 10, "symbol_size": 10,
@ -379,10 +379,10 @@
}, },
"RR": { "RR": {
"underlying_symbol": "RR", "underlying_symbol": "RR",
"mi_symbol": "rr2005", "mi_symbol": "rr2009",
"full_symbol": "RR2005", "full_symbol": "RR2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.05, "margin_rate": 0.06,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 1.0 "price_tick": 1.0
}, },
@ -397,8 +397,8 @@
}, },
"RU": { "RU": {
"underlying_symbol": "RU", "underlying_symbol": "RU",
"mi_symbol": "ru2005", "mi_symbol": "ru2009",
"full_symbol": "RU2005", "full_symbol": "RU2009",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.11, "margin_rate": 0.11,
"symbol_size": 10, "symbol_size": 10,
@ -406,8 +406,8 @@
}, },
"SA": { "SA": {
"underlying_symbol": "SA", "underlying_symbol": "SA",
"mi_symbol": "SA005", "mi_symbol": "SA009",
"full_symbol": "SA2005", "full_symbol": "SA2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.05, "margin_rate": 0.05,
"symbol_size": 20, "symbol_size": 20,
@ -415,17 +415,17 @@
}, },
"SC": { "SC": {
"underlying_symbol": "SC", "underlying_symbol": "SC",
"mi_symbol": "sc2004", "mi_symbol": "sc2006",
"full_symbol": "SC2004", "full_symbol": "SC2006",
"exchange": "INE", "exchange": "INE",
"margin_rate": 0.2, "margin_rate": 0.11,
"symbol_size": 1000, "symbol_size": 1000,
"price_tick": 0.1 "price_tick": 0.1
}, },
"SF": { "SF": {
"underlying_symbol": "SF", "underlying_symbol": "SF",
"mi_symbol": "SF005", "mi_symbol": "SF009",
"full_symbol": "SF2005", "full_symbol": "SF2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.07, "margin_rate": 0.07,
"symbol_size": 5, "symbol_size": 5,
@ -433,8 +433,8 @@
}, },
"SM": { "SM": {
"underlying_symbol": "SM", "underlying_symbol": "SM",
"mi_symbol": "SM005", "mi_symbol": "SM009",
"full_symbol": "SM2005", "full_symbol": "SM2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.07, "margin_rate": 0.07,
"symbol_size": 5, "symbol_size": 5,
@ -451,8 +451,8 @@
}, },
"SP": { "SP": {
"underlying_symbol": "SP", "underlying_symbol": "SP",
"mi_symbol": "sp2005", "mi_symbol": "sp2009",
"full_symbol": "SP2005", "full_symbol": "SP2009",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.08, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
@ -460,8 +460,8 @@
}, },
"SR": { "SR": {
"underlying_symbol": "SR", "underlying_symbol": "SR",
"mi_symbol": "SR005", "mi_symbol": "SR009",
"full_symbol": "SR2005", "full_symbol": "SR2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.05, "margin_rate": 0.05,
"symbol_size": 10, "symbol_size": 10,
@ -487,8 +487,8 @@
}, },
"TA": { "TA": {
"underlying_symbol": "TA", "underlying_symbol": "TA",
"mi_symbol": "TA005", "mi_symbol": "TA009",
"full_symbol": "TA2005", "full_symbol": "TA2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.07, "margin_rate": 0.07,
"symbol_size": 5, "symbol_size": 5,
@ -496,8 +496,8 @@
}, },
"TF": { "TF": {
"underlying_symbol": "TF", "underlying_symbol": "TF",
"mi_symbol": "TF2004", "mi_symbol": "TF2006",
"full_symbol": "TF2004", "full_symbol": "TF2006",
"exchange": "CFFEX", "exchange": "CFFEX",
"margin_rate": 0.012, "margin_rate": 0.012,
"symbol_size": 10000, "symbol_size": 10000,
@ -514,8 +514,8 @@
}, },
"UR": { "UR": {
"underlying_symbol": "UR", "underlying_symbol": "UR",
"mi_symbol": "UR005", "mi_symbol": "UR009",
"full_symbol": "UR2005", "full_symbol": "UR2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.05, "margin_rate": 0.05,
"symbol_size": 20, "symbol_size": 20,
@ -523,10 +523,10 @@
}, },
"V": { "V": {
"underlying_symbol": "V", "underlying_symbol": "V",
"mi_symbol": "v2005", "mi_symbol": "v2009",
"full_symbol": "V2005", "full_symbol": "V2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.1, "margin_rate": 0.08,
"symbol_size": 5, "symbol_size": 5,
"price_tick": 5.0 "price_tick": 5.0
}, },
@ -550,17 +550,17 @@
}, },
"Y": { "Y": {
"underlying_symbol": "Y", "underlying_symbol": "Y",
"mi_symbol": "y2005", "mi_symbol": "y2009",
"full_symbol": "Y2005", "full_symbol": "Y2009",
"exchange": "DCE", "exchange": "DCE",
"margin_rate": 0.06, "margin_rate": 0.08,
"symbol_size": 10, "symbol_size": 10,
"price_tick": 2.0 "price_tick": 2.0
}, },
"ZC": { "ZC": {
"underlying_symbol": "ZC", "underlying_symbol": "ZC",
"mi_symbol": "ZC005", "mi_symbol": "ZC009",
"full_symbol": "ZC2005", "full_symbol": "ZC2009",
"exchange": "CZCE", "exchange": "CZCE",
"margin_rate": 0.06, "margin_rate": 0.06,
"symbol_size": 100, "symbol_size": 100,
@ -568,11 +568,38 @@
}, },
"ZN": { "ZN": {
"underlying_symbol": "ZN", "underlying_symbol": "ZN",
"mi_symbol": "zn2005", "mi_symbol": "zn2006",
"full_symbol": "ZN2005", "full_symbol": "ZN2006",
"exchange": "SHFE", "exchange": "SHFE",
"margin_rate": 0.1, "margin_rate": 0.1,
"symbol_size": 5, "symbol_size": 5,
"price_tick": 5.0 "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 pickle
import bz2 import bz2
import traceback import traceback
import pandas as pd
from datetime import datetime, timedelta from datetime import datetime, timedelta
from logging import ERROR from logging import ERROR
from pytdx.hq import TdxHq_API from pytdx.hq import TdxHq_API
from pytdx.params import TDXParams from pytdx.params import TDXParams
from pandas import to_datetime
from vnpy.trader.object import BarData from vnpy.trader.object import BarData
from vnpy.trader.constant import Exchange from vnpy.trader.constant import Exchange
@ -268,7 +269,7 @@ class TdxStockData(object):
current_datetime = datetime.now() current_datetime = datetime.now()
data = self.api.to_df(_bars) 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 = data.assign(ticker=symbol)
data['symbol'] = symbol data['symbol'] = symbol
data = data.drop( data = data.drop(
@ -506,3 +507,63 @@ class TdxStockData(object):
self.write_error( self.write_error(
'exception in get_transaction_data:{},{},{}'.format(symbol, str(ex), traceback.format_exc())) 'exception in get_transaction_data:{},{},{}'.format(symbol, str(ex), traceback.format_exc()))
return False, ret_datas 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( order = OrderData(
symbol=symbol, symbol=symbol,
exchange=exchange, exchange=exchange,
accountid=self.accountid,
orderid=orderid, orderid=orderid,
type=order_type, type=order_type,
direction=DIRECTION_CTP2VT[data["Direction"]], direction=DIRECTION_CTP2VT[data["Direction"]],

View File

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

View File

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