Skip to content

Commit 1929492

Browse files
committed
Merge branch 'master' into feature_stock_screener
market screener
2 parents 684d950 + d359baf commit 1929492

File tree

82 files changed

+4007
-2419
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+4007
-2419
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,3 @@ cython_debug/
139139

140140
.idea
141141
.DS_Store
142-

CHANGELOG.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,143 @@
1+
## 2.2.2 (2022-11-22)
2+
### New
3+
- 订单支持GTD类型, 下单时可通过指定 Order 属性 time_in_force = "GTD" 设置
4+
- 订单成交明细支持长链接订阅推送
5+
6+
## 2.2.1 (2022-11-07)
7+
### Fixed
8+
- 修复 `TradeClient.get_trade_ticks` begin_index 参数传 0 不生效的问题
9+
10+
11+
## 2.2.0 (2022-11-01)
12+
### New
13+
- 长链接支持期货逐笔推送. 可通过 `PushClient.subscribe_tick` 订阅,使用 `PushClient.tick_changed` 接收回调
14+
15+
16+
## 2.1.9 (2022-10-12)
17+
### New
18+
- 支持多牌照配置, 分牌照请求不同域名. 可通过 client_config.license 指定牌照
19+
### Modify
20+
- `Contract` 新增属性 `short_initial_margin`, `short_maintenance_margin`, 新增方法 `to_str()` 可打印全部属性
21+
- `QuoteClient.get_financial_report` 增加参数 `begin_date`, `end_date`
22+
- `QuoteClient.get_trade_ticks` 兼容 1.0 版本接口
23+
24+
25+
## 2.1.8 (2022-08-26)
26+
### Modify
27+
- `TradeClient.get_orders` 新增参数 `seg_type`, 可指定交易品种(证券SEC/期货FUT/全部ALL)
28+
- `PushClient` 修改自动重连重试次数
29+
- `TradeClient.get_contract` 接口版本升级到V3
30+
### Fixed
31+
- 修复 `TradeClient.get_contract` 获取港股期权合约时返回空的问题
32+
33+
34+
## 2.1.7 (2022-08-19)
35+
### New
36+
- 新增获取期货某类型所有合约接口 `QuoteClient.get_all_future_contracts`
37+
- 附加订单支持追踪止损单
38+
39+
### Breaking
40+
- 期货tick接口 `QuoteClient.get_future_trade_ticks`, 合约参数由接受列表改为只接受单个合约
41+
42+
## 2.1.6 (2022-08-11)
43+
### Modify
44+
- 支持全局时区配置, 可通过 ClientConfig.timezone 设置时区
45+
46+
47+
## 2.1.5 (2022-08-01)
48+
### Modify
49+
- 交易相关接口支持全局语言配置, 可通过 ClientConfig.language 改变默认语言
50+
51+
52+
## 2.1.4 (2022-07-18)
53+
### New
54+
- 新增历史资产分析接口 `TradeClient.get_analytics_asset`
55+
- 新增合约价格校正工具函数 `tigeropen.common.util.price_util.PriceUtil`, 可根据请求到的合约tick size, 校正输入的下单价格
56+
- 订单对象新增属性: 更新时间: `update_time`
57+
- 查询订单列表接口 `TradeClieng.get_orders (get_open_orders/get_filled_orders)` 支持指定排序规则, 按照订单创建时间或订单状态更新时间排序
58+
- 查询持仓接口 `TradeClient.get_positions` 支持期权要素(expiry, strike, put_call)参数过滤
59+
60+
61+
## 2.1.3 (2022-07-01)
62+
### New
63+
- 长连接新增逐笔订阅: `PushClient.subscribe_tick`, 退订 `PushClient.unsubscribe_tick`
64+
- 新增已订阅查询回调方法 `PushClient.query_subscribed_callback` 取代旧有的 `Pushclient.subscribed_symbols`
65+
- `QuoteClient.get_trade_ticks` 新增 `trade_session` 参数,可指定该参数查询盘前盘后数据
66+
67+
### Modify
68+
- `Pushclient.subscribed_symbols` 标记为废弃
69+
70+
71+
## 2.1.2 (2022-06-14)
72+
### Modify
73+
- 升级 stomp.py 版本, 将之前的 4.1.24 升级到 8.0.1
74+
### Breaking
75+
- PushClient 去除 `auto_reconnect` 参数,如需自定义重连方式,可自定义方法并绑定 `disconnect_callback` 进行重连
76+
- 处理连接被踢的情况,如果有多台设备使用相同 tiger_id 连接, 新连接会将较早的连接踢掉,较早连接会抛出异常,停止接收消息
77+
78+
## 2.1.1 (2022-05-25)
79+
### New
80+
- 新增批量分页获取k线接口
81+
股票:`QuoteClient.get_bars_by_page`
82+
期货:`QuoteClient.get_future_bars_by_page`
83+
- `QuoteClient.get_future_bars`, `QuoteClient.get_bars` 增加 `page_token` 参数,可用于分页请求定位下一页位置
84+
- `tigeropen.trade.domain.order.Order` 新增 `user_mark` 属性,用户下单时可传入一定长度的备注信息,该属性值在查询订单时会返回。(需用户提前向平台申请配置)
85+
86+
## 2.1.0 (2022-05-07)
87+
### New
88+
- 动态获取服务域名;更改默认域名
89+
- 新增期权计算工具(examples.option_helpers.helpers)
90+
- 新增根据期货代码获取期货合约接口 `QuoteClient.get_future_contract`
91+
- 新增根据正股查衍生合约接口 `TradeClient.get_derivative_contracts`
92+
93+
94+
## 2.0.9 (2022-04-18)
95+
### New
96+
- 新增历史分时接口 `QuoteClient.get_timeline_history`
97+
- Order 对象新增字段
98+
sub_ids: 附加订单子订单id列表(仅在下附加订单时此字段会有值)
99+
adjust_limit: 限价单价格调整限制比例(作为下单参数使用, 查询时不返回)
100+
101+
### Breaking
102+
- 下单 `TradeClient.place_order`, 改单 `TradeClient.modify_order`, 撤单 `TradeClient.cancel_order` 三个接口返回值,由之前的
103+
`True``False` 改为订单 id
104+
- 行情权限抢占,改为在 `QuoteClient` 初始化时默认自动抢占,提供参数 `is_grab_permission` 可配置为不自动抢占。若该参数设置为 `False`,
105+
则需用户自行调用 `QuoteClient.grab_quote_permission()` 进行行情权限抢占
106+
107+
108+
## 2.0.7 (2022-01-31)
109+
### Modify
110+
- 修改服务域名
111+
112+
## 2.0.6 (2022-01-24)
113+
### New
114+
- Contract 合约对象新增字段。
115+
marginable:是否可融资
116+
close_only:是否只允许平仓
117+
shortable_count:做空池剩余
118+
- Order 订单对象新增字段。
119+
attr_desc:属性描述(如期权是否为被动行权)
120+
source:订单来源
121+
122+
### Breaking
123+
-`tigeropen.quote.request.OpenApiRequest` 移动到 `tigeropen.common.request.OpenApiRequest`
124+
125+
126+
## 2.0.5 (2022-01-10)
127+
### New
128+
- 查询行情权限接口 QuoteClient.get_quote_permission
129+
- 订单综合账户成交记录接口 TradeClient.get_transactions
130+
- 增加一个完整的策略示例
131+
132+
### Changed
133+
- 方法枚举参数优化,使用枚举参数的方法也可以直接使用该枚举对应值
134+
- TradeClient.place_order 去除返回数据中 Order.order_id 属性的校验
135+
- 将 SDK 内部的日志级别由 INFO 调整为 DEBUG, 防止默认情况下输出 SDK 的日志
136+
- 去除 pandas 固定版本号, 方便安装时灵活指定版本
137+
138+
### Breaking
139+
- 行情权限抢占接口 QuoteClient.grab_quote_permission 返回的数据项中,'expireAt' 字段格式转换为 'expire_at'
140+
1141
## 2.0.4 (2021-12-08)
2142
### New
3143
- 综合/模拟账户查询资产接口 TradeClient.get_prime_assets

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
老虎开放平台可以为个人开发者和机构客户提供接口服务,投资者可以充分的利用老虎的交易服务、行情服务、账户服务等实现自己的投资应用程序。
66

7-
- [官方在线文档](https://quant.itiger.com/openapi/py-docs/zh-cn/docs/intro/quickstart.html)
7+
- [官方在线文档](https://quant.itiger.com/openapi/zh/python/overview/introduction.html)
88

99
-------------------
1010

@@ -22,9 +22,9 @@ python setup.py install
2222
### 使用须知
2323

2424
- 接入前需要在[开放平台](https://quant.itiger.com/#openapi)登记开发者信息
25-
- 详情查看[接入说明](https://quant.itiger.com/openapi/py-docs/zh-cn/docs/intro/quickstart.html)
25+
- 详情查看[接入说明](https://quant.itiger.com/openapi/zh/python/overview/introduction.html)
2626

27-
###### 注: 本SDK当前支持Python2, Python3
27+
###### 注: 本SDK当前支持 Python3.4 及以上版本
2828

2929
---
3030

@@ -47,7 +47,6 @@ from tigeropen.trade.trade_client import TradeClient
4747
4848
def get_client_config():
4949
"""
50-
https://www.itiger.com/openapi/info 开发者信息获取
5150
:return:
5251
"""
5352
is_sandbox = False

requirements.txt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
simplejson==3.17.3
1+
simplejson==3.17.6
22
delorean==1.0.0
3-
pandas==1.1.5
3+
pandas
44
python-dateutil==2.8.2
5-
pytz==2021.1
5+
pytz==2022.1
66
pyasn1==0.4.8
7-
rsa==4.7.2
8-
stomp.py==4.1.24
9-
getmac==0.8.2
7+
rsa==4.8
8+
stomp.py==8.0.1
9+
getmac==0.8.3
10+
cryptography==37.0.2

setup.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@
88
from setuptools import find_packages, setup
99
from tigeropen import __VERSION__
1010

11-
1211
with open(path.join(path.abspath(path.dirname(__file__)), 'requirements.txt')) as f:
1312
install_requires = f.read()
13+
with open(path.join(path.abspath(path.dirname(__file__)), 'README.md')) as f:
14+
long_description = f.read()
1415

1516
setup(
1617
name='tigeropen',
1718
version=__VERSION__,
1819
description='TigerBrokers Open API',
19-
long_description = file: README.md
20-
long_description_content_type = text/markdown
21-
packages=find_packages(exclude=[]),
20+
long_description=long_description,
21+
long_description_content_type='text/markdown',
22+
packages=find_packages(exclude=["tests"]),
2223
author='TigerBrokers',
2324
author_email='[email protected]',
2425
license='Apache License v2',
@@ -36,5 +37,6 @@
3637
'Programming Language :: Python :: 3.7',
3738
'Programming Language :: Python :: 3.8',
3839
'Programming Language :: Python :: 3.9',
40+
'Programming Language :: Python :: 3.10',
3941
],
4042
)

tests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/6/24
4+
# @Author : sukai

tests/test_client_config.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/10/8
4+
# @Author : sukai
5+
import unittest
6+
from unittest.mock import MagicMock
7+
8+
from tigeropen.common.consts import License
9+
from tigeropen.tiger_open_config import TigerOpenClientConfig, GATEWAY_SUFFIX
10+
11+
12+
class TestClientConfig(unittest.TestCase):
13+
14+
def test_refresh_server_info(self):
15+
domain_map = {
16+
'socket_port': 9883,
17+
'port': 9887,
18+
'TBSG-QUOTE': 'https://openapi.tigerfintech.com/sgp-quote',
19+
'TBNZ-QUOTE': 'https://openapi.tigerfintech.com/hkg-quote',
20+
'TBSG-PAPER': 'https://openapi-sandbox.tigerfintech.com/sgp',
21+
'TBNZ-PAPER': 'https://openapi-sandbox.tigerfintech.com/hkg',
22+
'TBSG': 'https://openapi.tigerfintech.com/sgp',
23+
'TBNZ': 'https://openapi.tigerfintech.com/hkg',
24+
'COMMON': 'https://openapi.tigerfintech.com',
25+
}
26+
config = TigerOpenClientConfig()
27+
config.query_domains = MagicMock(name='query_domains', return_value=domain_map)
28+
config.domain_conf = config.query_domains()
29+
30+
self.assertEqual('https://openapi.tigerfintech.com' + GATEWAY_SUFFIX, config.server_url)
31+
self.assertEqual(('ssl', 'openapi.tigerfintech.com', 9883), config.socket_host_port)
32+
33+
config.license = License.TBNZ
34+
config.refresh_server_info()
35+
self.assertEqual('https://openapi.tigerfintech.com/hkg' + GATEWAY_SUFFIX, config.server_url)
36+
self.assertEqual('https://openapi.tigerfintech.com/hkg-quote' + GATEWAY_SUFFIX, config.quote_server_url)
37+
38+
config.license = 'TBSG'
39+
config.refresh_server_info()
40+
self.assertEqual('https://openapi.tigerfintech.com/sgp' + GATEWAY_SUFFIX, config.server_url)
41+
self.assertEqual('https://openapi.tigerfintech.com/sgp-quote' + GATEWAY_SUFFIX, config.quote_server_url)
42+
43+
config.is_paper = True
44+
config.license = 'TBNZ'
45+
config.refresh_server_info()
46+
self.assertEqual('https://openapi-sandbox.tigerfintech.com/hkg' + GATEWAY_SUFFIX, config.server_url)
47+
self.assertEqual('https://openapi.tigerfintech.com/hkg-quote' + GATEWAY_SUFFIX, config.quote_server_url)
48+
49+
config = TigerOpenClientConfig(enable_dynamic_domain=False)
50+
config.query_domains = MagicMock(name='query_domains', return_value=domain_map)
51+
config.domain_conf = config.query_domains()
52+
config.license = 'TBNZ'
53+
config.refresh_server_info()
54+
self.assertEqual('https://openapi.tigerfintech.com' + GATEWAY_SUFFIX, config.server_url)
55+
self.assertEqual(('ssl', 'openapi.tigerfintech.com', 9883), config.socket_host_port)

tests/test_push_client.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/6/24
4+
# @Author : sukai
5+
import unittest
6+
7+
from tigeropen.push.push_client import PushClient
8+
9+
10+
class TestPushClient(unittest.TestCase):
11+
12+
def test_tick_convert(self):
13+
body = '{"symbol":"QQQ","tickType":"*****","serverTimestamp":1656062042242,"priceOffset":2,' \
14+
'"volumes":[99,10,10,10,800],"partCode":["t","p","p","p","t"],"cond":"IIIIT","type":"TradeTick",' \
15+
'"times":[1656062084833,11,0,0,31],"quoteLevel":"usStockQuote","priceBase":28770,"sn":878,' \
16+
'"prices":[6,3,2,2,0],"timestamp":1656062085570}'
17+
18+
expected = 'QQQ', [{'tick_type': '*', 'price': 287.76, 'volume': 99, 'part_code': 'NSDQ',
19+
'part_code_name': 'NASDAQ Stock Market, LLC (NASDAQ)', 'cond': 'US_ODD_LOT_TRADE',
20+
'time': 1656062084833, 'server_timestamp': 1656062042242, 'type': 'TradeTick',
21+
'quote_level': 'usStockQuote', 'sn': 878, 'timestamp': 1656062085570},
22+
{'tick_type': '*', 'price': 287.73, 'volume': 10, 'part_code': 'ARCA',
23+
'part_code_name': 'NYSE Arca, Inc. (NYSE Arca)', 'cond': 'US_ODD_LOT_TRADE',
24+
'time': 1656062084844, 'server_timestamp': 1656062042242, 'type': 'TradeTick',
25+
'quote_level': 'usStockQuote', 'sn': 878, 'timestamp': 1656062085570},
26+
{'tick_type': '*', 'price': 287.72, 'volume': 10, 'part_code': 'ARCA',
27+
'part_code_name': 'NYSE Arca, Inc. (NYSE Arca)', 'cond': 'US_ODD_LOT_TRADE',
28+
'time': 1656062084844, 'server_timestamp': 1656062042242, 'type': 'TradeTick',
29+
'quote_level': 'usStockQuote', 'sn': 878, 'timestamp': 1656062085570},
30+
{'tick_type': '*', 'price': 287.72, 'volume': 10, 'part_code': 'ARCA',
31+
'part_code_name': 'NYSE Arca, Inc. (NYSE Arca)', 'cond': 'US_ODD_LOT_TRADE',
32+
'time': 1656062084844, 'server_timestamp': 1656062042242, 'type': 'TradeTick',
33+
'quote_level': 'usStockQuote', 'sn': 878, 'timestamp': 1656062085570},
34+
{'tick_type': '*', 'price': 287.7, 'volume': 800, 'part_code': 'NSDQ',
35+
'part_code_name': 'NASDAQ Stock Market, LLC (NASDAQ)', 'cond': 'US_FORM_T',
36+
'time': 1656062084875, 'server_timestamp': 1656062042242, 'type': 'TradeTick',
37+
'quote_level': 'usStockQuote', 'sn': 878, 'timestamp': 1656062085570}]
38+
self.assertEqual(expected, PushClient._convert_tick(body))

tests/test_utils.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/7/14
4+
# @Author : sukai
5+
import unittest
6+
7+
from tigeropen.common.util.price_util import PriceUtil
8+
9+
10+
class TestUtils(unittest.TestCase):
11+
def test_price_util(self):
12+
delta = 1e-6
13+
tick_sizes = [{'begin': '0', 'end': '1', 'type': 'CLOSED', 'tick_size': 0.0001},
14+
{'begin': '1', 'end': 'Infinity', 'type': 'OPEN', 'tick_size': 0.01}]
15+
self.assertFalse(PriceUtil.match_tick_size(None, None))
16+
self.assertTrue(PriceUtil.match_tick_size(2.33, tick_sizes))
17+
self.assertTrue(PriceUtil.match_tick_size(2.3, tick_sizes))
18+
self.assertFalse(PriceUtil.match_tick_size(1.334, tick_sizes))
19+
self.assertTrue(PriceUtil.match_tick_size(0.5, tick_sizes))
20+
self.assertFalse(PriceUtil.match_tick_size(0.22223, tick_sizes))
21+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(2.334, tick_sizes, True), 2.34, delta=delta)
22+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(2.334, tick_sizes, False), 2.33, delta=delta)
23+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(2.3345, None), 2.3345, delta=delta)
24+
25+
tick_sizes = [{'begin': '0', 'end': '1', 'type': 'CLOSED', 'tick_size': 0.0005},
26+
{'begin': '1', 'end': '100', 'type': 'OPEN_CLOSED', 'tick_size': 0.05},
27+
{'begin': '100', 'end': '1000', 'type': 'OPEN_CLOSED', 'tick_size': 1.0},
28+
{'begin': '1000', 'end': '10000', 'type': 'OPEN_CLOSED', 'tick_size': 2.0},
29+
{'begin': '10000', 'end': 'Infinity', 'type': 'OPEN', 'tick_size': 5.0}]
30+
self.assertTrue(PriceUtil.match_tick_size(0.0005, tick_sizes))
31+
self.assertTrue(PriceUtil.match_tick_size(1.15, tick_sizes))
32+
self.assertFalse(PriceUtil.match_tick_size(0.0008, tick_sizes))
33+
self.assertFalse(PriceUtil.match_tick_size(1.11, tick_sizes))
34+
self.assertTrue(PriceUtil.match_tick_size(300, tick_sizes))
35+
self.assertFalse(PriceUtil.match_tick_size(300.5, tick_sizes))
36+
self.assertFalse(PriceUtil.match_tick_size(5001, tick_sizes))
37+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(0.0021, tick_sizes), 0.002, delta=delta)
38+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(0.0021, tick_sizes, True), 0.0025, delta=delta)
39+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(3.027, tick_sizes), 3.0, delta=delta)
40+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(3.027, tick_sizes, True), 3.05, delta=delta)
41+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(200.5, tick_sizes), 200, delta=delta)
42+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(2001, tick_sizes, True), 2002, delta=delta)
43+
self.assertAlmostEqual(PriceUtil.fix_price_by_tick_size(20001, tick_sizes, True), 20005, delta=delta)

tigeropen/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
55
@author: gaoan
66
"""
7-
__VERSION__ = '2.0.4'
7+
__VERSION__ = '2.2.2'

0 commit comments

Comments
 (0)