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

情况是这样的,我进行股指交易,由于账户上资金是有限的,常年满仓操作,所以要开新仓,只有等平仓资金回流后,再开新仓位。
目前我在策略的self.on_bar()里面进行了微调,先检查平仓指令,再检查开仓指令(并且在开仓指令前面加入了time.sleep(0.3))。开仓前的代码如下。平仓指令在on_bar内一样也会触发self.write_log(),以便我检查这两单的下单时间。

time.sleep(0.3)
self.buy(vt_symbol, price, volume)
self.write_log("对{}进行加仓,加仓数量为:{},加仓下单价格为:{}".format(vt_symbol, pos_diff, price))

为了验证的我猜想,我又在self.send_order()函数下面,多写了一个self.write_log()

def send_order(
        self,
        vt_symbol: str,
        direction: Direction,
        offset: Offset,
        price: float,
        volume: float,
        lock: bool = False,
        net: bool = False,
    ) -> List[str]:
        if self.trading:
            self.write_log("下单参数vt_symbol:{},direction:{},offset:{},price:{},volume:{},lock:{},net:{}".
                           format(vt_symbol, direction, offset, price, volume, lock, net))
            vt_orderids = self.strategy_engine.send_order(
                self, vt_symbol, direction, offset, price, volume, lock, net
            )
            for vt_orderid in vt_orderids:
                self.active_orderids.add(vt_orderid)
            return vt_orderids
        else:
            return []

但是实际写出的log如下图

description
3,从这里的log看出,平仓和开仓指令只差了0.004s。。。如果稍有不慎,就不一定能下单成功(因为资金没有回流,不够钱下单)

请教一下,官方有什么好处理方案吗?我着实没办法了。谢谢

Member
avatar
加入于:
帖子: 4622
声望: 284

那可以收到平仓成交回报之后再开仓

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

xiaohe wrote:

那可以收到平仓成交回报之后再开仓

小何老师你好,那是在on_bar函数的内部,在发出平仓指令之后,获得这个vt_orderids,写一个循环,一直等待这个条件vt_orderids in self.active_orderids不成立,才进行下一步?下面这个简化的代码应该就可以了对吧?

short_vt_orderids = self.short(vt_symbol_0, price, volume)
while short_vt_orderids in self.active_orderids:
    time.sleep(0.02)
self.buy(vt_symbol_1, price, volume)  # 因为我这个是用多品种模块的,所以是不同的vt_symbol
Member
avatar
加入于:
帖子: 55
声望: 0

其实我原来的说到一个点,就是我在on_bar里面设置了time.sleep(0.3)似乎不起作用,按道理两个单的下单时间应该相差0.3s以上,但是看log,几乎是同时下的单

Member
avatar
加入于:
帖子: 4622
声望: 284

小刘小刘 wrote:

xiaohe wrote:

那可以收到平仓成交回报之后再开仓

小何老师你好,那是在on_bar函数的内部,在发出平仓指令之后,获得这个vt_orderids,写一个循环,一直等待这个条件vt_orderids in self.active_orderids不成立,才进行下一步?下面这个简化的代码应该就可以了对吧?

short_vt_orderids = self.short(vt_symbol_0, price, volume)
while short_vt_orderids in self.active_orderids:
    time.sleep(0.02)
self.buy(vt_symbol_1, price, volume)  # 因为我这个是用多品种模块的,所以是不同的vt_symbol

成交以后会有成交推送on_trade

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

xiaohe wrote:

小刘小刘 wrote:

xiaohe wrote:

那可以收到平仓成交回报之后再开仓

小何老师你好,那是在on_bar函数的内部,在发出平仓指令之后,获得这个vt_orderids,写一个循环,一直等待这个条件vt_orderids in self.active_orderids不成立,才进行下一步?下面这个简化的代码应该就可以了对吧?

short_vt_orderids = self.short(vt_symbol_0, price, volume)
while short_vt_orderids in self.active_orderids:
    time.sleep(0.02)
self.buy(vt_symbol_1, price, volume)  # 因为我这个是用多品种模块的,所以是不同的vt_symbol

成交以后会有成交推送on_trade

小何老师,现在的一个主要问题是,应该再哪里等待这个on_trade?因为经过我测试,再on_bar里面写循环等待,等待self.pos变化,是会一直卡死的。也就是,好像on_trade和on_bar是同步的(非异步),一定要等on_bar结束了,才会执行on_trade。

Member
avatar
加入于:
帖子: 716
声望: 62

发单不一定需要on_bar跑完,self.short()本身是异步的,但是你用sleep就把整个程序都堵塞住了。其实你没必要循环等待,你在on_bar回调函数里设置下单信号,然后在on_trade回调函数里判断信号下单就行。

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

郭易燔 wrote:

发单不一定需要on_bar跑完,self.short()本身是异步的,但是你用sleep就把整个程序都堵塞住了。其实你没必要循环等待,你在on_bar回调函数里设置下单信号,然后在on_trade回调函数里判断信号下单就行。

刚刚在反复调试过程中,发现确实是调用self.short()就会立即下单,由于还没看到你的回复,我怕产生误解,就把其中一楼给删了。抱歉。让我产生这个发单需要等待on_bar跑完的原因是,调用write_log()并非直接执行的,需要等on_bar走到最后的self.put_event(),才会一次性将log输出,就会产生我图上面那样的时间的log,让我误以为下单时间是这个节点。如果用print进行调试,就会发现下单时间还是进行了sleep之后才间隔下单的。
另,反复思考你最后这句“你在on_bar回调函数里设置下单信号,然后在on_trade回调函数里判断信号下单就行”,实在想不明白,如何在不用sleep堵塞的情况下,让新开仓的命令等到老仓平了的成交回报再发出?请指点一下,谢谢!!

Member
avatar
加入于:
帖子: 716
声望: 62

在on_bar里把新开仓需要的参数放进全局变量里,然后设置变量比如signal为true。在on_trade里做一个判断如果signal为true,说明有新单还没发,这时候老仓已经平了,因为on_trade只有成交是才会回报,直接在这里使用全局变量里的参数进行开仓就行,然后把signal改为false。如果signal是false,那就说明没有新开仓命令,直接跳过就行。大体是这个思路,可以再改进。

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

谢谢郭老师的指点,我下面写下简略的过程,给以后因为这个问题困惑的同学一些参考。由于我只做多,所以下面只涉及到多平和多两个指令。
首先,在策略的init()函数加入下面代码

self.wait_for_on_trade = False
self.wait_for_send_new_order_list = []  # 加入一个容器,存放等待下单的参数

然后在on_bar里面,先下多平,然后多平后面加上这个代码

self.sell(vt_symbol, price, volume)
self.wait_for_on_trade = True

然后在下新的多单这里改成这样

if self.wait_for_on_trade is False:
    self.buy(vt_symbol, price, volume)
else:
    #上面已经进行空仓过滤,这里不考虑空仓情况
    self.wait_for_send_new_order_list = [vt_symbol, price, volume]

然后是策略内部的self.update_trade()函数的最下面,加入以下代码

        if self.wait_for_on_trade and len(self.wait_for_send_new_order_list) != 0:
            self.buy(self.wait_for_send_new_order_list[0],
                     self.wait_for_send_new_order_list[1],
                     self.wait_for_send_new_order_list[2])
            self.wait_for_on_trade = False
            self.wait_for_send_new_order_list = []
Member
avatar
加入于:
帖子: 55
声望: 0

温馨提示,最好加一个过滤,当需要换仓的时候才用这个,不然会有bug

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

沪公网安备 31011502017034号

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