Skip to content

Commit 584eae7

Browse files
committed
capical flow api;
1 parent e140dfb commit 584eae7

File tree

11 files changed

+315
-24
lines changed

11 files changed

+315
-24
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 2.2.4 (2022-12-09)
2+
### new
3+
- 资金流接口 `QuoteClient.get_capital_flow`
4+
- 资金分布接口 `QuoteClient.get_capital_distribution`
5+
- 港股经纪商接口 `QuoteClient.get_stock_broker`
6+
7+
18
## 2.2.3 (2022-12-07)
29
### new
310
- 选股器 `QuoteClient.market_scanner`

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

tigeropen/common/consts/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ class BarPeriod(Enum):
107107
SIX_HOURS = '6hour' # 6小时
108108

109109

110+
class CapitalPeriod(Enum):
111+
INTRADAY = "intraday"
112+
DAY = "day"
113+
WEEK = "week"
114+
MONTH = "month"
115+
YEAR = "year"
116+
QUARTER = "quarter"
117+
HALFAYEAR = "6month"
118+
119+
110120
class OrderStatus(Enum):
111121
PENDING_NEW = 'PendingNew'
112122
NEW = 'Initial' # 订单初始状态

tigeropen/examples/quote_client_demo.py

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import pandas as pd
1111
from tigeropen.common.consts import Market, QuoteRight, FinancialReportPeriodType, Valuation, \
1212
Income, Balance, CashFlow, BalanceSheetRatio, Growth, Leverage, Profitability, IndustryLevel, BarPeriod, \
13-
SortDirection
13+
SortDirection, CapitalPeriod
1414
from tigeropen.common.consts.filter_fields import AccumulateField, StockField, FinancialField, MultiTagField, \
1515
AccumulatePeriod, FinancialPeriod
1616
from tigeropen.quote.domain.filter import OptionFilter, StockFilter, SortFilterData
@@ -187,7 +187,7 @@ def get_fundamental():
187187
print(stock_industry)
188188

189189

190-
def test_market_scanner(self):
190+
def test_market_scanner():
191191
# 股票基本数据过滤(is_no_filter为True时表示不启用该过滤器)
192192
base_filter1 = StockFilter(StockField.FloatShare, filter_min=1e7, filter_max=1e13, is_no_filter=True)
193193
base_filter2 = StockFilter(StockField.MarketValue, filter_min=1e8, filter_max=1e14, is_no_filter=False)
@@ -240,24 +240,47 @@ def test_market_scanner(self):
240240
print(f'scanned symbols:{scanner_result_symbols}')
241241

242242

243-
def test_stock_broker(self):
243+
def test_stock_broker():
244244
"""
245245
246246
:return:
247-
{'symbol': '00700',
248-
'bid_broker':
249-
[{'level': 1, 'price': 322.4, 'broker_count': 5,
250-
'broker': [{'id': '5345', 'name': 'J.P. Morgan'},
251-
{'id': '6996', 'name': '中国投资'}, {'id': '6999', 'name': '中国投资'}, {'id': '6999', 'name': '中国投资'},
252-
{'id': '6997', 'name': '中国投资'}]}],
253-
'ask_broker':
254-
[{'level': 1, 'price': 322.6, 'broker_count': 2,
255-
'broker': [{'id': '8461', 'name': 'FUTU Securities'}, {'id': '7389', 'name': '花旗'}]},
256-
{'level': 2, 'price': 322.8, 'broker_count': 3,
257-
'broker': [{'id': '6999', 'name': '中国投资'},
258-
{'id': '0746', 'name': '万邦亚太'}, {'id': '5339', 'name': 'J.P. Morgan'}]}]}
247+
StockBroker({'symbol': '01810',
248+
'bid_broker': [
249+
LevelBroker({'level': 1, 'price': 11.46, 'broker_count': 5,
250+
'broker': [Broker({'id': '5999', 'name': '中国创盈'}), Broker({'id': '4374', 'name': '巴克莱亚洲'}),
251+
Broker({'id': '1438', 'name': 'Susquehanna'}), Broker({'id': '4821', 'name': '华盛'}),
252+
Broker({'id': '6998', 'name': '中国投资'})]})],
253+
'ask_broker': [
254+
LevelBroker({'level': 1, 'price': 11.48, 'broker_count': 5,
255+
'broker': [Broker({'id': '4374', 'name': '巴克莱亚洲'}), Broker({'id': '9056', 'name': '瑞银'}),
256+
Broker({'id': '2027', 'name': '东亚'}), Broker({'id': '4821', 'name': '华盛'}),
257+
Broker({'id': '4374', 'name': '巴克莱亚洲'})]})]})
259258
"""
260-
result = openapi_client.get_stock_broker('00700', limit=5)
259+
result = openapi_client.get_stock_broker('01810', limit=5)
260+
print(result)
261+
262+
263+
def test_capital_flow():
264+
"""
265+
time timestamp net_inflow symbol period
266+
0 2022-02-24 1645678800000 -5.889058e+08 AAPL day
267+
1 2022-02-25 1645765200000 -1.229127e+08 AAPL day
268+
2 2022-02-28 1646024400000 1.763644e+08 AAPL day
269+
"""
270+
result = openapi_client.get_capital_flow('AAPL', market=Market.US, period=CapitalPeriod.INTRADAY)
271+
print(result)
272+
273+
274+
def test_capital_distribution():
275+
"""
276+
277+
:return:
278+
CapitalDistribution({'symbol': 'JD', 'net_inflow': -14178801.76, 'in_all': 157357147.5,
279+
'in_big': 25577130.842900004, 'in_mid': 13664116.789999994, 'in_small': 118115899.86410056,
280+
'out_all': 171535949.25, 'out_big': 22642951.677099995, 'out_mid': 12733553.691200001,
281+
'out_small': 136159443.88620025})
282+
"""
283+
result = openapi_client.get_capital_distribution('JD', market=Market.US)
261284
print(result)
262285

263286

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/12/9
4+
# @Author : sukai
5+
class CapitalDistribution:
6+
def __init__(self):
7+
self.symbol = None
8+
self.net_inflow = None
9+
self.in_all = None
10+
self.in_big = None
11+
self.in_mid = None
12+
self.in_small = None
13+
self.out_all = None
14+
self.out_big = None
15+
self.out_mid = None
16+
self.out_small = None
17+
18+
def __repr__(self):
19+
return "CapitalDistribution(%s)" % self.__dict__
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/12/9
4+
# @Author : sukai
5+
6+
class Broker:
7+
def __init__(self):
8+
self.id = None
9+
self.name = None
10+
11+
def __repr__(self):
12+
return "Broker(%s)" % self.__dict__
13+
14+
15+
class LevelBroker:
16+
def __init__(self):
17+
self.level = None
18+
self.price = None
19+
self.broker_count = None
20+
self.broker = None
21+
22+
def __repr__(self):
23+
return "LevelBroker(%s)" % self.__dict__
24+
25+
26+
class StockBroker:
27+
def __init__(self):
28+
self.symbol = None
29+
self.bid_broker = None
30+
self.ask_broker = None
31+
32+
def __repr__(self):
33+
return "StockBroker(%s)" % self.__dict__

tigeropen/quote/quote_client.py

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
from tigeropen.common.consts import THREAD_LOCAL, SecurityType, CorporateActionType, IndustryLevel
1616
from tigeropen.common.consts.filter_fields import FieldBelongType
1717
from tigeropen.common.consts.service_types import GRAB_QUOTE_PERMISSION, QUOTE_DELAY, GET_QUOTE_PERMISSION, \
18-
HISTORY_TIMELINE, FUTURE_CONTRACT_BY_CONTRACT_CODE, TRADING_CALENDAR, FUTURE_CONTRACTS, MARKET_SCANNER, STOCK_BROKER
18+
HISTORY_TIMELINE, FUTURE_CONTRACT_BY_CONTRACT_CODE, TRADING_CALENDAR, FUTURE_CONTRACTS, MARKET_SCANNER, \
19+
STOCK_BROKER, CAPITAL_FLOW, CAPITAL_DISTRIBUTION
1920
from tigeropen.common.consts.service_types import MARKET_STATE, ALL_SYMBOLS, ALL_SYMBOL_NAMES, BRIEF, \
2021
TIMELINE, KLINE, TRADE_TICK, OPTION_EXPIRATION, OPTION_CHAIN, FUTURE_EXCHANGE, OPTION_BRIEF, \
2122
OPTION_KLINE, OPTION_TRADE_TICK, FUTURE_KLINE, FUTURE_TICK, FUTURE_CONTRACT_BY_EXCHANGE_CODE, \
@@ -39,7 +40,9 @@
3940
from tigeropen.quote.request.model import MarketParams, MultipleQuoteParams, MultipleContractParams, \
4041
FutureQuoteParams, FutureExchangeParams, FutureContractParams, FutureTradingTimeParams, SingleContractParams, \
4142
SingleOptionQuoteParams, DepthQuoteParams, OptionChainParams, TradingCalendarParams, MarketScannerParams, \
42-
StockBrokerParams
43+
StockBrokerParams, CapitalParams
44+
from tigeropen.quote.response.capital_distribution_response import CapitalDistributionResponse
45+
from tigeropen.quote.response.capital_flow_response import CapitalFlowResponse
4346
from tigeropen.quote.response.future_briefs_response import FutureBriefsResponse
4447
from tigeropen.quote.response.future_contract_response import FutureContractResponse
4548
from tigeropen.quote.response.future_exchange_response import FutureExchangeResponse
@@ -1411,7 +1414,6 @@ def grab_quote_permission(self):
14111414
return response.permissions
14121415
else:
14131416
raise ApiException(response.code, response.message)
1414-
return False
14151417

14161418
def get_quote_permission(self):
14171419
"""
@@ -1431,7 +1433,6 @@ def get_quote_permission(self):
14311433
return response.permissions
14321434
else:
14331435
raise ApiException(response.code, response.message)
1434-
return False
14351436

14361437
def get_trading_calendar(self, market, begin_date=None, end_date=None):
14371438
"""
@@ -1455,7 +1456,6 @@ def get_trading_calendar(self, market, begin_date=None, end_date=None):
14551456
return response.calendar
14561457
else:
14571458
raise ApiException(response.code, response.message)
1458-
return False
14591459

14601460
def get_stock_broker(self, symbol, limit=40, lang=None):
14611461
"""Get stock broker information
@@ -1476,4 +1476,52 @@ def get_stock_broker(self, symbol, limit=40, lang=None):
14761476
return response.result
14771477
else:
14781478
raise ApiException(response.code, response.message)
1479-
return False
1479+
1480+
def get_capital_flow(self, symbol, market, period, begin_time=-1, end_time=-1, limit=200, lang=None):
1481+
"""Get capital net inflow Data, including different time periods, such as daily, weekly, monthly, etc.
1482+
:param symbol: 股票代号
1483+
:param market: tigeropen.common.consts.Market
1484+
:param period: period, possible values are: intraday, day, week, month, year, quarter, 6month
1485+
:param begin_time: 开始时间. 若是时间戳需要精确到毫秒, 为13位整数;
1486+
或是日期时间格式的字符串, 如 "2019-01-01" 或 "2019-01-01 12:00:00"
1487+
:param end_time: 结束时间. 格式同 begin_time
1488+
:param limit: 数量限制
1489+
:param lang: 语言支持: zh_CN,zh_TW,en_US
1490+
"""
1491+
params = CapitalParams()
1492+
params.symbol = symbol
1493+
params.market = get_enum_value(market)
1494+
params.period = get_enum_value(period)
1495+
params.begin_time = begin_time
1496+
params.end_time = end_time
1497+
params.limit = limit
1498+
params.lang = get_enum_value(lang) if lang else get_enum_value(self._lang)
1499+
request = OpenApiRequest(CAPITAL_FLOW, biz_model=params)
1500+
response_content = self.__fetch_data(request)
1501+
if response_content:
1502+
response = CapitalFlowResponse()
1503+
response.parse_response_content(response_content)
1504+
if response.is_success():
1505+
return response.result
1506+
else:
1507+
raise ApiException(response.code, response.message)
1508+
1509+
def get_capital_distribution(self, symbol, market, lang=None):
1510+
"""Get capital distribution.
1511+
:param symbol: 股票代号
1512+
:param market: tigeropen.common.consts.Market
1513+
:param lang: 语言支持: zh_CN,zh_TW,en_US
1514+
"""
1515+
params = CapitalParams()
1516+
params.symbol = symbol
1517+
params.market = get_enum_value(market)
1518+
params.lang = get_enum_value(lang) if lang else get_enum_value(self._lang)
1519+
request = OpenApiRequest(CAPITAL_DISTRIBUTION, biz_model=params)
1520+
response_content = self.__fetch_data(request)
1521+
if response_content:
1522+
response = CapitalDistributionResponse()
1523+
response.parse_response_content(response_content)
1524+
if response.is_success():
1525+
return response.result
1526+
else:
1527+
raise ApiException(response.code, response.message)

tigeropen/quote/request/model.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,3 +979,78 @@ def to_openapi_dict(self):
979979
if self.limit:
980980
params['limit'] = self.limit
981981
return params
982+
983+
984+
class CapitalParams(BaseParams):
985+
def __init__(self):
986+
super().__init__()
987+
self._symbol = None
988+
self._market = None
989+
self._period = None
990+
self._begin_time = None
991+
self._end_time = None
992+
self._limit = None
993+
994+
@property
995+
def symbol(self):
996+
return self._symbol
997+
998+
@symbol.setter
999+
def symbol(self, value):
1000+
self._symbol = value
1001+
1002+
@property
1003+
def market(self):
1004+
return self._market
1005+
1006+
@market.setter
1007+
def market(self, value):
1008+
self._market = value
1009+
1010+
@property
1011+
def period(self):
1012+
return self._period
1013+
1014+
@period.setter
1015+
def period(self, value):
1016+
self._period = value
1017+
1018+
@property
1019+
def begin_time(self):
1020+
return self._begin_time
1021+
1022+
@begin_time.setter
1023+
def begin_time(self, value):
1024+
self._begin_time = value
1025+
1026+
@property
1027+
def end_time(self):
1028+
return self._end_time
1029+
1030+
@end_time.setter
1031+
def end_time(self, value):
1032+
self._end_time = value
1033+
1034+
@property
1035+
def limit(self):
1036+
return self._limit
1037+
1038+
@limit.setter
1039+
def limit(self, value):
1040+
self._limit = value
1041+
1042+
def to_openapi_dict(self):
1043+
params = super().to_openapi_dict()
1044+
if self.symbol:
1045+
params['symbol'] = self.symbol
1046+
if self.market:
1047+
params['market'] = self.market
1048+
if self.period:
1049+
params['period'] = self.period
1050+
if self.begin_time:
1051+
params['begin_time'] = self.begin_time
1052+
if self.end_time:
1053+
params['end_time'] = self.end_time
1054+
if self.limit:
1055+
params['limit'] = self.limit
1056+
return params
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022-12-09
4+
# @Author : sukai
5+
from tigeropen.common.response import TigerResponse
6+
from tigeropen.common.util import string_utils
7+
from tigeropen.quote.domain.capital_distribution import CapitalDistribution
8+
9+
10+
class CapitalDistributionResponse(TigerResponse):
11+
def __init__(self):
12+
super().__init__()
13+
self.result = None
14+
self._is_success = None
15+
16+
def parse_response_content(self, response_content):
17+
response = super().parse_response_content(response_content)
18+
if 'is_success' in response:
19+
self._is_success = response['is_success']
20+
21+
if self.data:
22+
capital_distribution = CapitalDistribution()
23+
capital_distribution.__dict__ = string_utils.camel_to_underline_obj(self.data)
24+
self.result = capital_distribution

0 commit comments

Comments
 (0)