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

比如说我想实现买入后经历5根1分钟k线后卖出,我的代码是:

def on_bar(self, bar: BarData):
        self.cancel_all()
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return
        fast_ma = am.sma(self.fast_window, array=True)
        self.fast_ma0 = fast_ma[-1]
        self.fast_ma1 = fast_ma[-2]

        slow_ma = am.sma(self.slow_window, array=True)
        self.slow_ma0 = slow_ma[-1]
        self.slow_ma1 = slow_ma[-2]

        cross_over = self.fast_ma0 > self.slow_ma0 and self.fast_ma1 < self.slow_ma1
        cross_below = self.fast_ma0 < self.slow_ma0 and self.fast_ma1 > self.slow_ma1

        if cross_over:
            if self.pos == 0:
                self.buy(bar.close_price, 1)

            # 记录入场时间
        if self.long_entry_time:
            self.passed_datetime = (bar.datetime - self.long_entry_time).total_seconds()/60

        if self.pos > 0:
            if self.passed_datetime > 5: 
                self.sell(bar.close_price, abs(self.pos), stop=True)  # 立即以市价卖出                                       
                   # 重置买入时间和K线计数
                self.long_entry_time = None
                self.long_entry_bar = 0       
        self.put_event()

但实际回测出来是间隔8分钟卖出,找了好多天都没发现问题。想知道我的代码问题在哪里,如何解决,或者我们是否有专门表示买入或卖出后经历多少根k线(或多长时间)的写法
description

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

具体需要自己基于策略逻辑进行打印排查的
想获取开仓时间可以在收到on_trade的时候获取trade.datetime
要计算K线根数弄个变量累加就好,最好不要用秒数去除
passed_datetime大于5就至少要6才能委托
你本地停止单的触发价是bar.close_price不是市价,是触发价格之后市价发出,而且最快也要下一根K线才能成交的
限价委托也是上一分钟委托,最快下一分钟才能成交,持仓才能变化

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

xiaohe wrote:

具体需要自己基于策略逻辑进行打印排查的
想获取开仓时间可以在收到on_trade的时候获取trade.datetime
要计算K线根数弄个变量累加就好,最好不要用秒数去除
passed_datetime大于5就至少要6才能委托
你本地停止单的触发价是bar.close_price不是市价,是触发价格之后市价发出,而且最快也要下一根K线才能成交的
限价委托也是上一分钟委托,最快下一分钟才能成交,持仓才能变化

on trade 我是有写的,具体代码如下:

def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.offset == Offset.OPEN:
            # 区分多空开仓价
            if trade.direction == Direction.LONG:
                self.long_entry = trade.price
                self.long_entry_time = trade.datetime  # 记录买入时间
                self.long_entry_bar = 0  # 重置买入后K线计数
        self.put_event()

想了解:
1、变量累加要如何实现的?我只能想到用self.passed_datetime = (bar.datetime - self.long_entry_time).total_seconds()/60表示买入后累计k线个数,能否简单列示下?
2、BarData中只有open high low close,如果想触发市价,该如何表示的?
谢谢

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

就设置一个全局变量bar_since_entry和open_traded,如果on_trade收到开仓委托并trade.ALLTRADED open_traded就为True。on_bar里如果open_traded为True,bar_since_entry就开始累加。发出平仓委托后,bar_since_entry变为0,open_traded变为False。
上面只是一个示例,要排查策略问题需要你自己先明确策略逻辑(比如是要持仓五分钟还是委托以后五分钟就发单,这两个时间间隔是不一样的)。
不知道你说的想触发市价具体是什么意思了,本地停止单的原理项目文档有介绍的https://www.vnpy.com/docs/cn/community/app/cta_strategy.html#id19

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

xiaohe wrote:

就设置一个全局变量bar_since_entry和open_traded,如果on_trade收到开仓委托并trade.ALLTRADED open_traded就为True。on_bar里如果open_traded为True,bar_since_entry就开始累加。发出平仓委托后,bar_since_entry变为0,open_traded变为False。
上面只是一个示例,要排查策略问题需要你自己先明确策略逻辑(比如是要持仓五分钟还是委托以后五分钟就发单,这两个时间间隔是不一样的)。
不知道你说的想触发市价具体是什么意思了,本地停止单的原理项目文档有介绍的https://www.vnpy.com/docs/cn/community/app/cta_strategy.html#id19

elif self.pos > 0:
            # 如果已经开仓,增加K线计数器
            if self.open_traded:
                self.bar_since_entry += 1
     if self.bar_since_entry >= self.monitoring:
                # 如果经过k线超过买入观察K
                if bar.close_price <= target: 
                    if bar.close_price >= exit_price:  
                        self.sell(bar.close_price, abs(self.pos))
                    elif bar.close_price > long_stop:
                        self.sell(exit_price, abs(self.pos), stop=True)   
                    else:
                        self.sell(long_stop, abs(self.pos), stop=True)  # 立即以市价卖出
                if bar.close_price >= target:
                    self.sell(self.exit_down, abs(self.pos), stop=True)

            elif self.bar_since_entry < self.monitoring_period and bar.close_price > long_stop:
                pass
            elif self.bar_since_entry < self.monitoring_period and bar.close_price < long_stop:
                self.sell(long_stop, abs(self.pos), stop=True)

description

description
上述按照设置全局变量bar_since_entry和open_traded进行了修改,基本比之前使用时间变量能更准确反映k线数量。
但是出现两个问题,首先就是根据策略卖出的逻辑,在k线走过16根时,判断是否符合条件来挂出停止单,但是在回测过程中,实际不管有无符合条件都直接委托卖出(详见回测委托记录)。
第二就是委托卖出价格高于实际成交价格,正常情况不应该是委托卖价低于买价才能够成交吗?为什么高于买价也能成交?(将滑点设置为0问题仍然存在)
具体如何解决?谢谢

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

你平仓用的是本地停止单,不是限价单。建议看下cross_stop_order的代码吧,本地停止单的介绍上面也给过链接了

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

xiaohe wrote:

你平仓用的是本地停止单,不是限价单。建议看下cross_stop_order的代码吧,本地停止单的介绍上面也给过链接了
我知道是本地停止单的,所以我设置要等符合条件时才触发而不是实操中的立即触发。
想问一下有没有jupyter notebook中导入本地数据回测的教程,能否用jupyter notebook实现策略逐行验证的?

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

https://gitee.com/vnpy/vnpy/blob/master/examples/cta_backtesting/backtesting_demo.ipynb
通过print函数打印排查即可

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

xiaohe wrote:

https://gitee.com/vnpy/vnpy/blob/master/examples/cta_backtesting/backtesting_demo.ipynb
通过print函数打印排查即可
有没有使用本地数据回测的方法的?我看BacktestingEngine里面没有可以使用本地数据回测的函数。

Member
avatar
加入于:
帖子: 1475
声望: 105

用DataManager将你的CSV数据导入vn数据库即可

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

沪公网安备 31011502017034号

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