网站首页 > 技术文章 正文
对于量化交易策略而言,交易所发布的实时行情数据是远远不够的。通常需要经过大量的计算,得到衍生因子指标,再进行逻辑判断,最后输出交易信号。
今天就以最常见的移动平均为例,讲一下优化算法的一个思路。
移动平均是最近N个数据的算数平均。随着新数据的产生,移动平均的区间起点也会随之移动,起点到最新位置共有N个数据。
通常,用到的是K线收盘价的移动平均。
K线收盘价是指的固定区间内最后一笔Tick的价格。交易所以固定的频率发布Tick数据,假设每秒发布2笔,则1分钟K线就包含120笔Tick数据。当1分钟结束时,最一笔Tick的价格就是这1分钟K线的收盘价。
如上图,Last是最新K线位置,盘中Tick更新时,Last的价格随之变化。直到K线结束,产生了一个新的K线Last',旧的Last就变成了Last-1。
基于以上认知,可以写出常规的算法:
首先,把源数据存储到vector中,每120次追加一次新数据,如果不是新数据,则更新最后一个数据;
然后,对vector最后N个数据求和;
最后,除以参数N,就得到了移动平均。
void maJunior()
{
std::cout << "===>>> " << "maJunior" << " <<<===" << std::endl;
double dSumValue = 0;
/// 均线参数,从10到500
for (int nParameter = 10; nParameter <= 500; ++nParameter)
{
std::chrono::time_point<std::chrono::high_resolution_clock> tAnchor;
time_t nElapse = 0;
/// 随机数
std::uniform_real_distribution<double> u(9000, 11000);
std::default_random_engine e;
/// 进行100次重复实验
for (int ikk = 0; ikk < 100; ++ikk)
{
/// 存放均线计算结果
std::vector<double> vJuniorResultVector;
vJuniorResultVector.reserve(110000);
/// 存放数据源
std::vector<double> vSourceVector;
vSourceVector.reserve(2000);
std::vector<double>::iterator itVector;
/// 初始化
int nIndex = 0;
for (; nIndex < nParameter; ++nIndex)
{
vSourceVector.push_back(u(e));
}
--nIndex;
double dValue;
bool bIsStart;
double dJuniorValue;
/// 按照顺序生成10万个数据,并计算移动平均
for (int jkk = 0; jkk < 100000; ++jkk)
{
/// 随机生成源数据
dValue = u(e);
/// 每120个数据占据一个K线位置
bIsStart = (((jkk) % 120) == 0);
/// 计时
tAnchor = std::chrono::high_resolution_clock::now();
/// 存放源数据
if (bIsStart)
{
/// 一个新K线位置
vSourceVector.push_back(dValue);
++nIndex;
}
else
{
/// 更新当前K线位置数据
vSourceVector[nIndex] = dValue;
}
/// 均值
dJuniorValue = std::accumulate(vSourceVector.end() - nParameter, vSourceVector.end(), 0.0) / nParameter;
/// 耗时
nElapse += std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - tAnchor).count();
vJuniorResultVector.push_back(dJuniorValue);
}
dSumValue += std::accumulate(vJuniorResultVector.begin(), vJuniorResultVector.end(), 0.0);
}
std::cout << "Parameter:" << nParameter << ",Elapse:" << nElapse / 100000 / 100 << ",SumValue:" << dSumValue << std::endl;
}
std::cout << "===>>>" << "<<<===" << std::endl;
}
因为,每次都需要对K线序列中最后N个数据求和,所以该常规算法的耗时会随着参数N的增加而增加。
现在,我们来思考优化这个算法。
当K线结束时,这个K线收盘价也就固定了。在K线序列中,除了最后一个位置的数据在实时变化,之前的数据都是不变的。
如果我们把N个数据的和拆解为N-1个固定数据(Inactive),和1个变化数据(Last)。每次更新Last,只需要计算一次加法,即Last+Inactive,就可以得到N个数据的和。
当新K线Last'产生时,只要更新Inactive,从Inactive中减去Last-N-1,再加上Last,成为新的Inactive',再与新的Last'相加可以了。
这样一来,优化后的算法的耗时就与参数N就没有关系了。
在服务器上运行测试代码,耗时数据也印证了这一点。
常规算法耗时随着参数N增加而增加,计算参数为500的移动平均,单数据点耗时670纳秒左右。
优化后的算法耗时与参数N无关,单数据点耗时124纳秒左右。
除了简单移动平均之外,常用的加权平均、区间最大/小值、线性回归等,都可以基于这个思路,拆解出来不变的部分和变化的部分,从而设计出来耗时与参数无关的算法。
猜你喜欢
- 2024-10-17 找不到中文语音预训练模型?中文版 Wav2vec 2.0和HuBERT来了
- 2024-10-17 数据分析师必备的五类Excel数据分析函数,超全总结,易收藏
- 2024-10-17 Excel查找和引用函数(二) excel查找和引用函数有哪些
- 2024-10-17 经典面试题目「回溯算法」求组合总和(二)
- 2024-10-17 蚂蚁金服核心技术:百亿特征实时推荐算法揭秘
- 2024-10-17 内存用量1/20,速度加快80倍,QQ提全新BERT蒸馏框架,未来将开源
- 2024-10-17 一文读懂C++ 异步编程 c++异步调用
- 2024-10-17 遍地开花的 Attention,你真的懂吗?
- 2024-10-17 程序员必学算法「动态规划」:最大子序和
- 2024-10-17 Python 中的 Numpy 总结 python的numpy库详细教程
你 发表评论:
欢迎- 11-19零基础学习!数据分析分类模型「支持向量机」
- 11-19机器学习 | 算法笔记(三)- 支持向量机算法以及代码实现
- 11-19我以前一直没有真正理解支持向量机,直到我画了一张图
- 11-19研一小姑娘分享机器学习之SVM支持向量机
- 11-19[机器学习] sklearn支持向量机
- 11-19支持向量机
- 11-19初探支持向量机:用大白话解释、原理详解、Python实现
- 11-19支持向量机的核函数
- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)