//+——————————————————————+ //| Test_ChartSaveTemplate.mq4 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+——————————————————————+ #property copyright “Copyright 2011, MetaQuotes Software Corp.” #property link “https://www.mql5.com” #property version “1.00” #property script_show_inputs //— input parameters input string symbol=“GBPUSD”; // The symbol of a new chart input ENUM_TIMEFRAMES period=PERIOD_H3; // The timeframe of a new chart //+——————————————————————+ //| Script program start function | //+——————————————————————+ void OnStart() { //— First attach indicators to the chart int handle; //— Prepare the indicator for use if(!PrepareZigzag(NULL,0,handle)) return; // Failed, so exit //— Attach the indicator to the current chart, but in a separate window. 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()); //— Terminate the program operation return; } //— Refresh the chart to see the indicator ChartRedraw(); //— Find the last two last fractures of the zigzag double two_values[]; datetime two_times[]; if(!GetLastTwoFractures(two_values,two_times,handle)) { PrintFormat(“Failed to find two last fractures in the Zigzag!”); //— Terminate the program operation return; } //— Now attach a standard deviation channel 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 { //— The channel has been created, define the second point ObjectSetInteger(0,channel,OBJPROP_TIME,1,two_times[0]); //— Set a tooltip text for the channel ObjectSetString(0,channel,OBJPROP_TOOLTIP,“Demo from MQL4 Help”); //— Refresh the chart ChartRedraw(); } //— Save the result in a template ChartSaveTemplate(0,“StdDevChannelOnZigzag”); //— Open a new chart and apply a saved template to it long new_chart=ChartOpen(symbol,period); //— Enable tooltips for graphical objects ChartSetInteger(new_chart,CHART_SHOW_OBJECT_DESCR,true); if(new_chart!=0) { //— Apply the saved template to a chart ChartApplyTemplate(new_chart,“StdDevChannelOnZigzag”); } Sleep(10000); } //+——————————————————————+ //| Creates a zigzag handle and ensures readiness of its data | //+——————————————————————+ bool PrepareZigzag(string sym,ENUM_TIMEFRAMES tf,int &h) { ResetLastError(); //— The Zigzag indicator must be located in terminal_data_folder\MQL4\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; } //— When creating an indicator handle, it requires time to calculate values int k=0; // The number of attempts to wait for the indicator calculation //— Wait for the calculation in a loop, pausing to 50 milliseconds if the calculation is not yet ready while(BarsCalculated(h)<=0) { k++; //— Show the number of attempts PrintFormat(“%s: k=%d”,__FUNCTION__,k); //— Wait 50 milliseconds to wait until the indicator is calculated Sleep(50); //— If more than 100 attempt, then something is wrong if(k>100) { //— Report a problem PrintFormat(“Failed to calculate the indicator for %d attempts!”); //— Terminate the program operation return false; } } //— Everything is ready, the indicator is created and values are calculated return true; } //+——————————————————————+ //| Searches for the last 2 zigzag fractures and places to arrays | //+——————————————————————+ bool GetLastTwoFractures(double &get_values[],datetime &get_times[],int handle) { double values[]; // An array for the values of the zigzag datetime times[]; // An array to get time int size=100; // Size of the array ResetLastError(); //— Copy the last 100 values of the indicator int copied=CopyBuffer(handle,0,0,size,values); //— Check the number of values copied 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; } //— Define the order of access to the array as in a timeseries ArraySetAsSeries(values,true); //— Write here the numbers of bars, in which fractures were found int positions[]; //— Set array sizes ArrayResize(get_values,3); ArrayResize(get_times,3); ArrayResize(positions,3); //— Counters int i=0,k=0; //— Start to search for fractures while(i<100) { double v=values[i]; //— We are not interested in empty values if(v!=0.0) { //— Remember the bar number positions[k]=i; //— Remember the value of a zigzag on the fracture get_values[k]=values[i]; PrintFormat(“%s: Zigzag[%d]=%G”,__FUNCTION__,i,values[i]); //— Increase the counter k++; //— If two fractures found, break the loop if(k>2) break; } i++; } //— Define the order of access to the arrays as in a timeseries 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; } //— Open the bar open time, on which the last 2 fractures occurred get_times[0]=times[positions[1]];// The last but one value will be written as the first fracture get_times[1]=times[positions[2]];// The value third from the end will be the second fracture PrintFormat(“%s: first=%s, second=%s”,__FUNCTION__,TimeToString(get_times[1]),TimeToString(get_times[0])); //— Successful return true; } |