首页 > 提升投资报酬 > 量化分析

在复数图表中同步趋势线图式的方法

量化分析 2023-09-14 10:30:23

检测对象的新增与删除


在本篇章节中,将介绍在复数图表中同步趋势线的方法。具体来说,便是在设定指针的图表中制作新趋势线时,于其他图表产生相同的绘制动作。

首先在制作新档案中选择「自定义指标」,并将文件名设定为「TrendlineSync」,无需新增参数即可移至下一步;在「自定义指针程序的的事件处理程序」中勾选「OnChartEvent」,点击「完成」即可呈现雏形。

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 (ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_TREND) {

}

}
在此if文体中追加趋势线的相关编码。此处复制并使用MQL4帮助文件中的样本编码;在MQL4帮助文件目录中,点击「Constants, Enumerations and Structures」→「Objects Constants」→「Object Types」便会出现对象一览,从中选择「OBJ_TREND」之后,复制并贴上预先准备的下列编码。
 
//+——————————————————————+

//| 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);

}
复制后,可以删除以下不需要的9行。
 
const bool selection=true, // highlight to move

//— 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);
接下来,将「hidden = true」变更为「hidden = false」,2处「ray_right」变更为「ray」,「OBJPROP_RAY_RIGHT」则改为「OBJPROP_RAY」;如此便完成了趋势线样本编码的准备。顺道一提,「OBJPROP_RAY_RIGHT」是MT5用的指示。
 
//+——————————————————————+

//| 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) {

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);

}

}
其后,将此部分的编码如下所示进行改写。如欲取得趋势线的状态,便应将「ObjectSetInteger」全数替换为「ObjectGetInteger」,并设定「OBJPROP_TIME」以获取时间信息、设定「OBJPROP_PRICE」以获取价格信息。
 
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();

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;

}
上列编码的目的为同步图表范围,故此处将替换为同步趋势线。首先将范围相关的「if (ChartGetInteger(chart_id, CHART_SCALE) != scale) {」「ChartSetInteger(chart_id, CHART_SCALE, scale);」2行予以删除。

本次将从第一项图表开始依序取得信息;在每一次进展时,使用「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 条评论)
验证码:

免责声明

特别提示:根据《关于严厉查处非法外汇期货和外汇按金交易活动的通知》(证监发字[1978]105号)规定凡未经批准的机构在大陆境内擅自开展外汇期货交易均属非法,提高意识,谨防损失!

本网站所有刊登内容,以及所提供的信息资料,目的是为了更好地服务我们的访问者,本网站不保证所有信息、文本、图形、链接及其它项目的绝对准确性和完整性,网站没有任何盈利目的,故仅供访问者参照使用。本网站已尽力确保所有资料是准确、完整及最新的。就该资料的针对性、精确性以及特定用途的适合性而言,本网站不能作出最对应的方案。所以因依赖该资料所致的任何损失,本网均不负责。 除特别注明之服务条款外,其他一切因使用本站而引致的任何意外、疏忽、合约毁坏、隐秘汇漏、诽谤、版权或知识产权侵犯及其所造成的损失,本站概不负责,亦不承担任何法律责任。如您(单位或个人)认为本网站某部分内容有侵权嫌疑,敬请立即通知我们,我们将在第一时间予以更改或删除。以上声明之解释权归牛犇财经网站所有。法律上有相关解释的,以中国法律之解释为基准。如有争议限在我方所在地司法部门解决。