//+------------------------------------------------------------------+
//| Test_ChartSaveTemplate.mq5 |
//| Copyright 2011, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property script_show_inputs
//--- 输入参数
input string symbol="GBPUSD"; // 新图表的交易品种
input ENUM_TIMEFRAMES period=PERIOD_H3; // 新图表的时间帧
//+------------------------------------------------------------------+
//| 脚本程序起始函数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 首先附加指标到图表
int handle;
//--- 准备使用指标
if(!PrepareZigzag(NULL,0,handle)) return; // 失败,所以退出
//--- 附加指标到当前图表,但是在独立窗口。
if(!ChartIndicatorAdd(0,1,handle))
{
PrintFormat("Failed to attach to chart %s/%s an indicator with the handle=%d. Error code %d",
_Symbol,
EnumToString(_Period),
handle,
GetLastError());
//--- 终止程序操作
return;
}
//--- 刷新图表看指标
ChartRedraw();
//--- 找出最近两个Z字形断裂
double two_values[];
datetime two_times[];
if(!GetLastTwoFractures(two_values,two_times,handle))
{
PrintFormat("Failed to find two last fractures in the Zigzag!");
//--- 终止程序操作
return;
}
//--- 现在附加标准偏差通道
string channel="StdDeviation Channel";
if(!ObjectCreate(0,channel,OBJ_STDDEVCHANNEL,0,two_times[1],0))
{
PrintFormat("Failed to create object %s. Error code %d",
EnumToString(OBJ_STDDEVCHANNEL),GetLastError());
return;
}
else
{
//--- 通道已经创建,定义第二点
ObjectSetInteger(0,channel,OBJPROP_TIME,1,two_times[0]);
//--- 为通道设置提示工具文本
ObjectSetString(0,channel,OBJPROP_TOOLTIP,"Demo from MQL5 Help");
//--- 刷新图表
ChartRedraw();
}
//--- 在模板中保存结果
ChartSaveTemplate(0,"StdDevChannelOnZigzag");
//--- 打开新图表并应用保存的模板
long new_chart=ChartOpen(symbol,period);
//--- 启用图形对象的工具提示
ChartSetInteger(new_chart,CHART_SHOW_OBJECT_DESCR,true);
if(new_chart!=0)
{
//--- 将保存的模板应用到图表
ChartApplyTemplate(new_chart,"StdDevChannelOnZigzag");
}
Sleep(10000);
}
//+------------------------------------------------------------------+
//| 创建Z字形句柄并确保其数据准备就绪 |
//+------------------------------------------------------------------+
bool PrepareZigzag(string sym,ENUM_TIMEFRAMES tf,int &h)
{
ResetLastError();
//--- Z字形指标必须位于terminal_data_folder\MQL5\Examples
h=iCustom(sym,tf,"Examples\\Zigzag");
if(h==INVALID_HANDLE)
{
PrintFormat("%s: Failed to create the handle of the Zigzag indicator. Error code %d",
__FUNCTION__,GetLastError());
return false;
}
//--- 创建指标句柄时,它需要时间计算价值
int k=0; // 等候指标计算的尝试数量
//--- 等候循环计算,如果计算还未做好准备,暂停50毫秒
while(BarsCalculated(h)<=0)
{
k++;
//--- 显示尝试的数量
PrintFormat("%s: k=%d",__FUNCTION__,k);
//--- 等候50毫秒,直至指标被计算
Sleep(50);
//--- 如果尝试超过100次,那么有些事情就是错误的
if(k>100)
{
//--- 报告问题
PrintFormat("Failed to calculate the indicator for %d attempts!");
//--- 终止程序操作
return false;
}
}
//--- 一切做好准备,指标被创建,价值被计算
return true;
}
//+------------------------------------------------------------------+
//| 搜索最近的2个Z字形断裂,置于数组 |
//+------------------------------------------------------------------+
bool GetLastTwoFractures(double &get_values[],datetime &get_times[],int handle)
{
double values[]; // Z字形价值的数组
datetime times[]; // 获得时间的数组
int size=100; // 数组大小
ResetLastError();
//--- 复制指标最近的100值
int copied=CopyBuffer(handle,0,0,size,values);
//--- 检查复制值的数量
if(copied<100)
{
PrintFormat("%s: Failed to copy %d values of the indicator with the handle=%d. Error code %d",
__FUNCTION__,size,handle,GetLastError());
return false;
}
//--- 按照时间序列定义访问数组的顺序
ArraySetAsSeries(values,true);
//--- 在这里写下断裂处的柱形数量
int positions[];
//--- 设置数组大小
ArrayResize(get_values,3); ArrayResize(get_times,3); ArrayResize(positions,3);
//--- 计数器
int i=0,k=0;
//--- 开始搜索断裂处
while(i<100)
{
double v=values[i];
//--- 我们对空值不感兴趣W
if(v!=0.0)
{
//--- 记住柱形数
positions[k]=i;
//--- 记住断裂上的Z字形值
get_values[k]=values[i];
PrintFormat("%s: Zigzag[%d]=%G",__FUNCTION__,i,values[i]);
//--- 增加计数器
k++;
//--- 如果找到两个断裂,中断循环
if(k>2) break;
}
i++;
}
//--- 按照时间序列定义访问数组的顺序
ArraySetAsSeries(times,true); ArraySetAsSeries(get_times,true);
if(CopyTime(_Symbol,_Period,0,size,times)<=0)
{
PrintFormat("%s: Failed to copy %d values from CopyTime(). Error code %d",
__FUNCTION__,size,GetLastError());
return false;
}
//--- 打开柱形图的开盘时间,在这上面出现最近的2个断裂
get_times[0]=times[positions[1]];// 倒数第二个值将被写成第一个断裂
get_times[1]=times[positions[2]];// 倒数第三个值将是第二个断裂
PrintFormat("%s: first=%s, second=%s",__FUNCTION__,TimeToString(get_times[1]),TimeToString(get_times[0]));
//--- 成功
return true;
}
|