Merge pull request #1828 from 1122455801/converter_md_0613
【Add】增加cta引擎中的锁仓相关文档
This commit is contained in:
commit
0e540386c7
@ -1134,3 +1134,199 @@ def optimize(
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 锁仓操作
|
||||
|
||||
用户在编写策略时,可以通过填写lock字段来让策略完成锁仓操作,即禁止平今,通过反向开仓来代替。
|
||||
|
||||
- 在cta策略模板template中,可以看到如下具体委托函数都有lock字段,并且默认为False。
|
||||
|
||||
```
|
||||
def buy(self, price: float, volume: float, stop: bool = False, lock: bool = False):
|
||||
"""
|
||||
Send buy order to open a long position.
|
||||
"""
|
||||
return self.send_order(Direction.LONG, Offset.OPEN, price, volume, stop, lock)
|
||||
|
||||
def sell(self, price: float, volume: float, stop: bool = False, lock: bool = False):
|
||||
"""
|
||||
Send sell order to close a long position.
|
||||
"""
|
||||
return self.send_order(Direction.SHORT, Offset.CLOSE, price, volume, stop, lock)
|
||||
|
||||
def short(self, price: float, volume: float, stop: bool = False, lock: bool = False):
|
||||
"""
|
||||
Send short order to open as short position.
|
||||
"""
|
||||
return self.send_order(Direction.SHORT, Offset.OPEN, price, volume, stop, lock)
|
||||
|
||||
def cover(self, price: float, volume: float, stop: bool = False, lock: bool = False):
|
||||
"""
|
||||
Send cover order to close a short position.
|
||||
"""
|
||||
return self.send_order(Direction.LONG, Offset.CLOSE, price, volume, stop, lock)
|
||||
|
||||
def send_order(
|
||||
self,
|
||||
direction: Direction,
|
||||
offset: Offset,
|
||||
price: float,
|
||||
volume: float,
|
||||
stop: bool = False,
|
||||
lock: bool = False
|
||||
):
|
||||
"""
|
||||
Send a new order.
|
||||
"""
|
||||
if self.trading:
|
||||
vt_orderids = self.cta_engine.send_order(
|
||||
self, direction, offset, price, volume, stop, lock
|
||||
)
|
||||
return vt_orderids
|
||||
else:
|
||||
return []
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 设置lock=True后,cta实盘引擎send_order()函数发生响应,并且调用其最根本的委托函数send_server_order()去处理锁仓委托转换。首先是创建原始委托original_req,然后调用converter文件里面OffsetConverter类的convert_order_request来进行相关转换。
|
||||
|
||||
```
|
||||
def send_order(
|
||||
self,
|
||||
strategy: CtaTemplate,
|
||||
direction: Direction,
|
||||
offset: Offset,
|
||||
price: float,
|
||||
volume: float,
|
||||
stop: bool,
|
||||
lock: bool
|
||||
):
|
||||
"""
|
||||
"""
|
||||
contract = self.main_engine.get_contract(strategy.vt_symbol)
|
||||
if not contract:
|
||||
self.write_log(f"委托失败,找不到合约:{strategy.vt_symbol}", strategy)
|
||||
return ""
|
||||
|
||||
if stop:
|
||||
if contract.stop_supported:
|
||||
return self.send_server_stop_order(strategy, contract, direction, offset, price, volume, lock)
|
||||
else:
|
||||
return self.send_local_stop_order(strategy, direction, offset, price, volume, lock)
|
||||
else:
|
||||
return self.send_limit_order(strategy, contract, direction, offset, price, volume, lock)
|
||||
|
||||
def send_limit_order(
|
||||
self,
|
||||
strategy: CtaTemplate,
|
||||
contract: ContractData,
|
||||
direction: Direction,
|
||||
offset: Offset,
|
||||
price: float,
|
||||
volume: float,
|
||||
lock: bool
|
||||
):
|
||||
"""
|
||||
Send a limit order to server.
|
||||
"""
|
||||
return self.send_server_order(
|
||||
strategy,
|
||||
contract,
|
||||
direction,
|
||||
offset,
|
||||
price,
|
||||
volume,
|
||||
OrderType.LIMIT,
|
||||
lock
|
||||
)
|
||||
|
||||
def send_server_order(
|
||||
self,
|
||||
strategy: CtaTemplate,
|
||||
contract: ContractData,
|
||||
direction: Direction,
|
||||
offset: Offset,
|
||||
price: float,
|
||||
volume: float,
|
||||
type: OrderType,
|
||||
lock: bool
|
||||
):
|
||||
"""
|
||||
Send a new order to server.
|
||||
"""
|
||||
# Create request and send order.
|
||||
original_req = OrderRequest(
|
||||
symbol=contract.symbol,
|
||||
exchange=contract.exchange,
|
||||
direction=direction,
|
||||
offset=offset,
|
||||
type=type,
|
||||
price=price,
|
||||
volume=volume,
|
||||
)
|
||||
|
||||
# Convert with offset converter
|
||||
req_list = self.offset_converter.convert_order_request(original_req, lock)
|
||||
|
||||
# Send Orders
|
||||
vt_orderids = []
|
||||
|
||||
for req in req_list:
|
||||
vt_orderid = self.main_engine.send_order(
|
||||
req, contract.gateway_name)
|
||||
vt_orderids.append(vt_orderid)
|
||||
|
||||
self.offset_converter.update_order_request(req, vt_orderid)
|
||||
|
||||
# Save relationship between orderid and strategy.
|
||||
self.orderid_strategy_map[vt_orderid] = strategy
|
||||
self.strategy_orderid_map[strategy.strategy_name].add(vt_orderid)
|
||||
|
||||
return vt_orderids
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 在convert_order_request_lock()函数中,先计算今仓的量和昨可用量;然后进行判断:若有今仓,只能开仓(锁仓);无今仓时候,若平仓量小于等于昨可用,全部平昨,反之,先平昨,剩下的反向开仓。
|
||||
|
||||
```
|
||||
def convert_order_request_lock(self, req: OrderRequest):
|
||||
""""""
|
||||
if req.direction == Direction.LONG:
|
||||
td_volume = self.short_td
|
||||
yd_available = self.short_yd - self.short_yd_frozen
|
||||
else:
|
||||
td_volume = self.long_td
|
||||
yd_available = self.long_yd - self.long_yd_frozen
|
||||
|
||||
# If there is td_volume, we can only lock position
|
||||
if td_volume:
|
||||
req_open = copy(req)
|
||||
req_open.offset = Offset.OPEN
|
||||
return [req_open]
|
||||
# If no td_volume, we close opposite yd position first
|
||||
# then open new position
|
||||
else:
|
||||
open_volume = max(0, req.volume - yd_available)
|
||||
req_list = []
|
||||
|
||||
if yd_available:
|
||||
req_yd = copy(req)
|
||||
if self.exchange == Exchange.SHFE:
|
||||
req_yd.offset = Offset.CLOSEYESTERDAY
|
||||
else:
|
||||
req_yd.offset = Offset.CLOSE
|
||||
req_list.append(req_yd)
|
||||
|
||||
if open_volume:
|
||||
req_open = copy(req)
|
||||
req_open.offset = Offset.OPEN
|
||||
req_open.volume = open_volume
|
||||
req_list.append(req_open)
|
||||
|
||||
return req_list
|
||||
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user