Skip to content

Commit

Permalink
Update Version 3.5.9
Browse files Browse the repository at this point in the history
  • Loading branch information
shinny-pack authored and shinny-mayanqiong committed May 9, 2024
1 parent ded2cec commit 1734bd5
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 102 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.5.8
Version: 3.5.9
Summary: TianQin SDK
Home-page: https://www.shinnytech.com/tqsdk
Author: TianQin
Expand Down
4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
version = u'3.5.8'
version = u'3.5.9'
# The full version, including alpha/beta/rc tags.
release = u'3.5.8'
release = u'3.5.9'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
6 changes: 6 additions & 0 deletions doc/version.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

版本变更
=============================
3.5.9 (2024/05/09)

* 增加::py:meth:`~tqsdk.TqApi.query_all_level_finance_options` 增加中金所股指期权标的
* 优化::py:meth:`~tqsdk.TqApi.get_kline_data_series`、:py:meth:`~tqsdk.TqApi.get_tick_data_series` 接口在请求没有任何成交数据的合约时能够及时退出,避免等待超时


3.5.8 (2024/04/29)

* 增加::py:class:`~tqsdk.tools.DataDownloader` 增加 write_mode 参数,作为写入模式参数,并且在模式为 'a' 时,不写入标题行
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.5.8",
version="3.5.9",
description='TianQin SDK',
author='TianQin',
author_email='[email protected]',
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.5.8'
__version__ = '3.5.9'
7 changes: 5 additions & 2 deletions tqsdk/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2928,7 +2928,9 @@ def query_all_level_finance_options(self, underlying_symbol, underlying_price, o
Args:
underlying_symbol (str): [必填] 标的合约 (针对 ETF 期权和股指期权,只支持以下几个合约)
* "SSE.000300" 为中金所股指期权标的
* "SSE.000300" 为中金所沪深 300 股指期权(IO)标的
* "SSE.000852" 为中金所中证 1000 股指期权(MO)标的
* "SSE.000016" 为中金所上证 50 股指期权(HO)标的
* "SSE.510050" 为上交所华夏上证 50 ETF 期权标的
* "SSE.510300" 为上交所华泰柏瑞沪深 300 ETF 期权标的
* "SZSE.159919" 为深交所嘉实沪深 300 ETF 期权标的
Expand Down Expand Up @@ -2991,7 +2993,8 @@ def query_all_level_finance_options(self, underlying_symbol, underlying_price, o
"""
if self._stock is False:
raise Exception("期货行情系统(_stock = False)不支持当前接口调用")
if underlying_symbol not in ["SSE.000300", "SSE.510050", "SSE.510300", "SZSE.159919", "SZSE.159915", "SZSE.159922", "SSE.510500"]:
if underlying_symbol not in ["SSE.000300", "SSE.510050", "SSE.510300", "SZSE.159919", "SZSE.159915", "SZSE.159922", "SSE.510500",
"SSE.000016", "SSE.000852"]:
raise Exception("不支持的标的合约")
if option_class not in ['CALL', 'PUT']:
raise Exception("option_class 参数错误,option_class 必须是 'CALL' 或者 'PUT'")
Expand Down
60 changes: 7 additions & 53 deletions tqsdk/data_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
from tqsdk.channel import TqChan
from tqsdk.diff import _get_obj
from tqsdk.rangeset import _rangeset_difference, _rangeset_intersection
from tqsdk.tafunc import get_dividend_df
from tqsdk.utils import _generate_uuid
from tqsdk.utils import _generate_uuid, _get_dividend_factor

CACHE_DIR = os.path.join(os.path.expanduser('~'), ".tqsdk/data_series_1")

Expand Down Expand Up @@ -144,7 +143,8 @@ async def _run(self):
# 复权, 如果存在 STOCK / FUND 并且 adj_type is not None, 这里需要提前准备下载时间段内的复权因子
quote = self._api.get_quote(symbol)
if self._adj_type and quote.ins_class in ["STOCK", "FUND"]:
factor_df = await self._update_dividend_factor(symbol) # 复权需要根据日线计算除权因子,todo: 如果本地下载过日线,不需要再从服务器获取日线数据
factor_df = await _get_dividend_factor(self._api, quote, self._start_dt_nano, self._end_dt_nano,
chart_id_prefix="PYSDK_data_factor") # 复权需要根据日线计算除权因子,todo: 如果本地下载过日线,不需要再从服务器获取日线数据
if self._adj_type == "F":
# 倒序循环 factor_df, 对于小于当前 factor_df[datetime] 的行 乘以 factor_df[factor]
for i in range(factor_df.shape[0] - 1, -1, -1):
Expand Down Expand Up @@ -212,13 +212,12 @@ async def _download_data(self, start_dt, end_dt, data_chan):
async for _ in update_chan:
if not (chart_info.items() <= _get_obj(chart, ["state"]).items()):
continue # 当前请求还没收齐回应, 不应继续处理
if chart.get("ready", False) is False:
continue # 数据还没全部收到
if serial.get("last_id", -1) == -1:
return # 合约没有任何数据
left_id = chart.get("left_id", -1)
right_id = chart.get("right_id", -1)
if (left_id == -1 and right_id == -1) or self._api._data.get("mdhis_more_data", True):
continue # 定位信息还没收到, 或数据序列还没收到
# 检查合约的数据是否收到
if serial.get("last_id", -1) == -1:
continue
if current_id is None:
current_id = max(left_id, 0)
while current_id <= right_id:
Expand All @@ -245,51 +244,6 @@ async def _download_data(self, start_dt, end_dt, data_chan):
"view_width": 2000,
})

async def _update_dividend_factor(self, symbol):
quote = self._api.get_quote(symbol)
df = get_dividend_df(quote.stock_dividend_ratio, quote.cash_dividend_ratio)
between = df["datetime"].between(self._start_dt_nano, self._end_dt_nano) # 只需要开始时间~结束时间之间的复权因子
df["pre_close"] = float('nan')
for i in df[between].index:
chart_info = {
"aid": "set_chart",
"chart_id": _generate_uuid("PYSDK_data_factor"),
"ins_list": symbol,
"duration": 86400 * 1000000000,
"view_width": 2,
"focus_datetime": int(df.iloc[i].datetime),
"focus_position": 1
}
await self._api._send_chan.send(chart_info)
chart = _get_obj(self._api._data, ["charts", chart_info["chart_id"]])
serial = _get_obj(self._api._data, ["klines", symbol, str(86400000000000)])
try:
async with self._api.register_update_notify() as update_chan:
async for _ in update_chan:
if not (chart_info.items() <= _get_obj(chart, ["state"]).items()):
continue # 当前请求还没收齐回应, 不应继续处理
left_id = chart.get("left_id", -1)
right_id = chart.get("right_id", -1)
if (left_id == -1 and right_id == -1) or self._api._data.get("mdhis_more_data",
True) or serial.get("last_id",
-1) == -1:
continue # 定位信息还没收到, 或数据序列还没收到, 合约的数据是否收到
last_item = serial["data"].get(str(left_id), {})
# 复权时间点的昨收盘
df.loc[i, 'pre_close'] = last_item['close'] if last_item.get('close') else float('nan')
break
finally:
await self._api._send_chan.send({
"aid": "set_chart",
"chart_id": chart_info["chart_id"],
"ins_list": "",
"duration": 86400000000000,
"view_width": 2
})
df["factor"] = (df["pre_close"] - df["cash_dividend"]) / df["pre_close"] / (1 + df["stock_dividend"])
df["factor"].fillna(1, inplace=True)
return df

def _merge_rangeset(self):
symbol = self._symbol_list[0]
rangeset = DataSeries._get_rangeset_id(symbol, self._dur_nano)
Expand Down
44 changes: 2 additions & 42 deletions tqsdk/tools/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
from tqsdk.api import TqApi
from tqsdk.datetime import _cst_tz, _convert_user_input_to_nano
from tqsdk.diff import _get_obj
from tqsdk.tafunc import get_dividend_df
from tqsdk.utils import _generate_uuid
from tqsdk.utils import _generate_uuid, _get_dividend_factor

try:
file_path = os.path.split(os.path.abspath(__file__))[0]
Expand Down Expand Up @@ -188,46 +187,7 @@ def _get_data_series(self) -> Optional[pandas.DataFrame]:

async def _ensure_dividend_factor(self, quote, timestamp):
if quote.instrument_id not in self._dividend_cache:
# 对每个除权除息矩阵增加 factor 序列,为当日的复权因子
df = get_dividend_df(quote.stock_dividend_ratio, quote.cash_dividend_ratio)
df = df[df["datetime"].between(timestamp, self._end_dt_nano, inclusive="right")] # 只需要第一笔行情时间~结束时间之间的复权因子, 左开右闭
df["pre_close"] = float('nan') # 初始化 pre_close 为 nan
for i in range(len(df)):
chart_info = {
"aid": "set_chart",
"chart_id": _generate_uuid("PYSDK_downloader"),
"ins_list": quote.instrument_id,
"duration": 86400 * 1000000000,
"view_width": 2,
"focus_datetime": int(df["datetime"].iloc[i]),
"focus_position": 1
}
await self._api._send_chan.send(chart_info)
chart = _get_obj(self._api._data, ["charts", chart_info["chart_id"]])
serial = _get_obj(self._api._data, ["klines", quote.instrument_id, str(86400000000000)])
try:
async with self._api.register_update_notify() as update_chan:
async for _ in update_chan:
if not (chart_info.items() <= _get_obj(chart, ["state"]).items()):
continue # 当前请求还没收齐回应, 不应继续处理
if chart.get("ready", False) is False:
continue # 合约的数据是否收到
left_id = chart.get("left_id", -1)
assert left_id != -1 # 需要下载除权除息日的前一天行情,即这一天一定是有行情的,left_id 一定不是 -1
last_item = serial["data"].get(str(left_id), {})
# 复权时间点的昨收盘
df.loc[i, 'pre_close'] = last_item['close'] if last_item.get('close') else float('nan')
break
finally:
await self._api._send_chan.send({
"aid": "set_chart",
"chart_id": chart_info["chart_id"],
"ins_list": "",
"duration": 86400000000000,
"view_width": 2
})
df["factor"] = (df["pre_close"] - df["cash_dividend"]) / df["pre_close"] / (1 + df["stock_dividend"])
df["factor"].fillna(1.0, inplace=True)
df = await _get_dividend_factor(self._api, quote, timestamp, self._end_dt_nano, chart_id_prefix="PYSDK_downloader")
# 插入结束时间这条记录, 因为可能存在行情时间等于 _end_dt_nano 的行情,因此这里 +1
df = df.append({"datetime": self._end_dt_nano+1, "factor": 1.0}, ignore_index=True)
if self._adj_type == "F":
Expand Down
47 changes: 47 additions & 0 deletions tqsdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
from sgqlc.operation import Operation
from pandas.core.internals import BlockManager

from tqsdk.diff import _get_obj
from tqsdk.ins_schema import ins_schema, _add_all_frags
from tqsdk.tafunc import get_dividend_df

RD = random.Random(secrets.randbits(128)) # 初始化随机数引擎,使用随机数作为seed,防止用户同时拉起多个策略,产生同样的 seed

Expand Down Expand Up @@ -150,3 +152,48 @@ def __init__(self, *args, **kwargs):
self._known_consolidated = False

def _consolidate_inplace(self): pass


async def _get_dividend_factor(api, quote, start_dt_nano, end_dt_nano, chart_id_prefix="PYSDK_dividend_factor"):
# 对每个除权除息矩阵增加 factor 序列,为当日的复权因子
df = get_dividend_df(quote.stock_dividend_ratio, quote.cash_dividend_ratio)
df = df[df["datetime"].between(start_dt_nano, end_dt_nano, inclusive="right")] # 只需要一段时间之间的复权因子, 左开右闭
df["pre_close"] = float('nan') # 初始化 pre_close 为 nan
for i in range(len(df)):
chart_info = {
"aid": "set_chart",
"chart_id": _generate_uuid(chart_id_prefix),
"ins_list": quote.instrument_id,
"duration": 86400 * 1000000000,
"view_width": 2,
"focus_datetime": int(df["datetime"].iloc[i]),
"focus_position": 1
}
await api._send_chan.send(chart_info)
chart = _get_obj(api._data, ["charts", chart_info["chart_id"]])
serial = _get_obj(api._data, ["klines", quote.instrument_id, str(86400000000000)])
try:
async with api.register_update_notify() as update_chan:
async for _ in update_chan:
if not (chart_info.items() <= _get_obj(chart, ["state"]).items()):
continue # 当前请求还没收齐回应, 不应继续处理
if chart.get("ready", False) is False:
continue # 合约的数据是否收到
left_id = chart.get("left_id", -1)
assert left_id != -1 # 需要下载除权除息日的前一天行情,即这一天一定是有行情的,left_id 一定不是 -1
last_item = serial["data"].get(str(left_id), {})
# 复权时间点的昨收盘
df.loc[i, 'pre_close'] = last_item['close'] if last_item.get('close') else float('nan')
break
finally:
await api._send_chan.send({
"aid": "set_chart",
"chart_id": chart_info["chart_id"],
"ins_list": "",
"duration": 86400000000000,
"view_width": 2
})
df["factor"] = (df["pre_close"] - df["cash_dividend"]) / df["pre_close"] / (1 + df["stock_dividend"])
df["factor"].fillna(1.0, inplace=True)
return df

0 comments on commit 1734bd5

Please sign in to comment.