龙听期货论坛's Archiver

龙听 发表于 2024-12-6 13:18

C++程序化/量化学习视频教程系列 第024节:鼎元C++量化之调用map调用bar数据(K线开、高、低及收盘价格调用)知识及C++量化开发中的注意事项【C++量化指标公式开发系列】

C++程序化/量化学习视频教程系列 第024节:鼎元C++量化之使用map调用bar数据(K线开、高、低及收盘价格调用)知识及C++量化开发中的注意事项【C++量化指标公式开发系列】

[mp4]http://mp4.qhlt.club/Cpp-Video/024.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-6 13:19

演示:用数组、容器及map进行数据的操作:[code]#include<iostream>
#include<map>
#include <cstring>
#include <vector>
#include <math.h>
#include <iomanip>
using namespace std;
using std::setw;

int main()
{
        double nice[5]={0,1,2,3,4};

        for (int i = 0; i < 5; i++)
        {
                cout << nice[i] << endl;

        }

        for (int j = 0; j < 5; j++)
        {
                nice[j] = 2 * j;
                cout << nice[j] << endl;
        }

        vector<double>mynice = { 0,1,2,3,4,5 };
        for (int i = 0; i < 5; i++)
        {
                cout << "用vector输出:" << mynice[i] <<endl;
        }

        for (int i = 0; i < 5; i++)
        {
                mynice.push_back(i*2);
                cout << mynice[i] << endl;
        }
        for (int i = 0; i < mynice.size(); i++)
        {
                cout << mynice[i] << endl;
        }

        return 0;
}[/code]

龙听 发表于 2024-12-6 14:11

声明 map 容器:[code]std::map<key_type, value_type> myMap;[/code]key_type 是键的类型。
    value_type 是值的类型。

插入元素:[code]myMap[key] = value;[/code]访问元素:[code]value = myMap[key];[/code]遍历 map:[code]for (std::map<key_type, value_type>::iterator it = myMap.begin(); it != myMap.end(); ++it) {
    std::cout << it->first << " => " << it->second << std::endl;
}[/code][code]
std::map<key_type, value_type>::iterator
for (it = myMap.begin(); it != myMap.end(); ++it) {
    std::cout << it->first << " => " << it->second << std::endl;
}
[/code][code]
#include <iostream>#include <map>
#include <string>

int main() {
    // 创建一个 map 容器,存储员工的姓名和年龄
    std::map<std::string, int> employees;

    // 插入员工信息
    employees["Alice"] = 30;
    employees["Bob"] = 25;
    employees["Charlie"] = 35;

    // 遍历 map 并打印员工信息
    std::map<std::string, int>::iterator
    for ( it = employees.begin(); it != employees.end(); ++it) {
        std::cout << it->first << " is " << it->second << " years old." << std::endl;
    }

    return 0;
}
[/code]在鼎元C++中请求调用数据函数:
RsqBar:[code]RsqBar(sPeriod, sInst);//查询历史K线数据
        ma = average(sPeriod, sInst, length); //调用简单移动平均线数值[/code][code]void test::RsqBar(string period, string inst)
{
        TRSQBAR* t = new TRSQBAR();
        t->Name = sName;
        t->Type = "RsqBar";
        t->Period = period;
        t->Inst = inst;
        if (hwnd)SendMessage(hwnd, WM_RSQBAR, (WPARAM)t, (LPARAM)36);
}[/code][img]http://p.algo2.net/2024/1206/3d2602497133f.png[/img]

函数注意事项:[code]double test::average(string period, string inst, int num)[/code][code]struct TKVALUE
{
        string sDate;
        string sTime;
        string InstrumentID;
        string sPeriod;
        double dOpen = 0;
        double dHigh = 0;
        double dLow = 0;
        double dClose = 0;
        int nVolume = 0;
        int nOpenInterest = 0;
        string sDayNight;
};[/code][b]逆向遍历:[/b][code]
map<string, TKVALUE>::reverse_iterator it;
for (it = mapK[period][inst].rbegin(); it != mapK[period][inst].rend(); ++it)
[/code][b]正向遍历:[/b][code]
map<string, TKVALUE >::iterator it;
for (it = mapK[period][inst].begin(); it != mapK[period][inst].end(); ++it)
[/code][b]形象展示:[/b]

[img]http://p.algo2.net/2024/1206/9b6cfb8d4ecef.png[/img]

说明:

1、因为周期、品种合约代码都是固定的。所以在map里面KVALUE中的要素还包括:

2、日期和时间:平时多用不着。但是当需要从左向右的正序调用数据时或从 右向左逆向调用数据时时间是一个排序的工具。

3、k线的主要要素(开、高、低、收)。

4、成交量;

5、持仓量;

总结:以蜡烛图的四要素与成交持仓两要素组成了交易策略的大部分设计元素。

[b]如何调用:[/b][code]map<string, TKVALUE >::iterator it; //建立正迭代器,标号从0开始,一般从左向右开始
for (it = mapK[period][inst].begin(); it != mapK[period][inst].end(); ++it) //从第一开始的bar数据开始遍历
        {       
                 it->second.
        }[/code]在TKVALUE中能调用的素材:[code]
        string sDate;
        string sTime;
        string InstrumentID;
        string sPeriod;
        double dOpen = 0;
        double dHigh = 0;
        double dLow = 0;
        double dClose = 0;
        int nVolume = 0;
        int nOpenInterest = 0;
        string sDayNight;
[/code]所以在用k线做策略时我们多数能调用的也就是dhigh,dlow,dopen,dclose,nvolume,nopeninterest 这六个要素。制作均线,常用的就是dclose,区间上沿多用dhigh,区间下沿多用dlow。

龙听 发表于 2024-12-6 14:53

我要是想调用最新bar的开盘价。

我要做三件事:

1、建立遍历用的迭代器,因为我是要用到最新的,所以我要建立一个逆向迭代器。
2、找到最新的bar,因为我是用的逆向的,所以第一个数据就是我要调用的,只需要循环一次就行了。我要用到一个开关,就是控制只允许它循环一轮就结束。
3、把dopen调来用。

完整流程是这样的:

1、建立正向迭代器:[code]map<string, TKVALUE>::reverse_iterator it; [/code]2、用for循环来进行遍历:(因为我仅允许它循环一次,所以我加一个开关)[code]
   int key = 0; //建立一个开关,下面看我是怎么使用这个开关的
   int closep; //声明一个变量用来存储最新bar的开盘价
for (it = mapK[period][inst].rbegin(); it != mapK[period][inst].rend(); it++)



[/code]3、调用我需要的最新的开盘价

(1)声明一个变量用来存这个收盘价: int closep;
  (2)  将最新的bar的开盘价赋值给(1)中的变量:closep = it ->second.dopen;

完整的程式码是这样的:[code]
        RsqBar(period, sInst); //申请调用数据指令
        double key = 0; //建立一个开关
        map<string, TKVALUE>::reverse_iterator it; //建立逆向迭代器
        for (it = mapK[period][inst].rbegin(); it != mapK[period][inst].rend(); ++it)  //进行遍历
        {
                closep = it->second.dopen; //将最新的bar的开盘价赋值给closep;
                key++;  //开关自动加1,即从0变为1
                if (key > 0) break; //进行判断如果key大于0就跳出结束循环,也可以使用key == 1 然后结束循环等等
        }
[/code]

龙听 发表于 2024-12-6 15:22

另一种办法调用最新bar的开盘价。

1、思路:

1、大体思路仍然是建立迭代器、for循环。
2、但是建立for循环后我用一个vector来装TKVALUE中所有bar的开盘价。
3、然后我用vector[标号]来直接引用。
4、甚至我要是想进行平均,计算方差类的,也可以继续用这个vector。

完整流程是这样的:

(1)、在头文件中声明变量:[code]        vector<double>openp;[/code](2)、在源文件:[code]RsqBar(sPeriod, sInst); //调用数据申请指令

map<string, TKVALUE >::iterator it;  //建立一个正向的迭代器
        for (it = mapK[sPeriod][sInst].begin(); it != mapK[sPeriod][sInst].end(); ++it) //建立for遍历
        {
                openp.push_back(it->second.dopen);  //从左至右将每一个bar的开盘价加到openp容器vector中
        }
        closep = openp[openp.size()-1];  //通过下标号将用最新的dopen价格给closep;[/code]

龙听 发表于 2024-12-6 15:25

使用场景有两个:一个是在onrun中调用最新bar的开价,然后在tick中直接使用即可。二是将上面的的程式码再加到onbariopen中。每新生成一个bar就会运行一次,将最新的bar开盘价调用出来供使用。

龙听 发表于 2024-12-6 15:32

再发个更详细的map(TKVALUE)形象图:
[img]http://p.algo2.net/2024/1206/003ef0e5d2fed.png[/img]

页: [1]