1. 形态形成的理论观点
在价格图表上可以频繁返现双顶/双底形态。 它的形成与交易价位理论密切相关。 当价格达到支撑位或阻力位时(取决于之前的走势),该形态在趋势结束时形成。 在重复测试价位过程中进行调整之后,它会再次回滚而非突破。
在这一点位上,逆势交易者开始从该价位回滚时交易,并将价格推向调整。 在调整走势获得动量的同时,顺势交易者开始获利了结离场,或将亏损持仓平仓来避免突破该价位。 这进一步加强了走势,导致了新趋势的出现。
编辑
添加图片注释,不超过 140 字(可选)
在图表上搜索形态时,不必搜索顶部/底部的精准匹配。 顶部/底部价位的偏差被认为是正常的。 只需确保峰值在相同的支撑/阻力位之内。 形态可靠性取决于它所基于的级别强度。
2. 形态交易策略
形态的普及引发了多种涉及它的策略。 在互联网上,交易这种形态至少有三个不同的入场点。
2.1. 案例 1
第一个入场点是基于颈线的突破。 止损设置在顶/底线之外。 有不同的方法来定义“颈线突破”。 交易者可以使用在颈线下方收盘的柱线,以及突破颈线一段固定距离的柱线。 两种方法都有其优点和缺点。 在凌厉走势的情况下,蜡烛可以在距颈线足够的距离处收盘,令形态效率很低。
编辑
添加图片注释,不超过 140 字(可选)
这种方法的缺点是止损价位相对较高,这降低了策略的利润/风险比。
2.2. 案例 2
第二个入场点基于镜面等级理论,当颈线从支撑变成阻力时,反之亦然。 此处的入场点是在价格突破后回到颈线时进行的。 在这种情况下,止损设置超出最后一次调整的极值,从而显著降低止损价位。 不幸的是,价格并不总是在突破后回测颈线,从而减少了入场次数。
编辑
添加图片注释,不超过 140 字(可选)
2.3. 案例 3
第三个入场点基于趋势理论。 它的定义是突破从走势起点到颈线极值的趋势线。 与第一种情况一样,止损设置在顶/底线之外。 与第一个入场点相比,早期入场提供较低的止损价位。 与第二种情况相比,它还提供更多信号。 与此同时,这样的入场点会发出更多的假信号,因为在极值线和颈部之间可能形成通道,或者可能存在旗形形态。 两种情况都表示趋势延续。
编辑
添加图片注释,不超过 140 字(可选)
所有三种策略都指示在等于极值和颈线之间距离的价位上离场。
编辑
添加图片注释,不超过 140 字(可选)
此外,在判断图表上的形态时,您应该注意到双顶/双底应该从价格走势中清晰地脱颖而出。 在描述形态时,通常会添加限制:两个顶部/底部之间应该至少有六根柱线。
此外,由于形态形成是基于价位理论,形态交易不应该与之相矛盾。 因此,基于预期目的,颈线不应低于初始走势的菲波纳奇等级 50。 此外,为了滤除假信号,赫兹股票量化可以添加第一次调整的最低价位(形成颈线)作为价格等级强度的指标。
3. 创建 EA
3.1. 搜索极值
赫兹股票量化将从形态搜索模块开始开发 EA。 我们用赫兹股票量化标准发行包中的之字折线指标来搜索价格极值。 将指标计算部分移至文章 [1] 中所述的类。 该指标包含两个指标缓冲区,其中包含极值点的价格值。 指标缓冲区包含极值之间的空值。 为了避免创建两个包含多个空值的指标缓冲区,它们由包含有关极值信息的结构数组所取代。 用于存储有关极值信息的结构如下所示。
struct s_Extremum { datetime TimeStartBar; double Price; s_Extremum(void) : TimeStartBar(0), Price(0) { } void Clear(void) { TimeStartBar=0; Price=0; } };
如果您至少使用过一次之字折线指标,您就会知道在搜索最佳参数时必须要做出一些妥协。 参数值太小会将大走势分成小部分,而太大的参数值会掩盖短期走势。 搜索形态图形的算法对于寻找极值的品质要求很高。 在尝试寻找中间点的同时,我决定使用具有小参数值的指标,并创建一个额外的上层结构,将单向走势与短期调整合并到一个走势。
CTrends 类是为解决这个问题而开发的。 类的头部提供如下。 在初始化期间,将指标类对象的引用和趋势延续的最小移动值传递给类。
class CTrends : public CObject { private: CZigZag *C_ZigZag; // 链接到之字折线指标对象 s_Extremum Trends[]; // 极值数组 int i_total; // 保存的极值总数 double d_MinCorrection; // 趋势延续的最小移动值 public: CTrends(); ~CTrends(); //--- 类初始化方法 virtual bool Create(CZigZag *pointer, double min_correction); //--- 获取有关极值的信息 virtual bool IsHigh(s_Extremum &pointer) const; virtual bool Extremum(s_Extremum &pointer, const int position=0); virtual int ExtremumByTime(datetime time); //--- 获取一般信息 virtual int Total(void) { Calculate(); return i_total; } virtual string Symbol(void) const { if(CheckPointer(C_ZigZag)==POINTER_INVALID) return "Not Initilized"; return C_ZigZag.Symbol(); } virtual ENUM_TIMEFRAMES Timeframe(void) const { if(CheckPointer(C_ZigZag)==POINTER_INVALID) return PERIOD_CURRENT; return C_ZigZag.Timeframe(); } protected: virtual bool Calculate(void); virtual bool AddTrendPoint(s_Extremum &pointer); };
要获取极值数据,类中提供了以下方法:
-
ExtremumByTime — 获取数据库中指定时间的极值数字,
-
Extremum — 返回数据库中指定位置的极值,
-
IsHigh — 如果指定的极值是顶部,则返回 true; 如果是底部,则返回 false。
通用信息模块拥有返回已保存的极值总数,所用品名和时间帧的方法。
类的主要逻辑在 Calculate 方法中实现。 我们来仔细查看。
在方法的开头,检查指标类对象的引用的相关性,以及指标已发现的存在极值。