螺纹钢吧 关注:16,504贴子:49,369
  • 0回复贴,共1

量化软件——赫兹MT5 向导技术07 部分树状图

只看楼主收藏回复

波动率
在交易的境况下,价格柱线范围(这就是我们在本文中量化波动性的方式)是交易品种价格在设定时间帧内的最高价和最低价之间的差值。故此,如果我们假设取日线时间帧,并且在一天内,交易品种的价格上涨到 H 且不高于 H,然后下降到 L,且一样不低于 L,那么就本文而言,我们的范围是:
H – L;
关注波动率可以说是重要的,因为通常被称为波动率聚类。这是一种现象,即高波动区间之后倾向于更多的波动性,相反,低波动性区间之后也会后随较低的波动性。若这是主观的,如上强调那样,那么对于大多数交易者(包括我认为的所有初学者)来说,知道如何运用杠杆进行交易从长远来看可能是一个加分项,因为正如大多数交易者所熟悉的那样,高波动性可能会令账户爆仓,并非由于入场信号是错误的,而是因为波动性太过分。大多数人也能意识到,即使您的持仓有一个不错的止损,有时止损价可能不可用,以 2015 年 1 月的瑞士法郎崩盘为例,在这种情况下,您的持仓将被券商以下一次最佳可用价格平仓,这通常比您的止损更糟糕。这是因为只有限价单才会保证价格,破位单和止损不会。
因此,价格柱线范围除了提供市场环境的整体感觉外,还有助于指导入场、甚至离场价位。同样,根据您的策略,举例,如果您做多某个特定品种,那么您的价格柱线范围展望(您预测的内容)的程度可以很容易地判定或至少指导您在哪里放置入场价格,以至止盈。
所冒风险听起来很平凡,它也许有助于突出一些非常基本的价格蜡烛类型,并勾勒它们各自的范围。更显要的类型是看跌、看涨、锤子、墓碑、长腿、和蜻蜓。当然还有更多类型,但可以说这些类型确实涵盖了人们在面对价格图表时最有可能遇到的那些。所有这些实例,如下图所示,价格柱线范围只是最高价减去最低价。
集聚层次化分类
集聚层次化分类(AHC) 是一种将数据分类为预设数量的聚类,然后通过所谓的树状图以系统层次化方式把这些聚类关联起来的手段。这样做的益处主要源于这样一个事实,即被分类的数据通常是多维的,因此在进行比较时,需要考虑单个数据点中的许多变量也许不太容易设法解决。例如,一家寻找基于来自客户的信息为他们进行评级的公司就可以利用这一点,因为这些信息必然涵盖客户生活的不同方面,譬如过去的消费习惯、他们的年龄、性别、地址、等等。AHC,通过量化每位客户的所有这些变量,从每个数据点的表观质心创建聚类。但比之更重要的是,这些聚类被分组到系统化关系的层次结构之中,由此如果分类需要 5 个聚类,那么 AHC 将按排序格式提供这 5 个聚类,这意味着您可以推断哪些聚类更相似,哪些更具差别。这种聚类比较虽然是次要的,但如果您需要比较多个数据点,且它们摆明位于不同的聚类中,那么它就可以派上用场。聚类排位将通过聚类各自之间的间隔幅度来告知两个点之间的差距有多大。
AHC 的分类是无监督的,这意味着它可以用于不同分类器下的预测。在我们的案例中,我们正在预测价格柱线范围,具有相同训练聚类的其他人可以用它们来预测收盘价的变化,或与他的交易相关的其它方面。这比在特定分类器上进行监督和训练具有更大的灵活性,因为在这种情况下,模型将仅对所分类的内容进行预测,这意味着若要出于其它目的进行预测,模型将需要依据该新数据集重新训练。
工具和库
MQL5 平台在其 IDE 的帮助下,确实允许从头开始开发自定义智能交易系统,为了展示这里共享的内容,我们可以假定采取这条路线。然而,该选项将涉及对交易系统做出许多决定,而在面对实施相同概念时,其他交易者可能会采取不同的决定。还有,这样实现的代码可能定制过度,且也许容易出错 — 很容易针对不同状况进行修改。这就是为什么将我们的想法作为由 MQL5 向导提供的其它“标准”智能系统类的一部分进行组装是一个令人信服的案例。我们不仅需要减少调试(即使在 MQL5 的内置类中也偶尔会出现错误,但不是很多),而且通过将其保存为标准类之一的实例,它可以与 MQL5 向导中的各种其它类一起使用和组合,以便得到不同的智能系统,从而提供更全面的测试平台。
MQL5 函数库代码提供了 AlgLib 类,这些类已在本系列的前面文章中引用,并在本文中再次使用。具体来说,在 “DATAANALYSIS.MQH“ 文件内,我们将依靠 ”CClustering“ 类和其它几个相关类来为我们的价格序列数据提供 AHC 分类。由于我们的主要兴趣是价格柱线范围,后续我们的训练数据将由前段时期的此类范围构成。当使用来自数据分析包含文件中的数据训练类时,典型用法将该数据放置在一个 “XY” 矩阵当中,其中 X 代表自变量,Y 代表模型训练所用的分类器或“标签”。两者通常位于同一矩阵之中。
准备训练数据
不过,就本文而言,由于我们进行的是无监督训练,因此我们的输入数据仅包含 X 自变量。这些将是历史价格柱线范围。同时,我们希望通过参考另一个相关数据流来做出预测,即最终的价格柱线范围。这相当于上面提到的 Y。为了将这两个数据集结合起来,同时保持无监督学习的灵活性,我们可以采用以下数据结构:
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CMoneyAHC : public CExpertMoney
{
protected:
double m_decrease_factor;
int m_clusters; // clusters
int m_training_points; // training points
int m_point_featues; // point featues
...
public:
CMoneyAHC(void);
~CMoneyAHC(void);
virtual bool ValidationSettings(void);
//---
virtual double CheckOpenLong(double price,double sl);
virtual double CheckOpenShort(double price,double sl);
//---
void DecreaseFactor(double decrease_factor) { m_decrease_factor=decrease_factor; }
void Clusters(int value) { m_clusters=value; }
void TrainingPoints(int value) { m_training_points=value; }
void PointFeatures(int value) { m_point_featues=value; }
protected:
double Optimize(double lots);
double GetOutput();
CClusterizerState m_state;
CAHCReport m_report;
struct Sdata
{
CMatrixDouble x;
CRowDouble y;
Sdata(){};
~Sdata(){};
};
Sdata m_data;
CClustering m_clustering;
CRowInt m_clustering_index;
CRowInt m_clustering_z;
};
如此,将在每根新柱线开立时收集新一批的历史价格柱线范围。由 MQL5 向导生成的智能系统倾向于在每根新柱开立时执行交易决策,对于我们的测试目的来说,这已经足够了。确实有替代方式,诸如获得跨越数月甚至数年的大批次数据,然后据测试检验模型的聚类如何最终将低波动率价格柱线与高波动率价格柱线区分开来。还要记得,我们只用 3 个聚类,其中一个极端聚类用于波动剧烈的柱线,一个用于波动非常低的,一个用于中等波动。同样,我们可以用 5 个聚类进行调查举例,但就我们的目的而言,原理是相同的。将聚类按最高波动率到最低波动率的顺序放置,并识别我们当前数据点所在的聚类。
填充数据
每根新柱开立时,获取最新柱线范围,并填充自定义结构的代码如下所示:
m_data.x.Resize(m_training_points,m_point_featues);
m_data.y.Resize(m_training_points-1);
m_high.Refresh(-1);
m_low.Refresh(-1);
for(int i=0;i<m_training_points;i++)
{
for(int ii=0;ii<m_point_featues;ii++)
{
m_data.x.Set(i,ii,m_high.GetData(StartIndex()+ii+i)-m_low.GetData(StartIndex()+ii+i));
}
}
训练点的数量定义了我们的训练数据集有多大。这是一个可自定义的输入参数,是为数据点特征参数。该参数定义了每个数据点具有的“维度”数量。因此,在我们的案例中,我们默认有 4 个,但这仅仅意味着我们使用最后 4 个价格柱线范围来定义任何给定的数据点。它类似于向量。
生成聚类
因此,一旦我们的自定义结构中有了数据,下一步就是调用 AlgLib AHC 模型生成器对其进行建模。该模型在代码清单中称为“状态”,为此,我们的模型最终被命名为 “m_state”。这是一个两步过程。首先,我们必须基于提供的训练数据生成模型点,然后运行 AHC 生成器。设置点可以看作是初始化模型,并确保所有关键参数都得到良好的定义。这在我们的代码中如下调用:
m_clustering.ClusterizerSetPoints(m_state, m_data.x, m_training_points, m_point_featues, 20);
第二个重要步骤是运行模型,以便定义训练数据集中每个所提供数据点的聚类。这是通过调用 “ClusterizerRunAHC” 函数来完成的,如下所示:
m_clustering.ClusterizerRunAHC(m_state, m_report);
从 AlgLib 端来看,这是生成我们所需聚类的肉和土豆。该函数执行一些简短的预处理,然后调用受保护的(专用)函数 “ClusterizerRunAHCInternal”,该函数执行繁琐的工作。所有这些源代码都在您的 “include\math\AlgLib\dataanalysis.mqh” 文件当中,从第 22463 行可见。这里值得注目的是在 “cidx” 输出数组中生成树状图。该数组巧妙地将大量聚类信息压缩到单个数组之中。此前,需要利用所有训练数据点的质心为它们生成距离矩阵。该数组捕获距离矩阵值到聚类索引的映射,第一个值直到训练点总数表示每个点的聚类,后续索引表示这些聚类的合并,形成树状图。
同样值得注意的大概就是生成距离矩阵所用的距离类型。有九个选项可供选择,从切比雪夫(Chebyshev)距离、欧几里得(Euclidean)距离、到长矛手等级相关性。这些备选方案中的每一个都被分配了一个索引,当我们调用上述设定点函数时,我们会建立该索引。距离类型的选择必然对所生成聚类的性质和类型非常敏感,因此应注意这一点。在设置 AHC 算法时,使用欧几里得距离(其索引为 2)可以更灵活地实现,因为 Ward 方法与其它距离类型的用法不同。
提取聚类
提取聚类也与生成集群一样简单。我们只需调用一个函数 “ClusterizerGetKClusters”,它就会从我们之前调用的聚类生成函数的输出报告中提取两个数组(运行 AHC)。这些数组是聚类索引数组和聚类 z 数组,它们不仅指导如何定义聚类,还指导如何据它们形成树状图。调用此函数简单地如下所示:
m_clustering.ClusterizerGetKClusters(m_report, m_clusters, m_clustering_index, m_clustering_z);
生成的聚类结构非常简单,因为在我们的案例中,我们仅将训练数据集分类为 3 个聚类。这意味着我们在树状图中的合并级别不超过三个。如果我们用到更多的聚类,那么我们的树状图肯定会更复杂,可能拥有 n-1 合并级别,其中 n 是模型用到的聚类数量。


IP属地:浙江1楼2024-06-27 16:26回复