在复数图表中同步趋势线图式的方法
量化分析
2023-09-14 10:30:23
2023年外汇交易商最新排名更多
检测对象的新增与删除
在本篇章节中,将介绍在复数图表中同步趋势线的方法。具体来说,便是在设定指针的图表中制作新趋势线时,于其他图表产生相同的绘制动作。
首先在制作新档案中选择「自定义指标」,并将文件名设定为「TrendlineSync」,无需新增参数即可移至下一步;在「自定义指针程序的的事件处理程序」中勾选「OnChartEvent」,点击「完成」即可呈现雏形。
因为想要在制作新趋势线时予以同步,所以需要在OnInit函数下设置图表属性的ChartSetInteger函数中先行宣告「CHART_EVENT_OBJECT_CREATE」。另外,为了当趋势线遭到删除时能够检测,亦须设定「CHART_EVENT_OBJECT_DELETE」。
ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
复制并运用「OBJ_TREND」的样本编码
接下来,将在OnChartEvent函数下,写入当图表中发生事件时予以处理的if文体。首先是「CHART_EVENT_OBJECT_CREATE」;只要新增的对象为趋势线,便会取得该趋势线的信息并加以同步。
if (id == CHARTEVENT_OBJECT_CREATE) {在此if文体中追加趋势线的相关编码。此处复制并使用MQL4帮助文件中的样本编码;在MQL4帮助文件目录中,点击「Constants, Enumerations and Structures」→「Objects Constants」→「Object Types」便会出现对象一览,从中选择「OBJ_TREND」之后,复制并贴上预先准备的下列编码。
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
}
}
//+——————————————————————+复制后,可以删除以下不需要的9行。
//| Create a trend line by the given coordinates |
//+——————————————————————+
bool TrendCreate(const long chart_ID=0, // chart’s ID
const string name=”TrendLine”, // line name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
const color clr=clrRed, // line color
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=1, // line width
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_right=false, // line’s continuation to the right
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//— set anchor points’ coordinates if they are not set
ChangeTrendEmptyPoints(time1,price1,time2,price2);
//— reset the error value
ResetLastError();
//— create a trend line by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_TREND,sub_window,time1,price1,time2,price2))
{
Print(__FUNCTION__,
“: failed to create a trend line! Error code = “,GetLastError());
return(false);
}
//— set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//— set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//— set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//— 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 line by mouse
//— when creating a graphical object using ObjectCreate function, the object cannot be
//— highlighted and moved by default. Inside this method, selection parameter
//— is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//— enable (true) or disable (false) the mode of continuation of the line’s display to the right
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//— 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);
}
const bool selection=true, // highlight to move接下来,将「hidden = true」变更为「hidden = false」,2处「ray_right」变更为「ray」,「OBJPROP_RAY_RIGHT」则改为「OBJPROP_RAY」;如此便完成了趋势线样本编码的准备。顺道一提,「OBJPROP_RAY_RIGHT」是MT5用的指示。
//— set anchor points’ coordinates if they are not set
ChangeTrendEmptyPoints(time1,price1,time2,price2);
//— reset the error value
ResetLastError();
Print(__FUNCTION__,
“: failed to create a trend line! Error code = “,GetLastError());
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//+——————————————————————+
//| Create a trend line by the given coordinates |
//+——————————————————————+
bool TrendCreate(const long chart_ID=0, // chart’s ID
const string name=”TrendLine”, // line name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
const color clr=clrRed, // line color
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=1, // line width
const bool back=false, // in the background
const bool ray=false, // line’s continuation to the right
const bool hidden=false, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//— create a trend line by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_TREND,sub_window,time1,price1,time2,price2))
{
return(false);
}
//— set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//— set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//— set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//— 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 line by mouse
//— when creating a graphical object using ObjectCreate function, the object cannot be
//— highlighted and moved by default. Inside this method, selection parameter
//— is true by default making it possible to highlight and move the object
//— enable (true) or disable (false) the mode of continuation of the line’s display to the right
ObjectSetInteger(chart_ID,name,OBJPROP_RAY,ray);
//— 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);
}
取得趋势线的时间与价格等信息
接下来,将修改此编码以取得并同步趋势线的信息。首先,从准备的趋势线相关编码中,复制「ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);」开始的下列13行,并贴至if文体处。
if (id == CHARTEVENT_OBJECT_CREATE) {其后,将此部分的编码如下所示进行改写。如欲取得趋势线的状态,便应将「ObjectSetInteger」全数替换为「ObjectGetInteger」,并设定「OBJPROP_TIME」以获取时间信息、设定「OBJPROP_PRICE」以获取价格信息。
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//— set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//— set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//— 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 line by mouse
//— when creating a graphical object using ObjectCreate function, the object cannot be
//— highlighted and moved by default. Inside this method, selection parameter
//— is true by default making it possible to highlight and move the object
//— enable (true) or disable (false) the mode of continuation of the line’s display to the right
ObjectSetInteger(chart_ID,name,OBJPROP_RAY,ray);
}
}
if (id == CHARTEVENT_OBJECT_CREATE) {
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
datetime time0 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 0);
datetime time1 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 1);
double price0 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 0);
double price1 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 1);
color clr = (color)ObjectGetInteger(0, sparam, OBJPROP_COLOR);
ENUM_LINE_STYLE style = (ENUM_LINE_STYLE)ObjectGetInteger(0, sparam, OBJPROP_STYLE);
int width = (int)ObjectGetInteger(0, sparam, OBJPROP_WIDTH);
bool back = ObjectGetInteger(0, sparam, OBJPROP_BACK);
bool ray = ObjectGetInteger(0, sparam, OBJPROP_RAY);
}
}
将获取的信息同步于各个图表
接下来,要将获取的信息同步于各个图表。关于同步的程序,将沿用「同步复数图表」一文中的内容。在MQL4帮助文件目录中,点击「Chart Operations」→「ChartNext」,便会出现执行所有图表处理的参考范例页面,可从中加以运用。
long chart_id = ChartFirst();上列编码的目的为同步图表范围,故此处将替换为同步趋势线。首先将范围相关的「if (ChartGetInteger(chart_id, CHART_SCALE) != scale) {」「ChartSetInteger(chart_id, CHART_SCALE, scale);」2行予以删除。
while (true) {
if (chart_id != ChartID()) {
if (ChartGetInteger(chart_id, CHART_SCALE) != scale) {
ChartSetInteger(chart_id, CHART_SCALE, scale);
}
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
本次将从第一项图表开始依序取得信息;在每一次进展时,使用「ChartNext」切换至下一个图表。由于只要在遇到非原本的图表、或与原本图表相同的货币对时执行处理,因此要修正第一个if文体。如此一来,只要没有相同名称的组件,便会开始制作趋势线。
long chart_id = ChartFirst();于此处进行编译,并设定两个图表来绘制趋势线作为测试;可以见到,当在其中一个图表上拉出趋势线,另一个图表上便会出现相同的线条。
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
if (ObjectFind(chart_id, sparam) == -1)
TrendCreate(chart_id, sparam, 0, time0, price0, time1, price1, clr, style, width, back, ray);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
同步趋势线的位置信息
目前已经能够在图表中同步趋势线。但是,在这样的状态下,尚无法同步趋势线的移动;因此, 接下来就要在图表中拖曳趋势线时,于其他图表中同步该位置信息。
此处将沿用制作新趋势线时的同步编码,并新增移动趋势线时的同步编码。使用变更对象坐标的「ObjectMove」函数作为「CHARTEVENT_OBJECT_DRAG」。
if (id == CHARTEVENT_OBJECT_DRAG) {添加上列编码后进行编译,即可同步趋势线的位置。只要当原本图表的趋势线遭到拖曳移动,另一个图表上的趋势线也会移至相同的位置。
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
datetime time0 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 0);
datetime time1 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 1);
double price0 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 0);
double price1 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 1);
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
ObjectMove(chart_id, sparam, 0, time0, price0);
ObjectMove(chart_id, sparam, 1, time1, price1);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
同步趋势线的绘图样式与删除等操作
最后,将针对趋势线的颜色、粗细、线条种类等样式的变更,以及趋势线遭到删除等操作予以同步。首先是样式相关的设定处理,「CHARTEVENT_OBJECT_CHANGE」将如以下所示进行编写;趋势线的状态设定则使用「ObjectSetInteger」。
if (id == CHARTEVENT_OBJECT_CHANGE) {如此进行编译后,可见当原本的图表线条变成黄色、种类变成虚线时,另一条趋势线也会出现相同的改变。
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
color clr = (color)ObjectGetInteger(0, sparam, OBJPROP_COLOR);
ENUM_LINE_STYLE style = (ENUM_LINE_STYLE)ObjectGetInteger(0, sparam, OBJPROP_STYLE);
int width = (int)ObjectGetInteger(0, sparam, OBJPROP_WIDTH);
bool back = ObjectGetInteger(0, sparam, OBJPROP_BACK);
bool ray = ObjectGetInteger(0, sparam, OBJPROP_RAY);
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
ObjectSetInteger(chart_id, sparam, OBJPROP_COLOR, clr);
ObjectSetInteger(chart_id, sparam, OBJPROP_STYLE, style);
ObjectSetInteger(chart_id, sparam, OBJPROP_WIDTH, width);
ObjectSetInteger(chart_id, sparam, OBJPROP_BACK, back);
ObjectSetInteger(chart_id, sparam, OBJPROP_RAY, ray);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
至于删除趋势线的信息同步,则是以「CHARTEVENT_OBJECT_DELETE」如下方所示进行编写。将第二个if文体的「ObjectGetInteger」变更为「StringFind」之后,只要含有制作趋势线时的「Trendline」名称遭到删除,便会开始予以同步删除。(由于趋势线删除后,无法透过「ObjectGetInteger」 取得信息,因此需利用「StringFind」进行辨认。)。
if (id == CHARTEVENT_OBJECT_DELETE) {如此即是完成。进行编译之后,只要原本图表上的趋势线遭到删除,另一个趋势线也会同时消失。
if (StringFind(sparam, “Trendline “) != -1) {
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
ObjectDelete(chart_id, sparam);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
原始码
本次制作的原始码如以下所示。
//+——————————————————————+
//| TrendlineSync.mq4 |
//| Copyright 2022, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+——————————————————————+
#property copyright “Copyright 2022, MetaQuotes Software Corp.”
#property link “https://www.mql5.com”
#property version “1.00”
#property strict
#property indicator_chart_window
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int OnInit()
{
//— indicator buffers mapping
ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| 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[])
{
//—
//— 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_OBJECT_CREATE) {
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
datetime time0 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 0);
datetime time1 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 1);
double price0 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 0);
double price1 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 1);
color clr = (color)ObjectGetInteger(0, sparam, OBJPROP_COLOR);
ENUM_LINE_STYLE style = (ENUM_LINE_STYLE)ObjectGetInteger(0, sparam, OBJPROP_STYLE);
int width = (int)ObjectGetInteger(0, sparam, OBJPROP_WIDTH);
bool back = ObjectGetInteger(0, sparam, OBJPROP_BACK);
bool ray = ObjectGetInteger(0, sparam, OBJPROP_RAY);
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
if (ObjectFind(chart_id, sparam) == -1)
TrendCreate(chart_id, sparam, 0, time0, price0, time1, price1, clr, style, width, back, ray);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
if (id == CHARTEVENT_OBJECT_DRAG) {
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
datetime time0 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 0);
datetime time1 = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME, 1);
double price0 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 0);
double price1 = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 1);
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
ObjectMove(chart_id, sparam, 0, time0, price0);
ObjectMove(chart_id, sparam, 1, time1, price1);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
if (id == CHARTEVENT_OBJECT_CHANGE) {
if (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {
color clr = (color)ObjectGetInteger(0, sparam, OBJPROP_COLOR);
ENUM_LINE_STYLE style = (ENUM_LINE_STYLE)ObjectGetInteger(0, sparam, OBJPROP_STYLE);
int width = (int)ObjectGetInteger(0, sparam, OBJPROP_WIDTH);
bool back = ObjectGetInteger(0, sparam, OBJPROP_BACK);
bool ray = ObjectGetInteger(0, sparam, OBJPROP_RAY);
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
ObjectSetInteger(chart_id, sparam, OBJPROP_COLOR, clr);
ObjectSetInteger(chart_id, sparam, OBJPROP_STYLE, style);
ObjectSetInteger(chart_id, sparam, OBJPROP_WIDTH, width);
ObjectSetInteger(chart_id, sparam, OBJPROP_BACK, back);
ObjectSetInteger(chart_id, sparam, OBJPROP_RAY, ray);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
if (id == CHARTEVENT_OBJECT_DELETE) {
if (StringFind(sparam, “Trendline “) != -1) {
long chart_id = ChartFirst();
while (true) {
if (chart_id != ChartID() && ChartSymbol(chart_id) == _Symbol) {
ObjectDelete(chart_id, sparam);
ChartRedraw(chart_id);
}
chart_id = ChartNext(chart_id);
if (chart_id < 0) break;
}
}
}
}
//+——————————————————————+
//| Create a trend line by the given coordinates |
//+——————————————————————+
bool TrendCreate(const long chart_ID = 0, // chart’s ID
const string name = “TrendLine”, // line name
const int sub_window = 0, // subwindow index
datetime time1 = 0, // first point time
double price1 = 0, // first point price
datetime time2 = 0, // second point time
double price2 = 0, // second point price
const color clr = clrRed, // line color
const ENUM_LINE_STYLE style = STYLE_SOLID, // line style
const int width = 1, // line width
const bool back = false, // in the background
const bool ray = false, // line’s continuation to the right
const bool hidden = false, // hidden in the object list
const long z_order = 0) // priority for mouse click
{
//— create a trend line by the given coordinates
if(!ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2)) {
return(false);
}
//— set line color
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//— set line display style
ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);
//— set line width
ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);
//— 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 line by mouse
//— when creating a graphical object using ObjectCreate function, the object cannot be
//— highlighted and moved by default. Inside this method, selection parameter
//— is true by default making it possible to highlight and move the object
//— enable (true) or disable (false) the mode of continuation of the line’s display to the right
ObjectSetInteger(chart_ID, name, OBJPROP_RAY, ray);
//— 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);
}
//+——————————————————————+
哪些贵金属平台好?不错的贵金属交易汇平台推荐:哪些贵金属平台好?2023年平台最新排名
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
本文相关:无相关信息
留言与评论(共有 0 条评论) |