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

在CTA策略-课时29-委托控制 中, 提到了关于order_control 的精细控制, 为了保证再新下单前, 基于last_bar的order_data能被取消, 所以通过遍历的方式在每次下单前都先检查是否有旧的订单, 如有有就用cancel_order取消之前的订单.

通过上面的遍历方式已经能保证下新订单前已经没有旧订单了,同时也已经发出了新订单委托, 为什么又需要在on_stop_order中再次发出委托.

如下是代码:


from vnpy.app.cta_strategy import (
    CtaTemplate,
    StopOrder,
    TickData,
    BarData,
    TradeData,
    OrderData,
    BarGenerator,
    ArrayManager,
    Direction
)

from vnpy.app.cta_strategy.base import StopOrderStatus


class OrderDemoStrategy(CtaTemplate):
    """"""
    author = "用Python的交易员"

    boll_window = 18
    boll_dev = 3.4
    fixed_size = 1
    atr_window = 20
    atr_multiplier = 2

    boll_up = 0
    boll_down = 0
    boll_mid = 0

    atr_value = 0
    intra_trade_high = 0
    long_sl = 0
    intra_trade_low = 0
    short_sl = 0

    long_entry = 0
    short_entry = 0

    parameters = [
        "boll_window", "boll_dev", 
        "fixed_size", 
        "atr_window", "atr_multiplier"
    ]
    variables = [
        "boll_up", "boll_down", "boll_mid",
        "atr_value",
        "intra_trade_high", "long_sl",
        "intra_trade_low", "short_sl"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am = ArrayManager()

        self.buy_vt_orderids = []
        self.sell_vt_orderids = []
        self.short_vt_orderids = []
        self.cover_vt_orderids = []

        self.buy_price = 0
        self.sell_price = 0
        self.short_price = 0
        self.cover_price = 0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_15min_bar(self, bar: BarData):
        """"""
        # 生成交易信号
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev)
        self.boll_mid = am.sma(self.boll_window)
        self.atr_value = am.atr(self.atr_window)

        if self.pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            self.buy_price = self.boll_up
            self.sell_price = 0
            self.short_price = self.boll_down
            self.cover_price = 0

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            self.long_sl = self.intra_trade_high - self.atr_value * self.atr_multiplier
            self.long_sl = max(self.boll_mid, self.long_sl)

            self.buy_price = 0
            self.sell_price = self.long_sl
            self.short_price = 0
            self.cover_price = 0

        elif self.pos < 0:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.intra_trade_high = bar.high_price

            self.short_sl = self.intra_trade_low + self.atr_value * self.atr_multiplier
            self.short_sl = min(self.boll_mid, self.short_sl)

            self.buy_price = 0
            self.sell_price = 0
            self.short_price = 0
            self.cover_price = self.short_sl

        # 根据信号执行挂撤交易
        if self.pos == 0:
            # 检查之前委托都已经结束
            if not self.buy_vt_orderids:
                # 检查存在信号
                if self.buy_price:
                    self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True)
                    self.buy_price = 0      # 执行需要清空信号
            else:
                # 遍历委托号列表撤单
                for vt_orderid in self.buy_vt_orderids:
                    self.cancel_order(vt_orderid)

            if not self.short_vt_orderids:
                if self.short_price:
                    self.short_vt_orderids = self.short(self.short_price, self.fixed_size, True)
                    self.short_price = 0
            else:
                for vt_orderid in self.short_vt_orderids:
                    self.cancel_order(vt_orderid)
        elif self.pos > 0:
            if not self.sell_vt_orderids:
                if self.sell_price:
                    self.sell_vt_orderids = self.sell(self.sell_price, abs(self.pos), True)
                    self.sell_price = 0
            else:
                for vt_orderid in self.sell_vt_orderids:
                    self.cancel_order(vt_orderid)
        else:
            if not self.cover_vt_orderids:
                if self.cover_price:
                    self.cover_vt_orderids = self.cover(self.cover_price, abs(self.pos), True)
                    self.cover_price = 0
            else:
                for vt_orderid in self.cover_vt_orderids:
                    self.cancel_order(vt_orderid)

        # Update UI
        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        # 只处理撤销或者触发的停止单委托
        if stop_order.status == StopOrderStatus.WAITING:
            return

        # 移除已经结束的停止单委托号
        for buf_orderids in [
            self.buy_vt_orderids,
            self.sell_vt_orderids,
            self.short_vt_orderids,
            self.cover_vt_orderids
        ]:
            if stop_order.stop_orderid in buf_orderids:
                buf_orderids.remove(stop_order.stop_orderid)

        # 发出新的委托
        if self.pos == 0:
            if not self.buy_vt_orderids:
                if self.buy_price:
                    self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True)
                    self.buy_price = 0

            if not self.short_vt_orderids:
                if self.short_price:
                    self.short_vt_orderids = self.short(self.short_price, self.fixed_size, True)
                    self.short_price = 0

        elif self.pos > 0:
            if not self.sell_vt_orderids:
                if not self.sell_price:
                    self.sell_vt_orderids = self.sell(self.sell_price, abs(self.pos), True)
                    self.sell_price = 0

        else:
            if not self.cover_vt_orderids:
                if not self.cover_price:
                    self.cover_vt_orderids = self.cover(self.cover_price, abs(self.pos), True)
                    self.cover_price = 0

问题所关注的code是:
def on_stop_order(self, stop_order: StopOrder):
"""
Callback of stop order update.
""'

    # 发出新的委托
    if self.pos == 0:
        if not self.buy_vt_orderids:
            if self.buy_price:
                self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True)
                self.buy_price = 0

        if not self.short_vt_orderids:
            if self.short_price:
                self.short_vt_orderids = self.short(self.short_price, self.fixed_size, True)
                self.short_price = 0

    elif self.pos > 0:
        if not self.sell_vt_orderids:
            if not self.sell_price:
                self.sell_vt_orderids = self.sell(self.sell_price, abs(self.pos), True)
                self.sell_price = 0

    else:
        if not self.cover_vt_orderids:
            if not self.cover_price:
                self.cover_vt_orderids = self.cover(self.cover_price, abs(self.pos), True)
                self.cover_price = 0
Member
avatar
加入于:
帖子: 4713
声望: 287

cancel_order是撤销已发出但没成交的订单,on_stop_order是发出停止单的函数,这是两个概念吧

Member
avatar
加入于:
帖子: 5
声望: 1

xiaohe wrote:

cancel_order是撤销已发出但没成交的订单,on_stop_order是发出停止单的函数,这是两个概念吧

在on_15min_bar已经有下单函数了啊, 这个时候vt_orderid不是已经生成了吗? 为什么还要在on_stop_order那里重新写一遍下单函数?

Member
avatar
加入于:
帖子: 4713
声望: 287

本地停止单和限价单下单方法是不一样的。限价单是下出去的单,本地停止单没有下出去,只是记录了信息,在价格满足要求的时候才会以涨跌停价或者盘口五档的价格发出

Member
avatar
加入于:
帖子: 5
声望: 1

xiaohe wrote:

本地停止单和限价单下单方法是不一样的。限价单是下出去的单,本地停止单没有下出去,只是记录了信息,在价格满足要求的时候才会以涨跌停价或者盘口五档的价格发出
停止单和限价单的差别我知道, 只是不理解为什么在on_15min_bar函数已经下单的情况下, or_stop_order函数为什么还要再检查下一遍

因为在or_15min_bar中, 如果产生了下单信号, 比如:

 def on_15min_bar(self, bar: BarData):
if self.pos == 0:
            # 检查之前委托都已经结束
            if not self.buy_vt_orderids:
                # 检查存在信号
                if self.buy_price:
                    self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True)
                    self.buy_price = 0      # 执行需要清空信号

这个时候已经同时:发出买单信号+清空了self.buy_price

这时候产生的orderdata传on_stop_order的时候, 如果这个orderdata没有成功买入, self.pos == 0的情况下, 因为self.buy_price = 0 ,on_stop_order中的下单程序也执行不了啊.

def on_order(self, order: OrderData):
  # 发出新的委托
        if self.pos == 0:
            if not self.buy_vt_orderids:
                if self.buy_price:
                    self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True)
                    self.buy_price = 0
Member
avatar
加入于:
帖子: 4713
声望: 287

还是那句话,一个是下限价单,一个是下停止单,这不是同一种单,所以只有在你下了停止单的时候才会触发on_stop_order的状态推送。因为粗粒度都是on_bar驱动,但是细粒度可能是在on_bar/on_trade/on_stop_order,这个都取决于你的策略的交易逻辑。

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

沪公网安备 31011502017034号

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