//+------------------------------------------------------------------+ 
//|                                       Test_ChartSaveTemplate.mq4 | 
//|                        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 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; 
  }  |