From 55d7ae2022326bd7d315d6f6d338c3f74f2d8998 Mon Sep 17 00:00:00 2001 From: shinny-pack Date: Fri, 23 Feb 2024 02:43:30 +0000 Subject: [PATCH] Update Version 3.5.3 --- PKG-INFO | 2 +- doc/conf.py | 4 ++-- doc/version.rst | 6 ++++++ setup.py | 2 +- tqsdk/__version__.py | 2 +- tqsdk/algorithm/twap.py | 20 ++++++------------ tqsdk/backtest/backtest.py | 35 ++++++++++++++++++++++--------- tqsdk/lib/target_pos_scheduler.py | 7 ++++--- tqsdk/lib/target_pos_task.py | 20 ++++++------------ 9 files changed, 52 insertions(+), 46 deletions(-) diff --git a/PKG-INFO b/PKG-INFO index 935ea73e..1edf8388 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: tqsdk -Version: 3.5.2 +Version: 3.5.3 Summary: TianQin SDK Home-page: https://www.shinnytech.com/tqsdk Author: TianQin diff --git a/doc/conf.py b/doc/conf.py index be4fea02..cc4d6daf 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -48,9 +48,9 @@ # built documents. # # The short X.Y version. -version = u'3.5.2' +version = u'3.5.3' # The full version, including alpha/beta/rc tags. -release = u'3.5.2' +release = u'3.5.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/version.rst b/doc/version.rst index 19014aa5..11ca3511 100644 --- a/doc/version.rst +++ b/doc/version.rst @@ -2,6 +2,12 @@ 版本变更 ============================= +3.5.3 (2024/02/23) + +* 修复:使用 :py:class:`~tqsdk.TargetPosScheduler`,并且最后一项调仓目标为 0 时,可能出现任务无法结束的问题 +* 修复:回测时如果订阅多个不同周期 K 线时,成交可能不符合预期的问题 + + 3.5.2 (2024/02/07) * 新增::py:class:`~tqsdk.objs.Quote` 增加以下属性 diff --git a/setup.py b/setup.py index 6edd8ea0..5a8a1eff 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name='tqsdk', - version="3.5.2", + version="3.5.3", description='TianQin SDK', author='TianQin', author_email='tianqincn@gmail.com', diff --git a/tqsdk/__version__.py b/tqsdk/__version__.py index 0bc4055f..455727c5 100644 --- a/tqsdk/__version__.py +++ b/tqsdk/__version__.py @@ -1 +1 @@ -__version__ = '3.5.2' +__version__ = '3.5.3' diff --git a/tqsdk/algorithm/twap.py b/tqsdk/algorithm/twap.py index 18b6e389..5649d269 100644 --- a/tqsdk/algorithm/twap.py +++ b/tqsdk/algorithm/twap.py @@ -117,20 +117,6 @@ def __init__(self, api: TqApi, symbol: str, direction: str, offset: str, volume: print(target_twap.average_trade_price) api.close() """ - if symbol.startswith("CZCE.ZC"): - raise Exception("动力煤期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 4 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.WH"): - raise Exception("强麦期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.PM"): - raise Exception("普麦期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.RI"): - raise Exception("早籼稻期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.JR"): - raise Exception("粳稻期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.LR"): - raise Exception("晚籼稻期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol == "CZCE.SA309" or symbol == "CZCE.SA310": - raise Exception("纯碱期货 2309 合约及 2310 合约不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 4 手,这些函数还未支持该规则!") self._api = api self._account = api._account._check_valid(account) if self._account is None: @@ -167,6 +153,12 @@ def average_trade_price(self): async def _run(self, volume_list, interval_list): self._quote = await self._api.get_quote(self._symbol) + # 判断最小下单手数是否大于1 + if self._quote.open_min_market_order_volume > 1 or self._quote.open_min_limit_order_volume > 1: + raise Exception( + f"交易所规定 {self._symbol} 的最小市价开仓手数 ({self._quote.open_min_market_order_volume})" + f" 或最小限价开仓手数 ({self._quote.open_min_limit_order_volume}) 大于 1,targetpostask、twap、vwap 这些函数还未支持该规则!" + ) # 计算得到时间序列,每个时间段快要结束的时间点,此时应该从被动价格切换为主动价格 deadline_timestamp_list, strict_deadline_timestamp_list = self._get_deadline_timestamp(interval_list) for i in range(len(volume_list)): diff --git a/tqsdk/backtest/backtest.py b/tqsdk/backtest/backtest.py index d9d0b585..010a7f3f 100644 --- a/tqsdk/backtest/backtest.py +++ b/tqsdk/backtest/backtest.py @@ -607,9 +607,11 @@ async def _gen_serial(self, ins, dur): } } } + is_min_dur = dur == self._quotes[symbol]["min_duration"] yield timestamp, diff, self._get_quotes_from_kline(self._data["quotes"][symbol_list[0]], timestamp, - item) # K线结束时生成quote数据 + item, + is_min_dur) # K线结束时生成quote数据 current_id += 1 finally: # 释放chart资源 @@ -696,15 +698,16 @@ def _get_quotes_from_kline_open(info, timestamp, kline): ] @staticmethod - def _get_quotes_from_kline(info, timestamp, kline): + def _get_quotes_from_kline(info, timestamp, kline, is_min_dur): """ 分为三个包发给下游: 1. 根据 diff 协议,对于用户收到的最终结果没有影响 2. TqSim 撮合交易会按顺序处理收到的包,分别比较 high、low、close 三个价格对应的买卖价 3. TqSim 撮合交易只用到了买卖价,所以最新价只产生一次 close,而不会发送三次 + 4. 最高最低仅用于 TqSim 撮合交易,由最小周期生成 """ - return [ - { + if is_min_dur: + return [{ "datetime": _timestamp_nano_to_str(timestamp), "ask_price1": kline["high"] + info["price_tick"], "ask_volume1": 1, @@ -717,13 +720,25 @@ def _get_quotes_from_kline(info, timestamp, kline): "volume": 0, "amount": float("nan"), "open_interest": kline["close_oi"], - }, - { + }, { "ask_price1": kline["low"] + info["price_tick"], "bid_price1": kline["low"] - info["price_tick"], - }, - { + }, { "ask_price1": kline["close"] + info["price_tick"], "bid_price1": kline["close"] - info["price_tick"], - } - ] + }] + else: + return [{ + "datetime": _timestamp_nano_to_str(timestamp), + "ask_price1": kline["close"] + info["price_tick"], + "ask_volume1": 1, + "bid_price1": kline["close"] - info["price_tick"], + "bid_volume1": 1, + "last_price": kline["close"], + "highest": float("nan"), + "lowest": float("nan"), + "average": float("nan"), + "volume": 0, + "amount": float("nan"), + "open_interest": kline["close_oi"], + }] diff --git a/tqsdk/lib/target_pos_scheduler.py b/tqsdk/lib/target_pos_scheduler.py index ca509d89..9e1d02cd 100644 --- a/tqsdk/lib/target_pos_scheduler.py +++ b/tqsdk/lib/target_pos_scheduler.py @@ -137,9 +137,10 @@ async def _run(self): break elif target_pos_task: # 最后一项,如果有 target_pos_task 等待持仓调整完成,否则直接退出 position = self._account.get_position(self._symbol) - async for _ in self._api.register_update_notify(position): - if position.pos == row['target_pos']: - break + if position.pos != row['target_pos']: + async for _ in self._api.register_update_notify(position): + if position.pos == row['target_pos']: + break _index = _index + 1 finally: if target_pos_task: diff --git a/tqsdk/lib/target_pos_task.py b/tqsdk/lib/target_pos_task.py index ebe4561a..7149bbf8 100644 --- a/tqsdk/lib/target_pos_task.py +++ b/tqsdk/lib/target_pos_task.py @@ -198,20 +198,6 @@ def get_price(direction): # 2021-03-15 11:29:48 - INFO - 时间: 2021-03-15 11:29:47.533515, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 3, 价格: 4687.000,手续费: 14.12 """ - if symbol.startswith("CZCE.ZC"): - raise Exception("动力煤期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 4 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.WH"): - raise Exception("强麦期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.PM"): - raise Exception("普麦期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.RI"): - raise Exception("早籼稻期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.JR"): - raise Exception("粳稻期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol.startswith("CZCE.LR"): - raise Exception("晚籼稻期货不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 10 手,这些函数还未支持该规则!") - if symbol == "CZCE.SA309" or symbol == "CZCE.SA310": - raise Exception("纯碱期货 2309 合约及 2310 合约不支持创建 targetpostask、twap、vwap 任务,交易所规定该品种最小开仓手数为大于等于 4 手,这些函数还未支持该规则!") super(TargetPosTask, self).__init__() self._api = api self._account = api._account._check_valid(account) @@ -345,6 +331,12 @@ async def _target_pos_task(self): all_tasks = [] try: self._quote = await self._api.get_quote(self._symbol) + # 判断最小下单手数是否大于1 + if self._quote.open_min_market_order_volume > 1 or self._quote.open_min_limit_order_volume > 1: + raise Exception( + f"交易所规定 {self._symbol} 最小市价开仓手数 ({self._quote.open_min_market_order_volume})" + f" 或最小限价开仓手数 ({self._quote.open_min_limit_order_volume}) 大于 1,targetpostask、twap、vwap 这些函数还未支持该规则!" + ) async for target_pos in self._pos_chan: # lib 中对于时间判断的方案: # 如果当前时间(模拟交易所时间)不在交易时间段内,则:等待直到行情更新