Skip to content

Commit 81c9f5b

Browse files
committed
prime assets api
1 parent 90c6ac4 commit 81c9f5b

File tree

7 files changed

+166
-2
lines changed

7 files changed

+166
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.4
2+
### New
3+
- 综合/模拟账户查询资产接口 TradeClient.get_prime_assets
4+
15
## 2.0.3 (2021-12-01)
26
### New
37
- 期权链查询接口支持过滤 QuoteClient.get_option_chain

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

tigeropen/common/consts/service_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"""
1717
ACCOUNTS = "accounts"
1818
ASSETS = "assets"
19+
PRIME_ASSETS = "prime_assets"
1920
POSITIONS = "positions"
2021
ORDERS = "orders"
2122
ACTIVE_ORDERS = "active_orders" # 待成交订单

tigeropen/common/util/string_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@ def add_start_end(key, start_marker, end_marker):
1919

2020
def camel_to_underline(hunp_str):
2121
return re.sub(CAMEL_PATTERN, r'\1_\2', hunp_str).lower()
22+
23+
24+
def camel_to_underline_obj(d):
25+
if isinstance(d, list):
26+
return [camel_to_underline_obj(i) if isinstance(i, (dict, list)) else i for i in d]
27+
return {camel_to_underline(k): camel_to_underline_obj(v) if isinstance(v, (dict, list)) else v
28+
for k, v in d.items()}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2021/12/2
4+
# @Author : sukai
5+
MODEL_REPR = '{}({})'
6+
7+
8+
class PortfolioAccount:
9+
"""
10+
prime/paper account assets
11+
"""
12+
def __init__(self, account):
13+
self.account = account
14+
self._segments = dict()
15+
16+
@property
17+
def segments(self):
18+
"""account information by contract type
19+
:return: dict with two keys, 'SEC' for stocks, 'FUT' for futures;
20+
"""
21+
return self._segments
22+
23+
def add_segment(self, segment):
24+
if segment.category not in self._segments:
25+
self._segments[segment.category] = segment
26+
return segment
27+
else:
28+
return self._segments.get(segment.category)
29+
30+
def __repr__(self):
31+
d = {'account': self.account, 'segments': self.segments}
32+
return MODEL_REPR.format(self.__class__.__name__, d)
33+
34+
35+
class Segment:
36+
def __init__(self):
37+
self.currency = None
38+
self.capability = None
39+
self.category = None
40+
self.cash_balance = float('inf')
41+
self.cash_available_for_trade = float('inf')
42+
self.cash_available_for_withdrawal = float('inf')
43+
self.gross_position_value = float('inf')
44+
self.equity_with_loan = float('inf')
45+
self.net_liquidation = float('inf')
46+
self.init_margin = float('inf')
47+
self.maintain_margin = float('inf')
48+
self.overnight_margin = float('inf')
49+
self.unrealized_pl = float('inf')
50+
self.realized_pl = float('inf')
51+
self.excess_liquidation = float('inf')
52+
self.overnight_liquidation = float('inf')
53+
self.buying_power = float('inf')
54+
self.leverage = float('inf')
55+
self._currency_assets = dict()
56+
57+
@property
58+
def currency_assets(self):
59+
return self._currency_assets
60+
61+
def add_currency_asset(self, asset):
62+
if asset.currency not in self._currency_assets:
63+
self._currency_assets[asset.currency] = asset
64+
return asset
65+
else:
66+
return self._currency_assets.get(asset.currency)
67+
68+
def __repr__(self):
69+
d = {k: v for k, v in self.__dict__.items() if not k.startswith('_')}
70+
d['currency_assets'] = self.currency_assets
71+
return MODEL_REPR.format(self.__class__.__name__, d)
72+
73+
74+
class CurrencyAsset:
75+
def __init__(self):
76+
self.currency = None
77+
self.cash_balance = float('inf')
78+
self.cash_available_for_trade = float('inf')
79+
self.gross_position_value = float('inf')
80+
self.stock_market_value = float('inf')
81+
self.futures_market_value = float('inf')
82+
self.option_market_value = float('inf')
83+
self.unrealized_pl = float('inf')
84+
self.realized_pl = float('inf')
85+
86+
@staticmethod
87+
def from_dict(d):
88+
currency_asset = CurrencyAsset()
89+
currency_asset.__dict__.update(d)
90+
return currency_asset
91+
92+
def __repr__(self):
93+
return MODEL_REPR.format(self.__class__.__name__, self.__dict__)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2021/12/2
4+
# @Author : sukai
5+
6+
from tigeropen.common.response import TigerResponse
7+
from tigeropen.trade.domain.prime_account import PortfolioAccount, Segment, CurrencyAsset
8+
from tigeropen.common.util.string_utils import camel_to_underline, camel_to_underline_obj
9+
10+
11+
class PrimeAssetsResponse(TigerResponse):
12+
def __init__(self):
13+
super(PrimeAssetsResponse, self).__init__()
14+
self.assets = None
15+
self._is_success = None
16+
17+
def parse_response_content(self, response_content):
18+
response = super(PrimeAssetsResponse, self).parse_response_content(response_content)
19+
if 'is_success' in response:
20+
self._is_success = response['is_success']
21+
22+
if self.data:
23+
assets = PortfolioAccount(self.data['accountId'])
24+
25+
for segment_data in self.data.get('segments', list()):
26+
segment = Segment()
27+
for key, value in segment_data.items():
28+
if key == 'currencyAssets':
29+
currency_assets = camel_to_underline_obj(value)
30+
[segment.add_currency_asset(CurrencyAsset.from_dict(i)) for i in currency_assets]
31+
else:
32+
setattr(segment, camel_to_underline(key), value)
33+
assets.add_segment(segment)
34+
self.assets = assets
35+
36+

tigeropen/trade/trade_client.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
from tigeropen.common.consts import THREAD_LOCAL, SecurityType, Market, Currency
1010
from tigeropen.common.consts.service_types import CONTRACTS, ACCOUNTS, POSITIONS, ASSETS, ORDERS, ORDER_NO, \
11-
CANCEL_ORDER, MODIFY_ORDER, PLACE_ORDER, ACTIVE_ORDERS, INACTIVE_ORDERS, FILLED_ORDERS, CONTRACT, PREVIEW_ORDER
11+
CANCEL_ORDER, MODIFY_ORDER, PLACE_ORDER, ACTIVE_ORDERS, INACTIVE_ORDERS, FILLED_ORDERS, CONTRACT, PREVIEW_ORDER, \
12+
PRIME_ASSETS
1213
from tigeropen.common.exceptions import ApiException
1314
from tigeropen.quote.request import OpenApiRequest
1415
from tigeropen.tiger_open_client import TigerOpenClient
@@ -22,6 +23,7 @@
2223
from tigeropen.trade.response.order_preview_response import PreviewOrderResponse
2324
from tigeropen.trade.response.orders_response import OrdersResponse
2425
from tigeropen.trade.response.positions_response import PositionsResponse
26+
from tigeropen.trade.response.prime_assets_response import PrimeAssetsResponse
2527

2628

2729
class TradeClient(TigerOpenClient):
@@ -241,6 +243,27 @@ def get_assets(self, account=None, sub_accounts=None, segment=False, market_valu
241243

242244
return None
243245

246+
def get_prime_assets(self, account=None):
247+
"""
248+
get prime account assets
249+
:param account:
250+
:return: tigeropen.trade.domain.prime_account.PortfolioAccount
251+
"""
252+
params = AssetParams()
253+
params.account = account if account else self._account
254+
params.secret_key = self._secret_key
255+
256+
request = OpenApiRequest(PRIME_ASSETS, biz_model=params)
257+
response_content = self.__fetch_data(request)
258+
if response_content:
259+
response = PrimeAssetsResponse()
260+
response.parse_response_content(response_content)
261+
if response.is_success():
262+
return response.assets
263+
else:
264+
raise ApiException(response.code, response.message)
265+
return None
266+
244267
def get_orders(self, account=None, sec_type=None, market=Market.ALL, symbol=None, start_time=None, end_time=None,
245268
limit=100, is_brief=False, states=None):
246269
"""

0 commit comments

Comments
 (0)