From a24d8842a769a20c0e998c2b3045b531a960d40d Mon Sep 17 00:00:00 2001 From: shinny-hongyan Date: Thu, 12 Sep 2024 10:35:00 +0000 Subject: [PATCH] Update Version 3.7.2 --- PKG-INFO | 2 +- doc/conf.py | 4 +- doc/reference/index.rst | 1 + doc/reference/tqsdk.tqrohon.rst | 7 +++ doc/version.rst | 6 +++ setup.py | 4 +- tqsdk/__init__.py | 2 +- tqsdk/__version__.py | 2 +- tqsdk/api.py | 8 ++-- tqsdk/connect.py | 2 +- tqsdk/multiaccount.py | 6 +-- tqsdk/tradeable/__init__.py | 2 +- tqsdk/tradeable/otg/__init__.py | 1 + tqsdk/tradeable/otg/tqctp.py | 4 ++ tqsdk/tradeable/otg/tqrohon.py | 75 +++++++++++++++++++++++++++++++++ tqsdk/zq_otg.py | 15 ++++--- 16 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 doc/reference/tqsdk.tqrohon.rst create mode 100644 tqsdk/tradeable/otg/tqrohon.py diff --git a/PKG-INFO b/PKG-INFO index 20ceaff9..d6bbe9bb 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: tqsdk -Version: 3.7.1 +Version: 3.7.2 Summary: TianQin SDK Home-page: https://www.shinnytech.com/tqsdk Author: TianQin diff --git a/doc/conf.py b/doc/conf.py index cfa43c73..810411a4 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -48,9 +48,9 @@ # built documents. # # The short X.Y version. -version = u'3.7.1' +version = u'3.7.2' # The full version, including alpha/beta/rc tags. -release = u'3.7.1' +release = u'3.7.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/reference/index.rst b/doc/reference/index.rst index e7297b1f..7b58e835 100644 --- a/doc/reference/index.rst +++ b/doc/reference/index.rst @@ -12,6 +12,7 @@ TqSdk 模块参考 tqsdk.tqkq.rst tqsdk.tqzq.rst tqsdk.tqctp.rst + tqsdk.tqrohon.rst tqsdk.sim.rst tqsdk.multiaccount.rst tqsdk.objs.rst diff --git a/doc/reference/tqsdk.tqrohon.rst b/doc/reference/tqsdk.tqrohon.rst new file mode 100644 index 00000000..3d1b3a09 --- /dev/null +++ b/doc/reference/tqsdk.tqrohon.rst @@ -0,0 +1,7 @@ +.. _tqsdk.tqrohon: + +tqsdk.TqRohon - 融航资管交易类 +------------------------------------------------------------------ +.. autoclass:: tqsdk.TqRohon + :members: + :inherited-members: diff --git a/doc/version.rst b/doc/version.rst index 2265dca4..9e573f5f 100644 --- a/doc/version.rst +++ b/doc/version.rst @@ -2,6 +2,12 @@ 版本变更 ============================= +3.7.2 (2024/09/12) + +* 新增::py:class:`~tqsdk.TqRohon` 账户类型,支持融航资管柜台 +* BREAKING:从安装依赖中移除 tqsdk_zq_otg 模块,用户使用多柜台需要手动安装依赖包:``pip install -U tqsdk_zq_otg`` + + 3.7.1 (2024/08/29) * 修复:在 Windows 系统上使用 :py:class:`~tqsdk.TqCtp` 账户导致多 TqApi 实例无法运行的问题 diff --git a/setup.py b/setup.py index 45f7732a..570a32ab 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name='tqsdk', - version="3.7.1", + version="3.7.2", description='TianQin SDK', author='TianQin', author_email='tianqincn@gmail.com', @@ -18,7 +18,7 @@ packages=setuptools.find_packages(exclude=["tqsdk.test", "tqsdk.test.*"]), python_requires='>=3.6.4', install_requires=["websockets>=8.1", "requests", "numpy", "pandas>=1.1.0", "scipy", "simplejson", "aiohttp", - "certifi", "pyjwt", "psutil", "shinny_structlog", "sgqlc", "filelock", "tqsdk_ctpse", "tqsdk_sm", "tqsdk_zq_otg==1.1.1"], + "certifi", "pyjwt", "psutil", "shinny_structlog", "sgqlc", "filelock", "tqsdk_ctpse", "tqsdk_sm"], classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", diff --git a/tqsdk/__init__.py b/tqsdk/__init__.py index dfc9e696..442e2af3 100644 --- a/tqsdk/__init__.py +++ b/tqsdk/__init__.py @@ -4,7 +4,7 @@ name = "tqsdk" from tqsdk.api import TqApi -from tqsdk.tradeable import TqAccount, TqZq, TqKq, TqKqStock, TqSim, TqSimStock, TqCtp +from tqsdk.tradeable import TqAccount, TqZq, TqKq, TqKqStock, TqSim, TqSimStock, TqCtp, TqRohon from tqsdk.auth import TqAuth from tqsdk.channel import TqChan from tqsdk.backtest import TqBacktest, TqReplay diff --git a/tqsdk/__version__.py b/tqsdk/__version__.py index 380cd80a..368b1f26 100644 --- a/tqsdk/__version__.py +++ b/tqsdk/__version__.py @@ -1 +1 @@ -__version__ = '3.7.1' +__version__ = '3.7.2' diff --git a/tqsdk/api.py b/tqsdk/api.py index d66715b8..0a061ae2 100644 --- a/tqsdk/api.py +++ b/tqsdk/api.py @@ -72,7 +72,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, TqZq, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, BaseOtg, TqCtp +from tqsdk.tradeable import TqAccount, TqZq, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, BaseOtg, TqCtp, TqRohon 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, \ @@ -82,7 +82,7 @@ from .__version__ import __version__ -UnionTradeable = Union[TqAccount, TqKq, TqZq, TqKqStock, TqSim, TqSimStock, TqCtp] +UnionTradeable = Union[TqAccount, TqKq, TqZq, TqKqStock, TqSim, TqSimStock, TqCtp, TqRohon] class TqApi(TqBaseApi): @@ -119,8 +119,10 @@ def __init__(self, account: Optional[Union[TqMultiAccount, UnionTradeable]] = No * :py:class:`~tqsdk.TqCtp` : 使用直连 CTP 账号 + * :py:class:`~tqsdk.TqRohon` : 使用融航资管账号 + * :py:class:`~tqsdk.TqMultiAccount` : 多账户列表,列表中支持 :py:class:`~tqsdk.TqAccount`、:py:class:`~tqsdk.TqKq`、:py:class:`~tqsdk.TqKqStock`、\ - :py:class:`~tqsdk.TqSim`、:py:class:`~tqsdk.TqSimStock`、:py:class:`~tqsdk.TqZq` 和 :py:class:`~tqsdk.TqCtp` 中的 0 至 N 个或者组合 + :py:class:`~tqsdk.TqSim`、:py:class:`~tqsdk.TqSimStock`、:py:class:`~tqsdk.TqZq`、:py:class:`~tqsdk.TqRohon` 和 :py:class:`~tqsdk.TqCtp` 中的 0 至 N 个或者组合 auth (TqAuth/str): [必填]用户快期账户: * :py:class:`~tqsdk.TqAuth` : 添加快期账户类,例如:TqAuth("tianqin@qq.com", "123456") diff --git a/tqsdk/connect.py b/tqsdk/connect.py index eab6f0a0..fefe89e3 100644 --- a/tqsdk/connect.py +++ b/tqsdk/connect.py @@ -130,7 +130,7 @@ async def _run(self, api, url, send_chan, recv_chan): url_info = url_info._replace(scheme="ws", path="/".join(sm_info[:1]+sm_info[4:])) elif url_info.scheme.startswith("zqotg"): url_info = url_info._replace(scheme="ws") - cm = ZqOtgContext() + cm = ZqOtgContext(self._api) count = 0 async with cm: diff --git a/tqsdk/multiaccount.py b/tqsdk/multiaccount.py index bb7d35cd..53fe1a19 100644 --- a/tqsdk/multiaccount.py +++ b/tqsdk/multiaccount.py @@ -8,7 +8,7 @@ from shinny_structlog import ShinnyLoggerAdapter from tqsdk.channel import TqChan -from tqsdk.tradeable import TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, TqZq, TqCtp +from tqsdk.tradeable import TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, BaseSim, TqZq, TqCtp, TqRohon from tqsdk.tradeable.mixin import StockMixin @@ -27,12 +27,12 @@ class TqMultiAccount(object): """ - def __init__(self, accounts: Optional[List[Union[TqAccount, TqKq, TqZq, TqKqStock, TqSim, TqSimStock, TqZq, TqCtp]]] = None): + def __init__(self, accounts: Optional[List[Union[TqAccount, TqKq, TqZq, TqKqStock, TqSim, TqSimStock, TqZq, TqCtp, TqRohon]]] = None): """ 创建 TqMultiAccount 实例 Args: - accounts (List[Union[TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, TqZq, TqCtp]]): [可选] 多账户列表, 若未指定任何账户, 则为 [TqSim()] + accounts (List[Union[TqAccount, TqKq, TqKqStock, TqSim, TqSimStock, TqZq, TqCtp, TqRohon]]): [可选] 多账户列表, 若未指定任何账户, 则为 [TqSim()] Example1:: diff --git a/tqsdk/tradeable/__init__.py b/tqsdk/tradeable/__init__.py index 599b43f1..35c2b810 100644 --- a/tqsdk/tradeable/__init__.py +++ b/tqsdk/tradeable/__init__.py @@ -5,6 +5,6 @@ from tqsdk.tradeable.otg.base_otg import BaseOtg -from tqsdk.tradeable.otg import TqAccount, TqZq, TqKq, TqKqStock, TqCtp +from tqsdk.tradeable.otg import TqAccount, TqZq, TqKq, TqKqStock, TqCtp, TqRohon from tqsdk.tradeable.sim.basesim import BaseSim from tqsdk.tradeable.sim import TqSim, TqSimStock diff --git a/tqsdk/tradeable/otg/__init__.py b/tqsdk/tradeable/otg/__init__.py index 970e9d6c..f3b9697f 100644 --- a/tqsdk/tradeable/otg/__init__.py +++ b/tqsdk/tradeable/otg/__init__.py @@ -7,3 +7,4 @@ from tqsdk.tradeable.otg.tqzq import TqZq from tqsdk.tradeable.otg.tqkq import TqKq, TqKqStock from tqsdk.tradeable.otg.tqctp import TqCtp +from tqsdk.tradeable.otg.tqrohon import TqRohon diff --git a/tqsdk/tradeable/otg/tqctp.py b/tqsdk/tradeable/otg/tqctp.py index 3e6ce4e6..0a655276 100644 --- a/tqsdk/tradeable/otg/tqctp.py +++ b/tqsdk/tradeable/otg/tqctp.py @@ -34,6 +34,10 @@ def __init__(self, account_id: str, password: str, front_broker: str, front_url: account = TqCtp(account_id="CTP 账户", password="CTP 密码", front_broker="CTP 柜台代码", front_url="CTP 柜台地址", app_id="CTP AppID", auth_code="CTP AuthCode") api = TqApi(account, auth=TqAuth("快期账户", "账户密码")) + 注意: + 1. 使用 TqCtp 账户需要安装 tqsdk_zq_otg 包: pip install -U tqsdk_zq_otg + 2. front_broker, front_url, app_id 和 auth_code 信息需要向期货公司申请程序化外接后取得 + """ self._account_id = account_id self._front_broker = front_broker diff --git a/tqsdk/tradeable/otg/tqrohon.py b/tqsdk/tradeable/otg/tqrohon.py new file mode 100644 index 00000000..e30f95f1 --- /dev/null +++ b/tqsdk/tradeable/otg/tqrohon.py @@ -0,0 +1,75 @@ +#!usr/bin/env python3 +# -*- coding:utf-8 -*- +__author__ = 'chenli' + +import hashlib + +from tqsdk.tradeable.otg.base_otg import BaseOtg +from tqsdk.tradeable.mixin import FutureMixin + + +class TqRohon(BaseOtg, FutureMixin): + """融航资管账户类""" + + def __init__(self, account_id: str, password: str, front_broker: str, front_url: str, app_id: str, auth_code: str) -> None: + """ + 创建融航账户实例 + + Args: + account_id (str): 帐号 + + password (str): 密码 + + front_broker (str): 融航柜台代码 + + front_url (str): 融航柜台地址 + + app_id (str): 融航 AppID + + auth_code (str): 融航 AuthCode + + Example1:: + + from tqsdk import TqApi, TqRohon + account = TqRohon(account_id="融航账户", password="融航密码", front_broker="融航柜台代码", front_url="融航柜台地址", app_id="融航 AppID", auth_code="融航 AuthCode") + api = TqApi(account, auth=TqAuth("快期账户", "账户密码")) + + 注意: + 1. 使用 TqRohon 账户需要安装 tqsdk_zq_otg 包: pip install -U tqsdk_zq_otg + 2. front_broker, front_url, app_id 和 auth_code 信息需要融航申请程序化外接后取得 + + """ + self._account_id = account_id + self._front_broker = front_broker + self._front_url = front_url + self._app_id = app_id + self._auth_code = auth_code + super(TqRohon, self).__init__(broker_id="", account_id=account_id, password=password, td_url="zqotg://127.0.0.1:0/trade") + + @property + def _account_auth(self): + return { + "feature": "tq_direct", + "account_id": self._account_id, + "auto_add": True, + } + + def _get_account_key(self): + s = self._broker_id + self._account_id + s += self._front_broker if self._front_broker else "" + s += self._front_url if self._front_url else "" + return hashlib.md5(s.encode('utf-8')).hexdigest() + + async def _send_login_pack(self): + req = { + "aid": "req_login", + "bid": "tqsdk_zq_otg", + "user_name": self._account_id, + "password": self._password, + "broker_id": self._front_broker, + "front": self._front_url, + "app_id": self._app_id, + "auth_code": self._auth_code, + "backend": "rohon" + } + await self._td_send_chan.send(req) diff --git a/tqsdk/zq_otg.py b/tqsdk/zq_otg.py index 1e94dfd1..948feb54 100644 --- a/tqsdk/zq_otg.py +++ b/tqsdk/zq_otg.py @@ -6,18 +6,23 @@ import json import os import tempfile -import signal import sys import subprocess -import contextlib from pathlib import Path from asyncio.subprocess import DEVNULL, PIPE -from tqsdk_zq_otg import get_zq_otg_path - class ZqOtgContext(object): - def __init__(self): + def __init__(self, api): + acc_types = ", ".join([type(acc).__name__ for acc in api._account._account_list if acc._account_auth.get("feature") == "tq_direct"]) + try: + from tqsdk_zq_otg import __version__ as otg_version + from tqsdk import __version__ as tqsdk_version + from tqsdk_zq_otg import get_zq_otg_path + except ImportError: + raise Exception(f"使用 {acc_types} 账户需要安装 tqsdk_zq_otg 包: pip install -U tqsdk_zq_otg") from None + if otg_version != tqsdk_version: + raise Exception(f"使用 {acc_types} 账户需要更新 tqsdk_zq_otg 包到最新版本: pip install -U tqsdk_zq_otg") self._zq_otg_path = get_zq_otg_path() self._zq_otg_exe = str(Path(self._zq_otg_path) / "otg_adapter") self._zq_otg_env = os.environ.copy()