English Русский Español Deutsch 日本語 Português
preview
MQL5中的ALGLIB数值分析库

MQL5中的ALGLIB数值分析库

MetaTrader 5示例 | 31 一月 2024, 10:50
453 0
MetaQuotes
MetaQuotes

概述

金融市场生成的数据具有大量复杂的关系,为了分析它们,我们需要使用最现代的应用数学方法。成功地将金融数据的高度复杂性与分析的简单性和效率相结合是一项具有挑战性的任务。ALGLIB是一个高性能的库,专门用于处理数值方法和数据分析算法,它是分析金融市场的可靠助手。

ALGLIB 的通用性如今,ALGLIB被公认为使用数值方法的最佳开发库之一。它支持多种编程语言(C++、C#、Java、Python、Delphi)和操作系统(Windows和POSIX,包括Linux)。

在ALGLIB的众多功能中,以下部分尤为突出:

  • 线性代数:包括直接算法、特征值(EVD)和奇异值(SVD)方法,这些方法对数据分析很重要。
  • 求解方程:支持线性和非线性方程组,这在建模复杂的金融过程时很有用。
  • 插值和近似:支持各种数据插值和近似方法,这在分析和预测市场趋势方面很有用。
  • 优化:ALGLIB提供了寻找最佳解决方案的算法,这对于优化投资组合和其他金融决策非常重要。
  • 数值积分:允许计算定积分,这在评估金融工具时很有用。
  • 机器学习:包括数据分析、分类、回归,甚至使用神经网络,为预测市场趋势开辟了新的可能性。


ALGLIB的优势

为什么在处理金融数据时选择ALGLIB?

以下是库的主要优点:

  • 可移植性:ALGLIB使用各种编译器在各种平台上轻松编译,使不同背景的开发人员都可以访问它。
  • 易用性:支持多种编程语言,因此您可以选择最熟悉的语言,而无需学习新的语法。
  • 开源:ALGLIB是开源的,可以在GPL2+协议下使用。这使得科学研究和商业项目都可以使用它。
  • 商业用户支持:商业用户可以购买许可证,在使用ALGLIB时为他们提供法律保护。

此外,该库包含大量测试用例,涵盖了所提出方法功能的主要部分。这将允许您进行测试,并向项目作者报告检测到的错误。有关该库的更多详细信息,请访问项目网站https://www.alglib.net/

ALGLIB于2012年首次使用MQL5语言改写,这个改编是对3.5版本库的转换。从那时起,10多年过去了。在此期间,ALGLIB在金融市场交易领域的开发者和分析师中广为人知。多年来,开发团队一直在积极改进库,进行了70多项更改,包括添加新的类、函数和改进。

还应注意的是,现有库类已重新设计为使用矩阵和向量,并添加了ALGLIB 3.19中引入的新功能。“Complex”数据类型现在用于处理复数。所有源代码都按照统一的设计风格进行了修订和结构化。

不幸的是,在3.19版本中对MQL5的ALGLIB库所做的更改非常显著,因此不提供向前兼容性。建议在项目中应用ALGLIB 3.5版的用户彻底审查他们的程序并进行任何必要的调整。

除了库本身,测试脚本也已更新。现在有91个用于类(class),152个用于接口(interface)。这有助于对库功能进行更可靠和全面的测试。

ALGLIB的新版本可在此处获得:ALGLIB-数值分析库-MetaTrader 5的库,以及MetaTrader 5平台的一部分(\MQL5\Include\Math\ALGLIB\,包括\MQL5\Scripts\UnitTests\ALGLIB\中的测试用例)。


1. ALGLIB 3.19新增功能(自3.5版以来的更改列表)

3.19:

  • ALGLIB 3.19.0中最重要的功能是用于处理大型数据集的新RBF(Radial Basis Function, 径向基函数)求解器,它支持薄板样条、二次谐波样条和多次二次曲面。此解算器支持插值和拟合(平滑)问题;
  • 新的RBF算法采用域分解方法求解线性系统。因此,它具有O(N)内存需求和O(N2)执行时间,这比其他开源实现所需的O(N2)内存需求以及O(N3)执行时间有了显著改进。它可以用于超过100,000 点的数据集。

3.18:

  • 增加了线性方程的稀疏GMRES求解器;
  • AMD算法的改进性能(当优化具有密集行的矩阵的处理时);
  • 由于新的Cholesky分解和求解器代码的广泛优化,提高了线性规划(linear programming, LP)和二次规划(quadratic programming, QP)的内点求解器的速度。

3.17:

  • 增加了稀疏超级节点Cholesky分解(具有专家功能和用户友好的包装器)和相应的稀疏直接线性解算器。启用置换填充减少和未定义因子分解;
  • 增加了大规模内点线性规划(linear programming, LP)问题的求解器;
  • 增加了一个求解大规模内点半定二次规划(quadratic programming, QP)问题的求解器。

3.16:

  • 实现了具有密集和稀疏版本的内点二次规划(quadratic programming, QP)问题的求解器;
  • 增加了一个新的子程序,用于快速拟合执行时间为O(N*logN)的惩罚三次样条曲线;
  • 为非线性规划增加了一个新的SQP求解器;
  • 为大型随机森林引入了压缩二进制存储格式(将内存使用量减少3.7-5.7倍);
  • 为CRS和Skyline矩阵添加了sparegemv()函数;
  • 实现了CDF和PDF二元正态函数。
  • QP求解器现在报告拉格朗日乘子;
  • QP求解器现在支持双向线性约束;
  • 提高了SLP解算器的稳定性;
  • 改进了LP求解器中的参考元素选择,以获得更准确的解。

3.15:

  • 实现了时间序列的奇异谱分析(Singular Spectrum Analysis,SSA,“毛虫”)算法,该实现经过优化,包括趋势提取、预测、平均预测和快速增量模型更新;
  • 增加了以Skyline(SKS)格式存储的稀疏线性系统的直接求解器;
  • 改进了QP-DENSE-AUL求解具有大量不等式的二次问题的性能;
  • 显著提高了BLEIC和QP-BLEIC解算器的速度(最多四倍)。修订了求解器的内部代码,显著改进了约束处理;
  • 增加了对次维特征值求解器的热触发支持。当求解一系列相关的特征值问题时,可以重用先前找到的基本解作为新求解会话的起点;
  • 简化了SKS格式条带矩阵的创建(稀疏创建sksband()函数);
  • 增加了一组新的BLAS 2级实数函数:GEMV、SYMV、TRSV;
  • spareset()函数现在支持SKS矩阵;
  • minqp求解器现在支持基于二次项的对角线自动计算可变尺度。

3.12:

  • rbfsetpoints()函数现在检查输入数据中是否存在NAN/INF;
  • k-均值聚类和特征值反迭代算法现在使用确定性种子值进行初始化,使结果在不同的运行中可重复;
  • 修正了QQP求解器中的一个小错误——二次项的自动缩放不正确。

3.11:

  • 增加了执行线性约束非线性最小二乘法(MinLM和LSFit)的能力。现在可以在参数上具有线性约束的情况下进行非线性近似;
  • 增加了对数据的近似最小外切圆、最小面积和最大内切N球的支持(在2D外切圆中,在3D内切球中);
  • 提高了MinNLC求解器的稳定性,增加了另一种预处理模式——“精确稳定(precise stable)”;
  • 添加了一个新的优化器-MinBC,仅对处于“活动(active)”状态的变量进行限制。这些限制允许使用一般线性约束不可能的激活策略;
  • 在C#和C++的ALGLIB版本中添加了流式序列化/反序列化;
  • 使用子空间方法实现了直接/稀疏/无序特征值求解器,使用子空间法实现了快速截断主成分分析(principal component analysis,PCA);
  • 改进了具有并行性支持的分层RBF——在某些数据集上速度快几个数量级,能够处理超过100,000个点;
  • 增加了线性约束二次规划问题(QP)求解器;
  • 改进的kd树-具有矩形区域上的查询和线程安全版本的查询函数。

3.10:

  • 增加了CSV导入功能-现在可以从CSV文件中读取2D矩阵;
  • 引入了AGS(Adaptive Gradient Sampling,自适应梯度采样)算法来优化非线性、非光滑和不一致约束问题,使ALGLIB成为少数支持非光滑优化的商业软件包之一;
  • 增加了层次聚类的Ward方法;
  • 实现了轻量级线性求解器,无需条件数估计和迭代校正——它们比“功能丰富”的类似库快很多倍。

3.9:

  • 稀疏/密集线性代数支持方面的显著改进:SKS稀疏矩阵存储格式,用于基于SKS的矩阵的线性代数运算,用于SKS的Cholesky分解器,用于稀疏矩阵的许多附加函数;
  • 求解器和优化器的改进:一种新的求解变量约束的有限二次规划问题的求解器——QuickQP、非线性增广拉格朗日优化器、改进的BLEIC优化器、多项式求解器和许多其他小的改进;
  • 增加了额外的插值/拟合功能:4/5参数的逻辑曲线拟合,Ramer-Douglas-Peucker(RDP)算法;
  • 提高了线性判别分析(linear discriminant analysis,LDA)算法的速度。

3.8:

  • 增加了排名功能(描述性统计)——用排名替换数据的功能;
  • 介绍了一种新的求解器QP-BLEIC,它能够求解具有边界和线性约束的稀疏和不一致的二次规划问题;
  • 改进的FFT性能(更高的性能,但仍然是单线程的);
  • 多个小的改进(BLEIC优化器的升级,MLP的更好的权重初始化,少于五点的Akima样条曲线)。

3.7:

  • 显著重新设计了BLEIC优化器。首先,它使用了Elvira Illarionova提出的一种新的三阶段主动集算法,该算法将梯度投影与L-BFGS约束等式的迭代相结合。其次,由于算法不再具有嵌套的外部/内部迭代,因此可以为算法设置更透明的停止标准。第三,它使用了一种新的约束激活/去激活策略,正确地处理退化约束;
  • 显著改进了ALGLIB中对神经网络的支持。引入了一个新的训练界面,极大地简化了具有相同设置和数据的多个网络的训练。现在可以使用稀疏矩阵来指定训练集;
  • 改进的集群支持-ALGLIB的新版本包括集群子包中的分层集群分析算法。该算法包括几种距离度量(欧几里得、1-范数、无穷远范数、基于皮尔逊-斯皮尔曼相关性的度量、余弦距离)和几种链路类型(单链路、全链路、平均链路)。K-means聚类功能(早在新算法之前就存在)与新的聚类算法相结合;
  • 稀疏线性解算器(CG和LSQR)现在支持自动对角线预处理器;
  • 线性/非线性最小二乘解算器(lsfit子包)现在报告比率中的误差;
  • 稀疏矩阵功能现在包括用于在哈希表和CRS视图之间转换的新函数,以及对SparseRewriteExisting函数的性能改进。

3.6:

  • 二次优化器现在支持边界和线性等式/不等式的任意组合。新版本的优化器使用了增广拉格朗日方法和主动集方法的组合;
  • Spline1D模块现在支持使用单调三次样条进行插值;
  • 增加了对向量双线性和双三次样条的支持;
  • 增加了对标量和矢量三线性(3D)样条曲线的支持;
  • 改进了对稀疏矩阵的支持:使用SparseEnumerate()函数高效枚举非零元素,对以CRS格式存储的矩阵使用更快的SparseGet();
  • 优化和非线性近似算法(子包LSFit、MinLM、MinBLEIC、MinLBFGS、MinCG)可以检查用户提供的梯度的有效性(数值程序中最常见的错误)。

2. 科学研究中的ALGLIB库

ALGLIB具有开放源代码的可用性和非商业项目的免费使用,已成为科学研究领域的重要工具。它被成功地用于解决各种复杂的问题。
ALGLIB的重大影响在定制软件的开发中显而易见,ALGLIB中的许多算法成为创建创新解决方案的基础。

此外,ALGLIB的单线程算法是开发并行版本迭代算法的基准和参考点,该算法旨在解决包含约200万个方程的庞大方程组。这证明了ALGLIB库提供的算法的可靠性和卓越的效率。

研究人员注意到ALGLIB算法的高质量和高效性,使其成为解决包括基础研究和工程在内的多个领域复杂研究问题的首选。


2.1. 优化问题中的ALGLIB

2014: Hugo J. Kuijf, Susanne J. van Veluw, Mirjam I. Geerlings, Max A. Viergever, Geert Jan Biessels & Koen L. Vincken. 使用Kullback–Leibler测量从脑MR图像中自动提取中矢面Neuroinform 12, 395–403 (2014)

上一节中计算的中矢面用于初始化中矢面的计算。如ALGLIB(Bochkanov和Bystritsky(2012))中所述,中矢面表示为双三次样条曲线。样条曲线的控制点放置在计算的中矢面上的规则网格中,控制点之间的距离为m

2017: Vadim Bulavintsev, 基于GPU的黑匣子优化在基于色散的地声反演中的应用(A GPU-enabled Black-box Optimization in Application to Dispersion-based Geoacoustic Inversion), 2017, in Yu. G. Evtushenko, M. Yu. Khachay, O. V. Khamisov, Yu. A. Kochetov, V.U. Malkova, M.A. Posypkin (eds.): OPTIMA-2017会议记录, Petrovac, Montenegro, 02-Oct-2017

作为参考,我们提供了基于AlgLib库[Bochkanov&Bystritsky,2016]的双精度版本,我们在之前的工作中使用了该版本[Zaikin et al.,press]。AlgLib库包括最先进的平分算法实现,经过彻底调整,可以使用现代CPU浮点单元(FPU)产生最准确的结果。我们基于CPU的平分算法的实现不能拥有这样的准确性然而,由于其简单性,它明显快于AlgLib。这就是为什么,我们和基于AlgLib的算法的结果不同。CPU和GPU上相同算法的输出(残差)之间的差异是浮点单元在这些平台上的不同实现的结果。

2.2. 插值问题中的ALGLIB

2021: Jasek K., Pasternak M., Miluski W., Bugaj J., Grabka M, 高斯径向基函数在不规则网格上探地雷达数据快速空间成像中的应用(Application of Gaussian Radial Basis Functions for Fast Spatial Imaging of Ground Penetration Radar Data Obtained on an Irregular Grid.) 电子学(Electronics)2021, 10, 2965.

ALGLIB包实现了两种RBF:全局高斯函数和紧凑支持。经典的高斯函数在距离中心大约3R0的距离处已经取较小的值,并且可以容易地被修改为紧凑地支持

在本文中,使用了在ALGLIB包中实现的RBF-ML算法。它有三个参数:初始半径R0、层数NL和正则化系数l。该算法建立了一个半径递减的模型层次[13]。在初始(可选)迭代中,该算法建立一个线性最小二乘模型。从节点处的函数值中减去线性模型预测的值,并将残差向量传递给下一次迭代。在第一次迭代中,建立了半径等于R0的传统RBF模型。但是,它不使用密集解算器,也不尝试精确地解决问题。它通过执行固定数量(约50)的LSQR[22]迭代来解决最小二乘问题。通常,第一次迭代就足够了。额外的迭代不会改善这种情况,因为有这么大的半径,线性系统是病态的。从节点处的函数值中减去由RBF模型的第一层预测的值,并且再次将残差向量传递给下一次迭代。对于每次连续迭代,通过执行相同的恒定数量的LSQR迭代,半径减半,并从残差向量中减去新模型的预测。

在所有后续迭代中,可以应用精细正则化来提高LSQR求解器的收敛性。正则化因子的较大值可以帮助减少数据噪声。控制平滑的另一种方法是选择适当数量的层。图2显示了B扫描的一个示例和通过层次模型进行近似的方法。后续层的半径是前一层的两倍,可以解释前一层之后的残留物。随着半径的减小,B扫描的更精细的细节被再现。

分层算法具有几个显著的优点:

• 高斯CS RBF产生具有稀疏矩阵的线性系统,允许使用稀疏LSQR解算器,该解算器可以与秩缺陷矩阵一起工作
• 与具有O(N3)效率的简单RBF实现相比,模型构建的时间取决于点的数量N,即N logN
• 迭代算法(连续层纠正前一层的错误)创建了一个稳健的模型,即使初始半径非常大。连续的层具有较小的半径,并校正由前一层引入的不准确度
• 多层模型允许通过改变正则化系数和不同层数来控制平滑。

所提出的分层RBF近似算法是处理大型分散数据集的最有效算法之一。它的实现位于ALGLIB库中,可以进行简单的软件开发,可以成功地用于分析探地雷达图像。


2022: Ruiz M., Nieto J., Costa V., Craciunescu T., Peluso E., Vega J, Murari A, JET Contributors, 加速基于最大似然Bolometry层析成像的算法,用于确定异质平台JET辐射发射的不确定性(Acceleration of an Algorithm Based on the Maximum Likelihood Bolometric Tomography for the Determination of Uncertainties in the Radiation Emission on JET Using Heterogeneous Platforms). Appl. Sci. 2022, 12, 6798.

ALGLIB是一个专注于解决一般数值问题的数值库。它可以与C++、C#和Delphi等不同的编程语言一起使用。它为不同的科学领域提供了各种各样的功能。在该特定应用中,需要对能够或不能等距(非均匀分布)的2D数据阵列进行插值。实现等效网格数据的函数的开发需要对稀疏/非均匀数据使用ALGLIB 2D插值函数。对于拟合部分,使用最小二乘解算器函数,有两个选项可用:BlockLLS或FastDDDM。选择FastDDDM选项是为了获得尽可能好的性能

ArrayFire提供了一个完整的API,解决了使用MATLAB语言实现的最常见的功能。因此,可以认为使用ArrayFire API将MATLAB移植到C++是相对简单的,并且代码的某些部分甚至是逐行等效的。尽管如此,ArrayFire并不包括MATLAB中提供的一些强大功能。例如,函数“gridata”允许使用均匀和不均匀的输入数据分布进行不同类型的插值。MATLAB中的这个函数有一些内部代码对用户可见,但其他部分不可用,因此无法重现其计算结果。虽然ArrayFire版本3.8.0包含插值功能,但它希望输入数据将是统一组织的,为了解决这个问题,我们选择了开源库ALGLIB,它为2D插值提供了一组函数,可以用来解决这个问题

虽然MATLAB中算法的大部分代码和函数都被翻译成C++并进行了优化,但其他代码和函数则无法直接翻译。原因是MATLAB中没有关于某些函数的内部计算的信息。这意味着在两种实现中获得的结果略有不同。这些差异主要体现在网格数据函数的实现上对于此应用程序,它已与“双三次样条曲线”插值方法一起使用,该方法包含在属于ALGLIB库的FastDDM解算器中。

2.3. ALGLIB算法作为比较基准

2015: Tarek Ibn Ziad, M. & Alkabani, Yousra & El-Kharashi, M. W. & Salah, Khaled & Abdelsalam, Mohamed. (2015). Accelerating electromagnetic simulations: A hardware emulation approach. 10.1109/ICECS.2015.7440386.

<a0>加速电磁模拟:一种硬件仿真方法(Accelerating electromagnetic simulations: A hardware emulation approach)</a0>.<b1> </b1> 10.1109/ICECS.2015.7440386. 在物理硬件仿真平台上实现了Jacobi迭代求解器,以加速EM模拟器的有限元求解器[5]。他们通过实现二维(2D)边缘单元代码来使用FEM求解超材料的麦克斯韦方程组,证明了他们的解决方案的有效性。在求解200万个方程的情况下,他们的设计比MATLAB[13]上的相同纯软件实现实现实现了101倍的加速,比ALGLIB C++库[14]中的最佳迭代软件求解器实现了35倍的加速

在本文中,我们提出了一种可扩展的体系结构,可以有效地加速EM模拟器的求解器核心。该体系结构在物理硬件仿真平台上实现,并与最先进的求解器进行了比较。实验结果表明,所提出的求解器能够在Matlab上的相同纯软件实现上实现522倍的加速,在ALGLIB C++库中的最佳迭代软件求解器上实现184倍的加速和在文献中的另一种基于仿真的硬件实现上实现5倍的加速(求解200万个方程)。

2016: Liu, Yongchao & Pan, Tony & Aluru, Srinivas (2016), Intel Xeon Phi集群上的并行成对相关计算(Parallel Pairwise Correlation Computation On Intel Xeon Phi Clusters).

使用人工和真实的基因表达数据集,我们将LightPCC与两种基于CPU的对应物进行了比较:ALGLIB中的顺序C++实现(http://www.alglib.net)以及基于“英特尔数学内核库”(MKL)中并行GEMM例程的实现。我们的实验结果表明,通过使用一个5110P Phi和16 Phi,LightPCC的运行速度分别比ALGLIB快20.6倍和218.2倍,比单线程MKL快6.8倍和71.4倍。

2.4. ALGLIB算法作为专用软件的一部分

2015: Kraff S, Lindauer A, Joerger M, Salamone SJ, Jaehde U. 基于Excel的紫杉醇药物动力学指导剂量调整工具(Excel-Based Tool for Pharmacokinetically Guided Dose Adjustment of Paclitaxel). Ther Drug Monit. 2015 Dec;37(6):725-32

方法:紫杉醇的群体PK参数取自已发表的PK模型。在Excel2007中实现了Alglib VBA代码,用于计算紫杉醇PK模型的微分方程。PK参数的最大后验贝叶斯估计是使用Excel Solver使用单个药物浓度确定的。对250名接受紫杉醇化疗1个周期的患者的浓度进行模拟。将Excel工具计算的紫杉醇Tc>0.05μmol/L的预测值与NONMEM进行比较,从而使用POSTHOC函数获得最大后验贝叶斯估计值。

2017: Hogland, John & Anderson, Nathaniel. (2017). 函数建模提高了利用遥感大数据进行空间建模的效率(Function Modeling Improves the Efficiency of Spatial Modeling Using Big Data from Remote Sensing)。大数据与认知计算1.3。

虽然统计和机器学习转换可以用于在表格字段中构建曲面和计算记录,但它们本身并不像预测模型那样定义响应和解释变量之间的关系。为了定义这些关系,我们构建了一套类,使用ALGLIB和Accord.net[15,16]中的许多优化算法和数学过程来执行各种统计测试和预测建模.

此外,我们还介绍了一个新的编码库,它集成了Accord。NET和ALGLIB数字库,并使用惰性评估在一个称为函数建模的新GIS建模框架内促进广泛的空间、统计和机器学习过程。模拟结果显示,由于功能建模,处理时间减少了64.3%,存储空间减少了84.4%。在一个应用案例研究中,这意味着处理时间从2247小时减少到488小时,存储空间从152 TB减少到913 GB。


3. 用于金融市场分析的ALGLIB库

MQL5库的第一个版本(ALGLIB 3.5)已广泛用于金融数据分析,使用现代算法解决各种问题。

以下是积极应用ALGLIB库中的类和函数的文章列表:

因此,ALGLIB数学库的功能被证明是分析金融数据的有用工具。


4. ALGLIB中的奇异谱分析

除了现有的方法外,ALGLIB库的新版本现在还包括奇异谱分析方法(Singular Spectrum Analysis,SSA,也称为“毛虫”)。这种方法大大扩展了分析金融时间序列的能力,尤其是在预测问题上。SSA算法从3.15版本开始提供,并且其实现已经优化。它提供了趋势提取、时间序列预测、平均预测的功能,并具有快速的增量模型更新。


我们邀请您熟悉这种方法在实践中的工作原理,并在制定交易策略时分享您的使用经验

下面是一个测试脚本,其中包含使用SSA方法的示例。在官方库帮助的“奇异频谱分析”部分中,查找ALGLIB库中有关使用SSA方法的示例和详细信息的其他信息

//+------------------------------------------------------------------+
//|                                                     SSA_Test.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Math\Alglib\alglib.mqh>

// Examples of SSA usage with ALGLIB
// https://www.alglib.net/translator/man/manual.cpp.html#example_ssa_d_basic
// https://www.alglib.net/translator/man/manual.cpp.html#example_ssВa_d_realtime
// https://www.alglib.net/translator/man/manual.cpp.html#example_ssa_d_forecast

//+------------------------------------------------------------------+
//| PrintMatrix                                                      |
//+------------------------------------------------------------------+
void PrintMatrix(CMatrixDouble &x)
  {
//--- print matrix
   string str="[";
   for(int i=0; i<x.Rows(); i++)
     {
      str+="[";
      for(int j=0; j<x.Cols(); j++)
        {
         str+=StringFormat("%f",x.Get(i,j));
         if(j<x.Cols()-1)
            str+=",";
        }
      str+="]";
      if(i<x.Rows()-1)
         str+=",";
     }
   str+="]";
   printf("%s",str);
  }
//+------------------------------------------------------------------+
//| PrintVector                                                      |
//+------------------------------------------------------------------+
void PrintVector(CRowDouble &x)
  {
//--- print vector
   string str="[";
   for(int i=0; i<x.Size(); i++)
     {
      str+=StringFormat("%f",x[i]);
      if(i<x.Size()-1)
         str+=",";
     }
   str+="]";
   printf("%s",str);
  }
//+------------------------------------------------------------------+
//| ssa_d_basic                                                      |
//+------------------------------------------------------------------+
//| Here we demonstrate SSA trend/noise separation for some toy      |
//| problem: small monotonically growing series X are analyzed with  |
//| 3-tick window and "top-K" version of SSA, which selects K largest|
//| singular vectors for analysis, with K=1.                         |
//+------------------------------------------------------------------+
int ssa_d_basic(void)
  {
//--- prepare input data
   double input_data[]= {0,0.5,1,1,1.5,2};
   CRowDouble x=input_data;
//--- first, we create SSA model, set its properties and add dataset.
//--- we use window with width=3 and configure model to use direct SSA algorithm which runs exact O(N*W^2) analysis - to extract one top singular vector.
//--- NOTE: SSA model may store and analyze more than one sequence (say, different sequences may correspond to data collected from different devices)
//--- ALGLIB wrapper class
   CAlglib alglib;
//--- SSA model
   CSSAModel ssa_model;
//--- create SSA model
   alglib.SSACreate(ssa_model);
//--- set window width for SSA model
   alglib.SSASetWindow(ssa_model,3);
//--- adds data sequence to SSA model
   alglib.SSAAddSequence(ssa_model,x);
//--- set SSA algorithm to "direct top-K" algorithm
   alglib.SSASetAlgoTopKDirect(ssa_model,1);
//--- now we begin analysis. Internally SSA model stores everything it needs:
//--- data, settings, solvers and so on. Right after first call to analysis-related function it will analyze dataset, build basis and perform analysis.
//--- subsequent calls to analysis functions will reuse previously computed basis, unless you invalidate it by changing model settings (or dataset).
//--- trend and noise
   CRowDouble trend,noise;
//--- build SSA basis using internally stored (entire) dataset and return reconstruction for the sequence being passed to this function
   alglib.SSAAnalyzeSequence(ssa_model,x,x.Size(),trend,noise);
//--- print result
   PrintVector(trend);
//--- output:   [0.381548,0.558290,0.781016,1.079470,1.504191,2.010505]
//--- EXPECTED: [0.3815,0.5582,0.7810,1.0794,1.5041,2.0105]
   return 0;
  }

//+------------------------------------------------------------------+
//| ssa_d_forecast                                                   |
//+------------------------------------------------------------------+
//| Here we demonstrate SSA forecasting on some toy problem with     |
//| clearly visible linear trend and small amount of noise.          |
//+------------------------------------------------------------------+
int ssa_d_forecast(void)
  {
//--- ALGLIB wrapper
   CAlglib alglib;
//--- model
   CSSAModel ssa_model;
//--- prepare input data
   double input_data[] = {0.05,0.96,2.04,3.11,3.97,5.03,5.98,7.02,8.02};
   CRowDouble x=input_data;
//--- first, we create SSA model, set its properties and add dataset.
//--- we use window with width=3 and configure model to use direct SSA algorithm - one which runs exact O(N*W^2) analysis-to extract two top singular vectors
//--- NOTE: SSA model may store and analyze more than one sequence (say, different sequences may correspond to data collected from different devices)
//--- create SSA model
   alglib.SSACreate(ssa_model);
//--- set window width for SSA model
   alglib.SSASetWindow(ssa_model,3);
//--- set window width for SSA model
   alglib.SSAAddSequence(ssa_model,x);
//--- set SSA algorithm to "direct top-K" algorithm
   alglib.SSASetAlgoTopKDirect(ssa_model,2);
//--- now we begin analysis. Internally SSA model stores everything it needs:
//--- data, settings, solvers and so on. Right after first call to analysis-related function it will analyze dataset, build basis and perform analysis.
//--- subsequent calls to analysis functions will reuse previously computed basis, unless you invalidate it by changing model settings (or dataset).
//--- in this example we show how to use ssaforecastlast() function, which predicts changed in the last sequence of the dataset.
//--- if you want to perform prediction for some other sequence, use alglib.SSAForecastSequence().
//--- trend
   CRowDouble trend;
   alglib.SSAForecastLast(ssa_model,3,trend);
//--- print result
   PrintVector(trend);
//--- output:   [9.000587,9.932294,10.805125]
//--- EXPECTED: [9.0005,9.9322,10.8051]
//--- well, we expected it to be [9,10,11]. There exists some difference, which can be explained by the artificial noise in the dataset.
   return 0;
  }
//+------------------------------------------------------------------+
//| ssa_d_realtime                                                   |
//+------------------------------------------------------------------+
//| Suppose that you have a constant stream of incoming data, and    |
//| you want to regularly perform singular spectral analysis         |
//| of this stream.                                                  |
//|                                                                  |
//| One full run of direct algorithm costs O(N*Width^2) operations,  |
//| so the more points you have, the more it costs to rebuild basis  |
//| from scratch.                                                    |
//|                                                                  |
//| Luckily we have incremental SSA algorithm which can perform      |
//| quick updates of already computed basis in O(K*Width^2) ops,     |
//| where K is a number of singular vectors extracted. Usually it    |
//| is orders of magnitude faster than full update of the basis.     |
//|                                                                  |
//| In this example we start from some initial dataset x0. Then we   |
//| start appending elements one by one to the end of the last       |
//| sequence                                                         |
//|                                                                  |
//| NOTE: direct algorithm also supports incremental updates, but    |
//|       with O(Width^3) cost. Typically K<<Width, so specialized   |
//|       incremental algorithm is still faster.                     |
//+------------------------------------------------------------------+
int ssa_d_realtime(void)
  {
//--- ALGLIB wrapper
   CAlglib alglib;
//--- model
   CSSAModel ssa_model1;
//---
   CMatrixDouble a1;
   CRowDouble sv1;
   int w,k;
//--- prepare input data
   double input_data[]= {0.009,0.976,1.999,2.984,3.977,5.002};
   CRowDouble x0=input_data;
//--- create SSA model
   alglib.SSACreate(ssa_model1);
//--- set window width for SSA model
   alglib.SSASetWindow(ssa_model1,3);
//--- adds data sequence to SSA model
   alglib.SSAAddSequence(ssa_model1,x0);
//--- set algorithm to the real-time version of top-K, K=2
   alglib.SSASetAlgoTopKRealtime(ssa_model1,2);
//--- one more interesting feature of the incremental algorithm is "power-up" cycle.
//--- even with incremental algorithm initial basis calculation costs O(N*Width^2) ops.
//--- if such startup cost is too high for your real-time app, then you may divide initial basis calculation
//--- across several model updates. It results in better latency at the price of somewhat lesser precision during first few updates.
   alglib.SSASetPowerUpLength(ssa_model1,3);
//--- now, after we prepared everything, start to add incoming points one by one;
//--- in the real life, of course, we will perform some work between subsequent update (analyze something, predict, and so on).
//--- after each append we perform one iteration of the real-time solver. Usually
//--- one iteration is more than enough to update basis. If you have REALLY tight performance constraints,
//--- you may specify fractional amount of iterations, which means that iteration is performed with required probability.
   double updateits = 1.0;
//--- append single point to last data sequence stored in the SSA model and update model in the incremental manner
   alglib.SSAAppendPointAndUpdate(ssa_model1,5.951,updateits);
//--- execute SSA on internally stored dataset and get basis found by current method
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,7.074,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,7.925,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,8.992,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,9.942,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,11.051,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,11.965,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,13.047,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- append single point to last data sequence
   alglib.SSAAppendPointAndUpdate(ssa_model1,13.970,updateits);
//--- execute SSA
   alglib.SSAGetBasis(ssa_model1,a1,sv1,w,k);
//--- ok, we have our basis in a1[] and singular values at sv1[]. But is it good enough? Let's print it.
   PrintMatrix(a1);
//--- output:   [[0.510607,0.753611],[0.575201,0.058445],[0.639081,-0.654717]]
//--- EXPECTED: [[0.510607,0.753611],[0.575201,0.058445],[0.639081,-0.654717]]
//--- ok, two vectors with 3 components each. but how to understand that is it really good basis? let's compare it with direct SSA algorithm on the entire sequence.
   CSSAModel ssa_model2;
   CMatrixDouble a2;
   CRowDouble sv2;
//--- input data
   double input_data2[]= {0.009,0.976,1.999,2.984,3.977,5.002,5.951,7.074,7.925,8.992,9.942,11.051,11.965,13.047,13.970};
   CRowDouble x2=input_data2;
//--- create SSA model
   alglib.SSACreate(ssa_model2);
//--- set window width for SSA model
   alglib.SSASetWindow(ssa_model2,3);
//--- add data sequence to SSA model
   alglib.SSAAddSequence(ssa_model2,x2);
//--- set SSA algorithm to "direct top-K" algorithm
   alglib.SSASetAlgoTopKDirect(ssa_model2,2);
//--- execute SSA on internally stored dataset and get basis found by current method
   alglib.SSAGetBasis(ssa_model2,a2,sv2,w,k);
//--- it is exactly the same as one calculated with incremental approach!
   PrintMatrix(a2);
//--- output:   [[0.510607,0.753611],[0.575201,0.058445],[0.639081,-0.654717]]
//--- EXPECTED: [[0.510607,0.753611],[0.575201,0.058445],[0.639081,-0.654717]]
   return 0;
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- the very simple example of trend/noise separation
   ssa_d_basic();
//--- forecasting with SSA
   ssa_d_forecast();
//--- real-time analysis of constantly arriving data
   ssa_d_realtime();
  }
//+------------------------------------------------------------------+


结论

ALGLIB是分析金融市场数据的强大工具。多语言、跨平台性质、丰富的功能和开源使其成为财务分析和建模领域研究人员和开发人员的一个有吸引力的选择。人们一直需要可靠的数据分析工具,ALGLIB通过支持不断的开发和改进成功地应对了这一挑战。

MetaTrader 5平台开发人员为交易者提供最佳解决方案:

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/13289

附加的文件 |
SSA_Test.mq5 (26.56 KB)
在 MQL4 和 MQL5 框架下开发 OpenAI  的 ChatGPT 功能 在 MQL4 和 MQL5 框架下开发 OpenAI 的 ChatGPT 功能
在本文中,我们将尝鲜来自 OpenAI 的 ChatGPT,从而了解它在降低开发智能系统、指标、和脚本的时间和劳动强度方面的能力。我将引导您快速通览这项技术,并尝试向您展示如何正确地使用它在 MQL4 和 MQL5 中进行编程。
简单均值回归交易策略 简单均值回归交易策略
均值回归是一种逆势交易,交易者预估价格将返回到某种形式的均衡点位,通常依据均值或其它向心趋势统计值来衡量。
使用MQL5轻松创建图形面板 使用MQL5轻松创建图形面板
在这篇文章中,我们将为任何需要创建交易中最有价值和最有用的工具之一的人提供一个简单易行的指南,即简化和轻松执行交易任务的图形面板,这有助于节省时间,并在不受任何干扰的情况下更多地关注您的交易过程本身。
Heiken-Ashi指标与移动平均指标组合能够提供好的信号吗? Heiken-Ashi指标与移动平均指标组合能够提供好的信号吗?
策略的组合可能会提供更好的机会,我们可以把指标和形态一起使用,或者更进一步,多个指标和形态一起,这样我们可以获得额外的确认因子。移动平均帮我们确认和驾驭趋势,它们是最为人所知的技术指标,这是因为它们的简单性和为分析增加价值的良好记录。