VeighNa量化社区
你的开源社区量化交易平台
easibay's Avatar
Member
离线
59 帖子
声望: 4

mark一下,parameters列表里面的参数能同步,那仓位同步是在哪控制的?

细颗粒度,考虑到挂单排队的回测,工作量巨大啊,必须mark

用Python的交易员 wrote:

  1. 每个CTA策略只能交易一个合约,你可以启动多个策略来交易多个合约
  2. risk_level是个参数,你可以提前计算好想要交易的最大手数,并反推出risk_level
  3. 加仓代码的写法没有固定范式,简单的话可以写在开仓代码里
  4. Github仓库中的examples代码里,有cta_backtesting目录,其中有组合回测说明

mark一下,组合回测说明,跨品种策略

目前看到的样例是轮询驱动

while engine.strategy_active:
    ......
    sleep(1)

自己想到的接近on_tick的模式是,不断轮询,判断tick的datetime是否有更新,最大误差就是sleep的时间

while engine.strategy_active:
    for i in range(10):
        tick = engine.get_tick(vt_symbol, use_df=True)
        if tick['datetime'][0] != tick_pre['datetime'][0]:
            break    # 如果是新tick数据,则跳出循环
        sleep(0.1)
    ......

请问 jupyter notebook是否可以on_tick或on_trade事件驱动触发?可不可以举个简单例子?
非常感谢

最大的缺点就是:注释太少了
月总,能多加些注释么?

on_tick函数内撤单追单详解,实盘在用的代码
mark

VNPY 1.9.2版本支持看穿式终端的流程
必须mark一下,非常实用

vnpy版本1.9.2
onTick触发时,程序开始和结束的时候,都记录本地时间,并writeCtaLog出来

def onTick(self, tick):
    self.writeCtaLog(u'本地时间: %s' %(datetime,datetime.now())
    tickstarttime = datetime.datetime.now()
    策略主体
    tickendtime = datetime.datetime.now()
    passtime = str(tickendtime - tickstarttime)
    self.writeCtaLog(u'onTick程序运行时长: %s' %(passtime))

一、发现两个现象
有时候打印出来的Log时间差大于onTick程序实际的运行时间,有时候Log时间差又小于onTick程序实际的运行时间,如下:
1、onTick程序运行时间0.001s,Log记录的时间差有0.007s (即23,598 - 23,591)

2019-12-23 13:43:23,591  INFO: CTA_STRATEGY p2005 LongStrategy:本地时间: 2019-12-23 13:43:23.588000
2019-12-23 13:43:23,592  INFO: CTA_STRATEGY p2005 LongStrategy:pos     ****  :0
2019-12-23 13:43:23,592  INFO: CTA_STRATEGY p2005 LongStrategy:self.auto[self.vtSymbol]  :on
2019-12-23 13:43:23,594  INFO: CTA_STRATEGY p2005 LongStrategy:askprice askvolume:6014.0 595
2019-12-23 13:43:23,595  INFO: CTA_STRATEGY p2005 LongStrategy:bidprice bidvolume:6012.0 525
2019-12-23 13:43:23,595  INFO: CTA_STRATEGY p2005 LongStrategy:拒单数 撤单数:0 0
2019-12-23 13:43:23,595  INFO: CTA_STRATEGY p2005 LongStrategy:仓位:0
2019-12-23 13:43:23,596  INFO: CTA_STRATEGY p2005 LongStrategy:self.lastTick.lastVolume:0
2019-12-23 13:43:23,596  INFO: CTA_STRATEGY p2005 LongStrategy:self.lastTick.volume:2501110
2019-12-23 13:43:23,596  INFO: CTA_STRATEGY p2005 LongStrategy:self.limitVolume[self.vtSymbol]:200
2019-12-23 13:43:23,596  INFO: CTA_STRATEGY p2005 LongStrategy:order.price:6000.0
2019-12-23 13:43:23,598  INFO: CTA_STRATEGY p2005 LongStrategy:onTick程序运行时长  :0:00:00.001000

2、onTick程序运行时间0.005s,Log记录的时间只有0.004s (即07,096 - 07,092),
且记录的起始时间比程序本身的时间要晚0.020s,即第一条程序时间13:51:07.072000,Log时间13:51:07,092

2019-12-23 13:51:07,092  INFO: CTA_STRATEGY p2005 LongStrategy:本地时间: 2019-12-23 13:51:07.072000
2019-12-23 13:51:07,092  INFO: CTA_STRATEGY p2005 LongStrategy:pos     ****  :0
2019-12-23 13:51:07,094  INFO: CTA_STRATEGY p2005 LongStrategy:self.auto[self.vtSymbol]  :on
2019-12-23 13:51:07,094  INFO: CTA_STRATEGY p2005 LongStrategy:askprice askvolume:6024.0 415
2019-12-23 13:51:07,094  INFO: CTA_STRATEGY p2005 LongStrategy:bidprice bidvolume:6022.0 660
2019-12-23 13:51:07,095  INFO: CTA_STRATEGY p2005 LongStrategy:拒单数 撤单数:0 0
2019-12-23 13:51:07,095  INFO: CTA_STRATEGY p2005 LongStrategy:仓位:0
2019-12-23 13:51:07,095  INFO: CTA_STRATEGY p2005 LongStrategy:self.lastTick.lastVolume:0
2019-12-23 13:51:07,095  INFO: CTA_STRATEGY p2005 LongStrategy:self.lastTick.volume:2561906
2019-12-23 13:51:07,095  INFO: CTA_STRATEGY p2005 LongStrategy:self.limitVolume[self.vtSymbol]:200
2019-12-23 13:51:07,095  INFO: CTA_STRATEGY p2005 LongStrategy:order.price:6000.0
2019-12-23 13:51:07,096  INFO: CTA_STRATEGY p2005 LongStrategy:onTick程序运行时长  :0:00:00.005000

二、问题
1、writeCtaLog函数记录的时候和程序主体运行是什么样的关系?Log时间差一会大,一会小,感觉是相互独立的
2、如果onTick中运用了较多的writeCtaLog函数来记录,譬如20个策略,每个策略onTick中写出30个writeCtaLog函数,这样在效率上会影响onTick程序的运行么?
3、假如writeCtaLog函数较多会影响onTick程序的效率,怎么提高效率呢,Log的信息改用pandas输出?还是说用多进程multiprocessing包?

非常感谢!

测试账户是指什么?模拟账号?
徽商期货,客服回复:
1、徽商期货的IT 联系方式:0371-58670101
电话属于总部的 徽商期货负责郑州易盛,但期货公司不提供 测试账户,让直接联系易盛

2、易盛的联系方式
http://www.esunny.com.cn/index.php?a=lists&catid=9

description

3、易盛的程序化平台是极星 ,官方的 极星量化开发群 QQ群号是:472789093
4、易盛技术人员回复:极星仿真和易盛模拟不是一个后台(再具体我就不是很懂了)
5、关于易盛模拟账号:
http://www.esunny.com.cn/index.php?a=lists&catid=18

description

6、程序化在启动前,好像要同时先登录易盛的极星客户端(印象中是,没用过)

这些信息可以了么?

易盛 极星 内盘,在期货数据方面有些优势,譬如郑商所的商品期货,数据有免费五档行情,以及tick切片是0.25s,优势很明显,请问易盛 极星 内盘的数据api接口有没有上线的计划?谢谢

description

基础代码我再认真核对一下,找了好几圈了,目前还没找出哪里直接改了UI而没通过Singal/Slot

另外,从结构上,我看到一些有数据交互功能的UI,譬如CTA策略、价差交易,都被独立封装成了上层应用

    # 添加上层应用
    me.addApp(riskManager)
    me.addApp(ctaStrategy)
    me.addApp(spreadTrading)

description

交互功能如下,有按键修改策略状态初始化,有log输出到UI

description

我自己设计的UI也有类似的功能,就是按钮直接修改策略的参数和链接到策略的sendOrder发单

description

请问,也必须像价差交易、CTA策略等一样做成“上层应用”吗?
我参考的是没有实时交互功能的代码模式
如“打开配置编辑”模板,直接从菜单栏弹出:

    def openSettingEditor(self):
        """打开配置编辑"""
        try:
            self.widgetDict['settingEditor'].show()
        except KeyError:
            self.widgetDict['settingEditor'] = SettingEditor(self.mainEngine)
            self.widgetDict['settingEditor'].show()

自己设计的弹出窗口如下:

    def sniperTrade(self):
        """打开手动交易"""
        try:
            self.widgetDict['sniperTrade'].show()
        except KeyError:
            self.widgetDict['sniperTrade'] = SniperTradingWidget(self.mainEngine, self.eventEngine, self.ctaEngine)    # 无问西东 新建窗体 新增传入ctaEngine
            self.widgetDict['sniperTrade'].show()

交互功能UI,结构上必须做成上层应用么?还是可以做成简单的弹出窗口就行了?
这可能是最后一个疑问了,非常感谢群主的悉心指导

非常感谢群主百忙之中的解答
signal.emit注册是有的,因为这个UI窗口是照搬“简单交易组件”来的,所以,注册机制跟MainWindow里的您写的那个手动下单一致
参考的源代码:

class TradingWidget(QtWidgets.QFrame):
    """简单交易组件"""
    signal = QtCore.Signal(type(Event()))
    ......
    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.signal.connect(self.updateTick)
        self.eventEngine.register(EVENT_TICK, self.signal.emit)

实际代码如下,这两个class的注册是一模一样的

class SniperTradingWidget(QtWidgets.QFrame):
    """狙击交易组件"""
    signal = QtCore.Signal(type(Event()))
    ......
    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.signal.connect(self.updateTick)
        self.eventEngine.register(EVENT_TICK, self.signal.emit)

至于调用这个class的上层函数,我也是参考’功能应用‘菜单的模板
’功能应用‘菜单源码,参考’打开配置编辑‘代码:

    def createOpenAppFunction(self, appDetail):
        """创建打开应用UI的函数"""
        def openAppFunction():
            appName = appDetail['appName']
            try:
                self.widgetDict[appName].show()
            except KeyError:
                appEngine = self.mainEngine.getApp(appName)
                # self.widgetDict[appName] = appDetail['appWidget'](appEngine, self.eventEngine)

                # 无问西东,这部分细节实现还不太清楚,传递的参数不是(self.mainEngine, self.eventEngine, self.ctaEngine)
                # 譬如CtaEngineManager(ctaEngine, eventEngine, parent=None)
                self.widgetDict[appName] = appDetail['appWidget'](appEngine, self.eventEngine)
                self.widgetDict[appName].show()

        return openAppFunction

    def openSettingEditor(self):
        """打开配置编辑"""
        try:
            self.widgetDict['settingEditor'].show()
        except KeyError:
            self.widgetDict['settingEditor'] = SettingEditor(self.mainEngine)
            self.widgetDict['settingEditor'].show()

调用自编UI的代码(多传了一个ctaEngine,在初始化时的_init_里面就传入了):

    def sniperTrade(self):
        """打开手动交易"""
        try:
            self.widgetDict['sniperTrade'].show()
        except KeyError:
            self.widgetDict['sniperTrade'] = SniperTradingWidget(self.mainEngine, self.eventEngine, self.ctaEngine)    # 无问西东 新建窗体 新增传入ctaEngine
            self.widgetDict['sniperTrade'].show()

自己写的updateTick函数内容也挺简单,也就是参考“简单交易组件”更新一下数据

    def updateTick(self, event):
        """更新行情"""
        tick = event.dict_['data']

        if tick.vtSymbol != self.symbol:
            return
        self.tick = tick

        updateStart = datetime.datetime.now()
        self.ctaEngine.writeCtaLog(u'updateStart时间: %s' % (updateStart))

        # 新增
        self.lastTick = tick
        self.getVolume()    # 成交量相关计算函数

        if not self.checkFixed.isChecked():
            self.spinPrice.setValue(tick.lastPrice)

        # priceTick = self.mainEngine.getContract(self.vtSymbol).priceTick
        self.labelBidVolume1.setText(str(tick.bidVolume1))
        self.labelAskVolume1.setText(str(tick.askVolume1))

        self.labelBidPrice1.setText(str(tick.bidPrice1))
        self.labelBidPrice2.setText(str(tick.bidPrice1 - 1 * self.priceTick))
        self.labelBidPrice3.setText(str(tick.bidPrice1 - 2 * self.priceTick))
        self.labelBidPrice4.setText(str(tick.bidPrice1 - 3 * self.priceTick))
        self.labelBidPrice5.setText(str(tick.bidPrice1 - 4 * self.priceTick))

        self.labelAskPrice1.setText(str(tick.askPrice1))
        self.labelAskPrice2.setText(str(tick.askPrice1 + 1 * self.priceTick))
        self.labelAskPrice3.setText(str(tick.askPrice1 + 2 * self.priceTick))
        self.labelAskPrice4.setText(str(tick.askPrice1 + 3 * self.priceTick))
        self.labelAskPrice5.setText(str(tick.askPrice1 + 4 * self.priceTick))

        # 新增
        self.labelBidPrice1Middle.setText(str(tick.bidPrice1))
        self.labelAskPrice1Middle.setText(str(tick.askPrice1))
        self.labelBidVolume1Middle.setText(str(tick.bidVolume1))
        self.labelAskVolume1Middle.setText(str(tick.askVolume1))

        self.labelAskVolumeLast.setText(str(self.askVolumeLast))
        self.labelBidVolumeLast.setText(str(self.bidVolumeLast))
        self.labelAskVolumeSum.setText(str(self.askVolumeSum))
        self.labelBidVolumeSum.setText(str(self.bidVolumeSum))

        # 偏移与点差计算挂单价格
        self.labelAskpriceDiff.setText(str(tick.askPrice1 + self.spinDiff.value() * self.priceTick))
        self.labelBidpriceDiff.setText(str(tick.bidPrice1 - self.spinDiff.value() * self.priceTick))

        if tick.bidPrice2:
            self.labelBidPrice2.setText(str(tick.bidPrice2))
            self.labelBidPrice3.setText(str(tick.bidPrice3))
            self.labelBidPrice4.setText(str(tick.bidPrice4))
            self.labelBidPrice5.setText(str(tick.bidPrice5))

            self.labelAskPrice2.setText(str(tick.askPrice2))
            self.labelAskPrice3.setText(str(tick.askPrice3))
            self.labelAskPrice4.setText(str(tick.askPrice4))
            self.labelAskPrice5.setText(str(tick.askPrice5))

            self.labelBidVolume2.setText(str(tick.bidVolume2))
            self.labelBidVolume3.setText(str(tick.bidVolume3))
            self.labelBidVolume4.setText(str(tick.bidVolume4))
            self.labelBidVolume5.setText(str(tick.bidVolume5))

            self.labelAskVolume2.setText(str(tick.askVolume2))
            self.labelAskVolume3.setText(str(tick.askVolume3))
            self.labelAskVolume4.setText(str(tick.askVolume4))
            self.labelAskVolume5.setText(str(tick.askVolume5))

        self.labelLastPrice.setText(str(tick.lastPrice))

        if tick.preClosePrice:
            rt = (tick.lastPrice/tick.preClosePrice)-1
            self.labelReturn.setText(('%.2f' %(rt*100))+'%')
        else:
            self.labelReturn.setText('')

        # 新增
        self.askPricePrevious = self.lastTick.askPrice1
        self.bidPricePrevious = self.lastTick.bidPrice1
        self.volumePrevious = self.lastTick.volume

        updateEnd= datetime.datetime.now()
        self.ctaEngine.writeCtaLog(u'updateEnd时间: %s' % (updateEnd))
        self.ctaEngine.writeCtaLog(u'update运行时间: %s' % (updateEnd - updateStart))

感觉定义class 和调用class 都跟原版很接近的呀?好像不是注册事件的原因,还有什么其他的可能性么?或者我的调用class有问题?它的现象是可以正常启动,也可以正常运行,只是运行一个小时左右,就出现UI(未响应)。
感谢群主的指导

补充:
因为在updateTick函数的开始 和结尾都打印了时间戳
查看log发现,最后的时间戳是成对出现的,也就是最后一次是顺利的运行到了updateTick的结尾,不是死在了这个函数的内部计算过程中

2019-07-30 10:33:51,516  INFO: CTA_STRATEGY updateStart时间: 2019-07-30 10:33:51.400000
2019-07-30 10:33:51,571  INFO: CTA_STRATEGY updateEnd时间: 2019-07-30 10:33:51.409000
2019-07-30 10:33:51,572  INFO: CTA_STRATEGY update运行时间: 0:00:00.009000

目的是添加一个手动开仓的UI,按钮链接到策略的sendOrder,然后策略自动平仓(譬如止损),但失败了,启动半个小时左右,UI就 无响应了
版本 vnpy1.8.1
具体实施的步骤如下:
1、在主窗口增加了一个 “测试” 菜单
description
2、‘’测试‘下拉菜单里,添加按钮,连接到弹出窗口
测试按钮代码:

        # 帮助
        helpMenu = menubar.addMenu(vtText.HELP)
        helpMenu.addAction(self.createAction(vtText.CONTRACT_SEARCH, self.openContract, loadIconPath('contract.ico')))
        helpMenu.addAction(self.createAction(vtText.EDIT_SETTING, self.openSettingEditor, loadIconPath('editor.ico')))
        helpMenu.addSeparator()
        helpMenu.addAction(self.createAction(vtText.RESTORE, self.restoreWindow, loadIconPath('restore.ico')))
        helpMenu.addAction(self.createAction(vtText.ABOUT, self.openAbout, loadIconPath('about.ico')))
        helpMenu.addSeparator()
        helpMenu.addAction(self.createAction(vtText.TEST, self.test, loadIconPath('test.ico'))) 
       # 测试
        testMenu = menubar.addMenu(vtText.TEST)
        testMenu.addAction(self.createAction(u'参数配置', self.openSettingParameter, loadIconPath('editor.ico')))
        testMenu.addAction(self.createAction(u'sniper', self.sniperTrade, loadIconPath('editor.ico')))**

弹出窗口函数

    def sniperTrade(self):
        """打开手动交易"""
        try:
            self.widgetDict['sniperTrade'].show()
        except KeyError:
            self.widgetDict['sniperTrade'] = SniperTradingWidget(self.mainEngine, self.eventEngine, self.ctaEngine)    # 无问西东 新建窗体 新增传入ctaEngine
            self.widgetDict['sniperTrade'].show()

3、弹出窗口是参照“简单交易组件”照搬过来,增加了几个下单的按钮(可以连接到策略中的sendOrder)

class TradingWidget(QtWidgets.QFrame):

class SniperTradingWidget(QtWidgets.QFrame):

description

这个UI界面中没有耗时程序,基本updateTick函数,更新UI时间在10ms内

description

一般能正常启动和正常运行,半个小时到一个小时后,UI就无响应了(包括MainWindow),UI虽然无响应,但是后台的策略程序在正常运行。

description

请问这样加载一个新的弹出窗口的程序步骤是正确的么?无响应的问题会出在哪个环节?谢谢

知乎文章中 ,没找到底层调用 QueryPerformanceFrequency 函数 的位置,也写在头文件中了么?

应该还是在.h的头文件里有改动,请问这套代码的新链接在哪里?原来知乎上测试tick-to-trade的代码链接失效了

在头文件vnctpmd.h中的Task结构体中增加一行声明

//任务结构体
struct Task
{
    int task_name;      //回调函数名称对应的常量
    any task_data;      //数据结构体
    any task_error;     //错误结构体
    int task_id;        //请求id
    bool task_last;     //是否为最后返回
    LONGLONG task_time; //时间
};

增加上面最后一行,“task_time”: 不是“Task”的成员 的错误没有了

下面的错误依然存在:
错误 3 error C2039: “t”: 不是“MdApi”的成员
错误 4 error C2228: “.QuadPart”的左边必须有类/结构/联合
对应的代码段如下:

void MdApi::processRtnDepthMarketData(Task task)
{
    PyLock lock;
    CThostFtdcDepthMarketDataField task_data = any_cast<CThostFtdcDepthMarketDataField>(task.task_data);
    dict data;
    data["HighestPrice"] = task_data.HighestPrice;
    data["BidPrice5"] = task_data.BidPrice5;
    data["BidPrice4"] = task_data.BidPrice4;
    data["BidPrice1"] = task_data.BidPrice1;
    data["BidPrice3"] = task_data.BidPrice3;
    data["BidPrice2"] = task_data.BidPrice2;
    data["LowerLimitPrice"] = task_data.LowerLimitPrice;
    data["OpenPrice"] = task_data.OpenPrice;
    data["AskPrice5"] = task_data.AskPrice5;
    data["AskPrice4"] = task_data.AskPrice4;
    data["AskPrice3"] = task_data.AskPrice3;
    data["PreClosePrice"] = task_data.PreClosePrice;
    data["AskPrice1"] = task_data.AskPrice1;
    data["PreSettlementPrice"] = task_data.PreSettlementPrice;
    data["AskVolume1"] = task_data.AskVolume1;
    data["UpdateTime"] = task_data.UpdateTime;
    data["UpdateMillisec"] = task_data.UpdateMillisec;
    data["AveragePrice"] = task_data.AveragePrice;
    data["BidVolume5"] = task_data.BidVolume5;
    data["BidVolume4"] = task_data.BidVolume4;
    data["BidVolume3"] = task_data.BidVolume3;
    data["BidVolume2"] = task_data.BidVolume2;
    data["PreOpenInterest"] = task_data.PreOpenInterest;
    data["AskPrice2"] = task_data.AskPrice2;
    data["Volume"] = task_data.Volume;
    data["AskVolume3"] = task_data.AskVolume3;
    data["AskVolume2"] = task_data.AskVolume2;
    data["AskVolume5"] = task_data.AskVolume5;
    data["AskVolume4"] = task_data.AskVolume4;
    data["UpperLimitPrice"] = task_data.UpperLimitPrice;
    data["BidVolume1"] = task_data.BidVolume1;
    data["InstrumentID"] = task_data.InstrumentID;
    data["ClosePrice"] = task_data.ClosePrice;
    data["ExchangeID"] = task_data.ExchangeID;
    data["TradingDay"] = task_data.TradingDay;
    data["PreDelta"] = task_data.PreDelta;
    data["OpenInterest"] = task_data.OpenInterest;
    data["CurrDelta"] = task_data.CurrDelta;
    data["Turnover"] = task_data.Turnover;
    data["LastPrice"] = task_data.LastPrice;
    data["SettlementPrice"] = task_data.SettlementPrice;
    data["ExchangeInstID"] = task_data.ExchangeInstID;
    data["LowestPrice"] = task_data.LowestPrice;
    data["ActionDay"] = task_data.ActionDay;

    //保存测试时间
    data["tick_time"] = task.task_time;
    data["frequency_time"] = this->t.QuadPart;
    this->onRtnDepthMarketData(data);
};

问题出在,最后的这三行中,请问这个错误应该如何消除?

按照知乎帖子“vn.trader的tick-to-trade延时测试”一文,链接为https://zhuanlan.zhihu.com/p/24242972,想测试一下本机的内部耗时,vnpy为1.8.1版本,在visual studio 2013 (boost为boost_1_68_0版本)编译的时候,出现如下错误:
错误 2 error C2039: “task_time”: 不是“Task”的成员
错误 3 error C2039: “t”: 不是“MdApi”的成员
错误 4 error C2228: “.QuadPart”的左边必须有类/结构/联合
5 IntelliSense: class "Task" 没有成员 "task_time"

原文代码的github链接失效了,所以不知道具体还改了哪些地方,我只改了“vn.trader的tick-to-trade延时测试”一文中提到的内容,不知道为什么会出现这样的错误(boost版本的原因?),请指点一下,谢谢

© 2015-2022 微信 18391752892
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

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