Skip to content

Commit

Permalink
Update Version 3.7.8
Browse files Browse the repository at this point in the history
  • Loading branch information
shinny-hongyan authored and shinny-chenli committed Feb 2, 2025
1 parent 1adf688 commit 99411cd
Show file tree
Hide file tree
Showing 22 changed files with 103 additions and 133 deletions.
2 changes: 1 addition & 1 deletion PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: tqsdk
Version: 3.7.6
Version: 3.7.8
Summary: TianQin SDK
Home-page: https://www.shinnytech.com/tqsdk
Author: TianQin
Expand Down
1 change: 0 additions & 1 deletion doc/advanced/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,3 @@
unanttended.rst
targetpostask2.rst
scheduler.rst
tqsdk2ctptest.rst
6 changes: 3 additions & 3 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@

# General information about the project.
project = u'TianQin Python SDK'
copyright = u'2018-2024, TianQin'
copyright = u'2018-2025, TianQin'
author = u'TianQin'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'3.7.6'
version = u'3.7.8'
# The full version, including alpha/beta/rc tags.
release = u'3.7.6'
release = u'3.7.8'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
1 change: 1 addition & 0 deletions doc/profession.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ TqSdk 中大部分功能是供用户免费使用的, 同时我们也提供了专

.. figure:: images/how-grafana04.gif


`快期专业版官网地址 <https://www.shinnytech.com/qpro>`_

`快期专业版文档地址 <https://publish2.shinnytech.com/doc/qpro/latest/quickstart.html>`_
Expand Down
6 changes: 0 additions & 6 deletions doc/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,6 @@ klines是一个pandas.DataFrame对象. 跟 api.get_quote() 一样, api.get_kline

这部分的完整示例程序请见 :ref:`tutorial-t30` .

我们也可以通过传入一个合约列表作为参数,来获取包含多个合约数据的K线::

klines = api.get_kline_serial(["SHFE.au1912", "SHFE.au2006"], 5) # 获取SHFE.au2006向SHFE.au1912对齐的K线

详细使用方法及说明请见 :py:meth:`~tqsdk.TqApi.get_kline_serial` 函数说明。

到这里为止, 你已经知道了如何获取实时行情和K线数据, 下面一段将介绍如何访问你的交易账户并发送交易指令

.. _quickstart_2_web_gui:
Expand Down
6 changes: 2 additions & 4 deletions doc/usage/backtest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

策略程序回测
=================================================
策略程序回测是 TqSdk 专业版中的功能,能让用户在不改变代码的情况下去回测自己的策略在历史行情的表现
策略程序回测能让用户在不改变代码的情况下去回测自己的策略在历史行情的表现

如果想使用策略回测该功能,可以点击 `天勤量化专业版 <https://www.shinnytech.com/tqsdk-buy/>`_ 申请使用或购买

用户也可以申请模拟账户后模拟运行来检验策略 :ref:`sim_trading`
用户也可以使用快期模拟账户来模拟运行来检验策略 :ref:`sim_trading`

执行策略回测
-------------------------------------------------
Expand Down
6 changes: 1 addition & 5 deletions doc/usage/option_trade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

期权交易 & 交易所官方组合
====================================================
TqSdk 中期权交易(商品期权、金融期权和 ETF 期权)和交易所官方组合交易,均是 TqSdk 专业版中的功能

用户如果想在 TqSdk 中进行上述操作,可以点击 `天勤量化专业版 <https://www.shinnytech.com/tqsdk-buy/>`_ 申请使用或购买

TqSdk 中期权合和交易所官方组合的约代码格式参考如下::

DCE.m1807-C-2450 - 大商所豆粕期权
Expand All @@ -20,7 +16,7 @@ TqSdk 中期权合和交易所官方组合的约代码格式参考如下::



对于交易所官方组合,目前 TqSdk 中只支持交易所官方组合进行实盘交易
对于交易所官方组合,目前 TqSdk 中只支持交易所官方组合进行实盘交易,不支持在模拟中进行交易所官方组合交易


期权指标计算&序列计算函数
Expand Down
2 changes: 1 addition & 1 deletion doc/usage/shinny_account.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
-------------------------------------------------
对于 TqSdk 免费版,每个快期账户支持最多绑定一个实盘账户,而天勤量化专业版支持一个快期账户绑定任意多个实盘账户

快期账户会在用户使用实盘账户时自动进行绑定,直到该快期账户没有能绑定实盘账户的名额(自动绑定功能需要 TqSdk 版本> 1.8.3)::
快期账户会在用户使用实盘账户时自动进行绑定,直到该快期账户没有能绑定实盘账户的名额::

from tqsdk import TqApi, TqAccount, TqAuth, TqKq
api = TqApi(TqAccount("H海通期货", "320102", "123456"), auth=TqAuth("快期账户", "账户密码"))
Expand Down
2 changes: 0 additions & 2 deletions doc/usage/targetpostask.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,3 @@



:py:class:`~tqsdk.InsertOrderUntilAllTradedTask` 是追价下单task, 该task会在行情变化后自动撤单重下,直到全部成交.

12 changes: 12 additions & 0 deletions doc/version.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

版本变更
=============================
3.7.8 (2025/01/23)

* docs: 修正部分文档
* 修复: 因郑商所三位合约导致合约信息中部分字段错误的问题


3.7.7 (2025/01/14)

* docs: 修正部分文档,补充 wait_update 的 deadline 参数说明
* 自该版本起不再支持使用 api._data['quotes'] 获取全部合约


3.7.6 (2024/11/14)

* 修复: 增加依赖库 packaging
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setuptools.setup(
name='tqsdk',
version="3.7.6",
version="3.7.8",
description='TianQin SDK',
author='TianQin',
author_email='tianqincn@gmail.com',
Expand Down
2 changes: 1 addition & 1 deletion tqsdk/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '3.7.6'
__version__ = '3.7.8'
41 changes: 20 additions & 21 deletions tqsdk/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
from tqsdk.entity import Entity
from tqsdk.exceptions import TqTimeoutError
from tqsdk.log import _clear_logs, _get_log_name, _get_disk_free
from tqsdk.objs import Quote, TradingStatus, Kline, Tick, Account, Position, Order, Trade, QuotesEntity, RiskManagementRule, RiskManagementData
from tqsdk.objs import Quote, TradingStatus, Kline, Tick, Account, Position, Order, Trade, RiskManagementRule, RiskManagementData
from tqsdk.objs import SecurityAccount, SecurityOrder, SecurityTrade, SecurityPosition
from tqsdk.objs_not_entity import QuoteList, TqDataFrame, TqSymbolDataFrame, SymbolList, SymbolLevelList, \
TqSymbolRankingDataFrame, TqOptionGreeksDataFrame, TqMdSettlementDataFrame
Expand Down Expand Up @@ -276,8 +276,6 @@ def __init__(self, account: Optional[Union[TqMultiAccount, UnionTradeable]] = No
self._klines_update_range = {}
self._data = Entity() # 数据存储
self._data._instance_entity([])
self._data["quotes"] = QuotesEntity(self)
self._data["quotes"]._instance_entity(["quotes"])
self._diffs = [] # 自上次wait_update返回后收到更新数据的数组 (异步代码)
self._sync_diffs = [] # 自上次wait_update返回后收到更新数据的数组 (同步代码)
self._pending_diffs = [] # 从网络上收到的待处理的 diffs, 只在 wait_update 函数执行过程中才可能为非空
Expand All @@ -287,6 +285,7 @@ def __init__(self, account: Optional[Union[TqMultiAccount, UnionTradeable]] = No
self._dividend_cache = {} # 缓存合约对应的复权系数矩阵,每个合约只计算一次
self._send_chan, self._recv_chan = TqChan(self), TqChan(self) # 消息收发队列
self._ws_md_recv_chan = None # 记录 ws_md_recv_chan 引用
self._pre20_ins_info = {} # 20年9月份之前的合约信息

# slave模式的api不需要完整初始化流程
self._is_slave = isinstance(account, TqApi)
Expand Down Expand Up @@ -542,19 +541,20 @@ async def _ensure_symbol_async(self, symbol: Union[str, List[str]]):
if self._stock is False:
raise Exception("代码 %s 不存在, 请检查合约代码是否填写正确" % symbol_list)
else:
query_pack = _query_for_quote(symbol_list)
self._send_pack(query_pack)
for query in _query_for_quote(symbol_list, self._pre20_ins_info.keys()):
self._send_pack(query)
async with self.register_update_notify() as update_chan:
async for _ in update_chan:
# 这里用 price_tick 判断是否已经收到了合约信息,是为了兼容 2020年9月份之前上市的合约
# 合约服务没有提供这些合约,tqsdk 是通过预先加载本地缓存文件的方式提供这些合约的信息
# 理想的判断标准是 basktest 模块中的 _ensure_query 函数
if all([self._data.get("quotes", {}).get(symbol, {}).get('price_tick', float('nan')) > 0 for symbol in symbol_list]):
break

# ----------------------------------------------------------------------
def get_trading_status(self, symbol: str) -> TradingStatus:
"""
获取指定合约的交易状态. 此接口为 TqSdk 专业版提供,便于实现开盘抢单功能。
如果想使用此功能,可以点击 `天勤量化专业版 <https://www.shinnytech.com/tqsdk-buy/>`_ 申请试用或购买
获取指定合约的交易状态,便于实现开盘抢单功能。
Args:
symbol (str): 合约代码
Expand Down Expand Up @@ -1012,7 +1012,7 @@ def _get_data_series(self, call_func: str, symbol_list: Union[str, List[str]], d
# ----------------------------------------------------------------------
def get_trading_calendar(self, start_dt: Union[date, datetime], end_dt: Union[date, datetime]) -> pd.DataFrame:
"""
获取一段时间内的交易日历信息,交易日历可以处理的范围为 2003-01-01 ~ 2024-12-31。
获取一段时间内的交易日历信息,每年的交易日历将在交易所新一年的节假日安排后更新
Args:
start_dt (date/datetime): 起始时间
Expand Down Expand Up @@ -1068,7 +1068,7 @@ def get_trading_calendar(self, start_dt: Union[date, datetime], end_dt: Union[da
# ----------------------------------------------------------------------
def query_his_cont_quotes(self, symbol: Union[str, List[str]], n: int = 200) -> pd.DataFrame:
"""
获取指定的主连合约最近 n 天的标的,可以处理的范围为 2003-01-01 ~ 2022-12-31
获取指定的主连合约最近 n 天的标的。
Args:
symbol (str/list of str): 指定主连合约代码或主连合约代码列表.
Expand Down Expand Up @@ -1126,9 +1126,7 @@ def query_his_cont_quotes(self, symbol: Union[str, List[str]], n: int = 200) ->
# ----------------------------------------------------------------------
def add_risk_rule(self, rule: TqRiskRule) -> None:
"""
添加一项风控规则实例,此接口为 TqSdk 专业版提供。
如需使用此功能,可以点击 `天勤量化专业版 <https://www.shinnytech.com/tqsdk-buy/>`_ 申请试用或购买
添加一项风控规则实例。
Args:
rule (TqRiskRule): 风控规则实例,必须是 TqRiskRule 的子类型
Expand All @@ -1142,9 +1140,7 @@ def add_risk_rule(self, rule: TqRiskRule) -> None:

def delete_risk_rule(self, rule: TqRiskRule) -> None:
"""
删除一项风控规则实例,此接口为 TqSdk 专业版提供。
如需使用此功能,可以点击 `天勤量化专业版 <https://www.shinnytech.com/tqsdk-buy/>`_ 申请试用或购买
删除一项风控规则实例。
Args:
rule (TqRiskRule): 风控规则实例,必须是 TqRiskRule 的子类型
Expand Down Expand Up @@ -1884,7 +1880,7 @@ def wait_update(self, deadline: Optional[float] = None, _task: Union[asyncio.Tas
* 如果没有收到数据包,则挂起等待.
Args:
deadline (float): [可选]指定截止时间,自unix epoch(1970-01-01 00:00:00 GMT)以来的秒数(time.time())。默认没有超时(无限等待)
deadline (float): [可选]指定截止时间,自unix epoch(1970-01-01 00:00:00 GMT)以来的秒数(time.time())。默认没有超时(无限等待), 当 wait_update 有数据更新或者任务执行时会返回为 True,否则会陷入阻塞,使用 deadline 参数会让 wait_update 函数在当前时间大于 deadline 参数后返回 False ,避免长时间阻塞。非简单用法,如果设置的 deadline 过小,而计算任务过多,可能会导致处理任务堆积,引发潜在问题。
Returns:
bool: 如果收到业务数据更新则返回 True, 如果到截止时间依然没有收到业务数据更新则返回 False
Expand Down Expand Up @@ -3348,10 +3344,13 @@ def _setup_connection(self):
if quote["ins_class"] == "FUTURE_OPTION":
quote["exercise_year"] = _timestamp_nano_to_datetime(int(quote["expire_datetime"] * 1000000) * 1000).year
quote["exercise_month"] = _timestamp_nano_to_datetime(int(quote["expire_datetime"] * 1000000) * 1000).month
ws_md_recv_chan.send_nowait({
"aid": "rtn_data",
"data": [{"quotes": quotes}]
}) # 获取合约信息
if self._stock is False:
ws_md_recv_chan.send_nowait({
"aid": "rtn_data",
"data": [{"quotes": quotes}]
}) # 获取合约信息
else:
self._pre20_ins_info = quotes

self._ws_md_recv_chan = ws_md_recv_chan # 记录 ws_md_recv_chan 引用

Expand Down
22 changes: 14 additions & 8 deletions tqsdk/backtest/backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ async def _run(self, api, sim_send_chan, sim_recv_chan, md_send_chan, md_recv_ch
self._diffs.append({
"ins_list": pack["ins_list"]
})
await self._ensure_symbols(pack["ins_list"].split(","))
for ins in pack["ins_list"].split(","):
await self._ensure_quote(ins)
await self._send_diff() # 处理上一次未处理的 peek_message
Expand Down Expand Up @@ -451,16 +452,21 @@ async def _ensure_query(self, pack):
while not query_pack.items() <= self._data.get("symbols", {}).get(pack["query_id"], {}).items():
await update_chan.recv()

async def _ensure_quote(self, symbol):
async def _ensure_symbols(self, symbols):
# 在接新版合约服务器后,合约信息程序运行过程中查询得到的,这里不再能保证合约一定存在,需要添加 quote 默认值
quote = _get_obj(self._data, ["quotes", symbol], BtQuote(self._api))
if math.isnan(quote.get("price_tick")):
query_pack = _query_for_quote(symbol)
quotes = [_get_obj(self._data, ["quotes", symbol], BtQuote(self._api)) for symbol in symbols]
quotes = [q for q in quotes if math.isnan(q.get("price_tick"))]
if not quotes:
return
for query_pack in _query_for_quote([q._path[-1] for q in quotes], self._api._pre20_ins_info.keys()):
await self._md_send_chan.send(query_pack)
async with TqChan(self._api, last_only=True) as update_chan:
quote["_listener"].add(update_chan)
while math.isnan(quote.get("price_tick")):
await update_chan.recv()
async with TqChan(self._api, last_only=True) as update_chan:
for q in quotes:
q["_listener"].add(update_chan)
while any([math.isnan(q.get("price_tick")) for q in quotes]):
await update_chan.recv()

async def _ensure_quote(self, symbol):
if symbol not in self._quotes or self._quotes[symbol]["min_duration"] > 60000000000:
await self._ensure_serial(symbol, 60000000000)

Expand Down
30 changes: 1 addition & 29 deletions tqsdk/objs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,10 @@

import copy
import json
import warnings
from typing import List

from tqsdk.diff import _get_obj
from tqsdk.entity import Entity
from tqsdk.utils import _query_for_init, _generate_uuid


class QuotesEntity(Entity):

def __init__(self, api):
self._api = api
self._not_send_init_query = True

def __iter__(self):
message = """
不推荐使用 api._data['quotes'] 获取全部合约,该使用方法会在 20201101 之后的版本中放弃维护。
需要注意:
* 在同步代码中,初次使用 api._data['quotes'] 获取全部合约会产生一个耗时很长的查询。
* 在协程中,api._data['quotes'] 这种用法不支持使用。
请尽快修改使用新的接口,参考链接 http://doc.shinnytech.com/tqsdk/reference/tqsdk.api.html#tqsdk.api.TqApi.query_quotes
"""
warnings.warn(message, DeprecationWarning, stacklevel=3)
self._api._logger.warning("deprecation", content="Deprecation Warning in api._data['quotes']")

# 兼容旧版 tqsdk 所做的修改,来支持用户使用 for k,v in api._data.quotes.items() 类似的用法
# 从 api._init_() 最后 3 行移到这里
if self._not_send_init_query and self._api._stock:
self._not_send_init_query = False
q = _query_for_init()
self._api.query_graphql(q, {}, _generate_uuid("PYSDK_quote"))
return super().__iter__()


class Quote(Entity):
Expand Down Expand Up @@ -143,7 +115,7 @@ def __init__(self, api):
self.strike_price: float = float("nan")
#: 合约类型
self.ins_class: str = ""
#: 交易所内的合约代码
#: 合约代码,包含了交易所代码
self.instrument_id: str = ""
#: 合约中文名
self.instrument_name: str = ""
Expand Down
18 changes: 2 additions & 16 deletions tqsdk/objs_not_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from tqsdk.ins_schema import ins_schema, _add_all_frags
from tqsdk.objs import Quote
from tqsdk.diff import _get_obj
from tqsdk.utils import _query_for_quote, _generate_uuid
from tqsdk.utils import _generate_uuid
from tqsdk.tafunc import _get_t_series, get_impv, _get_d1, get_delta, get_theta, get_gamma, get_vega, get_rho

"""
Expand Down Expand Up @@ -54,22 +54,8 @@ def __init__(self, api, quotes):
if not hasattr(quote, '_task'):
quote._task = api.create_task(ensure_quote_with_underlying(api, quote), _caller_api=True)

async def _ensure_symbols(self):
if all([q.price_tick > 0 for q in self]):
return
query_symbols = [q._path[-1] for q in self if not q.price_tick > 0]
query_pack = _query_for_quote(query_symbols)
self._api._send_pack(query_pack)
async with self._api.register_update_notify(self) as update_chan:
async for _ in update_chan:
# 这里用 price_tick 判断是否已经收到了合约信息,是为了兼容 2020年9月份之前上市的合约
# 合约服务没有提供这些合约,tqsdk 是通过预先加载本地缓存文件的方式提供这些合约的信息
# 理想的判断标准是 basktest 模块中的 _ensure_query 函数
if all([q.price_tick > 0 for q in self]):
return

async def _ensure_quotes(self):
await self._ensure_symbols()
await self._api._ensure_symbol_async([q._path[-1] for q in self])
self._api._auth._has_md_grants([q._path[-1] for q in self]) # 权限检查
# 发送的请求会请求到所有字段,如果是期权也会请求标的的合约信息
underlying_symbols = set([q.underlying_symbol for q in self if q.underlying_symbol])
Expand Down
Loading

0 comments on commit 99411cd

Please sign in to comment.