VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 6
声望: 0

VNPY2.9版本,在脚本策略上跑上期所的品种,今开的仓位平仓时出现平昨仓位不足,查找原因后发现脚本策略没有自动处理平今平昨的功能,参考CTA策略模块添加了该功能,代码如下:

def send_order(
        self,
        vt_symbol: str,
        price: float,
        volume: float,
        direction: Direction,
        offset: Offset,
        order_type: OrderType,
        stop: bool = False,
        lock: bool = False,
        net: bool = False
    ):
        """"""
        contract: Optional[ContractData] = self.get_contract(vt_symbol)
        if not contract:
            self.write_log(f"委托失败,找不到合约:{vt_symbol}", vt_symbol)
            return ""
        # Round order price and volume to nearest incremental value
        price = round_to(price, contract.pricetick)
        volume = round_to(volume, contract.min_volume)

        original_req: OrderRequest = OrderRequest(
            symbol=contract.symbol,
            exchange=contract.exchange,
            direction=direction,
            type=order_type,
            volume=volume,
            price=price,
            offset=offset,
            reference=APP_NAME
        )
        print(original_req)
        # Convert with offset converter
        req_list = self.offset_converter.convert_order_request(original_req, lock, net)
        print(req_list)
        # Send Orders
        vt_orderids = []

        for req in req_list:
            vt_orderid = self.main_engine.send_order(req, contract.gateway_name)

            # Check if sending order successful
            if not vt_orderid:
                continue

            vt_orderids.append(vt_orderid)

            self.offset_converter.update_order_request(req, vt_orderid)

        return vt_orderids

        #vt_orderid: str = self.main_engine.send_order(req, contract.gateway_name)
        #return vt_orderid

打印出来之后,original_req有数据
OrderRequest(symbol='ru2209', exchange=<Exchange.SHFE: 'SHFE'>, direction=<Direction.SHORT: '空'>, type=<OrderType.LIMIT: '限价'>, volume=7.0, price=12825.0, offset=<Offset.CLOSE: '平'>, reference='ScriptTrader'),
但是转换之后的req_list为空[],请问一下这是什么原因?如何进行处理?谢谢!

Member
avatar
加入于:
帖子: 1448
声望: 102

OffsetConverter底层是要更新持仓、成交、委托信息进去后,才能进行计算的

Member
avatar
加入于:
帖子: 6
声望: 0

MTF wrote:

OffsetConverter底层是要更新持仓、成交、委托信息进去后,才能进行计算的
不好意思啊,那如何进行添加呢?我对底层不太了解,不知道应该怎么添加,查论坛的历史记录也没有找到具体如何做的

Member
avatar
加入于:
帖子: 6
声望: 0

研究了一下,解决脚本策略在上期所品种上平昨仓位不足的问题,对脚本策略的engine做了一些修改,对于上期所的品种每次平仓时都先平今,平今不足时再平昨。具体操作上,每次下单之前要读取一次仓位,读取里面的总仓位、昨仓,计算出今仓,然后修改下单请求。具体代码如下:

from copy import copy
from vnpy.trader.constant import Direction, Offset, OrderType, Interval, Exchange
from vnpy.trader.utility import round_to

    def send_order(
        self,
        vt_symbol: str,
        price: float,
        volume: float,
        direction: Direction,
        offset: Offset,
        order_type: OrderType,
        stop: bool = False,
        lock: bool = False,
        net: bool = False
    ):
        """"""
        contract: Optional[ContractData] = self.get_contract(vt_symbol)
        if not contract:
            self.write_log(f"委托失败,找不到合约:{vt_symbol}", vt_symbol)
            return ""
        # Round order price and volume to nearest incremental value
        price = round_to(price, contract.pricetick)
        volume = round_to(volume, contract.min_volume)

        original_req: OrderRequest = OrderRequest(
            symbol=contract.symbol,
            exchange=contract.exchange,
            direction=direction,
            type=order_type,
            volume=volume,
            price=price,
            offset=offset,
            reference=APP_NAME
        )
        print(original_req)
        # Convert with offset converter

        req_list = self.convert_order_request(original_req)
        print(req_list)
        # Send Orders
        vt_orderids = []

        for req in req_list:
            vt_orderid = self.main_engine.send_order(req, contract.gateway_name)

            # Check if sending order successful
            if not vt_orderid:
                continue

            vt_orderids.append(vt_orderid)

            self.offset_converter.update_order_request(req, vt_orderid)

        return vt_orderids

        #vt_orderid: str = self.main_engine.send_order(req, contract.gateway_name)
        #return vt_orderid

    def convert_order_request(
        self,
        req: OrderRequest
    ) -> List[OrderRequest]:
        """"""
        if not self.is_convert_required(req.vt_symbol):
            return [req]

        if req.exchange in [Exchange.SHFE, Exchange.INE]:
            return self.convert_order_request_shfe(req)
        else:
            return [req]

    def is_convert_required(self, vt_symbol: str) -> bool:
        """
        Check if the contract needs offset convert.
        """
        contract = self.main_engine.get_contract(vt_symbol)

        # Only contracts with long-short position mode requires convert
        if not contract:
            return False
        elif contract.net_position:
            return False
        else:
            return True

    def convert_order_request_shfe(self, req: OrderRequest) -> List[OrderRequest]:
        """"""
        if req.offset == Offset.OPEN:
            return [req]

        vt_symbol = req.symbol + "." + req.exchange.value
        longs_PositionData = self.get_position(vt_symbol + "." + Direction.LONG.value)
        short_PositionData = self.get_position(vt_symbol + "." + Direction.SHORT.value)

        if longs_PositionData:
            long_pos = longs_PositionData.volume
            long_pos_frozen = longs_PositionData.frozen
            long_pos_yd = longs_PositionData.yd_volume
        else:
            long_pos = 0
            long_pos_frozen = 0
            long_pos_yd = 0            

        if short_PositionData:
            short_pos = short_PositionData.volume
            short_pos_frozen = short_PositionData.frozen
            short_pos_yd = short_PositionData.yd_volume
        else:
            short_pos = 0
            short_pos_frozen = 0
            short_pos_yd = 0 


        if req.direction == Direction.LONG:
            pos_available = short_pos - short_pos_frozen

            short_td = short_pos - short_pos_yd
            td_available = short_td - short_pos_frozen
        else:
            pos_available = long_pos - long_pos_frozen
            long_td = long_pos - long_pos_yd
            td_available = long_td - long_pos_yd
        #print(pos_available)
        #print(td_available)
        #print(td_available)        
        if req.volume > pos_available:
            return []
        elif req.volume <= td_available:
            req_td = copy(req)
            req_td.offset = Offset.CLOSETODAY
            return [req_td]
        else:
            req_list = []

            if td_available > 0:
                req_td = copy(req)
                req_td.offset = Offset.CLOSETODAY
                req_td.volume = td_available
                req_list.append(req_td)

            req_yd = copy(req)
            req_yd.offset = Offset.CLOSEYESTERDAY
            req_yd.volume = req.volume - td_available
            req_list.append(req_yd)

            return req_list
Member
avatar
加入于:
帖子: 28
声望: 0
    longs_PositionData = self.get_position(vt_symbol + "." + Direction.LONG.value)
    short_PositionData = self.get_position(vt_symbol + "." + Direction.SHORT.value)

想问一下,你这self.get_position, 这个方法是哪来的,原始那个文件并没有这个方法

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】