[bug fix] 修复ctp对FAK支持,修复基础网格组件加载问题,修复转换持仓对非锁定品种支持,修复股票可转债价格问题,增加utility压缩文件方法
This commit is contained in:
parent
fa9edcb0d3
commit
91823b8c71
23
Q_n_A.md
23
Q_n_A.md
@ -133,3 +133,26 @@
|
||||
index-url=http://pypi.douban.com/simple
|
||||
[install]
|
||||
trusted-host=pypi.douban.com
|
||||
|
||||
13. 升级anaconda
|
||||
|
||||
|
||||
anaconda用法:
|
||||
查看已经安装的包:
|
||||
pip list 或者 conda list
|
||||
|
||||
安装和更新:
|
||||
pip install requests
|
||||
pip install requests --upgrade
|
||||
或者
|
||||
conda install requests
|
||||
conda update requests
|
||||
|
||||
更新所有库
|
||||
conda update --all
|
||||
|
||||
更新 conda 自身
|
||||
conda update conda
|
||||
|
||||
更新 anaconda 自身
|
||||
conda update anaconda
|
||||
|
@ -1238,7 +1238,7 @@ class CtaEngine(BaseEngine):
|
||||
try:
|
||||
# 5.保存策略切片
|
||||
snapshot = strategy.get_klines_snapshot()
|
||||
if len(snapshot) == 0:
|
||||
if not snapshot:
|
||||
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
||||
return
|
||||
|
||||
|
@ -789,6 +789,7 @@ class CtaFutureTemplate(CtaTemplate):
|
||||
|
||||
self.write_log(f'剩余委托单号:{grid.order_ids}')
|
||||
|
||||
self.gt.save()
|
||||
# 在策略得活动订单中,移除
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
|
@ -793,6 +793,10 @@ class CtaEngine(BaseEngine):
|
||||
|
||||
def get_price(self, vt_symbol: str):
|
||||
"""查询合约的最新价格"""
|
||||
price = self.main_engine.get_price(vt_symbol)
|
||||
if price:
|
||||
return price
|
||||
|
||||
tick = self.main_engine.get_tick(vt_symbol)
|
||||
if tick:
|
||||
return tick.last_price
|
||||
@ -819,6 +823,10 @@ class CtaEngine(BaseEngine):
|
||||
|
||||
def get_position(self, vt_symbol: str, direction: Direction, gateway_name: str = ''):
|
||||
""" 查询合约在账号的持仓,需要指定方向"""
|
||||
if len(gateway_name) == 0:
|
||||
contract = self.main_engine.get_contract(vt_symbol)
|
||||
if contract and contract.gateway_name:
|
||||
gateway_name = contract.gateway_name
|
||||
vt_position_id = f"{gateway_name}.{vt_symbol}.{direction.value}"
|
||||
return self.main_engine.get_position(vt_position_id)
|
||||
|
||||
@ -1178,7 +1186,7 @@ class CtaEngine(BaseEngine):
|
||||
try:
|
||||
# 5.保存策略切片
|
||||
snapshot = strategy.get_klines_snapshot()
|
||||
if len(snapshot) == 0:
|
||||
if not snapshot:
|
||||
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
||||
return
|
||||
|
||||
|
@ -1246,6 +1246,8 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
|
||||
self.write_log(f'剩余委托单号:{grid.order_ids}')
|
||||
|
||||
self.gt.save()
|
||||
|
||||
# 在策略得活动订单中,移除
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
@ -1274,6 +1276,16 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
old_order['traded'] = order.traded
|
||||
order_vt_symbol = copy(old_order['vt_symbol'])
|
||||
order_volume = old_order['volume'] - old_order['traded']
|
||||
|
||||
|
||||
order_price = old_order['price']
|
||||
order_type = old_order.get('order_type', OrderType.LIMIT)
|
||||
order_retry = old_order.get('retry', 0)
|
||||
grid = old_order.get('grid', None)
|
||||
if grid:
|
||||
if order.vt_orderid in grid.order_ids:
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
|
||||
if order_volume <= 0:
|
||||
msg = u'{} {}{}需重新开仓数量为{},不再开仓' \
|
||||
.format(self.strategy_name,
|
||||
@ -1286,10 +1298,6 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
return
|
||||
|
||||
order_price = old_order['price']
|
||||
order_type = old_order.get('order_type', OrderType.LIMIT)
|
||||
order_retry = old_order.get('retry', 0)
|
||||
grid = old_order.get('grid', None)
|
||||
if order_retry > 20:
|
||||
# 这里超过20次尝试失败后,不再尝试,发出告警信息
|
||||
msg = u'{} {}/{}手, 重试开仓次数{}>20' \
|
||||
@ -1299,15 +1307,9 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
order_retry)
|
||||
self.write_error(msg)
|
||||
self.send_wechat(msg)
|
||||
|
||||
if grid:
|
||||
if order.vt_orderid in grid.order_ids:
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
|
||||
# 网格的所有委托单已经执行完毕
|
||||
if len(grid.order_ids) == 0:
|
||||
grid.order_status = False
|
||||
|
||||
# 网格的所有委托单已经执行完毕
|
||||
if len(grid.order_ids) == 0:
|
||||
grid.order_status = False
|
||||
self.gt.save()
|
||||
self.write_log(u'网格信息更新:{}'.format(grid.__dict__))
|
||||
|
||||
@ -1319,8 +1321,18 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
|
||||
# FAK 重新开单
|
||||
if old_order['direction'] == Direction.LONG and order_type == OrderType.FAK:
|
||||
# 更新网格交易器
|
||||
|
||||
# 删除旧的委托记录
|
||||
self.write_log(u'移除旧的委托记录:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
if order.traded > 0:
|
||||
old_traded_volume = grid.traded_volume
|
||||
grid.traded_volume += order.traded
|
||||
self.write_log(f'{grid.direction.value}单部分{order.offset}仓,'
|
||||
+ f'网格volume:{grid.volume}, traded_volume:{old_traded_volume}=>{grid.traded_volume}')
|
||||
|
||||
# 更新网格交易器
|
||||
self.write_log(u'FAK模式,需要重新发送buy委托.grid:{}'.format(grid.__dict__))
|
||||
# 更新委托平仓价
|
||||
buy_price = max(self.cur_mi_tick.ask_price_1, self.cur_mi_tick.last_price, order_price) + self.price_tick
|
||||
@ -1350,11 +1362,18 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
info.update({'retry': order_retry})
|
||||
|
||||
self.gt.save()
|
||||
|
||||
|
||||
elif old_order['direction'] == Direction.SHORT and order_type == OrderType.FAK:
|
||||
# 删除旧的委托记录
|
||||
self.write_log(u'移除旧的委托记录:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
elif old_order['direction'] == Direction.SHORT and order_type == OrderType.FAK:
|
||||
if order.traded > 0:
|
||||
old_traded_volume = grid.traded_volume
|
||||
grid.traded_volume += order.traded
|
||||
self.write_log(f'{grid.direction.value}单部分{order.offset}仓,'
|
||||
+ f'网格volume:{grid.volume}, traded_volume:{old_traded_volume}=>{grid.traded_volume}')
|
||||
|
||||
self.write_log(u'FAK模式,需要重新发送short委托.grid:{}'.format(grid.__dict__))
|
||||
short_price = min(self.cur_mi_tick.bid_price_1, self.cur_mi_tick.last_price, order_price) - self.price_tick
|
||||
@ -1385,9 +1404,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
info.update({'retry': order_retry})
|
||||
|
||||
self.gt.save()
|
||||
# 删除旧的委托记录
|
||||
self.write_log(u'移除旧的委托记录:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
else:
|
||||
pre_status = old_order.get('status', Status.NOTTRADED)
|
||||
old_order.update({'status': Status.CANCELLED})
|
||||
@ -1423,6 +1440,15 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
# order_time = old_order['order_time']
|
||||
order_vt_symbol = copy(old_order['vt_symbol'])
|
||||
order_volume = old_order['volume'] - old_order['traded']
|
||||
|
||||
order_price = old_order['price']
|
||||
order_type = old_order.get('order_type', OrderType.LIMIT)
|
||||
order_retry = old_order.get('retry', 0)
|
||||
grid = old_order.get('grid', None)
|
||||
if grid:
|
||||
if order.vt_orderid in grid.order_ids:
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
|
||||
if order_volume <= 0:
|
||||
msg = u'{} {}{}重新平仓数量为{},不再平仓' \
|
||||
.format(self.strategy_name, order.vt_orderid, order_vt_symbol, order_volume)
|
||||
@ -1432,20 +1458,15 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
return
|
||||
|
||||
order_price = old_order['price']
|
||||
order_type = old_order.get('order_type', OrderType.LIMIT)
|
||||
order_retry = old_order.get('retry', 0)
|
||||
grid = old_order.get('grid', None)
|
||||
|
||||
if order_retry > 20:
|
||||
msg = u'{} 平仓撤单 {}/{}手, 重试平仓次数{}>20' \
|
||||
.format(self.strategy_name, order_vt_symbol, order_volume, order_retry)
|
||||
self.write_error(msg)
|
||||
self.send_wechat(msg)
|
||||
if grid:
|
||||
if order.vt_orderid in grid.order_ids:
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
if not grid.order_ids:
|
||||
grid.order_status = False
|
||||
|
||||
if not grid.order_ids:
|
||||
grid.order_status = False
|
||||
self.gt.save()
|
||||
self.write_log(u'更新网格=>{}'.format(grid.__dict__))
|
||||
|
||||
@ -1456,6 +1477,14 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
order_retry += 1
|
||||
|
||||
if old_order['direction'] == Direction.LONG and order_type == OrderType.FAK:
|
||||
self.write_log(u'移除活动订单:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
if order.traded > 0:
|
||||
old_traded_volume = grid.traded_volume
|
||||
grid.traded_volume += order.traded
|
||||
self.write_log(f'{grid.direction.value}单部分{order.offset}仓,'
|
||||
+ f'网格volume:{grid.volume}, traded_volume:{old_traded_volume}=>{grid.traded_volume}')
|
||||
|
||||
self.write_log(u'FAK模式,需要重新发送cover委托.grid:{}'.format(grid.__dict__))
|
||||
# 更新委托平仓价
|
||||
cover_tick = self.tick_dict.get(order_vt_symbol, self.cur_mi_tick)
|
||||
@ -1484,10 +1513,17 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
info.update({'retry': order_retry})
|
||||
|
||||
self.gt.save()
|
||||
self.write_log(u'移除活动订单:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
|
||||
elif old_order['direction'] == Direction.SHORT and order_type == OrderType.FAK:
|
||||
self.write_log(u'移除活动订单:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
if order.traded > 0:
|
||||
old_traded_volume = grid.traded_volume
|
||||
grid.traded_volume += order.traded
|
||||
self.write_log(f'{grid.direction.value}单部分{order.offset}仓,'
|
||||
+ f'网格volume:{grid.volume}, traded_volume:{old_traded_volume}=>{grid.traded_volume}')
|
||||
|
||||
self.write_log(u'FAK模式,需要重新发送sell委托.grid:{}'.format(grid.__dict__))
|
||||
sell_tick = self.tick_dict.get(order_vt_symbol, self.cur_mi_tick)
|
||||
sell_price = min(sell_tick.bid_price_1, sell_tick.last_price, order_price) - self.price_tick
|
||||
@ -1518,9 +1554,6 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
|
||||
self.gt.save()
|
||||
|
||||
self.write_log(u'移除活动订单:{}'.format(order.vt_orderid))
|
||||
self.active_orders.pop(order.vt_orderid, None)
|
||||
|
||||
else:
|
||||
pre_status = old_order.get('status', Status.NOTTRADED)
|
||||
old_order.update({'status': Status.CANCELLED})
|
||||
@ -1583,6 +1616,8 @@ class CtaProFutureTemplate(CtaProTemplate):
|
||||
if order_grid:
|
||||
if vt_orderid in order_grid.order_ids:
|
||||
order_grid.order_ids.remove(vt_orderid)
|
||||
if len(order_grid.order_ids) == 0:
|
||||
order_grid.order_status = False
|
||||
continue
|
||||
|
||||
# 处理状态为‘撤销’的委托单
|
||||
|
@ -123,9 +123,9 @@ class CtaGrid(object):
|
||||
def to_str(self):
|
||||
"""转换字符串显示内容"""
|
||||
|
||||
str = u'o:{}/{};c:{}/{},r:{}/opentime:{}/ordertime:{}' \
|
||||
str = u'o:{}/{};c:{}/{},r:{}/opentime:{}/ordertime:{},v:{}' \
|
||||
.format(self.open_price, self.open_status, self.close_price,
|
||||
self.close_status, self.order_ids, self.open_time, self.order_time)
|
||||
self.close_status, self.order_ids, self.open_time, self.order_time, self.volume)
|
||||
if len(self.vt_symbol) > 0:
|
||||
return u'{} {}'.format(self.vt_symbol, str)
|
||||
else:
|
||||
|
@ -373,7 +373,7 @@ class CtaLineBar(object):
|
||||
|
||||
self.para_boll2_len = 0 # 第二条布林的计算K线周期
|
||||
self.para_boll2_tb_len = 0 # 第二跳布林的计算K线周期( 适用于TB的计算方式)
|
||||
self.para_boll2_std_sate = 2 # 第二条布林标准差(缺省2倍)
|
||||
self.para_boll2_std_rate = 2 # 第二条布林标准差(缺省2倍)
|
||||
|
||||
self.para_kdj_len = 0 # KDJ指标的长度,缺省是9
|
||||
self.para_kdj_tb_len = 0 # KDJ指标的长度,缺省是9 ( for TB)
|
||||
@ -2059,9 +2059,9 @@ class CtaLineBar(object):
|
||||
boll2Len = min(self.bar_len, self.para_boll2_len)
|
||||
|
||||
# 不包含当前最新的Bar
|
||||
upper_list, middle_list, lower_list = ta.BBANDS(self.close_array[-2 * self.para_boll2_len],
|
||||
timeperiod=boll2Len, nbdevup=self.para_boll2_std_sate,
|
||||
nbdevdn=self.para_boll2_std_sate, matype=0)
|
||||
upper_list, middle_list, lower_list = ta.BBANDS(self.close_array,
|
||||
timeperiod=boll2Len, nbdevup=self.para_boll2_std_rate,
|
||||
nbdevdn=self.para_boll2_std_rate, matype=0)
|
||||
if len(self.line_boll2_upper) > self.max_hold_bars:
|
||||
del self.line_boll2_upper[0]
|
||||
if len(self.line_boll2_middle) > self.max_hold_bars:
|
||||
@ -2072,7 +2072,7 @@ class CtaLineBar(object):
|
||||
del self.line_boll2_std[0]
|
||||
|
||||
# 1标准差
|
||||
std = (upper_list[-1] - lower_list[-1]) / (self.para_boll2_std_sate * 2)
|
||||
std = (upper_list[-1] - lower_list[-1]) / (self.para_boll2_std_rate * 2)
|
||||
self.line_boll2_std.append(std)
|
||||
|
||||
upper = round(upper_list[-1], self.round_n)
|
||||
@ -2188,15 +2188,15 @@ class CtaLineBar(object):
|
||||
|
||||
middle = np.mean(self.close_array[-2 * boll2Len:])
|
||||
self.line_boll2_middle.append(middle) # 中轨
|
||||
self.cur_middle2 = middle - middle % self.price_tick # 中轨取整
|
||||
self.cur_middle2 = middle # 中轨取整
|
||||
|
||||
upper = middle + self.para_boll2_std_sate * std
|
||||
upper = middle + self.para_boll2_std_rate * std
|
||||
self.line_boll2_upper.append(upper) # 上轨
|
||||
self.cur_upper2 = upper - upper % self.price_tick # 上轨取整
|
||||
self.cur_upper2 = upper # 上轨取整
|
||||
|
||||
lower = middle - self.para_boll2_std_sate * std
|
||||
lower = middle - self.para_boll2_std_rate * std
|
||||
self.line_boll2_lower.append(lower) # 下轨
|
||||
self.cur_lower2 = lower - lower % self.price_tick # 下轨取整
|
||||
self.cur_lower2 = lower # 下轨取整
|
||||
|
||||
# 计算斜率
|
||||
if len(self.line_boll2_upper) > 2 and self.line_boll2_upper[-2] != 0:
|
||||
@ -2229,6 +2229,8 @@ class CtaLineBar(object):
|
||||
if not (boll_01_len > 0 or boll_02_len > 0): # 不计算
|
||||
return
|
||||
|
||||
rt_close_array = np.append(self.close_array, [self.line_bar[-1].close_price])
|
||||
|
||||
if boll_01_len > 0:
|
||||
if self.bar_len < min(14, boll_01_len) + 1:
|
||||
return
|
||||
@ -2236,7 +2238,7 @@ class CtaLineBar(object):
|
||||
bollLen = min(boll_01_len, self.bar_len)
|
||||
|
||||
if self.para_boll_tb_len == 0:
|
||||
upper_list, middle_list, lower_list = ta.BBANDS(self.close_array[-bollLen:],
|
||||
upper_list, middle_list, lower_list = ta.BBANDS(rt_close_array,
|
||||
timeperiod=bollLen, nbdevup=self.para_boll_std_rate,
|
||||
nbdevdn=self.para_boll_std_rate, matype=0)
|
||||
|
||||
@ -2247,8 +2249,8 @@ class CtaLineBar(object):
|
||||
self._rt_lower = round(lower_list[-1], self.round_n)
|
||||
else:
|
||||
# 1标准差
|
||||
std = np.std(np.append(self.close_array[-boll_01_len:], [self.line_bar[-1].close]), ddof=1)
|
||||
middle = np.mean(np.append(self.close_array[-boll_01_len:], [self.line_bar[-1].close]))
|
||||
std = np.std(rt_close_array[-boll_01_len:])
|
||||
middle = np.mean(rt_close_array[-boll_01_len:])
|
||||
self._rt_middle = round(middle, self.round_n)
|
||||
upper = middle + self.para_boll_std_rate * std
|
||||
self._rt_upper = round(upper, self.round_n)
|
||||
@ -2275,19 +2277,20 @@ class CtaLineBar(object):
|
||||
bollLen = min(boll_02_len, self.bar_len)
|
||||
|
||||
if self.para_boll2_tb_len == 0:
|
||||
upper_list, middle_list, lower_list = ta.BBANDS(self.close_array[-bollLen:],
|
||||
timeperiod=bollLen, nbdevup=self.para_boll_std_rate,
|
||||
nbdevdn=self.para_boll_std_rate, matype=0)
|
||||
upper_list, middle_list, lower_list = ta.BBANDS(
|
||||
rt_close_array,
|
||||
timeperiod=bollLen, nbdevup=self.para_boll2_std_rate,
|
||||
nbdevdn=self.para_boll2_std_rate, matype=0)
|
||||
|
||||
# 1标准差
|
||||
std = (upper_list[-1] - lower_list[-1]) / (self.para_boll2_std_sate * 2)
|
||||
std = (upper_list[-1] - lower_list[-1]) / (self.para_boll2_std_rate * 2)
|
||||
self._rt_upper2 = round(upper_list[-1], self.round_n)
|
||||
self._rt_middle2 = round(middle_list[-1], self.round_n)
|
||||
self._rt_lower2 = round(lower_list[-1], self.round_n)
|
||||
else:
|
||||
# 1标准差
|
||||
std = np.std(np.append(self.close_array[-boll_02_len:], [self.line_bar[-1].close]), ddof=1)
|
||||
middle = np.mean(np.append(self.close_array[-boll_02_len:], [self.line_bar[-1].close]))
|
||||
std = np.std(rt_close_array[-bollLen:], ddof=1)
|
||||
middle = np.mean(rt_close_array[-bollLen:])
|
||||
self._rt_middle2 = round(middle, self.round_n)
|
||||
upper = middle + self.para_boll_std_rate * std
|
||||
self._rt_upper2 = round(upper, self.round_n)
|
||||
|
@ -4,7 +4,7 @@
|
||||
"mi_symbol": "a2005",
|
||||
"full_symbol": "A2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.06,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -13,7 +13,7 @@
|
||||
"mi_symbol": "ag2007",
|
||||
"full_symbol": "AG2007",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 15,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -31,7 +31,7 @@
|
||||
"mi_symbol": "AP005",
|
||||
"full_symbol": "AP2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -67,7 +67,7 @@
|
||||
"mi_symbol": "bu2006",
|
||||
"full_symbol": "BU2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"margin_rate": 0.11,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -85,7 +85,7 @@
|
||||
"mi_symbol": "CF009",
|
||||
"full_symbol": "CF2009",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -112,7 +112,7 @@
|
||||
"mi_symbol": "cu2004",
|
||||
"full_symbol": "CU2004",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.09,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 10.0
|
||||
},
|
||||
@ -121,7 +121,7 @@
|
||||
"mi_symbol": "CY005",
|
||||
"full_symbol": "CY2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -130,7 +130,7 @@
|
||||
"mi_symbol": "eb2005",
|
||||
"full_symbol": "EB2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.11,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -139,7 +139,7 @@
|
||||
"mi_symbol": "eg2005",
|
||||
"full_symbol": "EG2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.11,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -148,9 +148,9 @@
|
||||
"mi_symbol": "fb2005",
|
||||
"full_symbol": "FB2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.2,
|
||||
"symbol_size": 500,
|
||||
"price_tick": 0.05
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
"FG": {
|
||||
"underlying_symbol": "FG",
|
||||
@ -166,7 +166,7 @@
|
||||
"mi_symbol": "fu2005",
|
||||
"full_symbol": "FU2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.2,
|
||||
"margin_rate": 0.11,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -175,7 +175,7 @@
|
||||
"mi_symbol": "hc2005",
|
||||
"full_symbol": "HC2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -184,7 +184,7 @@
|
||||
"mi_symbol": "i2005",
|
||||
"full_symbol": "I2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 100,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
@ -220,7 +220,7 @@
|
||||
"mi_symbol": "j2005",
|
||||
"full_symbol": "J2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 100,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
@ -229,7 +229,7 @@
|
||||
"mi_symbol": "jd2005",
|
||||
"full_symbol": "JD2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -238,7 +238,7 @@
|
||||
"mi_symbol": "jm2005",
|
||||
"full_symbol": "JM2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 60,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
@ -256,7 +256,7 @@
|
||||
"mi_symbol": "l2005",
|
||||
"full_symbol": "L2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -274,7 +274,7 @@
|
||||
"mi_symbol": "m2005",
|
||||
"full_symbol": "M2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.06,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -301,7 +301,7 @@
|
||||
"mi_symbol": "nr2004",
|
||||
"full_symbol": "NR2004",
|
||||
"exchange": "INE",
|
||||
"margin_rate": 0.09,
|
||||
"margin_rate": 0.11,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -319,14 +319,14 @@
|
||||
"mi_symbol": "p2005",
|
||||
"full_symbol": "P2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
"PB": {
|
||||
"underlying_symbol": "PB",
|
||||
"mi_symbol": "pb2003",
|
||||
"full_symbol": "PB2003",
|
||||
"mi_symbol": "pb2006",
|
||||
"full_symbol": "PB2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
@ -346,7 +346,7 @@
|
||||
"mi_symbol": "pp2005",
|
||||
"full_symbol": "PP2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -355,7 +355,7 @@
|
||||
"mi_symbol": "rb2005",
|
||||
"full_symbol": "RB2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -373,7 +373,7 @@
|
||||
"mi_symbol": "RM005",
|
||||
"full_symbol": "RM2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.06,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -391,7 +391,7 @@
|
||||
"mi_symbol": "RS011",
|
||||
"full_symbol": "RS2011",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.2,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -400,7 +400,7 @@
|
||||
"mi_symbol": "ru2005",
|
||||
"full_symbol": "RU2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"margin_rate": 0.11,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -418,7 +418,7 @@
|
||||
"mi_symbol": "sc2004",
|
||||
"full_symbol": "SC2004",
|
||||
"exchange": "INE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.2,
|
||||
"symbol_size": 1000,
|
||||
"price_tick": 0.1
|
||||
},
|
||||
@ -427,7 +427,7 @@
|
||||
"mi_symbol": "SF005",
|
||||
"full_symbol": "SF2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -436,7 +436,7 @@
|
||||
"mi_symbol": "SM005",
|
||||
"full_symbol": "SM2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -445,7 +445,7 @@
|
||||
"mi_symbol": "sn2006",
|
||||
"full_symbol": "SN2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.09,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 1,
|
||||
"price_tick": 10.0
|
||||
},
|
||||
@ -454,7 +454,7 @@
|
||||
"mi_symbol": "sp2005",
|
||||
"full_symbol": "SP2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -472,7 +472,7 @@
|
||||
"mi_symbol": "ss2006",
|
||||
"full_symbol": "SS2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -490,14 +490,14 @@
|
||||
"mi_symbol": "TA005",
|
||||
"full_symbol": "TA2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
"TF": {
|
||||
"underlying_symbol": "TF",
|
||||
"mi_symbol": "TF2003",
|
||||
"full_symbol": "TF2003",
|
||||
"mi_symbol": "TF2004",
|
||||
"full_symbol": "TF2004",
|
||||
"exchange": "CFFEX",
|
||||
"margin_rate": 0.012,
|
||||
"symbol_size": 10000,
|
||||
@ -526,7 +526,7 @@
|
||||
"mi_symbol": "v2005",
|
||||
"full_symbol": "V2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -535,7 +535,7 @@
|
||||
"mi_symbol": "WH011",
|
||||
"full_symbol": "WH2011",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 20,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -544,7 +544,7 @@
|
||||
"mi_symbol": "wr2101",
|
||||
"full_symbol": "WR2101",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.2,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -553,7 +553,7 @@
|
||||
"mi_symbol": "y2005",
|
||||
"full_symbol": "Y2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.06,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -562,14 +562,14 @@
|
||||
"mi_symbol": "ZC005",
|
||||
"full_symbol": "ZC2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.05,
|
||||
"margin_rate": 0.06,
|
||||
"symbol_size": 100,
|
||||
"price_tick": 0.2
|
||||
},
|
||||
"ZN": {
|
||||
"underlying_symbol": "ZN",
|
||||
"mi_symbol": "zn2003",
|
||||
"full_symbol": "ZN2003",
|
||||
"mi_symbol": "zn2005",
|
||||
"full_symbol": "ZN2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
|
@ -11,6 +11,20 @@ from vnpy.trader.utility import load_json, save_json
|
||||
# 期货的配置文件
|
||||
TDX_FUTURE_CONFIG = 'tdx_future_config.json'
|
||||
# 股票的配置文件
|
||||
# 存储格式 dict{
|
||||
# "cache_time": datetime,
|
||||
# "symbol_dict": {
|
||||
# "symbol_marketid": {
|
||||
# 'code', '395001',
|
||||
# 'volunit', 100,
|
||||
# 'decimal_point', 2,
|
||||
# 'name', '主板A股',
|
||||
# 'pre_close', 458.0,
|
||||
# 'exchagne','SZSE',
|
||||
# 'stock_type', 'index_cn',
|
||||
# 'market_id', 0
|
||||
# }
|
||||
# } }
|
||||
TDX_STOCK_CONFIG = 'tdx_stock_config.pkb2'
|
||||
|
||||
|
||||
@ -112,6 +126,64 @@ def save_cache_json(data_dict: dict, json_file_name: str):
|
||||
save_json(filename=config_file_name, data=data_dict)
|
||||
|
||||
|
||||
def get_stock_type(code):
|
||||
"""获取股票得分类"""
|
||||
market_id = get_tdx_market_code(code)
|
||||
|
||||
if market_id == 0:
|
||||
return get_stock_type_sz(code)
|
||||
else:
|
||||
return get_stock_type_sh(code)
|
||||
|
||||
|
||||
def get_stock_type_sz(code):
|
||||
"""深市代码分类
|
||||
Arguments:
|
||||
code {[type]} -- [description]
|
||||
Returns:
|
||||
[type] -- [description]
|
||||
"""
|
||||
|
||||
if str(code)[0:2] in ['00', '30', '02']:
|
||||
return 'stock_cn'
|
||||
elif str(code)[0:2] in ['39']:
|
||||
return 'index_cn'
|
||||
elif str(code)[0:2] in ['15']:
|
||||
return 'etf_cn'
|
||||
elif str(code)[0:2] in ['10', '11', '13']:
|
||||
# 10xxxx 国债现货
|
||||
# 11xxxx 债券
|
||||
# 12xxxx 国债回购
|
||||
return 'bond_cn'
|
||||
elif str(code)[0:2] in ['12']:
|
||||
# 12xxxx 可转换债券
|
||||
return 'cb_cn'
|
||||
|
||||
elif str(code)[0:2] in ['20']:
|
||||
return 'stockB_cn'
|
||||
else:
|
||||
return 'undefined'
|
||||
|
||||
|
||||
def get_stock_type_sh(code):
|
||||
if str(code)[0] == '6':
|
||||
return 'stock_cn'
|
||||
elif str(code)[0:3] in ['000', '880']:
|
||||
return 'index_cn'
|
||||
elif str(code)[0:2] == '51':
|
||||
return 'etf_cn'
|
||||
# 110×××120×××企业债券;
|
||||
# 129×××100×××可转换债券;
|
||||
elif str(code)[0:3] in ["009", "112", '120', "132", "204"]:
|
||||
return 'bond_cn'
|
||||
|
||||
elif str(code)[0:3] in ["110", "113", "121", "122", "126",
|
||||
"130", "181", "190", "191", "192", "201", "202", "203"]:
|
||||
return 'cb_cn'
|
||||
else:
|
||||
return 'undefined'
|
||||
|
||||
|
||||
class FakeStrategy(object):
|
||||
"""制作一个假得策略,用于测试"""
|
||||
|
||||
|
@ -241,6 +241,7 @@ class TdxFutureData(object):
|
||||
self.symbol_exchange_dict.update({tdx_symbol: Tdx_Vn_Exchange_Map.get(str(tdx_market_id))})
|
||||
self.symbol_market_dict.update({tdx_symbol: tdx_market_id})
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def get_bars(self,
|
||||
symbol: str,
|
||||
@ -292,7 +293,7 @@ class TdxFutureData(object):
|
||||
end_date = end_dt
|
||||
if qry_start_date > end_date:
|
||||
qry_start_date = end_date
|
||||
self.write_log('{}开始下载tdx:{} {}数据, {} to {}.'
|
||||
self.write_log('{}开始下载tdx:{},周期类型:{}数据, {} to {}.'
|
||||
.format(datetime.now(), tdx_symbol, period, qry_start_date, end_date))
|
||||
# print('{}开始下载tdx:{} {}数据, {} to {}.'.format(datetime.now(), tdx_symbol, tdx_period, last_date, end_date))
|
||||
|
||||
|
@ -28,6 +28,7 @@ from vnpy.data.tdx.tdx_common import (
|
||||
get_tdx_market_code,
|
||||
get_cache_config,
|
||||
save_cache_config,
|
||||
get_stock_type,
|
||||
TDX_STOCK_CONFIG)
|
||||
|
||||
# 每个周期包含多少分钟
|
||||
@ -58,6 +59,8 @@ TDX_RQ_STOCK_MARKET_MAP = {
|
||||
RQ_TDX_STOCK_MARKET_MAP = {v: k for k, v in TDX_RQ_STOCK_MARKET_MAP.items()}
|
||||
|
||||
|
||||
# 本地缓存文件
|
||||
|
||||
class TdxStockData(object):
|
||||
|
||||
def __init__(self, strategy=None):
|
||||
@ -139,6 +142,12 @@ class TdxStockData(object):
|
||||
continue
|
||||
for security in security_list:
|
||||
tdx_symbol = security.get('code', None)
|
||||
exchange = Exchange.SZSE.value if market_id == 0 else Exchange.SSE.value
|
||||
stock_type = get_stock_type(tdx_symbol)
|
||||
security.update({'market_id': market_id})
|
||||
security.update({'stock_type': stock_type})
|
||||
security.update({'exchange': exchange})
|
||||
|
||||
if tdx_symbol:
|
||||
self.symbol_dict.update({f'{tdx_symbol}_{market_id}': security})
|
||||
|
||||
@ -170,13 +179,21 @@ class TdxStockData(object):
|
||||
|
||||
return results
|
||||
|
||||
def get_name(self, code, market_id):
|
||||
symbol_info = self.symbol_dict.get(f'{code}_{market_id}')
|
||||
if symbol_info:
|
||||
return symbol_info.get('name', code)
|
||||
|
||||
return code
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def get_bars(self,
|
||||
symbol: str,
|
||||
period: str,
|
||||
callback=None,
|
||||
bar_freq: int = 1,
|
||||
start_dt: datetime = None):
|
||||
start_dt: datetime = None,
|
||||
return_bar: bool = True):
|
||||
"""
|
||||
返回k线数据
|
||||
symbol:股票 000001.XG
|
||||
@ -192,14 +209,15 @@ class TdxStockData(object):
|
||||
if '.' in symbol:
|
||||
tdx_code, market_str = symbol.split('.')
|
||||
# 1, 上交所 , 0, 深交所
|
||||
market_code = 1 if market_str.upper() in ['XSHG', Exchange.SSE.value] else 0
|
||||
market_id = 1 if market_str.upper() in ['XSHG', Exchange.SSE.value] else 0
|
||||
self.symbol_exchange_dict.update({tdx_code: symbol}) # tdx合约与vn交易所的字典
|
||||
self.symbol_market_dict.update({tdx_code: market_code}) # tdx合约与tdx市场的字典
|
||||
self.symbol_market_dict.update({tdx_code: market_id}) # tdx合约与tdx市场的字典
|
||||
else:
|
||||
market_code = get_tdx_market_code(symbol)
|
||||
market_id = get_tdx_market_code(symbol)
|
||||
tdx_code = symbol
|
||||
self.symbol_exchange_dict.update({symbol: symbol}) # tdx合约与vn交易所的字典
|
||||
self.symbol_market_dict.update({symbol: market_code}) # tdx合约与tdx市场的字典
|
||||
self.symbol_market_dict.update({symbol: market_id}) # tdx合约与tdx市场的字典
|
||||
name = self.get_name(tdx_code, market_id)
|
||||
|
||||
# period => tdx_period
|
||||
if period not in PERIOD_MAPPING.keys():
|
||||
@ -220,8 +238,8 @@ class TdxStockData(object):
|
||||
if qry_start_date > qry_end_date:
|
||||
qry_start_date = qry_end_date
|
||||
|
||||
self.write_log('{}开始下载tdx股票:{} {}数据, {} to {}.'
|
||||
.format(datetime.now(), tdx_code, tdx_period, qry_start_date, qry_end_date))
|
||||
self.write_log('{}开始下载tdx股票: {},代码:{} {}数据, {} to {}.'
|
||||
.format(datetime.now(), name, tdx_code, tdx_period, qry_start_date, qry_end_date))
|
||||
|
||||
try:
|
||||
_start_date = qry_end_date
|
||||
@ -230,7 +248,7 @@ class TdxStockData(object):
|
||||
while _start_date > qry_start_date:
|
||||
_res = self.api.get_security_bars(
|
||||
category=PERIOD_MAPPING[period],
|
||||
market=market_code,
|
||||
market=market_id,
|
||||
code=tdx_code,
|
||||
start=_pos,
|
||||
count=QSIZE)
|
||||
@ -273,43 +291,48 @@ class TdxStockData(object):
|
||||
data['time'] = data['datetime'].apply(lambda x: (x.strftime('%H:%M:%S')))
|
||||
data = data.set_index('datetime', drop=False)
|
||||
|
||||
for index, row in data.iterrows():
|
||||
add_bar = BarData()
|
||||
try:
|
||||
add_bar.symbol = symbol
|
||||
add_bar.datetime = index
|
||||
add_bar.date = row['date']
|
||||
add_bar.time = row['time']
|
||||
add_bar.trading_date = row['trading_date']
|
||||
add_bar.open_price = float(row['open'])
|
||||
add_bar.high_price = float(row['high'])
|
||||
add_bar.low_price = float(row['low'])
|
||||
add_bar.close_price = float(row['close'])
|
||||
add_bar.volume = float(row['volume'])
|
||||
except Exception as ex:
|
||||
self.write_error('error when convert bar:{},ex:{},t:{}'
|
||||
.format(row, str(ex), traceback.format_exc()))
|
||||
# print('error when convert bar:{},ex:{},t:{}'.format(row, str(ex), traceback.format_exc()))
|
||||
return False
|
||||
if return_bar:
|
||||
self.write_log('dataframe => [BarData]')
|
||||
for index, row in data.iterrows():
|
||||
add_bar = BarData()
|
||||
try:
|
||||
add_bar.symbol = symbol
|
||||
add_bar.datetime = index
|
||||
add_bar.date = row['date']
|
||||
add_bar.time = row['time']
|
||||
add_bar.trading_date = row['trading_date']
|
||||
add_bar.open_price = float(row['open'])
|
||||
add_bar.high_price = float(row['high'])
|
||||
add_bar.low_price = float(row['low'])
|
||||
add_bar.close_price = float(row['close'])
|
||||
add_bar.volume = float(row['volume'])
|
||||
except Exception as ex:
|
||||
self.write_error('error when convert bar:{},ex:{},t:{}'
|
||||
.format(row, str(ex), traceback.format_exc()))
|
||||
# print('error when convert bar:{},ex:{},t:{}'.format(row, str(ex), traceback.format_exc()))
|
||||
return False, ret_bars
|
||||
|
||||
if start_dt is not None and index < start_dt:
|
||||
continue
|
||||
ret_bars.append(add_bar)
|
||||
if start_dt is not None and index < start_dt:
|
||||
continue
|
||||
ret_bars.append(add_bar)
|
||||
|
||||
if callback is not None:
|
||||
freq = bar_freq
|
||||
bar_is_completed = True
|
||||
if period != '1min' and index == data['datetime'][-1]:
|
||||
# 最后一个bar,可能是不完整的,强制修改
|
||||
# - 5min修改后freq基本正确
|
||||
# - 1day在VNPY合成时不关心已经收到多少Bar, 所以影响也不大
|
||||
# - 但其它分钟周期因为不好精确到每个品种, 修改后的freq可能有错
|
||||
if index > current_datetime:
|
||||
bar_is_completed = False
|
||||
# 根据秒数算的话,要+1,例如13:31,freq=31,第31根bar
|
||||
freq = NUM_MINUTE_MAPPING[period] - int((index - current_datetime).total_seconds() / 60)
|
||||
callback(add_bar, bar_is_completed, freq)
|
||||
if callback is not None:
|
||||
freq = bar_freq
|
||||
bar_is_completed = True
|
||||
if period != '1min' and index == data['datetime'][-1]:
|
||||
# 最后一个bar,可能是不完整的,强制修改
|
||||
# - 5min修改后freq基本正确
|
||||
# - 1day在VNPY合成时不关心已经收到多少Bar, 所以影响也不大
|
||||
# - 但其它分钟周期因为不好精确到每个品种, 修改后的freq可能有错
|
||||
if index > current_datetime:
|
||||
bar_is_completed = False
|
||||
# 根据秒数算的话,要+1,例如13:31,freq=31,第31根bar
|
||||
freq = NUM_MINUTE_MAPPING[period] - int((index - current_datetime).total_seconds() / 60)
|
||||
callback(add_bar, bar_is_completed, freq)
|
||||
|
||||
else:
|
||||
self.write_log('dataframe => [ dict ]')
|
||||
ret_bars = list(data.T.to_dict().values())
|
||||
return True, ret_bars
|
||||
except Exception as ex:
|
||||
self.write_error('exception in get:{},{},{}'.format(tdx_code, str(ex), traceback.format_exc()))
|
||||
@ -400,6 +423,9 @@ class TdxStockData(object):
|
||||
self.symbol_exchange_dict.update({symbol: symbol}) # tdx合约与vn交易所的字典
|
||||
self.symbol_market_dict.update({symbol: market_code}) # tdx合约与tdx市场的字典
|
||||
|
||||
symbol_config = self.symbol_dict.get(f'{tdx_code}_{market_code}', {})
|
||||
decimal_point = symbol_config.get('decimal_point', 2)
|
||||
|
||||
q_size = QSIZE * 5
|
||||
# 每秒 2个, 10小时
|
||||
max_data_size = 1000000
|
||||
@ -462,6 +488,10 @@ class TdxStockData(object):
|
||||
last_dt = last_dt + timedelta(seconds=1)
|
||||
d.update({'datetime': last_dt})
|
||||
d.update({'volume': d.pop('vol', 0)})
|
||||
if decimal_point > 2:
|
||||
price = round(d.get('price') / (10 ** (decimal_point - 2)), decimal_point)
|
||||
d.update({'price': price})
|
||||
|
||||
d.update({'trading_date': last_dt.strftime('%Y-%m-%d')})
|
||||
|
||||
_datas = sorted(_datas, key=lambda s: s['datetime'])
|
||||
|
@ -693,10 +693,22 @@ class CtpTdApi(TdApi):
|
||||
symbol = data["InstrumentID"]
|
||||
exchange = symbol_exchange_map[symbol]
|
||||
|
||||
order_type = OrderType.LIMIT
|
||||
if data["OrderPriceType"] == THOST_FTDC_OPT_LimitPrice and data["TimeCondition"] == THOST_FTDC_TC_IOC:
|
||||
if data["VolumeCondition"] == THOST_FTDC_VC_AV:
|
||||
order_type = OrderType.FAK
|
||||
elif data["VolumeCondition"] == THOST_FTDC_VC_CV:
|
||||
order_type = OrderType.FOK
|
||||
|
||||
if data["OrderPriceType"] == THOST_FTDC_OPT_AnyPrice:
|
||||
order_type = OrderType.MARKET
|
||||
|
||||
|
||||
order = OrderData(
|
||||
symbol=symbol,
|
||||
exchange=exchange,
|
||||
orderid=orderid,
|
||||
type=order_type,
|
||||
direction=DIRECTION_CTP2VT[data["Direction"]],
|
||||
offset=OFFSET_CTP2VT.get(data["CombOffsetFlag"], Offset.NONE),
|
||||
price=data["LimitPrice"],
|
||||
@ -913,12 +925,22 @@ class CtpTdApi(TdApi):
|
||||
order_ref = data["OrderRef"]
|
||||
orderid = f"{frontid}_{sessionid}_{order_ref}"
|
||||
|
||||
order_type = OrderType.LIMIT
|
||||
if data["OrderPriceType"] == THOST_FTDC_OPT_LimitPrice and data["TimeCondition"] == THOST_FTDC_TC_IOC:
|
||||
if data["VolumeCondition"] == THOST_FTDC_VC_AV:
|
||||
order_type = OrderType.FAK
|
||||
elif data["VolumeCondition"] == THOST_FTDC_VC_CV:
|
||||
order_type = OrderType.FOK
|
||||
|
||||
if data["OrderPriceType"] == THOST_FTDC_OPT_AnyPrice:
|
||||
order_type = OrderType.MARKET
|
||||
|
||||
order = OrderData(
|
||||
symbol=symbol,
|
||||
exchange=exchange,
|
||||
orderid=orderid,
|
||||
sys_orderid=data.get('OrderSysID', ""),
|
||||
type=ORDERTYPE_CTP2VT[data["OrderPriceType"]],
|
||||
type=order_type,
|
||||
direction=DIRECTION_CTP2VT[data["Direction"]],
|
||||
offset=OFFSET_CTP2VT[data["CombOffsetFlag"]],
|
||||
price=data["LimitPrice"],
|
||||
|
@ -25,8 +25,8 @@ class OffsetConverter:
|
||||
|
||||
def update_position(self, position: PositionData) -> None:
|
||||
""""""
|
||||
if not self.is_convert_required(position.vt_symbol):
|
||||
return
|
||||
# if not self.is_convert_required(position.vt_symbol):
|
||||
# return
|
||||
|
||||
holding = self.get_position_holding(position.vt_symbol, position.gateway_name)
|
||||
holding.update_position(position)
|
||||
@ -57,6 +57,10 @@ class OffsetConverter:
|
||||
|
||||
def get_position_holding(self, vt_symbol: str, gateway_name: str = '') -> "PositionHolding":
|
||||
"""获取持仓信息"""
|
||||
if len(gateway_name) == 0:
|
||||
contract = self.main_engine.get_contract(vt_symbol)
|
||||
if contract:
|
||||
gateway_name = contract.gateway_name
|
||||
k = f'{gateway_name}.{vt_symbol}'
|
||||
holding = self.holdings.get(k, None)
|
||||
if not holding:
|
||||
|
@ -9,7 +9,7 @@ import os
|
||||
import csv
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Callable, Dict, Tuple, Union
|
||||
from typing import Callable, Dict, Tuple, Union, Any
|
||||
from decimal import Decimal
|
||||
from math import floor, ceil
|
||||
from time import time
|
||||
@ -17,6 +17,8 @@ from datetime import datetime, timedelta
|
||||
from functools import wraps, lru_cache
|
||||
import numpy as np
|
||||
import talib
|
||||
import pickle
|
||||
import bz2
|
||||
|
||||
from .object import BarData, TickData
|
||||
from .constant import Exchange, Interval
|
||||
@ -615,6 +617,21 @@ def display_dual_axis(df, columns1, columns2=[], invert_yaxis1=False, invert_yax
|
||||
plt.show()
|
||||
|
||||
|
||||
def load_data_from_pkb2(pkb2_file_name):
|
||||
"""获取本地压缩的数据"""
|
||||
data = None
|
||||
if not os.path.exists(pkb2_file_name):
|
||||
return data
|
||||
with bz2.BZ2File(pkb2_file_name, 'rb') as f:
|
||||
data = pickle.load(f)
|
||||
return data
|
||||
|
||||
def save_data_to_pkb2(data: Any, pkb2_file_name):
|
||||
"""保存本地缓存的配置地址信息"""
|
||||
with bz2.BZ2File(pkb2_file_name, 'wb') as f:
|
||||
pickle.dump(data, f)
|
||||
|
||||
|
||||
class BarGenerator:
|
||||
"""
|
||||
For:
|
||||
|
Loading…
Reference in New Issue
Block a user