Skip to content

Commit e6b7a76

Browse files
committed
attach order
1 parent 80e14d4 commit e6b7a76

File tree

5 files changed

+149
-19
lines changed

5 files changed

+149
-19
lines changed

tigeropen/common/util/order_utils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ def trail_order(account, contract, action, quantity, trailing_percent=None, aux_
7474
return Order(account, contract, action, 'TRAIL', quantity, trailing_percent=trailing_percent, aux_price=aux_price)
7575

7676

77+
def limit_order_with_attach(account, contract, action, quantity, limit_price, attach_type=None, stop_loss_price=None,
78+
stop_loss_tif='DAY', profit_taker_price=None, profit_taker_tif='DAY'):
79+
"""
80+
限价单 + 附加订单(仅环球账户支持)
81+
:param account:
82+
:param contract:
83+
:param action: BUY/SELL
84+
:param quantity:
85+
:param limit_price: 限价单价格
86+
:param attach_type: 附加订单类型. PROFIT 止盈单类型, LOSS 止损单类型, BRACKETS 括号订单类型(止损和止盈)
87+
:param stop_loss_price: 附加止损单价格. attach_type 为 LOSS 或 BRACKETS 时必选
88+
:param stop_loss_tif: 附加止损单有效期. 'DAY'(当日有效)和'GTC'(取消前有效 Good-Til-Canceled).
89+
:param profit_taker_price: 附加止盈单价格. attach_type 为 PROFIT 或 BRACKETS 时必选
90+
:param profit_taker_tif: 附加止盈单有效期. 'DAY'(当日有效)和'GTC'(取消前有效).
91+
:return:
92+
"""
93+
return Order(account, contract, action, 'LMT', quantity, limit_price=limit_price, attach_type=attach_type,
94+
stop_loss_price=stop_loss_price, stop_loss_tif=stop_loss_tif, profit_taker_price=profit_taker_price,
95+
profit_taker_tif=profit_taker_tif)
96+
97+
7798
def get_order_status(value):
7899
"""
79100
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
from tigeropen.quote.request import OpenApiRequest
1616
from tigeropen.examples.client_config import get_client_config
1717
# from tigeropen.common.util.contract_utils import stock_contract, option_contract, future_contract
18-
# from tigeropen.common.util.order_utils import limit_order
18+
from tigeropen.common.util.order_utils import limit_order, limit_order_with_attach
19+
1920

2021
logging.basicConfig(level=logging.INFO,
2122
format='%(asctime)s %(levelname)s %(message)s',
@@ -96,6 +97,19 @@ def trade_apis():
9697
result = openapi_client.preview_order(order)
9798
print(result)
9899

100+
# 限价单 + 附加订单 (仅主订单为限价单时支持附加订单)
101+
main_order = openapi_client.create_order(account, contract, 'BUY', 'LMT', quantity=100, limit_price=10.0,
102+
attach_type='BRACKETS', stop_loss_price=8.0, stop_loss_tif='GTC',
103+
profit_taker_price=12.0, profit_taker_tif='GTC')
104+
# 本地构造限价单 + 附加订单
105+
# main_order = limit_order_with_attach(account, contract, 'BUY', 100, limit_price=10.0, attach_type='LOSS',
106+
# stop_loss_price=8.0, stop_loss_tif='DAY')
107+
openapi_client.place_order(main_order)
108+
print(main_order)
109+
# 查询主订单所关联的附加订单
110+
attach_orders = openapi_client.get_open_orders(account, parent_id=main_order.order_id)
111+
print(attach_orders)
112+
99113

100114
if __name__ == '__main__':
101115
get_account_info()

tigeropen/trade/domain/order.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,52 @@ class Order(object):
1414
__slots__ = ["account", "id", "order_id", "parent_id", "order_time", "reason", "trade_time", "contract", "action",
1515
"quantity", "filled", "_remaining", "avg_fill_price", "commission", "realized_pnl", "_status",
1616
"trail_stop_price", "limit_price", "aux_price", "trailing_percent", "percent_offset", "action",
17-
"order_type", "time_in_force", "outside_rth"]
17+
"order_type", "time_in_force", "outside_rth", "attach_type", "stop_loss_price", "stop_loss_tif",
18+
"stop_loss_rth", "stop_loss_order_id", "profit_taker_price", "profit_taker_tif", "profit_taker_rth",
19+
"profit_taker_order_id"]
1820

1921
def __init__(self, account, contract, action, order_type, quantity, limit_price=None, aux_price=None,
2022
trail_stop_price=None, trailing_percent=None, percent_offset=None, time_in_force=None,
2123
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):
24+
id=None, order_id=None, parent_id=None, order_time=None, trade_time=None,
25+
attach_type=None, stop_loss_price=None, stop_loss_tif=None, stop_loss_rth=None,
26+
stop_loss_order_id=None, profit_taker_price=None, profit_taker_tif=None, profit_taker_rth=None,
27+
profit_taker_order_id=None):
2328
"""
2429
- account: 订单所属的账户
2530
- id: 全局订单 id
2631
- order_id: 账户自增订单号
27-
- parent_id: 母订单id,目前只用于 TigerTrade App端的附加订单中
32+
- parent_id: 主订单id, 目前只用于 TigerTrade App端的附加订单中
2833
- order_time: 下单时间
29-
- reason: 下单失败时会返回失败原因的描述
34+
- reason: 下单失败时, 会返回失败原因的描述
3035
- trade_time: 最新成交时间
31-
- action: 交易方向 'BUY' / 'SELL'
36+
- action: 交易方向, 'BUY' / 'SELL'
3237
- quantity: 下单数量
3338
- filled: 成交数量
3439
- avg_fill_price: 包含佣金的平均成交价
35-
- commission: 包含佣金印花税证监会费等系列费用
40+
- commission: 包含佣金, 印花税, 证监会费等系列费用
3641
- realized_pnl: 实现盈亏
3742
- trail_stop_price: 跟踪止损单--触发止损单的价格
3843
- limit_price: 限价单价格
39-
- aux_price: 在止损单中表示出发止损单的价格 在移动止损单中 表示跟踪的价差
40-
- trailing_percent: 跟踪止损单-百分比取值范围为0-100
44+
- aux_price: 在止损单中, 表示出发止损单的价格, 在移动止损单中, 表示跟踪的价差
45+
- trailing_percent: 跟踪止损单-百分比, 取值范围为0-100
4146
- percent_offset: None,
42-
- order_type: 订单类型, 'MKT'市价单/'LMT'限价单/'STP'止损单/'STP_LMT'止损限价单/'TRAIL'跟踪止损单
43-
- time_in_force: 有效期,'DAY'日内有效/'GTC'撤销前有效
44-
- outside_rth: 是否支持盘前盘后交易,美股专属
47+
- order_type: 订单类型, 'MKT' 市价单 / 'LMT' 限价单 / 'STP' 止损单 / 'STP_LMT' 止损限价单 / 'TRAIL' 跟踪止损单
48+
- time_in_force: 有效期,'DAY' 日内有效 / 'GTC' 撤销前有效
49+
- outside_rth: 是否允许盘前盘后交易(美股专属). True 允许, False 不允许
4550
- contract: 合约对象
46-
- status: Order_Status 的枚举 表示订单状态
51+
- status: Order_Status 的枚举, 表示订单状态
4752
- remaining: 未成交的数量
53+
54+
- attach_type: 附加订单类型(仅限价单支持附加订单). PROFIT 止盈单类型, LOSS 止损单类型, BRACKETS 括号订单类型(止损和止盈)
55+
- stop_loss_price: 附加止损单价格
56+
- stop_loss_tif: 附加止损单有效期. 同 time_in_force 字段. 'DAY' 日内有效 / 'GTC' 撤销前有效
57+
- stop_loss_rth: 附加止损单是否允许盘前盘后交易(美股专属). True 允许, False 不允许. 同 outside_rth 字段
58+
- stop_loss_order_id: 附加止损单号. 可以通过订单号接口获取, 如果传0或为空, 则服务器端会自动生成止损单号
59+
- profit_taker_price: 附加止盈单价格
60+
- profit_taker_tif: 附加止盈单有效期. 同 time_in_force 字段. 'DAY' 日内有效 / 'GTC' 撤销前有效
61+
- profit_taker_rth: 附加止盈单是否允许盘前盘后交易(美股专属). True 允许, False 不允许. 同 outside_rth 字段
62+
- profit_taker_order_id: 附加止盈单号. 可以通过订单号接口获取, 如果传0或为空, 则服务器端会自动生成止盈单号
4863
"""
4964

5065
self.id = id
@@ -71,6 +86,15 @@ def __init__(self, account, contract, action, order_type, quantity, limit_price=
7186
self.percent_offset = percent_offset
7287
self.order_time = order_time
7388
self.trade_time = trade_time
89+
self.attach_type = attach_type
90+
self.stop_loss_price = stop_loss_price
91+
self.stop_loss_tif = stop_loss_tif
92+
self.stop_loss_rth = stop_loss_rth
93+
self.stop_loss_order_id = stop_loss_order_id
94+
self.profit_taker_price = profit_taker_price
95+
self.profit_taker_tif = profit_taker_tif
96+
self.profit_taker_rth = profit_taker_rth
97+
self.profit_taker_order_id = profit_taker_order_id
7498

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

tigeropen/trade/request/model.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def expiry(self):
228228

229229
@expiry.setter
230230
def expiry(self, value):
231-
self._expiry= value
231+
self._expiry = value
232232

233233
@property
234234
def strike(self):
@@ -358,6 +358,7 @@ def __init__(self):
358358
self._end_date = None
359359
self._limit = None
360360
self._states = None
361+
self._parent_id = None
361362

362363
@property
363364
def account(self):
@@ -439,6 +440,14 @@ def states(self):
439440
def states(self, value):
440441
self._states = value
441442

443+
@property
444+
def parent_id(self):
445+
return self._parent_id
446+
447+
@parent_id.setter
448+
def parent_id(self, value):
449+
self._parent_id = value
450+
442451
def to_openapi_dict(self):
443452
params = dict()
444453
if self.account:
@@ -471,6 +480,9 @@ def to_openapi_dict(self):
471480
if self.states:
472481
params['states'] = self.states
473482

483+
if self.parent_id:
484+
params['parent_id'] = self.parent_id
485+
474486
return params
475487

476488

@@ -490,6 +502,15 @@ def __init__(self):
490502
self.percent_offset = None
491503
self.time_in_force = None
492504
self.outside_rth = None
505+
self.attach_type = None
506+
self.profit_taker_order_id = None
507+
self.profit_taker_price = None
508+
self.profit_taker_tif = None
509+
self.profit_taker_rth = None
510+
self.stop_loss_order_id = None
511+
self.stop_loss_price = None
512+
self.stop_loss_tif = None
513+
self.stop_loss_rth = None
493514

494515
def to_openapi_dict(self):
495516
params = dict()
@@ -542,6 +563,25 @@ def to_openapi_dict(self):
542563
if self.outside_rth is not None:
543564
params['outside_rth'] = self.outside_rth
544565

566+
if self.attach_type is not None:
567+
params['attach_type'] = self.attach_type
568+
if self.profit_taker_order_id is not None:
569+
params['profit_taker_order_id'] = self.profit_taker_order_id
570+
if self.profit_taker_price is not None:
571+
params['profit_taker_price'] = self.profit_taker_price
572+
if self.profit_taker_tif is not None:
573+
params['profit_taker_tif'] = self.profit_taker_tif
574+
if self.profit_taker_rth is not None:
575+
params['profit_taker_rth'] = self.profit_taker_rth
576+
if self.stop_loss_order_id is not None:
577+
params['stop_loss_order_id'] = self.stop_loss_order_id
578+
if self.stop_loss_price is not None:
579+
params['stop_loss_price'] = self.stop_loss_price
580+
if self.stop_loss_tif is not None:
581+
params['stop_loss_tif'] = self.stop_loss_tif
582+
if self.stop_loss_rth is not None:
583+
params['stop_loss_rth'] = self.stop_loss_rth
584+
545585
return params
546586

547587

tigeropen/trade/trade_client.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,10 @@ def get_orders(self, account=None, sec_type=None, market=Market.ALL, symbol=None
279279
return None
280280

281281
def get_open_orders(self, account=None, sec_type=None, market=Market.ALL, symbol=None, start_time=None,
282-
end_time=None):
282+
end_time=None, parent_id=None):
283283
"""
284284
获取待成交订单列表. 参数同 get_orders
285+
:param parent_id: 主订单 order_id
285286
"""
286287
params = OrdersParams()
287288
params.account = account if account else self._account
@@ -291,6 +292,7 @@ def get_open_orders(self, account=None, sec_type=None, market=Market.ALL, symbol
291292
params.symbol = symbol
292293
params.start_date = start_time
293294
params.end_date = end_time
295+
params.parent_id = parent_id
294296
request = OpenApiRequest(ACTIVE_ORDERS, biz_model=params)
295297
response_content = self.__fetch_data(request)
296298
if response_content:
@@ -377,7 +379,9 @@ def get_order(self, account=None, id=None, order_id=None, is_brief=False):
377379

378380
def create_order(self, account, contract, action, order_type, quantity, limit_price=None, aux_price=None,
379381
trail_stop_price=None, trailing_percent=None, percent_offset=None, time_in_force=None,
380-
outside_rth=None):
382+
outside_rth=None, attach_type=None, stop_loss_price=None, stop_loss_tif='DAY', stop_loss_rth=None,
383+
stop_loss_order_id=None, profit_taker_price=None, profit_taker_tif='DAY', profit_taker_rth=None,
384+
profit_taker_order_id=None):
381385
"""
382386
创建订单对象.
383387
:param account:
@@ -392,7 +396,16 @@ def create_order(self, account, contract, action, order_type, quantity, limit_pr
392396
:param percent_offset:
393397
:param time_in_force: 订单有效期, 'DAY'(当日有效)和'GTC'(取消前有效)
394398
:param outside_rth: 是否允许盘前盘后交易(美股专属)
395-
:return:
399+
400+
:param attach_type: 附加订单类型(仅限价单支持). PROFIT 止盈单类型, LOSS 止损单类型, BRACKETS 括号订单类型(止损和止盈)
401+
:param stop_loss_price: 附加止损单价格
402+
:param stop_loss_tif: 附加止损单有效期. 'DAY'(当日有效)和'GTC'(取消前有效). 同 time_in_force 字段
403+
:param stop_loss_rth: 附加止损单是否允许盘前盘后交易(美股专属). True 允许, False 不允许. 同 outside_rth 字段
404+
:param stop_loss_order_id: 附加止损单号. 可以通过订单号接口获取, 如果传0或为空, 则服务器端会自动生成止损单号
405+
:param profit_taker_price: 附加止盈单价格
406+
:param profit_taker_tif: 附加止盈单有效期. 'DAY'(当日有效)和'GTC'(取消前有效). 同 time_in_force 字段
407+
:param profit_taker_rth: 附加止盈单是否允许盘前盘后交易(美股专属). True 允许, False 不允许. 同 outside_rth 字段
408+
:param profit_taker_order_id: 附加止盈单号. 可以通过订单号接口获取, 如果传0或为空, 则服务器端会自动生成止盈单号
396409
"""
397410
params = AccountsParams()
398411
params.account = account if account else self._account
@@ -406,7 +419,11 @@ def create_order(self, account, contract, action, order_type, quantity, limit_pr
406419
order = Order(account, contract, action, order_type, quantity, limit_price=limit_price,
407420
aux_price=aux_price, trail_stop_price=trail_stop_price,
408421
trailing_percent=trailing_percent, percent_offset=percent_offset,
409-
time_in_force=time_in_force, outside_rth=outside_rth, order_id=order_id)
422+
time_in_force=time_in_force, outside_rth=outside_rth, order_id=order_id,
423+
attach_type=attach_type, stop_loss_price=stop_loss_price, stop_loss_tif=stop_loss_tif,
424+
stop_loss_rth=stop_loss_rth, stop_loss_order_id=stop_loss_order_id,
425+
profit_taker_price=profit_taker_price, profit_taker_tif=profit_taker_tif,
426+
profit_taker_rth=profit_taker_rth, profit_taker_order_id=profit_taker_order_id)
410427
return order
411428
else:
412429
raise ApiException(response.code, response.message)
@@ -476,14 +493,28 @@ def place_order(self, order):
476493
params.percent_offset = order.percent_offset
477494
params.time_in_force = order.time_in_force
478495
params.outside_rth = order.outside_rth
496+
params.attach_type = order.attach_type
497+
params.stop_loss_price = order.stop_loss_price
498+
params.stop_loss_tif = order.stop_loss_tif
499+
params.stop_loss_rth = order.stop_loss_rth
500+
params.stop_loss_order_id = order.stop_loss_order_id
501+
params.profit_taker_price = order.profit_taker_price
502+
params.profit_taker_tif = order.profit_taker_tif
503+
params.profit_taker_rth = order.profit_taker_rth
504+
params.profit_taker_order_id = order.profit_taker_order_id
505+
479506
request = OpenApiRequest(PLACE_ORDER, biz_model=params)
480507
response_content = self.__fetch_data(request)
481508
if response_content:
482509
response = OrderIdResponse()
483510
response.parse_response_content(response_content)
484511
if response.is_success():
485512
order.id = response.id
486-
return response.order_id == order.order_id if order.order_id else True
513+
if order.order_id:
514+
return response.order_id == order.order_id
515+
else:
516+
order.order_id = response.order_id
517+
return True
487518
else:
488519
raise ApiException(response.code, response.message)
489520

0 commit comments

Comments
 (0)