Skip to content

Commit 7ab4067

Browse files
authored
Merge pull request #48 from tigerfintech/feature_timehistory
timeline history
2 parents f72cbb9 + b5ec5b7 commit 7ab4067

File tree

12 files changed

+123
-20
lines changed

12 files changed

+123
-20
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## 2.0.9 (2022-04-18)
2+
### New
3+
- 新增历史分时接口 `QuoteClient.get_timeline_history`
4+
- Order 对象新增字段
5+
sub_ids: 附加订单子订单id列表(仅在下附加订单时此字段会有值)
6+
adjust_limit: 限价单价格调整限制比例(作为下单参数使用, 查询时不返回)
7+
8+
### Breaking
9+
- 下单 `TradeClient.place_order`, 改单 `TradeClient.modify_order`, 撤单 `TradeClient.cancel_order` 三个接口返回值,由之前的
10+
`True``False` 改为订单 id
11+
- 行情权限抢占,改为在 `QuoteClient` 初始化时默认自动抢占,提供参数 `is_grab_permission` 可配置为不自动抢占。若该参数设置为 `False`,
12+
则需用户自行调用 `QuoteClient.grab_quote_permission()` 进行行情权限抢占
13+
14+
115
## 2.0.7 (2022-01-31)
216
### Modify
317
- 修改服务域名

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.7'
7+
__VERSION__ = '2.0.9'

tigeropen/common/consts/service_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
BRIEF = "brief"
4040
STOCK_DETAIL = "stock_detail"
4141
TIMELINE = "timeline"
42+
HISTORY_TIMELINE = "history_timeline"
4243
KLINE = "kline"
4344
TRADE_TICK = "trade_tick"
4445
QUOTE_REAL_TIME = "quote_real_time"

tigeropen/examples/quote_client_demo.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ def get_quote():
4141
print(metas)
4242
timelines = openapi_client.get_timeline(['AAPL'], include_hour_trading=True)
4343
print(timelines)
44+
history_timelines = openapi_client.get_timeline_history(['AAPL'], date='2022-04-11')
45+
print(history_timelines)
4446
bars = openapi_client.get_bars(['AAPL'])
4547
print(bars)
4648
ticks = openapi_client.get_trade_ticks(['00700'])

tigeropen/quote/quote_client.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
from tigeropen.common.consts import Market, Language, QuoteRight, BarPeriod, OPEN_API_SERVICE_VERSION_V3
1313
from tigeropen.common.consts import THREAD_LOCAL, SecurityType, CorporateActionType, IndustryLevel
14-
from tigeropen.common.consts.service_types import GRAB_QUOTE_PERMISSION, QUOTE_DELAY, GET_QUOTE_PERMISSION
14+
from tigeropen.common.consts.service_types import GRAB_QUOTE_PERMISSION, QUOTE_DELAY, GET_QUOTE_PERMISSION, \
15+
HISTORY_TIMELINE
1516
from tigeropen.common.consts.service_types import MARKET_STATE, ALL_SYMBOLS, ALL_SYMBOL_NAMES, BRIEF, \
1617
TIMELINE, KLINE, TRADE_TICK, OPTION_EXPIRATION, OPTION_CHAIN, FUTURE_EXCHANGE, OPTION_BRIEF, \
1718
OPTION_KLINE, OPTION_TRADE_TICK, FUTURE_KLINE, FUTURE_TICK, FUTURE_CONTRACT_BY_EXCHANGE_CODE, \
@@ -53,6 +54,7 @@
5354
from tigeropen.quote.response.quote_depth_response import DepthQuoteResponse
5455
from tigeropen.quote.response.quote_grab_permission_response import QuoteGrabPermissionResponse
5556
from tigeropen.quote.response.quote_ticks_response import TradeTickResponse
57+
from tigeropen.quote.response.quote_timeline_history_response import QuoteTimelineHistoryResponse
5658
from tigeropen.quote.response.quote_timeline_response import QuoteTimelineResponse
5759
from tigeropen.quote.response.stock_briefs_response import StockBriefsResponse
5860
from tigeropen.quote.response.stock_details_response import StockDetailsResponse
@@ -64,14 +66,19 @@
6466

6567

6668
class QuoteClient(TigerOpenClient):
67-
def __init__(self, client_config, logger=None):
69+
70+
def __init__(self, client_config, logger=None, is_grab_permission=True):
6871
if not logger:
6972
logger = logging.getLogger('tiger_openapi')
7073
super(QuoteClient, self).__init__(client_config, logger=logger)
7174
if client_config:
7275
self._lang = client_config.language
7376
else:
7477
self._lang = Language.zh_CN
78+
self.permissions = None
79+
if is_grab_permission and self.permissions is None:
80+
self.permissions = self.grab_quote_permission()
81+
logger.info('Grab quote permission. Permissions:' + str(self.permissions))
7582

7683
def __fetch_data(self, request):
7784
try:
@@ -364,6 +371,33 @@ def get_timeline(self, symbols, include_hour_trading=False, begin_time=-1, lang=
364371
else:
365372
raise ApiException(response.code, response.message)
366373

374+
def get_timeline_history(self, symbols, date, right=QuoteRight.BR):
375+
"""
376+
get timeline history data
377+
:param symbols: security symbol list. like ['AAPL', 'BABA']
378+
:param date: date of timeline. yyyy-MM-dd format, like "2022-04-12"
379+
:param right: quote right. QuoteRight.BR: before right,QuoteRight.NR: no right
380+
:return: pandas.DataFrame, columns explanations:
381+
symbol: security symbol
382+
time: time in milliseconds
383+
price: close price of current minute
384+
avg_price: volume weighted average price up to now.
385+
"""
386+
params = MultipleQuoteParams()
387+
params.symbols = symbols
388+
params.date = date
389+
params.right = get_enum_value(right)
390+
391+
request = OpenApiRequest(HISTORY_TIMELINE, biz_model=params)
392+
response_content = self.__fetch_data(request)
393+
if response_content:
394+
response = QuoteTimelineHistoryResponse()
395+
response.parse_response_content(response_content)
396+
if response.is_success():
397+
return response.timelines
398+
else:
399+
raise ApiException(response.code, response.message)
400+
367401
def get_bars(self, symbols, period=BarPeriod.DAY, begin_time=-1, end_time=-1, right=QuoteRight.BR, limit=251,
368402
lang=None):
369403
"""

tigeropen/quote/request/model.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ def __init__(self):
231231
self._limit = None
232232
self._begin_index = None
233233
self._end_index = None
234+
self._date = None
234235

235236
@property
236237
def symbols(self):
@@ -312,6 +313,14 @@ def end_index(self):
312313
def end_index(self, value):
313314
self._end_index = value
314315

316+
@property
317+
def date(self):
318+
return self._date
319+
320+
@date.setter
321+
def date(self, value):
322+
self._date = value
323+
315324
def to_openapi_dict(self):
316325
params = super(MultipleQuoteParams, self).to_openapi_dict()
317326

@@ -345,6 +354,9 @@ def to_openapi_dict(self):
345354
if self.end_index:
346355
params['end_index'] = self.end_index
347356

357+
if self.date:
358+
params['date'] = self.date
359+
348360
return params
349361

350362

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/4/13
4+
# @Author : sukai
5+
6+
import pandas as pd
7+
8+
from tigeropen.common.response import TigerResponse
9+
10+
TIMELINE_FIELD_MAPPINGS = {'avgPrice': 'avg_price'}
11+
12+
13+
class QuoteTimelineHistoryResponse(TigerResponse):
14+
def __init__(self):
15+
super(QuoteTimelineHistoryResponse, self).__init__()
16+
self.timelines = None
17+
self._is_success = None
18+
19+
def parse_response_content(self, response_content):
20+
response = super(QuoteTimelineHistoryResponse, self).parse_response_content(response_content)
21+
if 'is_success' in response:
22+
self._is_success = response['is_success']
23+
24+
if self.data and isinstance(self.data, list):
25+
timeline_items = []
26+
for symbol_item in self.data:
27+
timeline_df = pd.DataFrame(symbol_item.get('items'))
28+
timeline_df.insert(0, 'symbol', symbol_item.get('symbol'))
29+
timeline_items.append(timeline_df)
30+
self.timelines = pd.concat(timeline_items).rename(columns=TIMELINE_FIELD_MAPPINGS)

tigeropen/trade/domain/order.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ class Order:
1515
__slots__ = ["account", "id", "order_id", "parent_id", "order_time", "reason", "trade_time", "contract", "action",
1616
"quantity", "filled", "_remaining", "avg_fill_price", "commission", "realized_pnl", "_status",
1717
"trail_stop_price", "limit_price", "aux_price", "trailing_percent", "percent_offset", "action",
18-
"order_type", "time_in_force", "outside_rth", "order_legs", "algo_params", "secret_key", "liquidation",
19-
"algo_strategy", "discount", "attr_desc", "source"]
18+
"order_type", "time_in_force", "outside_rth", "order_legs", "algo_params", "algo_strategy",
19+
"secret_key", "liquidation", "discount", "attr_desc", "source", 'adjust_limit', 'sub_ids']
2020

2121
def __init__(self, account, contract, action, order_type, quantity, limit_price=None, aux_price=None,
2222
trail_stop_price=None, trailing_percent=None, percent_offset=None, time_in_force=None,
@@ -39,7 +39,7 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
3939
- realized_pnl: 实现盈亏
4040
- trail_stop_price: 跟踪止损单--触发止损单的价格
4141
- limit_price: 限价单价格
42-
- aux_price: 在止损单中, 表示出发止损单的价格, 在移动止损单中, 表示跟踪的价差
42+
- aux_price: 在止损单中, 表示触发止损单的价格, 在移动止损单中, 表示跟踪的价差
4343
- trailing_percent: 跟踪止损单-百分比, 取值范围为0-100
4444
- percent_offset: None,
4545
- order_type: 订单类型, 'MKT' 市价单 / 'LMT' 限价单 / 'STP' 止损单 / 'STP_LMT' 止损限价单 / 'TRAIL' 跟踪止损单
@@ -54,6 +54,9 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
5454
- liquidation
5555
- algo_strategy
5656
- discount
57+
- adjust_limit 价格微调幅度(默认为0表示不调整,正数为向上调整,负数向下调整),对传入价格自动调整到合法价位上.
58+
例如:0.001 代表向上调整且幅度不超过 0.1%;-0.001 代表向下调整且幅度不超过 0.1%。默认 0 表示不调整
59+
- sub_ids id list of sub orders.
5760
"""
5861

5962
self.id = id
@@ -87,7 +90,9 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
8790
self.algo_strategy = kwargs.get('algo_strategy')
8891
self.discount = kwargs.get('discount')
8992
self.attr_desc = kwargs.get('attr_desc')
90-
self.source = kwargs.get("source")
93+
self.source = kwargs.get('source')
94+
self.adjust_limit = kwargs.get('adjust_limit')
95+
self.sub_ids = kwargs.get('sub_ids')
9196

9297
def to_dict(self):
9398
dct = {name: getattr(self, name) for name in self.__slots__ if name not in ORDER_FIELDS_TO_IGNORE}

tigeropen/trade/request/model.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,7 @@ def __init__(self):
724724
self.outside_rth = None
725725
self.order_legs = None
726726
self.algo_params = None
727+
self.adjust_limit = None
727728

728729
def to_openapi_dict(self):
729730
params = dict()
@@ -777,6 +778,8 @@ def to_openapi_dict(self):
777778
params['time_in_force'] = self.time_in_force
778779
if self.outside_rth is not None:
779780
params['outside_rth'] = self.outside_rth
781+
if self.adjust_limit is not None:
782+
params['adjust_limit'] = self.adjust_limit
780783

781784
if self.order_legs:
782785
if len(self.order_legs) > 2:

tigeropen/trade/response/order_id_response.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def __init__(self):
1313
super(OrderIdResponse, self).__init__()
1414
self.order_id = None
1515
self.id = None
16+
self.sub_ids = None
1617
self._is_success = None
1718

1819
def parse_response_content(self, response_content):
@@ -32,3 +33,6 @@ def parse_response_content(self, response_content):
3233

3334
if 'id' in data_json:
3435
self.id = data_json['id']
36+
37+
if 'subIds' in data_json:
38+
self.sub_ids = data_json['subIds']

0 commit comments

Comments
 (0)