Skip to content

Commit dc5d722

Browse files
authored
Merge pull request #46 from tigerfintech/feature_api_order_transactions
Order/Contract add fields;
2 parents 9f7fc79 + ba479ae commit dc5d722

File tree

12 files changed

+108
-119
lines changed

12 files changed

+108
-119
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.6 (2022-01-24)
2+
### New
3+
- Contract 合约对象新增字段。
4+
marginable:是否可融资
5+
close_only:是否只允许平仓
6+
shortable_count:做空池剩余
7+
- Order 订单对象新增字段。
8+
attr_desc:属性描述(如期权是否为被动行权)
9+
source:订单来源
10+
11+
### Breaking
12+
-`tigeropen.quote.request.OpenApiRequest` 移动到 `tigeropen.common.request.OpenApiRequest`
13+
14+
115
## 2.0.5 (2022-01-10)
216
### New
317
- 查询行情权限接口 QuoteClient.get_quote_permission

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

tigeropen/common/request.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# @Date : 2022/1/20
4+
# @Author : sukai
5+
import json
6+
7+
from tigeropen.common.consts.params import P_METHOD, P_VERSION, P_BIZ_CONTENT
8+
9+
10+
class OpenApiRequest:
11+
def __init__(self, method, biz_model=None):
12+
self._method = method
13+
self._biz_model = biz_model
14+
15+
@property
16+
def biz_model(self):
17+
return self._biz_model
18+
19+
@biz_model.setter
20+
def biz_model(self, value):
21+
self._biz_model = value
22+
23+
def get_params(self):
24+
params = dict()
25+
params[P_METHOD] = self._method
26+
params[P_VERSION] = getattr(self.biz_model, P_VERSION, None)
27+
28+
if self.biz_model:
29+
params[P_BIZ_CONTENT] = json.dumps(obj=self.biz_model.to_openapi_dict(), ensure_ascii=False, sort_keys=True,
30+
separators=(',', ':'))
31+
32+
return params

tigeropen/examples/trade_client_demo.py

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99

1010
from tigeropen.trade.domain.order import OrderStatus
1111
from tigeropen.trade.request.model import AccountsParams
12-
from tigeropen.common.response import TigerResponse
1312
from tigeropen.tiger_open_client import TigerOpenClient
1413
from tigeropen.trade.trade_client import TradeClient
15-
from tigeropen.quote.request import OpenApiRequest
16-
from tigeropen.examples.client_config import get_client_config
14+
from tigeropen.common.response import TigerResponse
15+
from tigeropen.common.request import OpenApiRequest
1716
from tigeropen.common.consts import Currency, SecurityType
1817
from tigeropen.common.util.contract_utils import stock_contract, option_contract_by_symbol, future_contract, \
1918
war_contract_by_symbol, iopt_contract_by_symbol
2019
from tigeropen.common.util.order_utils import limit_order, limit_order_with_legs, order_leg, algo_order_params, \
2120
algo_order
21+
from tigeropen.examples.client_config import get_client_config
2222

2323
logging.basicConfig(level=logging.INFO,
2424
format='%(asctime)s %(levelname)s %(message)s',
@@ -28,29 +28,6 @@
2828
client_config = get_client_config()
2929

3030

31-
def get_account_info():
32-
from tigeropen.common.consts.service_types import ACCOUNTS
33-
openapi_client = TigerOpenClient(client_config)
34-
account = AccountsParams()
35-
account.account = client_config.account
36-
request = OpenApiRequest(method=ACCOUNTS, biz_model=account)
37-
38-
response_content = None
39-
try:
40-
response_content = openapi_client.execute(request)
41-
except Exception as e:
42-
print(traceback.format_exc())
43-
if not response_content:
44-
print("failed to execute")
45-
else:
46-
response = TigerResponse()
47-
response.parse_response_content(response_content)
48-
if response.is_success():
49-
print("get response data:" + response.data)
50-
else:
51-
print("%d,%s,%s" % (response.code, response.message, response.data))
52-
53-
5431
def get_account_apis():
5532
openapi_client = TradeClient(client_config, logger=logger)
5633
openapi_client.get_managed_accounts()
@@ -144,7 +121,33 @@ def algo_order_demo():
144121
print(order)
145122

146123

124+
def get_account_info():
125+
"""
126+
request by build OpenApiRequest. Not recommend.
127+
:return:
128+
"""
129+
from tigeropen.common.consts.service_types import ACCOUNTS
130+
openapi_client = TigerOpenClient(client_config)
131+
account = AccountsParams()
132+
account.account = client_config.account
133+
request = OpenApiRequest(method=ACCOUNTS, biz_model=account)
134+
135+
response_content = None
136+
try:
137+
response_content = openapi_client.execute(request)
138+
except Exception as e:
139+
print(traceback.format_exc())
140+
if not response_content:
141+
print("failed to execute")
142+
else:
143+
response = TigerResponse()
144+
response.parse_response_content(response_content)
145+
if response.is_success():
146+
print("get response data:" + response.data)
147+
else:
148+
print("%d,%s,%s" % (response.code, response.message, response.data))
149+
150+
147151
if __name__ == '__main__':
148-
get_account_info()
149152
get_account_apis()
150153
trade_apis()

tigeropen/quote/quote_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
FUTURE_CURRENT_CONTRACT, QUOTE_REAL_TIME, QUOTE_STOCK_TRADE, FINANCIAL_DAILY, FINANCIAL_REPORT, CORPORATE_ACTION, \
2020
QUOTE_DEPTH, INDUSTRY_LIST, INDUSTRY_STOCKS, STOCK_INDUSTRY, STOCK_DETAIL
2121
from tigeropen.common.exceptions import ApiException
22+
from tigeropen.common.request import OpenApiRequest
2223
from tigeropen.common.util.common_utils import eastern, get_enum_value
2324
from tigeropen.common.util.contract_utils import extract_option_info
2425
from tigeropen.fundamental.request.model import FinancialDailyParams, FinancialReportParams, CorporateActionParams, \
@@ -31,7 +32,6 @@
3132
from tigeropen.fundamental.response.industry_response import IndustryListResponse, IndustryStocksResponse, \
3233
StockIndustryResponse
3334
from tigeropen.quote.domain.filter import OptionFilter
34-
from tigeropen.quote.request import OpenApiRequest
3535
from tigeropen.quote.request.model import MarketParams, MultipleQuoteParams, MultipleContractParams, \
3636
FutureQuoteParams, FutureExchangeParams, FutureTypeParams, FutureTradingTimeParams, SingleContractParams, \
3737
SingleOptionQuoteParams, DepthQuoteParams, OptionChainParams

tigeropen/quote/request/__init__.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,4 @@
55
@author: gaoan
66
"""
77

8-
import json
9-
from tigeropen.common.consts.params import *
10-
from tigeropen.common.consts import OPEN_API_SERVICE_VERSION
118

12-
13-
class OpenApiRequest:
14-
def __init__(self, method, biz_model=None):
15-
self._method = method
16-
self._biz_model = biz_model
17-
18-
@property
19-
def biz_model(self):
20-
return self._biz_model
21-
22-
@biz_model.setter
23-
def biz_model(self, value):
24-
self._biz_model = value
25-
26-
def get_params(self):
27-
params = dict()
28-
params[P_METHOD] = self._method
29-
params[P_VERSION] = getattr(self.biz_model, P_VERSION, None)
30-
31-
if self.biz_model:
32-
params[P_BIZ_CONTENT] = json.dumps(obj=self.biz_model.to_openapi_dict(), ensure_ascii=False, sort_keys=True,
33-
separators=(',', ':'))
34-
35-
return params

tigeropen/trade/domain/contract.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
class Contract:
1212
def __init__(self, symbol=None, currency=None, contract_id=None, sec_type=None, exchange=None, origin_symbol=None,
1313
local_symbol=None, expiry=None, strike=None, put_call=None, multiplier=None, name=None,
14-
short_margin=None, short_fee_rate=None, shortable=None, long_initial_margin=None,
14+
short_margin=None, short_fee_rate=None, shortable=None, shortable_count=None, long_initial_margin=None,
1515
long_maintenance_margin=None, contract_month=None, identifier=None, primary_exchange=None,
1616
market=None, min_tick=None, trading_class=None, status=None, continuous=None, trade=None,
17+
marginable=None, close_only=None,
1718
last_trading_date=None, first_notice_date=None, last_bidding_close_time=None):
1819
self.contract_id = contract_id
1920
self.symbol = symbol
@@ -28,7 +29,6 @@ def __init__(self, symbol=None, currency=None, contract_id=None, sec_type=None,
2829
self.strike = strike
2930
# 看跌/看涨
3031
self.put_call = put_call
31-
self.right = self.put_call
3232
# 合约乘数
3333
self.multiplier = multiplier
3434
# 合约名称
@@ -39,6 +39,7 @@ def __init__(self, symbol=None, currency=None, contract_id=None, sec_type=None,
3939
self.short_fee_rate = short_fee_rate
4040
# 做空池剩余
4141
self.shortable = shortable
42+
self.shortable_count = shortable_count
4243
# 做多初始保证金
4344
self.long_initial_margin = long_initial_margin
4445
# 做多维持保证金
@@ -57,17 +58,25 @@ def __init__(self, symbol=None, currency=None, contract_id=None, sec_type=None,
5758
self.trading_class = trading_class
5859
# 状态
5960
self.status = status
61+
# is marginable
62+
self.marginable = marginable
63+
# is tradeable
64+
self.trade = trade
65+
# is only closed a position allowed
66+
self.close_only = close_only
6067
# 期货专有,是否连续合约
6168
self.continuous = continuous
62-
# 期货专有,是否可交易
63-
self.trade = trade
6469
# 期货专有,最后交易日
6570
self.last_trading_date = last_trading_date
6671
# 期货专有,第一通知日,合约在第一通知日后无法开多仓. 已有的多仓会在第一通知日之前(通常为前三个交易日)被强制平仓
6772
self.first_notice_date = first_notice_date
6873
# 期货专有,竞价截止时间
6974
self.last_bidding_close_time = last_bidding_close_time
7075

76+
@property
77+
def right(self):
78+
return self.put_call
79+
7180
def __repr__(self):
7281
identifier = self.identifier if self.identifier else self.symbol
7382
if self.sec_type == SecurityType.FUT.value:

tigeropen/trade/domain/order.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Order:
1616
"quantity", "filled", "_remaining", "avg_fill_price", "commission", "realized_pnl", "_status",
1717
"trail_stop_price", "limit_price", "aux_price", "trailing_percent", "percent_offset", "action",
1818
"order_type", "time_in_force", "outside_rth", "order_legs", "algo_params", "secret_key", "liquidation",
19-
"algo_strategy", "discount"]
19+
"algo_strategy", "discount", "attr_desc", "source"]
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,
@@ -86,6 +86,8 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
8686
self.liquidation = kwargs.get('liquidation')
8787
self.algo_strategy = kwargs.get('algo_strategy')
8888
self.discount = kwargs.get('discount')
89+
self.attr_desc = kwargs.get('attr_desc')
90+
self.source = kwargs.get("source")
8991

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

tigeropen/trade/response/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
CONTRACT_FIELDS = set(['symbol', 'market', 'multiplier', 'sec_type', 'currency', 'local_symbol', 'origin_symbol',
99
'expiry', 'strike', 'right', 'put_call', 'contract_id', 'exchange', 'name', 'short_margin', 'short_fee_rate',
1010
'shortable', 'long_initial_margin', 'long_maintenance_margin', 'contract_month', 'identifier',
11-
'primary_exchange', 'min_tick', 'trading_class', 'continuous', 'trade',
12-
'last_trading_date', 'first_notice_date', 'last_bidding_close_time'])
11+
'primary_exchange', 'min_tick', 'trading_class', 'continuous', 'trade', 'tradeable',
12+
'last_trading_date', 'first_notice_date', 'last_bidding_close_time', 'shortable_count'])
1313

tigeropen/trade/response/contracts_response.py

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@
77
import json
88

99
from tigeropen.common.response import TigerResponse
10+
from tigeropen.common.util.string_utils import camel_to_underline
1011
from tigeropen.trade.domain.contract import Contract
11-
from tigeropen.trade.response import CONTRACT_FIELDS
1212

13-
CONTRACT_FIELD_MAPPINGS = {'secType': 'sec_type', 'localSymbol': 'local_symbol', 'originSymbol': 'origin_symbol',
14-
'conid': 'contract_id', 'contractId': 'contract_id',
15-
'shortMargin': 'short_margin', 'shortFeeRate': 'short_fee_rate',
16-
'longInitialMargin': 'long_initial_margin', 'contractMonth': 'contract_month',
17-
'longMaintenanceMargin': 'long_maintenance_margin', 'primaryExchange': 'primary_exchange',
18-
'tradingClass': 'trading_class', 'lastTradingDate': 'last_trading_date',
19-
'minTick': 'min_tick', 'firstNoticeDate': 'first_notice_date',
20-
'lastBiddingCloseTime': 'last_bidding_close_time'}
13+
CONTRACT_FIELD_MAPPINGS = {'conid': 'contract_id', 'right': 'put_call', 'tradeable': 'trade'}
2114

2215

2316
class ContractsResponse(TigerResponse):
@@ -37,49 +30,9 @@ def parse_response_content(self, response_content):
3730
for item in data_json['items']:
3831
contract_fields = {}
3932
for key, value in item.items():
40-
if value is None:
41-
continue
42-
tag = CONTRACT_FIELD_MAPPINGS[key] if key in CONTRACT_FIELD_MAPPINGS else key
43-
if tag in CONTRACT_FIELDS:
44-
contract_fields[tag] = value
45-
46-
contract_id = contract_fields.get('contract_id')
47-
symbol = contract_fields.get('symbol')
48-
currency = contract_fields.get('currency')
49-
sec_type = contract_fields.get('sec_type')
50-
exchange = contract_fields.get('exchange')
51-
origin_symbol = contract_fields.get('origin_symbol')
52-
local_symbol = contract_fields.get('local_symbol')
53-
expiry = contract_fields.get('expiry')
54-
strike = contract_fields.get('strike')
55-
put_call = contract_fields.get('right')
56-
multiplier = contract_fields.get('multiplier')
57-
name = contract_fields.get('name')
58-
short_margin = contract_fields.get('short_margin')
59-
short_fee_rate = contract_fields.get('short_fee_rate')
60-
shortable = contract_fields.get('shortable')
61-
long_initial_margin = contract_fields.get('long_initial_margin')
62-
long_maintenance_margin = contract_fields.get('long_maintenance_margin')
63-
contract_month = contract_fields.get('contract_month')
64-
identifier = contract_fields.get('identifier')
65-
primary_exchange = contract_fields.get('primary_exchange')
66-
market = contract_fields.get('market')
67-
min_tick = contract_fields.get('min_tick')
68-
trading_class = contract_fields.get('trading_class')
69-
status = contract_fields.get('status')
70-
continuous = contract_fields.get('continuous')
71-
trade = contract_fields.get('trade')
72-
last_trading_date = contract_fields.get('last_trading_date')
73-
first_notice_date = contract_fields.get('first_notice_date')
74-
last_bidding_close_time = contract_fields.get('last_bidding_close_time')
75-
contract = Contract(symbol, currency, contract_id=contract_id, sec_type=sec_type, exchange=exchange,
76-
origin_symbol=origin_symbol, local_symbol=local_symbol, expiry=expiry,
77-
strike=strike, put_call=put_call, multiplier=multiplier, name=name,
78-
short_margin=short_margin, short_fee_rate=short_fee_rate, shortable=shortable,
79-
long_initial_margin=long_initial_margin, contract_month=contract_month,
80-
long_maintenance_margin=long_maintenance_margin, identifier=identifier,
81-
primary_exchange=primary_exchange, market=market, min_tick=min_tick,
82-
trading_class=trading_class, status=status, continuous=continuous, trade=trade,
83-
last_trading_date=last_trading_date, first_notice_date=first_notice_date,
84-
last_bidding_close_time=last_bidding_close_time)
33+
tag = CONTRACT_FIELD_MAPPINGS[key] if key in CONTRACT_FIELD_MAPPINGS else camel_to_underline(key)
34+
contract_fields[tag] = value
35+
contract = Contract()
36+
for k, v in contract_fields.items():
37+
setattr(contract, k, v)
8538
self.contracts.append(contract)

0 commit comments

Comments
 (0)