Skip to content

Commit cf1a08c

Browse files
committed
Merge branch 'feature_algo_order' into 'dev_with_quote'
algo order support See merge request server/openapi/openapi-python-sdk!60
2 parents 5f96c60 + c498ff9 commit cf1a08c

File tree

7 files changed

+106
-13
lines changed

7 files changed

+106
-13
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
setup(
1414
name='tigeropen',
15-
version='1.2.0',
15+
version='1.3.0',
1616
description='TigerBrokers Open API',
1717
packages=find_packages(exclude=[]),
1818
author='TigerBrokers',

tigeropen/common/util/order_utils.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
@author: gaoan
66
"""
7-
from tigeropen.trade.domain.order import Order, OrderLeg
7+
from tigeropen.trade.domain.order import Order, OrderLeg, AlgoParams
88
from tigeropen.common.consts import OrderStatus
99

1010

@@ -101,6 +101,36 @@ def limit_order_with_legs(account, contract, action, quantity, limit_price, orde
101101
return Order(account, contract, action, 'LMT', quantity, limit_price=limit_price, order_legs=order_legs)
102102

103103

104+
def algo_order_params(start_time=None, end_time=None, no_take_liq=None, allow_past_end_time=None, participation_rate=None):
105+
"""
106+
算法订单参数
107+
:param start_time: 生效开始时间(时间戳 TWAP和VWAP专用)
108+
:param end_time: 生效结束时间(时间戳 TWAP和VWAP专用)
109+
:param no_take_liq: 是否尽可能减少交易次数(VWAP订单专用)
110+
:param allow_past_end_time: 是否允许生效时间结束后继续完成成交(TWAP和VWAP专用)
111+
:param participation_rate: 参与率(VWAP专用,0.01-0.5)
112+
:return:
113+
"""
114+
return AlgoParams(start_time=start_time, end_time=end_time, no_take_liq=no_take_liq,
115+
allow_past_end_time=allow_past_end_time, participation_rate=participation_rate)
116+
117+
118+
def algo_order(account, contract, action, quantity, strategy, algo_params=None, limit_price=None):
119+
"""
120+
算法订单
121+
:param account:
122+
:param contract:
123+
:param action:
124+
:param quantity:
125+
:param strategy: 交易量加权平均价格(VWAP)/时间加权平均价格(TWAP)
126+
:param algo_params: tigeropen.trade.domain.order.AlgoParams
127+
:param limit_price:
128+
:return:
129+
"""
130+
return Order(account, contract, action, order_type=strategy, quantity=quantity, algo_params=algo_params,
131+
limit_price=limit_price, outside_rth=False)
132+
133+
104134
def get_order_status(value):
105135
"""
106136
Invalid(-2), Initial(-1), PendingCancel(3), Cancelled(4), Submitted(5), Filled(6), Inactive(7), PendingSubmit(8)

tigeropen/examples/trade_client_demo.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
from tigeropen.quote.request import OpenApiRequest
1616
from tigeropen.examples.client_config import get_client_config
1717
# from tigeropen.common.consts import Currency, SecurityType
18-
# from tigeropen.common.util.contract_utils import stock_contract, option_contract_by_symbol, future_contract, \
19-
# war_contract_by_symbol, iopt_contract_by_symbol
20-
from tigeropen.common.util.order_utils import limit_order, limit_order_with_legs, order_leg
18+
from tigeropen.common.util.contract_utils import stock_contract, option_contract_by_symbol, future_contract, \
19+
war_contract_by_symbol, iopt_contract_by_symbol
20+
from tigeropen.common.util.order_utils import limit_order, limit_order_with_legs, order_leg, algo_order_params, \
21+
algo_order
2122

2223
logging.basicConfig(level=logging.INFO,
2324
format='%(asctime)s %(levelname)s %(message)s',
@@ -122,6 +123,17 @@ def trade_apis():
122123
print(order_legs)
123124

124125

126+
def algo_order_demo():
127+
account = client_config.account
128+
openapi_client = TradeClient(client_config, logger=logger)
129+
contract = stock_contract(symbol='AAPL', currency='USD')
130+
params = algo_order_params(start_time='2020-11-19 23:00:00', end_time='2020-11-19 23:50:00', no_take_liq=True,
131+
allow_past_end_time=True, participation_rate=0.1)
132+
order = algo_order(account, contract, 'BUY', 1000, 'VWAP', algo_params=params, limit_price=100.0)
133+
openapi_client.place_order(order)
134+
print(order)
135+
136+
125137
if __name__ == '__main__':
126138
get_account_info()
127139
get_account_apis()

tigeropen/trade/domain/order.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@
88
from tigeropen.common.consts import OrderStatus
99

1010
ORDER_FIELDS_TO_IGNORE = {'type', '_status', 'contract', '_remaining'}
11-
11+
ALGO_PARAMS_TAG_MAP = {'noTakeLiq': 'no_take_liq', 'startTime': 'start_time', 'endTime': 'end_time',
12+
'participationRate': 'participation_rate', 'allowPastEndTime': 'allow_past_end_time'}
1213

1314
class Order(object):
1415
__slots__ = ["account", "id", "order_id", "parent_id", "order_time", "reason", "trade_time", "contract", "action",
1516
"quantity", "filled", "_remaining", "avg_fill_price", "commission", "realized_pnl", "_status",
1617
"trail_stop_price", "limit_price", "aux_price", "trailing_percent", "percent_offset", "action",
17-
"order_type", "time_in_force", "outside_rth", "order_legs"]
18+
"order_type", "time_in_force", "outside_rth", "order_legs", "algo_params"]
1819

1920
def __init__(self, account, contract, action, order_type, quantity, limit_price=None, aux_price=None,
2021
trail_stop_price=None, trailing_percent=None, percent_offset=None, time_in_force=None,
2122
outside_rth=None, filled=0, avg_fill_price=0, commission=None, realized_pnl=None,
22-
id=None, order_id=None, parent_id=None, order_time=None, trade_time=None, order_legs=None):
23+
id=None, order_id=None, parent_id=None, order_time=None, trade_time=None, order_legs=None,
24+
algo_params=None):
2325
"""
2426
- account: 订单所属的账户
2527
- id: 全局订单 id
@@ -46,6 +48,7 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
4648
- status: Order_Status 的枚举, 表示订单状态
4749
- remaining: 未成交的数量
4850
- order_legs: 附加订单列表
51+
- algo_params: 算法订单参数
4952
"""
5053

5154
self.id = id
@@ -73,6 +76,7 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
7376
self.order_time = order_time
7477
self.trade_time = trade_time
7578
self.order_legs = order_legs
79+
self.algo_params = algo_params
7680

7781
def to_dict(self):
7882
dct = {name: getattr(self, name) for name in self.__slots__ if name not in ORDER_FIELDS_TO_IGNORE}
@@ -141,3 +145,44 @@ def to_dict(self):
141145

142146
def __repr__(self):
143147
return "OrderLeg(%s)" % self.to_dict()
148+
149+
150+
class AlgoParams(object):
151+
"""
152+
算法订单参数
153+
"""
154+
def __init__(self, start_time=None, end_time=None, no_take_liq=None, allow_past_end_time=None,
155+
participation_rate=None):
156+
"""
157+
:param start_time: 生效开始时间(时间戳 TWAP和VWAP专用)
158+
:param end_time: 生效结束时间(时间戳 TWAP和VWAP专用)
159+
:param no_take_liq: 是否尽可能减少交易次数(VWAP订单专用)
160+
:param allow_past_end_time: 是否允许生效时间结束后继续完成成交(TWAP和VWAP专用)
161+
:param participation_rate: 参与率(VWAP专用,0.01-0.5)
162+
"""
163+
self.start_time = start_time
164+
self.end_time = end_time
165+
self.no_take_liq = no_take_liq
166+
self.allow_past_end_time = allow_past_end_time
167+
self.participation_rate = participation_rate
168+
169+
def to_dict(self):
170+
return self.__dict__
171+
172+
@staticmethod
173+
def from_tags(tag_values):
174+
"""
175+
:param tag_values:
176+
:return: AlgoParams 对象
177+
"""
178+
algo_params = AlgoParams()
179+
if tag_values:
180+
for item in tag_values:
181+
tag = item.get('tag')
182+
value = item.get('value')
183+
setattr(algo_params, ALGO_PARAMS_TAG_MAP.get(tag), value)
184+
return algo_params
185+
return None
186+
187+
def __repr__(self):
188+
return "AlgoParams(%s)" % self.to_dict()

tigeropen/trade/request/model.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ def __init__(self):
503503
self.time_in_force = None
504504
self.outside_rth = None
505505
self.order_legs = None
506+
self.algo_params = None
506507

507508
def to_openapi_dict(self):
508509
params = dict()
@@ -582,6 +583,8 @@ def to_openapi_dict(self):
582583
if len(leg_types) == 2:
583584
params['attach_type'] = 'BRACKETS'
584585

586+
if self.algo_params:
587+
params['algo_params'] = [{'tag': item[0], 'value': item[1]} for item in self.algo_params.to_dict().items()]
585588
return params
586589

587590

tigeropen/trade/response/orders_response.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from tigeropen.common.util.string_utils import get_string
1111
from tigeropen.common.util.order_utils import get_order_status
1212
from tigeropen.trade.domain.contract import Contract
13-
from tigeropen.trade.domain.order import Order
13+
from tigeropen.trade.domain.order import Order, AlgoParams
1414
from tigeropen.trade.response import CONTRACT_FIELDS
1515

1616
ORDER_FIELD_MAPPINGS = {'parentId': 'parent_id', 'orderId': 'order_id', 'orderType': 'order_type',
@@ -22,7 +22,7 @@
2222
'timeInForce': 'time_in_force', 'openTime': 'order_time', 'latestTime': 'trade_time',
2323
'contractId': 'contract_id',
2424
'trailStopPrice': 'trail_stop_price', 'trailingPercent': 'trailing_percent',
25-
'percentOffset': 'percent_offset', 'identifier': 'identifier'}
25+
'percentOffset': 'percent_offset', 'identifier': 'identifier', 'algoParameters': 'algo_params'}
2626

2727

2828
class OrdersResponse(TigerResponse):
@@ -97,12 +97,13 @@ def parse_order(item):
9797
order_id = order_fields.get('order_id')
9898
parent_id = order_fields.get('parent_id')
9999
status = get_order_status(order_fields.get('status'))
100+
algo_params = AlgoParams.from_tags(order_fields.get('algo_params'))
100101

101102
order = Order(account, contract, action, order_type, quantity, limit_price=limit_price, aux_price=aux_price,
102103
trail_stop_price=trail_stop_price, trailing_percent=trailing_percent,
103104
percent_offset=percent_offset, time_in_force=time_in_force, outside_rth=outside_rth,
104105
filled=filled, avg_fill_price=avg_fill_price, commission=commission,
105-
realized_pnl=realized_pnl, id=id, order_id=order_id, parent_id=parent_id)
106+
realized_pnl=realized_pnl, id=id, order_id=order_id, parent_id=parent_id, algo_params=algo_params)
106107
if 'order_time' in order_fields:
107108
order.order_time = order_fields.get('order_time')
108109
if 'trade_time' in order_fields:

tigeropen/trade/trade_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def get_order(self, account=None, id=None, order_id=None, is_brief=False):
379379

380380
def create_order(self, account, contract, action, order_type, quantity, limit_price=None, aux_price=None,
381381
trail_stop_price=None, trailing_percent=None, percent_offset=None, time_in_force=None,
382-
outside_rth=None, order_legs=None):
382+
outside_rth=None, order_legs=None, algo_params=None):
383383
"""
384384
创建订单对象.
385385
:param account:
@@ -395,6 +395,7 @@ def create_order(self, account, contract, action, order_type, quantity, limit_pr
395395
:param time_in_force: 订单有效期, 'DAY'(当日有效)和'GTC'(取消前有效)
396396
:param outside_rth: 是否允许盘前盘后交易(美股专属)
397397
:param order_legs: 附加订单
398+
:param algo_params: 算法订单参数
398399
"""
399400
params = AccountsParams()
400401
params.account = account if account else self._account
@@ -409,7 +410,7 @@ def create_order(self, account, contract, action, order_type, quantity, limit_pr
409410
aux_price=aux_price, trail_stop_price=trail_stop_price,
410411
trailing_percent=trailing_percent, percent_offset=percent_offset,
411412
time_in_force=time_in_force, outside_rth=outside_rth, order_id=order_id,
412-
order_legs=order_legs)
413+
order_legs=order_legs, algo_params=algo_params)
413414
return order
414415
else:
415416
raise ApiException(response.code, response.message)
@@ -480,6 +481,7 @@ def place_order(self, order):
480481
params.time_in_force = order.time_in_force
481482
params.outside_rth = order.outside_rth
482483
params.order_legs = order.order_legs
484+
params.algo_params = order.algo_params
483485

484486
request = OpenApiRequest(PLACE_ORDER, biz_model=params)
485487
response_content = self.__fetch_data(request)

0 commit comments

Comments
 (0)