我撰写上一篇文章的目的是创建一个方便的工具包,允许使用键盘快捷键在图表上快速绘制直线。 第一篇文章里包括一段视频,演示了现成解决方案的工作原理。
当前的实现中未提供 GUI(尽管其已在未来计划中)。 该程序简单地根据键盘快捷键绘制直线。 它加快了访问诸如更改当前图表“层次”(Z-索引),切换时间帧和切换直线绘制模式(射线/线段)之类的操作速度。
鼠标位置判断对象应绘制的位置。 如果鼠标指针位于价格上方,则选烛条高点作为基点。 如果鼠标指针位于价格下方,则选低点。
当前函数库版本可以绘制以下对象:
- 简单 ("无终点")直线 — 水平和垂直线。
- 常规趋势线 (最接近鼠标的两个极值点)。 您可以将线条设置为线段或射线。 如果该线是线段,则可用特殊模式将线段的终点设置到未来的一点。 在这种情况下,该线大小等于两个极值点之间的距离乘以某个系数,该系数可在 EA 参数中指定。
- 水平级别具有一定长度的 (非无终点)。 该工具箱可以绘制短线和“延伸”线,您可以为其指定相对于短线的比率。
- 一条带有水平标签的垂线。
- 斐波那契扇形。 级别参数是可配置的,但我用的是经过稍微修改的版本,该版本曾经由绰号为 Vadimcha 的男子在 “Onyx” 上展示。 他们称这个扇形为 VFan,即我在代码中继续采用的名字。
- 安德鲁草叉一套由三个对象组成。
项目结构非常简单。 该函数库有五个相关文件:“ GlobalVariables.mqh”,“ Graphics.mqh”,“ Mouse.mqh”,“ Shortcuts.mqh”,“ Utilites.mqh ”。 所有文件都位于标准 Include 目录中的一个 Shortcuts 文件夹当中。
主文件是 “Shortcuts.mqh”,与所有其他文件连接。 在该文件中创建了 CShortcuts 类的实例,从而令该函数库可以轻松地与您的主要智能交易系统连接。
在前一篇文章中,我曾重点介绍了帮助文件 “Utilites.mqh”。 在本文中,我们将主要处理包含绘图逻辑的 “Graphics.mqh” 文件。
全局设置文件
第二个函数库版本提供了丰富的扩展配置选项,因为它含有更多会受到影响的对象。 当前版本的完整代码如下:
//+------------------------------------------------------------------+ //| GlobalVariables.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://www.mql5.com/en/articles/7908 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://www.mql5.com/en/articles/7908" //+------------------------------------------------------------------+ //| File describing parameters available to the user | //+------------------------------------------------------------------+ #define VERSION 2.0 // Not #property but a constant. A bit more convenient. //+------------------------------------------------------------------+ //| Key settings | //+------------------------------------------------------------------+ input string Keys="=== Key settings ==="; input string Up_Key="U"; // Switch timeframe up input string Down_Key="D"; // Switch timeframe down input string Trend_Line_Key="T"; // Trend line input string Switch_Trend_Ray_Key="R"; // Indication of a trend line ray input string Z_Index_Key="Z"; // Indication of the chart on top input string Vertical_With_Short_Levels_Key="V"; // Vertical segment input string Short_Level_Key="S"; // Short level input string Long_Level_Key="L"; // Extended level input string Simple_Horizontal_Line_Key="H"; // Simple horizontal line input string Simple_Vertical_Line_Key="I"; // Simple vertical line input string VFun_Key="F"; // Fibonacci fan input string Pitchfork_Key="P"; // Andrews' pitchfork //+------------------------------------------------------------------+ //| Color setting | //+------------------------------------------------------------------+ input string Colors="=== Color Settings ==="; input color VFan_Color=clrLightGray; // Color of the fan lines // (and an additional // one for special cases) //--- input color Pitchfork_Main_Color = clrBlue; // Andrews' pitchfork color input color Pitchfork_Shiff_Color = clrRed; // Schiff pitchfork color input color Pitchfork_Reverce_Color = clrYellow;// "Reverse" pitchfork color //+------------------------------------------------------------------+ //| Size settings | //+------------------------------------------------------------------+ input string Dimensions="=== Size settings ==="; input int Short_Level_Length=12; // Short level length (bar) input int Short_Level_Width=1; // Line width for the short level input int Long_Level_Width=2; // Line width for the long level input int Vertical_With_Short_Levels_Width=1; // Vertical line width with levels input int Short_Level_7_8_Width=1; // Level 7/8 line width input int Short_Level_14_8_Width=1; // Level 14/8 line width input int Simple_Vertical_Width=1; // Simple vertical line width input int Simple_Horizontal_Width=1; // Simple horizontal line width input int Trend_Line_Width=2; // Trend line width //+------------------------------------------------------------------+ //| Display styles | //+------------------------------------------------------------------+ input string Styles="=== Display styles ==="; input ENUM_LINE_STYLE Vertical_With_Short_Levels_Style=STYLE_SOLID; // Vertical Line style // with levels input ENUM_LINE_STYLE Short_Level_Style=STYLE_SOLID; // Short Level style input ENUM_LINE_STYLE Long_Level_Style=STYLE_SOLID; // Long level style input ENUM_LINE_STYLE Short_Level_7_8_Style=STYLE_SOLID; // Level 7/8 style input ENUM_LINE_STYLE Short_Level_14_8_Style=STYLE_DOT; // Level 14/8 style input ENUM_LINE_STYLE Simple_Vertical_Style=STYLE_DOT; // Simple Vertical style input ENUM_LINE_STYLE Simple_Horizontal_Style=STYLE_DOT; // Simple Horizontal style input ENUM_LINE_STYLE VFun_Levels_Style=STYLE_SOLID; // Fan Style input ENUM_LINE_STYLE Trend_Line_Style=STYLE_SOLID; // Trend line style //--- input ENUM_LINE_STYLE Pitchfork_Main_Style = STYLE_SOLID; // Andrews' Pitchfork style input ENUM_LINE_STYLE Pitchfork_Shiff_Style = STYLE_SOLID; // Schiff Pitchfork style input ENUM_LINE_STYLE Pitchfork_Reverce_Style = STYLE_SOLID; // Reverse Pitchfork style //+------------------------------------------------------------------+ //| Pitchfork extrema parameters | //+------------------------------------------------------------------+ input string Pitchforks="=== Pitchfork Extrema Parameters ==="; //--- input int Pitchfork_First_Point_Left_Bars=6; // Pitchfork - 1st point, bars on the left input int Pitchfork_First_Point_Right_Bars=6; // Pitchfork - 1st point, bars on the left //--- input int Pitchfork_Second_Point_Left_Bars=6; // Pitchfork - 2nd point, bars on the left input int Pitchfork_Second_Point_Right_Bars=6; // Pitchfork - 2nd point, bars on the right //--- input int Pitchfork_Third_Point_Left_Bars=6; // Pitchfork - 3rd point, bars on the left input int Pitchfork_Third_Point_Right_Bars=2; // Pitchfork - 3rd point, bars on the right //+------------------------------------------------------------------+ //| Other parameters | //+------------------------------------------------------------------+ input string Others="=== Other Parameters ==="; input double Vertical_Short_Level_Coefficient=0.825; // Coefficient of vertical levels input double Long_Level_Multiplicator=2; // Multiplier for the long level input int Trend_Length_Coefficient=4; // Coefficient for the trend line length input bool Is_Trend_Ray=false; // Trend line - ray input bool Is_Change_Timeframe_On_Create = true; // Hide objects on higher timeframes? // (true - hide, false - show) input bool Is_Select_On_Create=true; // Select upon creation input bool Is_Different_Colors=true; // Change colors for times // Number of bars on the left and on the right // for trend line and fan extreme points input int Fractal_Size_Left=1; // Size of the left fractal input int Fractal_Size_Right=1; // Size of the right fractal input bool Pitchfork_Show_Main = true; // Display Andrews' pitchfork input bool Pitchfork_Show_Shiff = true; // Display Schiff pitchfork input bool Pitchfork_Show_Reverce = true; // Display "Reverse" pitchfork input bool Print_Warning_Messages=true; // Display error messages input string VFun_Levels="-1.5,-0.618,-0.236,"+ " 0,0.236,0.382,"+ " 0.618,0.786,0.886,0.942"; // Fan levels input string Array_Delimiter=","; // Array elements separator //--- //+------------------------------------------------------------------+ //| Name prefixes of drawn shapes (can be change only in code, | //| not visible in EA parameters) | //+------------------------------------------------------------------+ //string Prefixes="=== Prefixes ==="; //string Vertical_With_Short_Levels_Prefix="Vertical_"; // Prefix for vertical lines with levels //string Short_Level_Prefix="Short_Level_"; // Prefix for short levels //string Long_Level_Prefix="Long_Level_"; // Prefix for long levels //string Simple_Horizontal_Prefix="Simple_H_"; // Prefix for simple horizontal lines //string Simple_Vertical_Prefix="Simple_V_"; // Prefix for simple vertical lines //string VFan_Prefix="VFan_"; // Prefix for fan //string Trend_Line_Prefix="Trend_"; // Prefix for trend lines //string Pitchfork_Prefix="Pitchfork_"; // Prefix for pitchfork string allPrefixes[] = // Prefixes for object names { "Trend_", // 0 - Prefix for trend lines "Simple_H_", // 1 - Prefix for simple horizontal lines "Simple_V_", // 2 - Prefix for simple vertical lines "VFan_", // 3 - Prefix for fan "Pitchfork_", // 4 - Prefix for pitchfork "Vertical_", // 5 - Prefix for vertical lines with levels "Short_Level_", // 6 - Prefix for short levels "Long_Level_" // 7 - Prefix for long levels }; //+------------------------------------------------------------------+ //| Colors for objects of one timeframe (can be changed only in code,| //| not visible in EA parameters) | //+------------------------------------------------------------------+ // string TimeframeColors="=== Standard Colors for Timeframes ==="; color mn1_color=clrCrimson; color w1_color=clrDarkOrange; color d1_color=clrGoldenrod; color h4_color=clrLimeGreen; color h1_color=clrLime; color m30_color=clrDeepSkyBlue; color m15_color=clrBlue; color m5_color=clrViolet; color m1_color=clrDarkViolet; color common_color=clrGray; //--- Auxiliary constant for displaying error messages #define DEBUG_MESSAGE_PREFIX "=== ",__FUNCTION__," === " //--- Constants for describing the main timeframes when drawing //--- For compatibility with version 4, timeframes that do not exist //--- in the toolbar are excluded. #define PERIOD_LOWER_M5 OBJ_PERIOD_M1|OBJ_PERIOD_M5 #define PERIOD_LOWER_M15 PERIOD_LOWER_M5|OBJ_PERIOD_M15 #define PERIOD_LOWER_M30 PERIOD_LOWER_M15|OBJ_PERIOD_M30 #define PERIOD_LOWER_H1 PERIOD_LOWER_M30|OBJ_PERIOD_H1 #define PERIOD_LOWER_H4 PERIOD_LOWER_H1|OBJ_PERIOD_H4 #define PERIOD_LOWER_D1 PERIOD_LOWER_H4|OBJ_PERIOD_D1 #define PERIOD_LOWER_W1 PERIOD_LOWER_D1|OBJ_PERIOD_W1 //+------------------------------------------------------------------+
与以前版本相比所有新添加的内容均以黄色高亮显示。 这些新功能不仅可以配置直线,还可以配置屏幕上显示的其他对象。
我将对象前缀的名称放入数组中,以便以后使用它们时会更方便。 例如,我计划添加一个删除复杂对象的功能(譬如说,带有级别的垂直线)。 针对这种情况下,该数组将更加方便。
现在我们已研究过设置,可以继续进行图形处理了。
绘制“基元”:垂直和水平线
也许您要创建的第一个对象是水平线和时间线(无限的水平和垂直线)。 实际上,函数库就是从这些直线开始的。
此为代码:
//+------------------------------------------------------------------+ //| Draws simple straight lines (vertical and horizontal) in the | //| position specified by mouse or parameters | //| Parameters: | //| _object_type - object type. Can be OBJ_VLINE or OBJ_HLINE | //| _time - time. If not specified, mouse time is used | //| _price - price. If not specified, price under index is used. | //+------------------------------------------------------------------+ void CGraphics::DrawSimple( ENUM_OBJECT _object_type, // Object type datetime _time=-1, // Time double _price=-1 // Price ) { //--- string Current_Object_Name; // The name of the future object color Current_Object_Color= // Color (depends on the "standard" color of the timeframe) CUtilites::GetTimeFrameColor(CUtilites::GetAllLowerTimeframes()); datetime Current_Object_Time; // Starting point time double Current_Object_Price; // Starting point price ENUM_LINE_STYLE Current_Object_Style=STYLE_DOT; // Line style int Current_Object_Width=1; // Line width int window=0; // Subwindow number //--- Set up line parameters depending on the type if(_object_type==OBJ_VLINE) // For vertical lines { Current_Object_Name= // Generate the name CUtilites::GetCurrentObjectName( Simple_Vertical_Prefix, _object_type ); // style - according to global parameters Current_Object_Style=Simple_Vertical_Style; // width - according to global parameters Current_Object_Width=Simple_Vertical_Width; } else if(_object_type==OBJ_HLINE)// For horizontal lines { Current_Object_Name= // Generate the name CUtilites::GetCurrentObjectName( Simple_Horizontal_Prefix, _object_type ); // style - according to global parameters Current_Object_Style=Simple_Horizontal_Style; // width - according to global parameters Current_Object_Width=Simple_Horizontal_Width; } else // This function only draws horizontal and vertical lines. { // If something else is passed in parameters... if(Print_Warning_Messages) { // ...report an error... Print(DEBUG_MESSAGE_PREFIX,"Error, wrong object type"); } // ...and exit. return; } //--- If coordinates are not specified in the parameters, use the coordinates of the mouse Current_Object_Price = _price==-1 ? CMouse::Price() : _price; Current_Object_Time = _time==-1 ? CMouse::Time() : _time; //--- Create the object ObjectCreate( 0, Current_Object_Name, _object_type, 0, Current_Object_Time, Current_Object_Price ); //--- Set display parameters for the created object CurrentObjectDecorate( Current_Object_Name, Current_Object_Color, Current_Object_Width, Current_Object_Style ); //--- Redraw the chart and complete ChartRedraw(0); }
操作非常简单。 生成名称,从 “GlobalVariables.mqh” 文件中定义的输入变量获取设置,获取对象起始点的坐标(即可来自函数参数,亦或简单地取用鼠标的坐标),对象就准备好了。
这就是所有了!
现在我们需要将此函数添加到文件头文件里
//+------------------------------------------------------------------+ //| Graphics.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://www.mql5.com/es/articles/7468 | //+------------------------------------------------------------------+ // ... //+------------------------------------------------------------------+ //| Class for plotting graphic objects | //+------------------------------------------------------------------+ class CGraphics { // ... public: // ... //--- Draws simple straight lines (vertical and horizontal) void CGraphics::DrawSimple( ENUM_OBJECT _object_type, // Object type datetime _time=-1, // Time double _price=-1 // Price ) // ... } ; //+------------------------------------------------------------------+
还有,为相应的按键添加处理:
//+------------------------------------------------------------------+ //| Shortcuts.mqh | //+------------------------------------------------------------------+ // ... //+------------------------------------------------------------------+ //| Event handling function | //+------------------------------------------------------------------+ void CShortcuts::OnChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam ) { //--- int window = 0; //--- switch(id) { // ... //--- Handle keystrokes case CHARTEVENT_KEYDOWN: // ... //--- Draw a simple vertical line if(CUtilites::GetCurrentOperationChar(Simple_Vertical_Line_Key) == lparam) { m_graphics.DrawSimple(OBJ_VLINE); } //--- Draw a simple horizontal line if(CUtilites::GetCurrentOperationChar(Simple_Horizontal_Line_Key) == lparam) { m_graphics.DrawSimple(OBJ_HLINE); } // ... break; //--- } }
在将来,为了节省屏幕空间,并专注于主要思想,在添加函数说明时,我不再编写头部注释,而是显示新添加命令的相应行(黄色高亮)。
所有添加和编译的结果非常简单:两个命令可在当前窗口的任何位置绘制图形基元:
这些直线的默认快捷键是 "I" (i) 和 "H" (h)。
不要忘记,所创建对象的颜色会有所不同,具体取决于当前时间帧。 来自较低时间帧的对象不会在较高时间帧里显示(默认设置)。
为了兼容 MQL4,我们仅采用来自标准工具栏的时间帧,作为默认显示。 选择这些时间帧时,您可用 "U" 和 "D" 键 (按这些键可向上或向下更改一次图表周期的时间帧;参见 CUtilites::ChangeTimeframes 函数)。
VFun, 或斐波那契扇形
下一个形状是斐波那契扇形。 我经常这样用它。 但每次都要用不同的终端来记住所有射线是非常不便的。 因此,我决定将此工具添加到精彩的 EA 当中。
我已进一步发展了这一思路,并决定为使用该函数库绘制的任何对象实现一个通用的设置斐波那契级别的函数(扇形通道或水平斐波级别)。 此为该函数。
//+------------------------------------------------------------------+ //| Sets level values and form in any Fibonacci object | //| Uses colors and styles from the class fields | //| Parameters: | //| _object_name - the name of the Fibonacci object | //| _levels_values[] - array of level values | //+------------------------------------------------------------------+ void CGraphics::SetFiboLevels( string _object_name, // Object name const double &_levels_values[] // Array of values ) { int i, // Current level counter levels_count=ArraySize(_levels_values); // Total number of levels //--- Check if the number of values in the array exceeds the allowed range if(levels_count>32 || levels_count==0) { Print(DEBUG_MESSAGE_PREFIX,": Levels cannot be set! Data array is incorrectly. "); return; } //--- Proceed with the implementation //--- Set the number of levels for the current object ObjectSetInteger(0,_object_name,OBJPROP_LEVELS,levels_count); //--- Set value, color and style for each level. for(i=0; i<levels_count; i++) { ObjectSetDouble(0,_object_name,OBJPROP_LEVELVALUE,i,_levels_values[i]); ObjectSetInteger(0,_object_name,OBJPROP_LEVELCOLOR,i,m_Fibo_Default_Color); ObjectSetInteger(0,_object_name,OBJPROP_LEVELSTYLE,i,m_Fibo_Default_Style); } //--- Redraw the chart before finishing ChartRedraw(0); }
传递给函数的参数包括为其设置级别的对象名称,以及所有级别值的数组。
首先,该函数检查所传递的级别数量。 如果数组太大,则该函数会假定已发生错误,且不执行任何操作。 如果数组中没有元素,它也会退出。
那么,若一切正常,且数组中的元素数量未超出允许的范围,那么我们开始添加级别。 对象的名称是在参数中指定的,因此我们只需将对象的相应属性设置为等于数组元素的数量,并在设置相应级别的同时遍历整个数组。
MQL5 还允许为不同的参数设置不同的级别。 例如,我们可以设置不同的颜色。 我们也可以使用不同的样式(实线、虚线、等等)。 MQL4 则未提供此类选项。 尽管如此,我还在循环中添加了定义直线颜色和样式。它们在编译时不会影响 MQL5 的通用性。
变量说明的默认参数被定义为 CGraphics 类的私有成员,并在类构造函数中以 EA 参数中的数值进行初始化。
//+------------------------------------------------------------------+ //| Graphics.mqh | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Class for plotting graphic objects | //+------------------------------------------------------------------+ class CGraphics { //--- Fields private: // ... color m_Fibo_Default_Color; ENUM_LINE_STYLE m_Fibo_Default_Style; // ... //+------------------------------------------------------------------+ //| Default constructor | //+------------------------------------------------------------------+ CGraphics::CGraphics(void) { //... m_Fibo_Default_Color = Fibo_Default_Color; m_Fibo_Default_Style = VFun_Levels_Style; } // ...
对于那些不关心兼容性的人,我还添加了该函数的一个覆盖。 它允许采用函数参数中所传递的数组为每个级别设置参数。 我想代码中的内容都很清楚。 如果您需要进一步的解说,请留下相应的评论。 在附带的 zip 中启用了函数覆盖。
此处是另一个函数,可为任何斐波那契对象设置级别描述。
//+------------------------------------------------------------------+ //| Sets descriptions of levels in any Fibonacci object | //| _object_name - the name of the Fibonacci object | //| _levels_descriptions[] - array of level descriptions | //+------------------------------------------------------------------+ void CGraphics::SetFiboDescriptions( string _object_name, // Object name const string &_levels_descriptions[] // Array of descriptions ) { int i, // Current level counter levels_count=(int)ObjectGetInteger(0,_object_name,OBJPROP_LEVELS), // The real number of levels array_size=ArraySize(_levels_descriptions); // The number of received descriptions //--- Loop through all levels for(i=0; i<levels_count; i++) { if(array_size>0 && i<array_size) // Choose a description from the array { //--- and write it to the level ObjectSetString(0,_object_name,OBJPROP_LEVELTEXT,i,_levels_descriptions[i]); } else // If the descriptions are not enough, { ObjectSetString(0,_object_name,OBJPROP_LEVELTEXT,i,""); // leave the description empty } } //--- Redraw the chart before finishing ChartRedraw(0); }
这里没什么复杂的。 唯一的条件是,在调用此函数时,必须已经设置了对象级别。 该函数只是简单地遍历这些级别,并将来自数组的相应值分配给每个级别的描述。 如果数组中的数据不足,某些级别将保持不变,且无需说明。
现在,在添加级别时变得更容易了,我们可以编写添加斐波那契扇形的函数。
//+------------------------------------------------------------------+ //| Draws a Fibonacci fan from the nearest local extremum. | //+------------------------------------------------------------------+ void CGraphics::DrawVFan(void) { //--- double levels_values[]; // Array of level values string levels_descriptions[] = {}; // Array of level descriptions int p1=0, // Bar number for the fan starting point p2=0; // Bar number for the fan ending point double price1=0, // First point price price2=0; // Second point price string fun_name = // Fan name CUtilites::GetCurrentObjectName(allPrefixes[3],OBJ_FIBOFAN), fun_0_name = CUtilites::GetCurrentObjectName(allPrefixes[3]+"0_",OBJ_TREND); //--- Get data for the fan from the parameter string CUtilites::StringToDoubleArray(VFun_Levels,levels_values); //--- Find the extreme points closest to the mouse if(CMouse::Below()) // If the mouse cursor is below the price { CUtilites::SetExtremumsBarsNumbers(false,p1,p2); price1=iLow(Symbol(),PERIOD_CURRENT,p1); price2=iLow(Symbol(),PERIOD_CURRENT,p2); } else if(CMouse::Above()) // If the mouse cursor is above the price { CUtilites::SetExtremumsBarsNumbers(true,p1,p2); price1=iHigh(Symbol(),PERIOD_CURRENT,p1); price2=iHigh(Symbol(),PERIOD_CURRENT,p2); } //--- Create the fan object ObjectCreate( 0,fun_name,OBJ_FIBOFAN,0, iTime(Symbol(),PERIOD_CURRENT,p1), price1, iTime(Symbol(),PERIOD_CURRENT,p2), price2 ); //--- The zero ray of this object is denoted by a colored line (for compatibility with MT4) TrendCreate( 0, fun_0_name, 0, iTime(Symbol(),PERIOD_CURRENT,p1), price1, iTime(Symbol(),PERIOD_CURRENT,p2), price2, CUtilites::GetTimeFrameColor(CUtilites::GetAllLowerTimeframes()), 0,1,false,true,true ); //--- Describe the fan levels SetFiboLevels(fun_name,levels_values); SetFiboDescriptions(fun_name, levels_descriptions); //--- Set standard parameters (such as timeframes and selection after creation) CurrentObjectDecorate(fun_name,m_Fibo_Default_Color); //--- Also make out the "substitute" ray CurrentObjectDecorate( fun_0_name, CUtilites::GetTimeFrameColor( CUtilites::GetAllLowerTimeframes() ) ); //--- ChartRedraw(0); }
我认为当形成扇形的射线具有不同的颜色时这会很方便。 为了在 MQL4 中实现此功能,我们必须像上一篇文章中那样在扇形上绘制一条常规直线。
在这种情况下,我们不需要级别标题,因此我简单地用了一个空数组。
数值数组是利用实用工具函数依据 EA 参数创建的
CUtilites::StringToDoubleArray(VFun_Levels,levels_values);
在第一篇文章中已介绍过将字符串转换为数字数组的实用程序。
将扇形绘图命令添加到命令定义列表之中:
//+------------------------------------------------------------------+ //| Shortcuts.mqhh | //+------------------------------------------------------------------+ //... //--- Draw a Fibonacci fan (VFun) if(CUtilites::GetCurrentOperationChar(VFun_Key) == lparam) { m_graphics.DrawVFan(); } break; //...
编译并检查结果。 打开终端并打开所需的图表。
将鼠标从图表的顶部或底部移动到基准极值的左侧,然后按 “ F”。
顺便说一句,查看此特定扇形的配置,我假设价格很快就会下跌。
价格最终下跌。
安德鲁草叉
我使用 3 类草叉。
首先,我选择所需的极值,并绘制“常规”草叉。 草叉的端点恰好处于极值价位。
安德鲁斯描述的第二类草叉是席夫草叉。 此处,端点 1 是在趋势方向上 1-2 距离的一半处。 相应地,中心线的斜率较小。 如果走势与这些草叉相适,则走势很可能是横盘,故而价格正处于“调整”走势当中。
第三类是“反转”草叉。 端点 1 是逆势方向上与 1-2 距离相同的偏移。 这种草叉可应对快速走势。 通常,它们的时间较短,但它们之间的价格差距较大。
在实际分析中,我希望同时将所有三种类型的草叉都放在图表上。 在这种情况下,价格走势以及未来可能出现的极端现象的关键点就更加清晰了。
用两个函数来绘制这样的集合。 第一个是绘制一个任意类型草叉的函数。
//+------------------------------------------------------------------+ //| Creates Andrews' pitchfork using specified coordinates | //| Parameters: | //| _name - the name of created pitchfork | //| _base - the structure containing coordinates of basic points | //| _type - pitchfork type (SIMPLE,SHIFF,REVERCE) | //+------------------------------------------------------------------+ void CGraphics::MakePitchfork( string _name, // The name of the created object PitchforkPoints &_base, // Structure describing pitchfork base points PitchforkType _type // Pitchfork type (SIMPLE,SHIFF,REVERCE) ) { //--- double price_first; // The price of the first point (depends on the type) color pitchfork_color; // Pitchfork color (depends on the type) int pitchfork_width; // Line width (depends on the type) ENUM_LINE_STYLE pitchfork_style; // Line style (depends on the type) double fibo_levels[] = {1}; // Add external levels (only for MQL5) string fibo_descriptions[] = {""}; // Level description (only for MQL5) //--- Set type dependent parameters: if(_type == SHIFF) // Schiff pitchfork { price_first = _base.shiffMainPointPrice; pitchfork_color = Pitchfork_Shiff_Color; pitchfork_width = Pitchfork_Shiff_Width; pitchfork_style = Pitchfork_Shiff_Style; } else if(_type == REVERCE) // "Reverse" pitchfork { price_first = _base.reverceMainPointPrice; pitchfork_color = Pitchfork_Reverce_Color; pitchfork_width = Pitchfork_Reverce_Width; pitchfork_style = Pitchfork_Reverce_Style; } else { // "classic" pitchfork price_first =_base.mainPointPrice; pitchfork_color = Pitchfork_Main_Color; pitchfork_width = Pitchfork_Main_Width; pitchfork_style = Pitchfork_Main_Style; } //--- Draw ObjectCreate(0,_name,OBJ_PITCHFORK,0, _base.time1,price_first, _base.time2,_base.secondPointPrice, _base.time3,_base.thirdPointPrice ); //--- Set the parameters common for all graphical objects CurrentObjectDecorate( _name, pitchfork_color, pitchfork_width, pitchfork_style ); //--- If MQL5 #ifdef __MQL5__ //--- add external levels (early levels for Andrews' pitchfork) SetFiboLevels(_name,fibo_levels); SetFiboDescriptions(_name,fibo_descriptions); #endif //--- Update the chart picture ChartRedraw(0); }
第二个函数计算所创建草叉的点 1、2 和 3(基准)的坐标,并依次开始绘制所有三个对象。 基于此函数,调用上面的 CGraphics::MakePitchfork 函数绘制草叉。
//+------------------------------------------------------------------+ //| Draws set of Andrews' pitchforks on one base. The set includes | //| three pitchfork types: regular, Schiff and reverse Schiff | //| (aka "micmed channel") | //+------------------------------------------------------------------+ void CGraphics::DrawPitchforksSet(void) { bool up=true; // direction (mouse below or above the price) double dropped_price = CMouse::Price(); // "Starting point" price int dropped_bar = CMouse::Bar(); // Starting point bar number string name = ""; // The name of the current object PitchforkPoints base; // Structure for the base coordinates //--- if(CMouse::Below()) { up=false; } else { if(!CMouse::Above()) // If the mouse pointer is on the candlestick, do nothing { if(Print_Warning_Messages) { Print(DEBUG_MESSAGE_PREFIX,": Set a point above or below the bar extreme price"); } return; } } //--- Find extremum bar numbers int bar_first = CUtilites::GetNearestExtremumBarNumber( dropped_bar, true, up, Pitchfork_First_Point_Left_Bars, Pitchfork_First_Point_Right_Bars ); int bar_second = CUtilites::GetNearestExtremumBarNumber( bar_first-1, true, !up, Pitchfork_Second_Point_Left_Bars, Pitchfork_Second_Point_Right_Bars ); int bar_third = CUtilites::GetNearestExtremumBarNumber( bar_second-1, true, up, Pitchfork_Third_Point_Left_Bars, Pitchfork_Third_Point_Right_Bars ); //--- If not found, report an error if(bar_first<0||bar_second<0||bar_third<0) { if(Print_Warning_Messages) { Print(DEBUG_MESSAGE_PREFIX,": Could not find points that match all conditions."); } return; } //--- Fill the structure for basic control points base.mainPointPrice = up ? // Price - first basic point iHigh(Symbol(),PERIOD_CURRENT,bar_first) : iLow(Symbol(),PERIOD_CURRENT,bar_first); base.secondPointPrice = up ? // Price - second basic point iLow(Symbol(),PERIOD_CURRENT,bar_second) : iHigh(Symbol(),PERIOD_CURRENT,bar_second); base.thirdPointPrice = up ? // Price - third basic point iHigh(Symbol(),PERIOD_CURRENT,bar_third) : iLow(Symbol(),PERIOD_CURRENT,bar_third); base.shiffMainPointPrice = base.mainPointPrice- // Price - first point of Schiff pitchfork (base.mainPointPrice-base.secondPointPrice)/2; base.reverceMainPointPrice = base.mainPointPrice+ // Price - first point of "reverse" pitchfork (base.mainPointPrice-base.secondPointPrice)/2; base.time1 = iTime(Symbol(),PERIOD_CURRENT,bar_first); // Time of the first point base.time2 = iTime(Symbol(),PERIOD_CURRENT,bar_second); // Time of the second point base.time3 = iTime(Symbol(),PERIOD_CURRENT,bar_third); // Time of the third point //--- Draw "regular" pitchfork if(Pitchfork_Show_Main) { name =CUtilites::GetCurrentObjectName(allPrefixes[4]+"_main",OBJ_PITCHFORK); MakePitchfork(name,base,SIMPLE); } //--- Draw Schiff pitchfork if(Pitchfork_Show_Shiff) { name =CUtilites::GetCurrentObjectName(allPrefixes[4]+"_shiff",OBJ_PITCHFORK); MakePitchfork(name,base,SHIFF); } //--- Draw "reverse" pitchfork if(Pitchfork_Show_Reverce) { name =CUtilites::GetCurrentObjectName(allPrefixes[4]+"_reverce",OBJ_PITCHFORK); MakePitchfork(name,base,REVERCE); } //--- //ChartRedraw(0); not needed here as it is called when drawing each object