Skip to content

Commit

Permalink
Update Version 3.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
shinny-pack authored and shinny-mayanqiong committed Jan 18, 2024
1 parent 138c302 commit d58739b
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 24 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.4.11
Version: 3.5.0
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.4.11'
version = u'3.5.0'
# The full version, including alpha/beta/rc tags.
release = u'3.4.11'
release = u'3.5.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
3 changes: 3 additions & 0 deletions doc/usage/mddatas.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ CZCE 郑州商品交易所
CFFEX 中国金融交易所
INE 上海能源中心(原油在这里)
KQ 快期 (所有主连合约, 指数都归属在这里)
KQD 快期外盘主连合约
SSWE 上期所仓单
SSE 上海证券交易所
SZSE 深圳证券交易所
Expand Down Expand Up @@ -52,6 +53,8 @@ GFEX 广州期货交易所
[email protected] - 中金所IF品种主连合约
[email protected] - 上期所bu品种指数

[email protected] - 美黄豆主连

SSWE.CUH - 上期所仓单铜现货数据

SSE.600000 - 上交所浦发银行股票编码
Expand Down
8 changes: 8 additions & 0 deletions doc/version.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

版本变更
=============================
3.5.0 (2024/01/18)

* 新增:行情增加外盘主连合约,通过 ``api.query_quotes(exchange_id=['KQD'])`` 查询外盘合约
* 新增::py:meth:`~tqsdk.TqZq` 众期账户类型,支持连接众期服务器交易
* 优化::py:meth:`~tqsdk.TqApi.query_quotes` 函数 ins_class、exchange_id、product_id 参数支持 list
* 修复:ticks 回测时,可能出现账户结算信息为 nan 的问题


3.4.11 (2024/01/03)

* 优化:支持天勤在不同时区设置的操作系统上使用。tqsdk 内部时间表示全部使用北京时间。
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.4.11",
version="3.5.0",
description='TianQin SDK',
author='TianQin',
author_email='[email protected]',
Expand Down
2 changes: 1 addition & 1 deletion tqsdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
name = "tqsdk"

from tqsdk.api import TqApi
from tqsdk.tradeable import TqAccount, TqKq, TqKqStock, TqSim, TqSimStock
from tqsdk.tradeable import TqAccount, TqZq, TqKq, TqKqStock, TqSim, TqSimStock
from tqsdk.auth import TqAuth
from tqsdk.channel import TqChan
from tqsdk.backtest import TqBacktest, TqReplay
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.4.11'
__version__ = '3.5.0'
26 changes: 16 additions & 10 deletions tqsdk/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
from tqsdk.risk_rule import TqRiskRule
from tqsdk.ins_schema import ins_schema, basic, derivative, future, option
from tqsdk.symbols import TqSymbols
from tqsdk.tradeable import TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, BaseOtg
from tqsdk.tradeable import TqAccount, TqZq, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, BaseOtg
from tqsdk.trading_status import TqTradingStatus
from tqsdk.tqwebhelper import TqWebHelper
from tqsdk.utils import _generate_uuid, _query_for_quote, BlockManagerUnconsolidated, _quotes_add_night, _bisect_value
Expand Down Expand Up @@ -99,7 +99,7 @@ def __init__(self, account: Optional[Union[TqMultiAccount, UnionTradeable]] = No
创建天勤接口实例
Args:
account (None/TqAccount/TqKq/TqKqStock/TqSim/TqSimStock/TqMultiAccount): [可选]交易账号:
account (None/TqAccount/TqKq/TqKqStock/TqSim/TqSimStock/TqZq/TqMultiAccount): [可选]交易账号:
* None: 账号将根据环境变量决定, 默认为 :py:class:`~tqsdk.TqSim`
* :py:class:`~tqsdk.TqAccount` : 使用实盘账号, 直连行情和交易服务器, 需提供期货公司/帐号/密码
Expand All @@ -112,6 +112,8 @@ def __init__(self, account: Optional[Union[TqMultiAccount, UnionTradeable]] = No
* :py:class:`~tqsdk.TqSimStock` : 使用 TqApi 自带的内部股票模拟账号
* :py:class:`~tqsdk.TqZq` : 使用众期账号
* :py:class:`~tqsdk.TqMultiAccount` : 多账户列表,列表中支持 :py:class:`~tqsdk.TqAccount`、:py:class:`~tqsdk.TqKq`、\
:py:class:`~tqsdk.TqKqStock`、:py:class:`~tqsdk.TqSim` 和 :py:class:`~tqsdk.TqSimStock` 中的 0 至 N 个或者组合
Expand Down Expand Up @@ -2317,30 +2319,31 @@ def query_symbol_ranking(self, symbol: str, ranking_type: str, days: int = 1, st
raise TqTimeoutError(f"获取 {symbol}, {ranking_type} 持仓排名信息信息超时,请检查客户端及网络是否正常")
return df

def query_quotes(self, ins_class: str = None, exchange_id: str = None, product_id: str = None, expired: bool = None,
has_night: bool = None) -> SymbolList:
def query_quotes(self, ins_class: Union[str, List[str]] = None, exchange_id: Union[str, List[str]] = None,
product_id: Union[str, List[str]] = None, expired: bool = None, has_night: bool = None) -> SymbolList:
"""
根据相应的参数发送合约服务请求查询,并返回查询结果
Args:
ins_class (str): [可选] 合约类型
ins_class (str / list of str): [可选] 合约类型
* FUTURE: 期货
* CONT: 主连
* COMBINE: 组合
* INDEX: 指数
* OPTION: 期权
* STOCK: 股票
exchange_id (str): [可选] 交易所
exchange_id (str / list of str): [可选] 交易所
* CFFEX: 中金所
* SHFE: 上期所
* DCE: 大商所
* CZCE: 郑商所
* INE: 能源交易所(原油)
* SSE: 上交所
* SZSE: 深交所
* KQD: 外盘主连
product_id (str): [可选] 品种(股票、期权不能通过 product_id 筛选查询)
product_id (str / list of str): [可选] 品种(股票、期权不能通过 product_id 筛选查询)
expired (bool): [可选] 是否已下市
Expand All @@ -2364,6 +2367,9 @@ def query_quotes(self, ins_class: str = None, exchange_id: str = None, product_i
ls = api.query_quotes(ins_class="FUTURE", product_id="au")
print(ls) # au 品种的全部合约,包括已下市以及未下市合约
ls = api.query_quotes(ins_class=["FUTURE"], product_id=["au", "cu"], expired=False)
print(ls) # au、cu 品种的全部未下市合约合约
ls = api.query_quotes(ins_class="INDEX", product_id="au")
print(ls) # au 品种指数合约
Expand Down Expand Up @@ -2392,17 +2398,17 @@ def query_quotes(self, ins_class: str = None, exchange_id: str = None, product_i
if ins_class is not None:
if ins_class == "":
raise Exception("ins_class 参数不能为空字符串。")
variables["class_"] = [ins_class]
variables["class_"] = [ins_class] if isinstance(ins_class, str) else ins_class
if exchange_id is not None:
if exchange_id == "":
raise Exception("exchange_id 参数不能为空字符串。")
# 如果是主连和指数,请求全部,在客户端区分交易所
if ins_class not in ["INDEX", "CONT"] or exchange_id not in ["CFFEX", "SHFE", "DCE", "CZCE", "INE"]:
variables["exchange_id"] = [exchange_id]
variables["exchange_id"] = [exchange_id] if isinstance(exchange_id, str) else exchange_id
if product_id is not None:
if product_id == "":
raise Exception("product_id 参数不能为空字符串。")
variables["product_id"] = [product_id]
variables["product_id"] = [product_id] if isinstance(product_id, str) else product_id
if expired is not None:
variables["expired"] = expired
if has_night is not None:
Expand Down
2 changes: 1 addition & 1 deletion tqsdk/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def _has_account(self, account):
def _has_md_grants(self, symbol):
symbol_list = symbol if isinstance(symbol, list) else [symbol]
for symbol in symbol_list:
if symbol.split('.', 1)[0] in ["SHFE", "DCE", "CZCE", "INE", "CFFEX", "KQ", "SSWE", "GFEX"] and self._has_feature("futr"):
if symbol.split('.', 1)[0] in ["SHFE", "DCE", "CZCE", "INE", "CFFEX", "KQ", "KQD", "SSWE", "GFEX"] and self._has_feature("futr"):
continue
elif symbol.split('.', 1)[0] in ["CSI", "SSE", "SZSE"] and self._has_feature("sec"):
continue
Expand Down
6 changes: 3 additions & 3 deletions tqsdk/multiaccount.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from shinny_structlog import ShinnyLoggerAdapter

from tqsdk.channel import TqChan
from tqsdk.tradeable import TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim
from tqsdk.tradeable import TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, TqZq
from tqsdk.tradeable.mixin import StockMixin


Expand All @@ -27,12 +27,12 @@ class TqMultiAccount(object):
"""

def __init__(self, accounts: Optional[List[Union[TqAccount, TqKq, TqKqStock, TqSim, TqSimStock]]] = None):
def __init__(self, accounts: Optional[List[Union[TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, TqZq]]] = None):
"""
创建 TqMultiAccount 实例
Args:
accounts (List[Union[TqAccount, TqKq, TqKqStock, TqSim, TqSimStock]]): [可选] 多账户列表, 若未指定任何账户, 则为 [TqSim()]
accounts (List[Union[TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, TqZq]]): [可选] 多账户列表, 若未指定任何账户, 则为 [TqSim()]
Example1::
Expand Down
2 changes: 1 addition & 1 deletion tqsdk/tradeable/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@


from tqsdk.tradeable.otg.base_otg import BaseOtg
from tqsdk.tradeable.otg import TqAccount, TqKq, TqKqStock
from tqsdk.tradeable.otg import TqAccount, TqZq, TqKq, TqKqStock
from tqsdk.tradeable.sim.basesim import BaseSim
from tqsdk.tradeable.sim import TqSim, TqSimStock
1 change: 1 addition & 0 deletions tqsdk/tradeable/otg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
__author__ = 'mayanqiong'

from tqsdk.tradeable.otg.tqaccount import TqAccount
from tqsdk.tradeable.otg.tqzq import TqZq
from tqsdk.tradeable.otg.tqkq import TqKq, TqKqStock
36 changes: 36 additions & 0 deletions tqsdk/tradeable/otg/tqzq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!usr/bin/env python3
# -*- coding:utf-8 -*-
__author__ = 'yanqiong'

import hashlib

from tqsdk.tradeable.otg.base_otg import BaseOtg
from tqsdk.tradeable.mixin import FutureMixin


class TqZq(BaseOtg, FutureMixin):
"""众期账户类"""

def __init__(self, account_id: str, password: str, td_url: str) -> None:
"""
创建众期账户实例
Args:
account_id (str): 帐号
password (str): 密码
td_url (str): 众期交易服务器地址, eg: "ws://1.2.3.4:8765/"
Example1::
from tqsdk import TqApi, TqZq
account = TqZq(user_name="众期账户", password="众期密码", td_url="众期柜台地址")
api = TqApi(account, auth=TqAuth("快期账户", "账户密码"))
"""
super(TqZq, self).__init__(broker_id="", account_id=account_id, password=password, td_url=td_url)

def _get_account_key(self):
s = self._account_id + self._td_url
return hashlib.md5(s.encode('utf-8')).hexdigest()
6 changes: 6 additions & 0 deletions tqsdk/tradeable/sim/trade_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ def _match_order(self, order, symbol, position, quote, underlying_quote=None):
if last_msg == "全部成交":
trade = self._generate_trade(order, quote, price)
self._trades.append(trade)
# 用 ticks 回测某些期权合约的时候,position['last_price'] 初始值可能是 nan,
# 当委托单成交时,由于 position['last_price'] 为 nan 会导致后续持仓市值、保证金等计算得到 nan
# 所以这里如果发现价格时 nan,就用当前成交价记为 position['last_price']
# 后续在 update_quotes 时,会更新 position['last_price'],因为 update_quotes 会跳过无效行情,所以这里不会再变为 nan
if math.isnan(position['last_price']):
position['last_price'] = price
self._on_order_traded(order, trade, symbol, position, quote, underlying_quote)
else:
self._on_order_failed(symbol, order)
Expand Down
14 changes: 11 additions & 3 deletions tqsdk/tradeable/sim/trade_future.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,21 @@ def _on_order_failed(self, symbol, order):

def _on_update_quotes(self, symbol, position, quote, underlying_quote):
# 调整持仓保证金和盈亏
underlying_last_price = underlying_quote["last_price"] if underlying_quote else float('nan')
if underlying_quote is None:
underlying_last_price = float("nan")
else:
# 期权,underlying_last_price 用于计算期权保证金,必须不是 nan,这里依次选取以下价格中第一个不为 nan 的
# 标的合约最新价,前一次持仓中记录的不为 nan 的标的最新价,期权行权价
if math.isnan(underlying_quote["last_price"]):
underlying_last_price = quote["strike_price"] if math.isnan(position["underlying_last_price"]) \
else position["underlying_last_price"]
else:
underlying_last_price = underlying_quote["last_price"]
future_margin = _get_future_margin(quote)
if position["volume_long"] > 0 or position["volume_short"] > 0:
if position["last_price"] != quote["last_price"] \
or (math.isnan(future_margin) or future_margin != position["future_margin"]) \
or (underlying_quote and (
math.isnan(underlying_last_price) or underlying_last_price != position["underlying_last_price"])):
or (underlying_quote and underlying_last_price != position["underlying_last_price"]):
self._adjust_position_account(symbol, quote, underlying_quote,
pre_last_price=position["last_price"],
last_price=quote["last_price"],
Expand Down

0 comments on commit d58739b

Please sign in to comment.