Skip to content

Commit 4fafe9d

Browse files
committed
Merge branch 'feature_pagetoken' into 'dev'
Feature pagetoken See merge request server/openapi/openapi-python-sdk!110
2 parents 8b41a71 + 23c2aa7 commit 4fafe9d

File tree

12 files changed

+161
-19
lines changed

12 files changed

+161
-19
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 2.1.1 (2022-05-25)
2+
### New
3+
- 新增批量分页获取k线接口
4+
股票:`QuoteClient.get_bars_by_page`
5+
期货:`QuoteClient.get_future_bars_by_page`
6+
- `QuoteClient.get_future_bars`, `QuoteClient.get_bars` 增加 `page_token` 参数,可用于分页请求定位下一页位置
7+
- `tigeropen.trade.domain.order.Order` 新增 `user_mark` 属性,用户下单时可传入一定长度的备注信息,该属性值在查询订单时会返回。(需用户提前向平台申请配置)
8+
19
## 2.1.0 (2022-05-07)
210
### New
311
- 动态获取服务域名;更改默认域名

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

tigeropen/examples/option_helpers/helpers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ def __init__(self,
268268
else:
269269
helper_class = FDAmericanDividendOptionHelper
270270

271+
ql.Settings.instance().evaluationDate = settlement_date
271272
helper = helper_class(option_type=ql_option_type,
272273
underlying=args.underlying,
273274
strike=args.strike,

tigeropen/examples/quote_client_demo.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
@author: gaoan
66
"""
77
import logging
8+
import time
9+
810
import pandas as pd
911
from tigeropen.common.consts import Market, QuoteRight, FinancialReportPeriodType, Valuation, \
10-
Income, Balance, CashFlow, BalanceSheetRatio, Growth, Leverage, Profitability, IndustryLevel
12+
Income, Balance, CashFlow, BalanceSheetRatio, Growth, Leverage, Profitability, IndustryLevel, BarPeriod
1113
from tigeropen.quote.domain.filter import OptionFilter
1214

1315
from tigeropen.quote.quote_client import QuoteClient
@@ -61,6 +63,17 @@ def get_quote():
6163
print(delay_brief)
6264

6365

66+
def test_gat_bars_by_page():
67+
bars = openapi_client.get_bars_by_page(['AAPL'], period=BarPeriod.DAY,
68+
end_time='2022-05-01',
69+
total=10,
70+
page_size=4,
71+
)
72+
bars['cn_date'] = pd.to_datetime(bars['time'], unit='ms').dt.tz_localize('UTC').dt.tz_convert('Asia/Shanghai')
73+
bars['us_date'] = pd.to_datetime(bars['time'], unit='ms').dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
74+
print(bars)
75+
76+
6477
def get_option_quote():
6578
symbol = 'AAPL'
6679
expirations = openapi_client.get_option_expirations(symbols=[symbol])
@@ -85,11 +98,11 @@ def get_option_quote():
8598
chains = openapi_client.get_option_chain('AAPL', '2023-01-20', implied_volatility_min=0.5, open_interest_min=200,
8699
vega_min=0.1, rho_max=0.9)
87100
# convert expiry date to US/Eastern
88-
chains['expiry_date'] = pd.to_datetime(chains['expiry'], unit='ms').dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
101+
chains['expiry_date'] = pd.to_datetime(chains['expiry'], unit='ms').dt.tz_localize('UTC').dt.tz_convert(
102+
'US/Eastern')
89103
print(chains)
90104

91105

92-
93106
def get_future_quote():
94107
exchanges = openapi_client.get_future_exchanges()
95108
print(exchanges)
@@ -107,18 +120,27 @@ def get_future_quote():
107120
print(briefs)
108121

109122

123+
def test_get_future_bars_by_page():
124+
bars = openapi_client.get_future_bars_by_page('CLmain',
125+
end_time=1648526400000,
126+
total=10,
127+
page_size=4)
128+
bars['cn_date'] = pd.to_datetime(bars['time'], unit='ms').dt.tz_localize('UTC').dt.tz_convert('Asia/Shanghai')
129+
bars['us_date'] = pd.to_datetime(bars['time'], unit='ms').dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
130+
print(bars)
131+
110132

111133
def get_fundamental():
112134
"""获取基础数据"""
113-
135+
114136
# 日级财务数据
115137
financial_daily = openapi_client.get_financial_daily(symbols=['AAPL', 'MSFT'],
116138
market=Market.US,
117139
fields=[Valuation.shares_outstanding],
118140
begin_date='2019-01-01',
119141
end_date='2019-01-10')
120142
print(financial_daily)
121-
143+
122144
# 财报数据(季报或年报)
123145
financial_report = openapi_client.get_financial_report(symbols=['AAPL', 'GOOG'],
124146
market=Market.US,

tigeropen/quote/quote_client.py

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
"""
77
import logging
88
import re
9+
import time
910

1011
import delorean
12+
import pandas as pd
1113

1214
from tigeropen.common.consts import Market, Language, QuoteRight, BarPeriod, OPEN_API_SERVICE_VERSION_V3
1315
from tigeropen.common.consts import THREAD_LOCAL, SecurityType, CorporateActionType, IndustryLevel
@@ -399,7 +401,7 @@ def get_timeline_history(self, symbols, date, right=QuoteRight.BR):
399401
raise ApiException(response.code, response.message)
400402

401403
def get_bars(self, symbols, period=BarPeriod.DAY, begin_time=-1, end_time=-1, right=QuoteRight.BR, limit=251,
402-
lang=None):
404+
lang=None, page_token=None):
403405
"""
404406
获取K线数据
405407
:param symbols: 股票代号列表
@@ -410,22 +412,25 @@ def get_bars(self, symbols, period=BarPeriod.DAY, begin_time=-1, end_time=-1, ri
410412
:param right: 复权选项 ,QuoteRight.BR: 前复权,nQuoteRight.NR: 不复权
411413
:param limit: 数量限制
412414
:param lang: 语言支持: zh_CN,zh_TW,en_US
415+
:param page_token: the token of next page. only supported when exactly one symbol
413416
:return: pandas.DataFrame 对象,各 column 的含义如下;
414417
time: 毫秒时间戳
415418
open: Bar 的开盘价
416419
close: Bar 的收盘价
417420
high: Bar 的最高价
418421
low: Bar 的最低价
419422
volume: Bar 的成交量
423+
next_page_token: token of next page
420424
"""
421425
params = MultipleQuoteParams()
422-
params.symbols = symbols
426+
params.symbols = symbols if isinstance(symbols, list) else [symbols]
423427
params.period = get_enum_value(period)
424428
params.begin_time = begin_time
425429
params.end_time = end_time
426430
params.right = get_enum_value(right)
427431
params.limit = limit
428432
params.lang = get_enum_value(lang) if lang else get_enum_value(self._lang)
433+
params.page_token = page_token if len(params.symbols) == 1 else None
429434

430435
request = OpenApiRequest(KLINE, biz_model=params)
431436
response_content = self.__fetch_data(request)
@@ -437,6 +442,41 @@ def get_bars(self, symbols, period=BarPeriod.DAY, begin_time=-1, end_time=-1, ri
437442
else:
438443
raise ApiException(response.code, response.message)
439444

445+
def get_bars_by_page(self, symbol, period=BarPeriod.DAY, begin_time=-1, end_time=-1, total=10000, page_size=1000,
446+
right=QuoteRight.BR, time_interval=2, lang=None):
447+
"""
448+
request bats by page
449+
:param symbol: symbol of stock.
450+
:param period:
451+
:param begin_time:
452+
:param end_time: time of the latest bar, excluded
453+
:param total: Total bars number
454+
:param page_size: Bars number of each request
455+
:param right:
456+
:param time_interval: Time interval between requests
457+
:param lang:
458+
:return:
459+
"""
460+
if begin_time == -1 and end_time == -1:
461+
raise ApiException(400, 'One of the begin_time or end_time must be specified')
462+
if isinstance(symbol, list) and len(symbol) != 1:
463+
raise ApiException(400, 'Paging queries support only one symbol at each request')
464+
current = 0
465+
next_page_token = None
466+
result = list()
467+
while current < total:
468+
if current + page_size >= total:
469+
page_size = total - current
470+
current += page_size
471+
bars = self.get_bars(symbols=symbol, period=period, begin_time=begin_time, end_time=end_time, right=right,
472+
limit=page_size, lang=lang, page_token=next_page_token)
473+
next_page_token = bars['next_page_token'].iloc[0]
474+
result.append(bars)
475+
if not next_page_token:
476+
break
477+
time.sleep(time_interval)
478+
return pd.concat(result).sort_values('time').reset_index(drop=True)
479+
440480
def get_trade_ticks(self, symbols, begin_index=None, end_index=None, limit=None, lang=None):
441481
"""
442482
获取逐笔成交
@@ -896,15 +936,16 @@ def get_future_trading_times(self, identifier, trading_date=None):
896936
raise ApiException(response.code, response.message)
897937
return None
898938

899-
def get_future_bars(self, identifiers, period=BarPeriod.DAY, begin_time=-1, end_time=-1, limit=1000):
939+
def get_future_bars(self, identifiers, period=BarPeriod.DAY, begin_time=-1, end_time=-1, limit=1000,
940+
page_token=None):
900941
"""
901942
获取期货K线数据
902943
:param identifiers: 期货代码列表
903944
:param period: day: 日K,week: 周K,month:月K ,year:年K,1min:1分钟,5min:5分钟,15min:15分钟,30min:30分钟,60min:60分钟
904945
:param begin_time: 开始时间. 若是时间戳需要精确到毫秒, 为13位整数;
905-
或是日期时间格式的字符串, 如 "2019-01-01" 或 "2019-01-01 12:00:00"
906946
:param end_time: 结束时间. 格式同 begin_time
907947
:param limit: 数量限制
948+
:param page_token: the token of next page. only supported when there exactly one identifier
908949
:return: pandas.DataFrame, 各column 含义如下:
909950
identifier: 期货合约代码
910951
time: Bar对应的时间戳, 即Bar的结束时间。Bar的切割方式与交易所一致,以CN1901举例,T日的17:00至T+1日的16:30的数据会被合成一个日级Bar。
@@ -916,13 +957,15 @@ def get_future_bars(self, identifiers, period=BarPeriod.DAY, begin_time=-1, end_
916957
settlement: 结算价,在未生成结算价时返回0
917958
volume: 成交量
918959
open_interest: 未平仓合约数量
960+
next_page_token: token of next page
919961
"""
920962
params = FutureQuoteParams()
921-
params.contract_codes = identifiers
963+
params.contract_codes = identifiers if isinstance(identifiers, list) else [identifiers]
922964
params.period = get_enum_value(period)
923965
params.begin_time = begin_time
924966
params.end_time = end_time
925967
params.limit = limit
968+
params.page_token = page_token if len(params.contract_codes) == 1 else None
926969

927970
request = OpenApiRequest(FUTURE_KLINE, biz_model=params)
928971
response_content = self.__fetch_data(request)
@@ -934,6 +977,39 @@ def get_future_bars(self, identifiers, period=BarPeriod.DAY, begin_time=-1, end_
934977
else:
935978
raise ApiException(response.code, response.message)
936979

980+
def get_future_bars_by_page(self, identifier, period=BarPeriod.DAY, begin_time=-1, end_time=-1, total=10000,
981+
page_size=1000, time_interval=2):
982+
"""
983+
request bats by page
984+
:param identifier: identifier of future
985+
:param period:
986+
:param begin_time:
987+
:param end_time: time of the latest bar, excluded
988+
:param total: Total bars number
989+
:param page_size: Bars number of each request
990+
:param time_interval: Time interval between requests
991+
:return:
992+
"""
993+
if begin_time == -1 and end_time == -1:
994+
raise ApiException(400, 'One of the begin_time or end_time must be specified')
995+
if isinstance(identifier, list) and len(identifier) != 1:
996+
raise ApiException(400, 'Paging queries support only one identifier at each request')
997+
current = 0
998+
next_page_token = None
999+
result = list()
1000+
while current < total:
1001+
if current + page_size >= total:
1002+
page_size = total - current
1003+
current += page_size
1004+
bars = self.get_future_bars(identifiers=identifier, period=period, begin_time=begin_time, end_time=end_time,
1005+
limit=page_size, page_token=next_page_token)
1006+
next_page_token = bars['next_page_token'].iloc[0]
1007+
result.append(bars)
1008+
if not next_page_token:
1009+
break
1010+
time.sleep(time_interval)
1011+
return pd.concat(result).sort_values('time').reset_index(drop=True)
1012+
9371013
def get_future_trade_ticks(self, identifiers, begin_index=0, end_index=30, limit=1000):
9381014
"""
9391015
获取期货逐笔成交
@@ -1263,4 +1339,4 @@ def get_quote_permission(self):
12631339
return response.permissions
12641340
else:
12651341
raise ApiException(response.code, response.message)
1266-
return False
1342+
return False

tigeropen/quote/request/model.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ def __init__(self):
232232
self._begin_index = None
233233
self._end_index = None
234234
self._date = None
235+
self._page_token = None
235236

236237
@property
237238
def symbols(self):
@@ -321,6 +322,14 @@ def date(self):
321322
def date(self, value):
322323
self._date = value
323324

325+
@property
326+
def page_token(self):
327+
return self._page_token
328+
329+
@page_token.setter
330+
def page_token(self, value):
331+
self._page_token = value
332+
324333
def to_openapi_dict(self):
325334
params = super(MultipleQuoteParams, self).to_openapi_dict()
326335

@@ -357,6 +366,9 @@ def to_openapi_dict(self):
357366
if self.date:
358367
params['date'] = self.date
359368

369+
if self.page_token:
370+
params['page_token'] = self.page_token
371+
360372
return params
361373

362374

@@ -619,6 +631,7 @@ def __init__(self):
619631
self._limit = None
620632
self._begin_index = None
621633
self._end_index = None
634+
self._page_token = None
622635

623636
@property
624637
def contract_codes(self):
@@ -676,6 +689,14 @@ def limit(self):
676689
def limit(self, value):
677690
self._limit = value
678691

692+
@property
693+
def page_token(self):
694+
return self._page_token
695+
696+
@page_token.setter
697+
def page_token(self, value):
698+
self._page_token = value
699+
679700
def to_openapi_dict(self):
680701
params = super(FutureQuoteParams, self).to_openapi_dict()
681702

@@ -700,6 +721,9 @@ def to_openapi_dict(self):
700721
if self.limit:
701722
params['limit'] = self.limit
702723

724+
if self.page_token:
725+
params['page_token'] = self.page_token
726+
703727
return params
704728

705729

tigeropen/quote/response/future_quote_bar_response.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
from tigeropen.common.response import TigerResponse
1010

11-
COLUMNS = ['identifier', 'time', 'latest_time', 'open', 'high', 'low', 'close', 'settlement', 'volume', 'open_interest']
11+
COLUMNS = ['identifier', 'time', 'latest_time', 'open', 'high', 'low', 'close', 'settlement', 'volume',
12+
'open_interest', 'next_page_token']
1213
BAR_FIELD_MAPPINGS = {'avgPrice': 'avg_price', 'openInterest': 'open_interest', 'lastTime': 'latest_time'}
1314

1415

@@ -27,9 +28,10 @@ def parse_response_content(self, response_content):
2728
bar_items = []
2829
for symbol_item in self.data:
2930
identifier = symbol_item.get('contractCode')
31+
next_page_token = symbol_item.get('nextPageToken')
3032
if 'items' in symbol_item:
3133
for item in symbol_item['items']:
32-
item_values = {'identifier': identifier}
34+
item_values = {'identifier': identifier, 'next_page_token': next_page_token}
3335
for key, value in item.items():
3436
if value is None:
3537
continue

tigeropen/quote/response/quote_bar_response.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from tigeropen.common.response import TigerResponse
1010

11-
COLUMNS = ['symbol', 'time', 'open', 'high', 'low', 'close', 'volume']
11+
COLUMNS = ['symbol', 'time', 'open', 'high', 'low', 'close', 'volume', 'next_page_token']
1212
BAR_FIELD_MAPPINGS = {'avgPrice': 'avg_price'}
1313

1414

@@ -27,9 +27,10 @@ def parse_response_content(self, response_content):
2727
bar_items = []
2828
for symbol_item in self.data:
2929
symbol = symbol_item.get('symbol')
30+
next_page_token = symbol_item.get('nextPageToken')
3031
if 'items' in symbol_item:
3132
for item in symbol_item['items']:
32-
item_values = {'symbol': symbol}
33+
item_values = {'symbol': symbol, 'next_page_token': next_page_token}
3334
for key, value in item.items():
3435
if value is None:
3536
continue

0 commit comments

Comments
 (0)