如何计算移动平均线角度并将其显示于图表上的方法
量化分析
2022-04-24 10:06:59
2023年外汇交易商最新排名更多
登录移动平均线用的缓冲器
在本篇章节中,将说明如何计算移动平均线角度并显示于图表中。
首先,在制作新档案中选择「自定义指标」,并将文件名命名为「MA_angle」。由于本次将使用「OnChartEvent」,因此在「自定义指针程序的事件处理程序」画面中,仅勾选「OnChartEvent」并进入下一步登录移动平均线用的缓冲器。卷标设定为「MA」、样式为「Line」、颜色为「White」后点击「完成」即是雏形。
定义接头辞以利删除对象
首先,由于缓冲器名称略嫌冗长,因此将「MABuffer」变更为「MA」。
double MA[];因本次将使用到对象,故为了能够一次进行删除,应先登录接头辞;在档案上方的属性「#property indicator_width1 1」下方,将「PREFIX」如以下所示加以定义。
SetIndexBuffer(0,MA);
#define PREFIX “MA_angle_”另外,在「Custom indicator initialization function」下方设定「Custom indicator deinitialization function」,并写入使用OnDeinit函数的以下编码。
void OnDeinit(const int reason)接下来,在OnCalculate函数下写入移动平均线的绘制公式。此处为假设绘制,故将省略详细说明; 可使用for文体,如以下所示进行编写。
{
ObjectsDeleteAll(0, PREFIX);
}
取得光标位置的移动平均线信息
接下来将制作程序,以检测光标的位置,并计算该处的移动平均线角度。
为了检测光标的位置,需在「ChartSetInteger」使用「CHART_EVENT MOUSE_MOVE」进行宣言。在OnInit函数下的「SetIndexBuffer(0,MA);」下方,如以下所示写入编码。
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);接着,在OnChartEvent函数旗下写入移动鼠标的处理动作。首先以「ChartXYToTimePrice」,将光标的XY坐标变更为价格与时间信息。X坐标为「lparam」、Y坐标为「dparam」。取得光标位置的时间之后,以「iBarShift」取得该时间的K线数量与位置。
if (id == CHARTEVENT_MOUSE_MOVE) {其后,将取得该光标位置的移动平均线信息。具体来说,应取得移动平均线的2个点,并从该处得出角度。使用将图表时间与价格变更为XY坐标的「ChartTimePriceToXY」,第1点为K线位置,故写入x[0]与y[0] ;第2点为前一个点,因此依样写入x[1]与y[1] 。
datetime time;
double price;
int win = 0;
ChartXYToTimePrice(0, (int)lparam, (int)dparam, win, time, price);
int bar = iBarShift(NULL, 0, time);
int x[2], y[2];如此即可取得2个点。
ChartTimePriceToXY(0, 0, Time[bar], MA[bar], x[0], y[0]);
ChartTimePriceToXY(0, 0, Time[bar + 1], MA[bar + 1], x[1], y[1]);
从移动平均线的2点信息计算角度
接下来,将利用已取得的移动平均线2点来计算角度。角度计算将在x[0]与x[1]不一致时进行,而计算公式如以下画面所示。
先前取得的2点即为黄色坐标。为了算出角度,应先求出三角形底边A的长度以及B的高度;而由于tanθ为A分之B,故能以「arctan(B/A)」来计算角度。
此处所运用的函数,为可返回指定数值arctan(反正切)的「MathArctan」;此函数所得出的答案,会以「弧度」为单位,故若希望转换为计算的单位「次」,便须乘以180并除以π(MT4的M_PI等同于π)。
double angle = 90;如此便能够得出角度。另外,X坐标与Y坐标的减法算式中,「1」与「0」将呈现颠倒,此原因在于坐标的标准点位于左上方,故Y坐标越往下、则数值会越发增加。
if (x[0] != x[1]) angle = MathArctan(double(y[1] – y[0]) / (x[0] – x[1])) * 180 / M_PI;
设定Label对象
方才已说明了如何利用移动平均线的2点信息来计算角度;其次,将尝试运用Label对象,把计算结果显示于图表中。
此处会从MQL4帮助文件中,复制Label对象的样本编码并加以运用。点击MQL4帮助文件目录的「Constants, Enumerations and Structures」→「Objects Constants」→「Object Types」,便会出现对象一览。
从中选择「OBJ_LABEL」后,复制预先准备的「Create a text label」编码,并贴至档案下方。
首先,删除不需要的「//— reset the error value」「ResetLastError();」等2行,以及「 Print(__FUNCTION__,」「”: failed to create text label! Error code = “,GetLastError());」2行。
另外,为了使显示数值能够改变,在「if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)){」下方插入「ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);」;为了使显示数值能够改变,则插入「ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);」。
//+——————————————————————+
//| Create a text label |
//+——————————————————————+
bool LabelCreate(const long chart_ID=0, // chart’s ID
const string name=”Label”, // label name
const int sub_window=0, // subwindow index
const int x=0, // X coordinate
const int y=0, // Y coordinate
const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, // chart corner for anchoring
const string text=”Label”, // text
const string font=”Arial”, // font
const int font_size=10, // font size
const color clr=clrRed, // color
const double angle=0.0, // text slope
const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type
const bool back=false, // in the background
const bool selection=false, // highlight to move
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//— create a text label
if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)){
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
return(false);
}
//— set label coordinates
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//— set the chart’s corner, relative to which point coordinates are defined
ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//— set the text
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//— set text font
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//— set font size
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//— set the slope angle of the text
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//— set anchor type
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//— set color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//— display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//— enable (true) or disable (false) the mode of moving the label by mouse
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//— hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//— set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//— successful execution
return(true);
}
依据角度大小改变文字颜色
将设定的LabelCreate写于OnChartEvent函数内;参数的X设定为「5」、Y为「15」、内容为「DoubleToString」的2行、文字字体为「Arial Bold」、大小为「30」。至于文字颜色的设定,则会在LabelCreate上执行;本次将文字颜色设为白色。
color clr = clrWhite;另外,如欲在K线尺寸大于MA序列尺寸时停止计算,便应在「int bar = iBarShift(NULL, 0, time);」下方增加以下if文体。
LabelCreate(0, PREFIX + “angle”, 0, 5, 15, CORNER_LEFT_UPPER, DoubleToString(angle, 2), “Arial Bold”, 30, clr);
最后,当移动平均线的角度大于45度时,将文字颜色设定为红色;负45度以下时则是蓝色。只要在「color clr = clrWhite;」下方添加下列if文体即可。
原始码
本次制作的原始码如以下所示。
//+——————————————————————+
//| MA_angle.mq4 |
//| Copyright 2021, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+——————————————————————+
#property copyright “Copyright 2021, MetaQuotes Software Corp.”
#property link “https://www.mql5.com”
#property version “1.00”
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//— plot MA
#property indicator_label1 “MA”
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrWhite
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#define PREFIX “MA_angle_”
//— indicator buffers
double MA[];
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int OnInit()
{
//— indicator buffers mapping
SetIndexBuffer(0, MA);
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| Custom indicator deinitialization function |
//+——————————————————————+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, PREFIX);
}
//+——————————————————————+
//| Custom indicator iteration function |
//+——————————————————————+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//—
int limit = Bars – prev_calculated – 1;
if (limit < 1) limit = 1;
for (int i = limit; i >= 0; i–)
MA[i] = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, i);
//— return value of prev_calculated for next call
return(rates_total);
}
//+——————————————————————+
//| ChartEvent function |
//+——————————————————————+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if (id == CHARTEVENT_MOUSE_MOVE) {
datetime time;
double price;
int win = 0;
ChartXYToTimePrice(0, (int)lparam, (int)dparam, win, time, price);
int bar = iBarShift(NULL, 0, time);
if (bar > ArraySize(MA) – 2) return;
int x[2], y[2];
ChartTimePriceToXY(0, 0, Time[bar], MA[bar], x[0], y[0]);
ChartTimePriceToXY(0, 0, Time[bar + 1], MA[bar + 1], x[1], y[1]);
double angle = 90;
if (x[0] != x[1]) angle = MathArctan(double(y[1] – y[0]) / (x[0] – x[1])) * 180 / M_PI;
color clr = clrWhite;
if (angle >= 45) clr = clrRed;
else if (angle <= -45) clr = clrDodgerBlue;
LabelCreate(0, PREFIX + “angle”, 0, 5, 15, CORNER_LEFT_UPPER, DoubleToString(angle, 2), “Arial Bold”, 30, clr);
}
}
//+——————————————————————+
//| Create a text label |
//+——————————————————————+
bool LabelCreate(const long chart_ID = 0, // chart’s ID
const string name = “Label”, // label name
const int sub_window = 0, // subwindow index
const int x = 0, // X coordinate
const int y = 0, // Y coordinate
const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring
const string text = “Label”, // text
const string font = “Arial”, // font
const int font_size = 10, // font size
const color clr = clrRed, // color
const double angle = 0.0, // text slope
const ENUM_ANCHOR_POINT anchor = ANCHOR_LEFT_UPPER, // anchor type
const bool back = false, // in the background
const bool selection = false, // highlight to move
const bool hidden = true, // hidden in the object list
const long z_order = 0) // priority for mouse click
{
//— create a text label
if(!ObjectCreate(chart_ID, name, OBJ_LABEL, sub_window, 0, 0)) {
ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
return(false);
}
//— set label coordinates
ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y);
//— set the chart’s corner, relative to which point coordinates are defined
ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner);
//— set the text
ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);
//— set text font
ObjectSetString(chart_ID, name, OBJPROP_FONT, font);
//— set font size
ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size);
//— set the slope angle of the text
ObjectSetDouble(chart_ID, name, OBJPROP_ANGLE, angle);
//— set anchor type
ObjectSetInteger(chart_ID, name, OBJPROP_ANCHOR, anchor);
//— set color
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//— display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
//— enable (true) or disable (false) the mode of moving the label by mouse
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
//— hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);
//— set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);
//— successful execution
return(true);
}
//+——————————————————————+
为了检测光标的位置,需在「ChartSetInteger」使用「CHART_EVENT MOUSE_MOVE」进行宣言。在OnInit函数下的「SetIndexBuffer(0,MA);」下方,如以下所示写入编码。
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);接着,在OnChartEvent函数旗下写入移动鼠标的处理动作。首先以「ChartXYToTimePrice」,将光标的XY坐标变更为价格与时间信息。X坐标为「lparam」、Y坐标为「dparam」。取得光标位置的时间之后,以「iBarShift」取得该时间的K线数量与位置。
if (id == CHARTEVENT_MOUSE_MOVE) {其后,将取得该光标位置的移动平均线信息。具体来说,应取得移动平均线的2个点,并从该处得出角度。使用将图表时间与价格变更为XY坐标的「ChartTimePriceToXY」,第1点为K线位置,故写入x[0]与y[0] ;第2点为前一个点,因此依样写入x[1]与y[1] 。
datetime time;
double price;
int win = 0;
ChartXYToTimePrice(0, (int)lparam, (int)dparam, win, time, price);
int bar = iBarShift(NULL, 0, time);
int x[2], y[2];如此即可取得2个点。
ChartTimePriceToXY(0, 0, Time[bar], MA[bar], x[0], y[0]);
ChartTimePriceToXY(0, 0, Time[bar + 1], MA[bar + 1], x[1], y[1]);
哪些贵金属平台好?不错的贵金属交易汇平台推荐:哪些贵金属平台好?2023年平台最新排名
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
本文相关:无相关信息
留言与评论(共有 0 条评论) |