龙听期货论坛's Archiver

龙听 发表于 2024-12-23 10:07

C++程序化/量化学习视频教程系列 第040节:鼎元C++量化之【tick进出场模块|bar进出场模块设计与逻辑】【C++量化开发进出场模块系列】

C++程序化/量化学习视频教程系列 第040节:鼎元C++量化之【tick进出场模块|bar进出场模块设计与逻辑】【C++量化开发进出场模块系列】

[mp4]http://mp4.qhlt.club/Cpp-Video/040.mp4[/mp4]

C++程序化学习视频教程系列安排如下:
第一楼:教学视频。一般控制在15分钟左右;
第二椄:视频课程中使用的程式源码。
第三楼:视频教学中需要用到的一些文档或资源。
第四楼:其它的一些边角料,特别是一些经典程序化策略的回测类的部分会放到下面楼层里面。

参与模式如下:
1、希望参与到编写策略与调试方面的工作通过上面的联系方式联系管理员咨询即可。记的加群,有问题第一时间交流,也可以在论坛指定版发贴交流,专用版地址:[url=http://www.qhlt.cn/forum-244-1.html]http://www.qhlt.cn/forum-244-1.html[/url];
2、有意申请试用及绑定期货账户跑实盘网友可以联系管理员,以及开通的方式。
3、基于C++策略交易软件具有:1、软件小(50兆不到);2、效率高(C++语言);3、功能精(专注于策略);4、对服务噐或电脑兼容性好(WIN系统)等优势,特别适合长期跑程序化的客户朋友,特别是有稳定交易模式客户更适合使用C++构建的交易系统。
4、最全的C++期货程序化(量化)教程、视频、源码、课件、资源汇总贴【C++期货程序化/量化研究必备资源贴!】:[url=http://www.qhlt.cn/thread-160231-1-1.html]http://www.qhlt.cn/thread-160231-1-1.html[/url];
5、鼎元C++量化程式码技术指标源码C++版模板【建议在test.h和test.cpp中同步至最新,方便统一调用和使用,一次编辑多次使用!】:[url=http://www.qhlt.cn/thread-160230-1-1.html]http://www.qhlt.cn/thread-160230-1-1.html[/url];
6、如何使用鼎元C++量化软件以及需要准备的些什么?[C++量化入门必读!]:[url=http://www.qhlt.cn/thread-160415-1-1.html]http://www.qhlt.cn/thread-160415-1-1.html[/url];

联系方式:
C++微信群:[img=180,180]http://p.algo2.net/2024/0922/23852f86ccf81.png[/img]  QQ群:[img=140,180]http://p.algo2.net/2024/0115/3c6af4df957c3.jpg[/img] 管理员微信:[img]http://www.qhlt.cn/link/wx.png[/img];管理员QQ:[img]http://www.qhlt.cn/link/q.png[/img]

龙听 发表于 2024-12-23 10:17

tick模块进出场模块设计:

1、【void test::OnMarketData(CThostFtdcDepthMarketDataField* t)】模块

2、必要配置设置[code]
        if (state != "run")return; //非运行状态返回
        if (t->OpenInterest < 1)return; //持仓小于1返回
        if (t->InstrumentID != sInst)return;//行情数据品种与选择交易品种不一致返回(多为写错品种代码)
[/code]3、【行情数据map】及时间设置[code]
mapMd[t->InstrumentID] = *t;
        string sss = t->UpdateTime; //刷新时间
        //交易委托时间控制模块(大陆国内期货市场交易时间,09:00-10:15,10:30-11:30,13:30-15:00,21:00-23:00)非交易时间不发委托
        if( (sss >= "00:00:00" && sss <= "09:00:00") || (sss >= "10:15:00" && sss <= "10:30:00") || (sss >= "11:30:00" && sss <= "13:30:00") || (sss >= "15:00:00" && sss <= "21:00:00") || (sss >= "23:00:00" && sss <= "23:59:59"))return; //非交易时间返回
[/code]4、进场设计模块:[code]
// 最新tick价格大于均线且持仓为0则进场做多
        if (t->LastPrice > ma && fx == 0)
        {
                fx = 1;
                ss = dbfx;
                map<string, double>::iterator it;
                for (it = mapSub.begin(); it != mapSub.end(); it++)
                {
                        int sl = (int)(ss*it->second);
                        OrderInsert(it->first, sInst, '0', '0', sl, t->AskPrice1 + hd * mapInstrument[sInst].PriceTick, "", "");//买入开仓语句
                        //输出至交易界面LOG日志里面
                        string s = it->first + "突破入场价格多单达到入场条件买入开仓" + to_string(sl) + "手,价格 " + to_string(t->AskPrice1 + hd * mapInstrument[sInst].PriceTick) + "基础手数 " + to_string(ss) + "均线值" + to_string(ma);
                        maps[num] = s;
                        num++;
                }
                if (num != 0) shuchurizhi();
                tm = 0;
                xieruzhuangtai();
        }
//最新价格小于均线且持仓为0则进场做空
        if (t->LastPrice < ma && fx == 0)
        {
                fx = -1;
                ss = dbfx;
                map<string, double>::iterator it;
                for(it = mapSub.begin(); it != mapSub.end();it++)
                {
                        int sl = (int)(ss * it->second);
                        OrderInsert(it->first, sInst, '1', '0', sl, t->BidPrice1 - hd * mapInstrument[sInst].PriceTick, "", ""); //卖出开仓语句
                        //输出至交易界面LOG日志里面
                        string s = it->first + "突破入场价格空单达到入场条件卖出开仓" + to_string(sl) + "手,价格 " + to_string(t->BidPrice1 - hd * mapInstrument[sInst].PriceTick) + "基础手数" + to_string(ss) + "均线值" + to_string(ma);
                        maps[num] = s;
                        num++;
                }
                if (num != 0)shuchurizhi();
                tm = 0;
                xieruzhuangtai();
        }
[/code]5、出场设计模块[code]
if (zt == 1 && fdzy == 1 && t->LastPrice < cb + (1 - hlbfb) * fdzyz)
        {
                zt = 0;
                map<string, double>::iterator it;
                for (it = mapSub.begin(); it != mapSub.end(); it++)
                {
                        int sl = (int)(ss * it->second);
                        if (yxpc == 0)
                        {
                                closesell1(it->first, sInst, sl, t->LastPrice - hd * mapInstrument[sInst].PriceTick); //多单卖出平仓
                        }
                        else if (yxpc == 1)
                        {
                                closesell2(it->first, sInst, sl, t->LastPrice - hd * mapInstrument[sInst].PriceTick); // 多单卖出平仓
                        }
                        string s = it->first + "    多单达到回落止盈条件后触发回落止盈条件卖出平仓    " + to_string(sl) + "    手,价格    " + to_string(t->LastPrice - hd * mapInstrument[sInst].PriceTick) + "  回落止盈价格 " + to_string(cb + (1-hlbfb)*fdzyz);
                        maps[num] = s;
                        num++;
                }
                if (num != 0)shuchurizhi();
                tm = 0;
                xierucanshu();
        }
[/code][code]
if (zt == -1 && fdzy == -1 && t->LastPrice > cb - (1 - hlbfb) * fdzyz)
        {
                zt = 0;
                map<string, double>::iterator it;
                for (it = mapSub.begin(); it != mapSub.end(); it++)
                {
                        int sl = (int)(ss * it->second);
                        if (yxpc == 0)
                        {
                                closebuy1(it->first, sInst, sl, t->LastPrice + hd * mapInstrument[sInst].PriceTick);  //空单买入平仓语句
                        }
                        else if (yxpc == 1)
                        {
                                closebuy2(it->first, sInst, sl, t->LastPrice + hd * mapInstrument[sInst].PriceTick);  //空单买入平仓语句
                        }

                        string s = it->first + "    空单达到回落止盈条件后触发回落止盈条件买入平仓    " + to_string(ss) + "    手,价格    " + to_string(t->LastPrice + hd * mapInstrument[sInst].PriceTick) + "  回落止盈价格 " + to_string(cb -(1-hlbfb)*fdzyz);
                        maps[num] = s;
                        num++;
                }
                if (num != 0)shuchurizhi();
                tm = 0;
                xierucanshu();
        }
[/code]6、尝试行情关于价格的要素:[code]///深度行情
struct CThostFtdcDepthMarketDataField
{
        ///交易日
        TThostFtdcDateType        TradingDay;
        ///合约代码
        TThostFtdcInstrumentIDType        InstrumentID;
        ///交易所代码
        TThostFtdcExchangeIDType        ExchangeID;
        ///合约在交易所的代码
        TThostFtdcExchangeInstIDType        ExchangeInstID;
        ///最新价
        TThostFtdcPriceType        LastPrice;
        ///上次结算价
        TThostFtdcPriceType        PreSettlementPrice;
        ///昨收盘
        TThostFtdcPriceType        PreClosePrice;
        ///昨持仓量
        TThostFtdcLargeVolumeType        PreOpenInterest;
        ///今开盘
        TThostFtdcPriceType        OpenPrice;
        ///最高价
        TThostFtdcPriceType        HighestPrice;
        ///最低价
        TThostFtdcPriceType        LowestPrice;
        ///数量
        TThostFtdcVolumeType        Volume;
        ///成交金额
        TThostFtdcMoneyType        Turnover;
        ///持仓量
        TThostFtdcLargeVolumeType        OpenInterest;
        ///今收盘
        TThostFtdcPriceType        ClosePrice;
        ///本次结算价
        TThostFtdcPriceType        SettlementPrice;
        ///涨停板价
        TThostFtdcPriceType        UpperLimitPrice;
        ///跌停板价
        TThostFtdcPriceType        LowerLimitPrice;
        ///昨虚实度
        TThostFtdcRatioType        PreDelta;
        ///今虚实度
        TThostFtdcRatioType        CurrDelta;
        ///最后修改时间
        TThostFtdcTimeType        UpdateTime;
        ///最后修改毫秒
        TThostFtdcMillisecType        UpdateMillisec;
        ///申买价一
        TThostFtdcPriceType        BidPrice1;
        ///申买量一
        TThostFtdcVolumeType        BidVolume1;
        ///申卖价一
        TThostFtdcPriceType        AskPrice1;
        ///申卖量一
        TThostFtdcVolumeType        AskVolume1;
        ///申买价二
        TThostFtdcPriceType        BidPrice2;
        ///申买量二
        TThostFtdcVolumeType        BidVolume2;
        ///申卖价二
        TThostFtdcPriceType        AskPrice2;
        ///申卖量二
        TThostFtdcVolumeType        AskVolume2;
        ///申买价三
        TThostFtdcPriceType        BidPrice3;
        ///申买量三
        TThostFtdcVolumeType        BidVolume3;
        ///申卖价三
        TThostFtdcPriceType        AskPrice3;
        ///申卖量三
        TThostFtdcVolumeType        AskVolume3;
        ///申买价四
        TThostFtdcPriceType        BidPrice4;
        ///申买量四
        TThostFtdcVolumeType        BidVolume4;
        ///申卖价四
        TThostFtdcPriceType        AskPrice4;
        ///申卖量四
        TThostFtdcVolumeType        AskVolume4;
        ///申买价五
        TThostFtdcPriceType        BidPrice5;
        ///申买量五
        TThostFtdcVolumeType        BidVolume5;
        ///申卖价五
        TThostFtdcPriceType        AskPrice5;
        ///申卖量五
        TThostFtdcVolumeType        AskVolume5;
        ///当日均价
        TThostFtdcPriceType        AveragePrice;
        ///业务日期
        TThostFtdcDateType        ActionDay;
};[/code]

龙听 发表于 2024-12-23 10:33

bar模块进出场模块设计:

1、【void test::OnBarOpen(TKVALUE t)】

2、bar进出必要参数配置[code]
        if (state != "run")return;
        if (t.InstrumentID != sInst)return;
        mapK[sPeriod][sInst][t.sDate + t.sDayNight + t.sTime] = t;
[/code]3、调用指标或变量[code]
        ma = average(sPeriod, sInst, length); //每个bar产生的时候都计算一次.[指标运行不包含正在形成的bar].
[/code]4、进场模块设计[code]
if (jyfx>-1 &&  ( dzqjx+dzqmacd>=1 ||(dzqjx==0 && dzqmacd==0) )   && xzqjx+xzqmacd>=2 )
                        {
                                zt = 1;
                                sfzy = 0;
                                fdzy = 0;
                                fdzyz = 0;
                                map<string, double>::iterator it;
                                for (it = mapSub.begin(); it != mapSub.end(); it++)
                                {
                                        int sl = (int)(ss * it->second);
                                        OrderInsert(it->first, sInst, '0', '0', sl, t.dClose + hd * mapInstrument[sInst].PriceTick, "", "");  //买入开仓语句
                                        string s = it->first +s4+ "    多单达到入场条件买入开仓    " + to_string(sl) + "    手,价格    " + to_string(t.dClose + hd * mapInstrument[sInst].PriceTick) + "    " + sInst;
                                        maps[num] = s;
                                        num++;
                                }
                                cb = t.dClose + hd * mapInstrument[sInst].PriceTick;
                                if (num != 0)shuchurizhi();
                                tm = 0;
                                xierucanshu();
                        }       
       
                        if ( jyfx<1 && (dzqjx+dzqmacd<=-1 ||(dzqjx==0 &&  dzqmacd==0) )&& xzqjx+xzqmacd<=-2 )
                        {
                                zt = -1;
                                sfzy = 0;
                                fdzy = 0;
                                fdzyz = 0;
                                map<string, double>::iterator it;
                                for (it = mapSub.begin(); it != mapSub.end(); it++)
                                {
                                        int sl = (int)(ss * it->second);
                                        OrderInsert(it->first, sInst, '1', '0', sl, t.dClose - hd * mapInstrument[sInst].PriceTick, "", "");  //卖出开仓语句
                                        string s = it->first +s4+ "    空单达到入场条件卖出开仓    " + to_string(sl) + "    手,价格    " + to_string(t.dClose - hd * mapInstrument[sInst].PriceTick) + "    " + sInst;
                                        maps[num] = s;
                                        num++;

                                }
                                cb = t.dClose + hd * mapInstrument[sInst].PriceTick;
                                if (num != 0)shuchurizhi();
                                tm = 0;
                                xierucanshu();
                        }
[/code]5、出场模块设计[code]
//(1)最新bar价格小于均线价格,且持仓多单则进行多单卖出模块(sell model)
        if (mapMd[sInst].LastPrice < ma && fx == 1)
        {
                fx = 0;
                map<string, double>::iterator it;
                for (it = mapSub.begin(); it != mapSub.end(); it++)
                {
                        int sl = (int)(ss * it->second);
                        if (yxpc == 0)
                        {
                                closesell1(it->first, sInst, sl, mapMd[sInst].AskPrice1 - hd * mapInstrument[sInst].PriceTick);//卖出平仓,优先平昨
                        }
                        else if (yxpc == 1)
                        {
                                closesell2(it->first, sInst, sl, mapMd[sInst].AskPrice1 - hd * mapInstrument[sInst].PriceTick); //卖出平仓,优先平今
                        }
                        string s = it->first + "多单跌破均线达到出场条件卖出平仓 " + to_string(sl) + " 手,价格 " + to_string(mapMd[sInst].AskPrice1 - hd * mapInstrument[sInst].PriceTick) + "基础手数 " + to_string(ss) + "均线值" + to_string(ma);
                        maps[num] = s;
                        num++;
                }
                if (num != 0)shuchurizhi();
                tm = 0;
                xieruzhuangtai();
        }
//(2)最新bar价格大于均线价格,且持仓空单则进行买入平仓空单模块(covertobuy model)
        if (mapMd[sInst].LastPrice > ma && fx == -1)
        {
                fx = 0;
                map<string, double>::iterator it;
                for (it = mapSub.begin(); it != mapSub.end(); it++)
                {
                        int sl = (int)(ss * it->second);
                        if (yxpc == 0)
                        {
                                closebuy1(it->first, sInst, sl, mapMd[sInst].BidPrice1 + hd * mapInstrument[sInst].PriceTick);//买入平仓语句.优先平昨
                        }
                        else if (yxpc == 1)
                        {
                                closebuy2(it->first, sInst, sl, mapMd[sInst].BidPrice1 + hd * mapInstrument[sInst].PriceTick);//买入平仓语句,优先平今
                        }
                        string s = it->first + " 空单涨破均线达到出场条件买入平仓 " + to_string(sl) + " 手,价格 " + to_string(mapMd[sInst].BidPrice1 + hd * mapInstrument[sInst].PriceTick) + "基础手数" + to_string(ss) + "均线值" + to_string(ma);
                        maps[num] = s;
                        num++;
                }
                if (num != 0)shuchurizhi();
                tm = 0;
                xieruzhuangtai();
        }
[/code]

龙听 发表于 2024-12-23 10:40

[b]重要说明:

1、调用最新价格,在tick行情模式下直接【t->LastPrice】即可,而在bar行情模式下需【mapMd[sInst].LastPrice】

2、除了用最新价lastpriceq外还可以使用bidprice或askprice。区别如下:

[img]http://p.algo2.net/2024/1109/bffbc7faba9b6.png[/img]

按照价格大小从上往下排列,中间以上的为卖方要价askprice,中间以下的为买方出价bidprice。

所以在写卖出类委托时要用bidprice来才保证成交率;同样在写买入类的策略时记的要用askprice以保证成交率。[/b]

龙听 发表于 2024-12-23 10:44

[code]
        ///申买价一
        TThostFtdcPriceType        BidPrice1;
        ///申卖价一
        TThostFtdcPriceType        AskPrice1;
[/code]用bidprice或askprice时建议用这两个,因为他们离最新价最近。

页: [1]