Ai
1 Star 0 Fork 163

麒云科技/tqsdk-python

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
auth.py 7.67 KB
一键复制 编辑 原始数据 按行查看 历史
shinny-pack 提交于 2022-01-12 09:51 +08:00 . Update Version 3.2.1
# !usr/bin/env python3
# -*- coding:utf-8 -*-
__author__ = 'yanqiong'
import json
import logging
import os
import jwt
import requests
from shinny_structlog import ShinnyLoggerAdapter
import tqsdk
class TqAuth(object):
"""信易用户认证类"""
def __init__(self, user_name: str = "", password: str = ""):
"""
创建信易用户认证类
Args:
user_name (str): [必填]信易账户,可以是 邮箱、用户名、手机号
password (str): [必填]信易账户密码
Example::
# 使用实盘帐号直连行情和交易服务器
from tqsdk import TqApi, TqAccount, TqAuth
api = TqApi(TqAccount("H海通期货", "022631", "123456"), auth=TqAuth("信易账户", "账户密码"))
"""
self._user_name = user_name
self._password = password
self._auth_url = os.getenv("TQ_AUTH_URL", "https://auth.shinnytech.com")
self._access_token = ""
self._refresh_token = ""
self._auth_id = ""
self._mode = "real" # 行情模式 real bt
self._grants = {
"features": [],
"accounts": []
}
self._logger = ShinnyLoggerAdapter(logging.getLogger("TqApi.TqAuth"), headers=self._base_headers, grants=self._grants)
@property
def _base_headers(self):
return {
"User-Agent": "tqsdk-python %s" % tqsdk.__version__,
"Accept": "application/json",
"Authorization": "Bearer %s" % self._access_token
}
def init(self, mode="real"):
self._mode = mode
def login(self):
self._logger.debug("login", user_name=self._user_name)
self._access_token, self._refresh_token = self._request_token({
"grant_type": "password",
"username": self._user_name,
"password": self._password
})
content = jwt.decode(self._access_token, options={"verify_signature": False})
self._grants = content["grants"]
self._auth_id = content["sub"]
self._logger = self._logger.bind(headers=self._base_headers, grants=self._grants)
def _request_token(self, payload):
data = {"client_id": "shinny_tq", "client_secret": "be30b9f4-6862-488a-99ad-21bde0400081"}
data.update(payload)
url = f"{self._auth_url}/auth/realms/shinnytech/protocol/openid-connect/token"
self._logger.debug("request token", url=url, params=data, method="POST")
response = requests.post(url=url, headers=self._base_headers, data=data, timeout=30)
self._logger.debug("request token result", url=response.url, status_code=response.status_code, headers=response.headers, reason=response.reason, text=response.text)
if response.status_code == 200:
content = json.loads(response.content)
return content["access_token"], content["refresh_token"]
else:
raise Exception("用户权限认证失败 (%d,%s)" % (response.status_code, json.loads(response.content)))
def _add_account(self, account_id):
if self._has_account(account_id):
return True
url = f"{self._auth_url}/auth/realms/shinnytech/rest/update-grant-accounts/{account_id}"
self._logger.debug("add account", account_id=account_id, url=url, method="PUT")
response = requests.put(url=url, headers=self._base_headers, timeout=30)
self._logger.debug("add account result", url=response.url, status_code=response.status_code, headers=response.headers, reason=response.reason, text=response.text)
if response.status_code == 200:
self._access_token, self._refresh_token = self._request_token({
"grant_type": "refresh_token",
"refresh_token": self._refresh_token,
})
content = jwt.decode(self._access_token, options={"verify_signature": False})
self._grants.update(content["grants"])
self._logger = self._logger.bind(headers=self._base_headers, grants=self._grants)
else:
raise Exception(f"添加期货账户失败。{response.status_code}, {json.loads(response.content)}")
def _get_td_url(self, broker_id, account_id):
"""获取交易网关地址"""
url = f"https://files.shinnytech.com/{broker_id}.json"
params = {
"account_id": account_id,
"auth": self._user_name
}
self._logger.debug("request td url", url=url, params=params, method="POST")
response = requests.get(url=url, params=params, headers=self._base_headers, timeout=30)
self._logger.debug("request td url result", url=response.url, status_code=response.status_code,
headers=response.headers, reason=response.reason, text=response.text)
if response.status_code != 200:
raise Exception(f"不支持该期货公司 - {broker_id},请联系期货公司。")
broker_list = json.loads(response.content)
if "TQ" not in broker_list[broker_id]["category"]:
raise Exception(f"该期货公司 - {broker_id} 暂不支持 TqSdk 登录,请联系期货公司。")
return broker_list[broker_id]["url"], broker_list[broker_id].get('broker_type', 'FUTURE')
def _get_md_url(self, stock, backtest):
"""获取行情网关地址"""
url = f"https://api.shinnytech.com/ns"
params = {"stock": str(stock).lower(), "backtest": str(backtest).lower()}
self._logger.debug("request md url", url=url, params=params, method="POST")
response = requests.get(url=url, params=params, headers=self._base_headers, timeout=30)
self._logger.debug("request md url result", url=response.url, status_code=response.status_code,
headers=response.headers, reason=response.reason, text=response.text)
if response.status_code == 200:
content = json.loads(response.content)
if "mdurl" in content:
return content["mdurl"]
else:
raise Exception(f"调用名称服务失败: {content}")
else:
raise Exception(f"调用名称服务失败: {response.status_code}, {response.content}")
def _has_feature(self, feature):
if self._mode == "bt" and feature in ["futr", "sec", "lmt_idx"]:
# 在回测模式中所有用户都有 futr sec lmt_idx 权限
return True
return feature in self._grants["features"]
def _has_account(self, account):
return account in self._grants["accounts"]
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"] and self._has_feature("futr"):
continue
elif symbol.split('.', 1)[0] in ["SSE", "SZSE"] and self._has_feature("sec"):
continue
elif symbol in ["SSE.000016", "SSE.000300", "SSE.000905"] and self._has_feature("lmt_idx"):
continue
else:
raise Exception(f"您的账户不支持查看 {symbol} 的行情数据,需要购买专业版本后使用。升级网址:https://account.shinnytech.com")
return True
def _has_td_grants(self, symbol):
# 对于 opt / cmb / adv 权限的检查由 OTG 做
if symbol.split('.', 1)[0] in ["SSE", "SZSE"] and self._has_feature("sec"):
return True
if symbol.split('.', 1)[0] in ["SHFE", "DCE", "CZCE", "INE", "CFFEX", "KQ"] and self._has_feature("futr"):
return True
raise Exception(f"您的账户不支持交易 {symbol},需要购买专业版本后使用。升级网址:https://account.shinnytech.com")
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/dantes/tqsdk-python.git
git@gitee.com:dantes/tqsdk-python.git
dantes
tqsdk-python
tqsdk-python
master

搜索帮助