SDX-TzPivots_005

Download script
Author: Copyright Shimodax
SDX-TzPivots_005

This script is designed to automatically calculate and display various technical trading levels—specifically Pivot Points, Fibonacci levels, and Camarilla levels—on a trading chart. Unlike standard indicators that might only look at the current candle, this tool is sophisticated because it allows you to define specific time zones to determine what constitutes "yesterday" or "today."

Time Zone Intelligence

The core logic begins by identifying the correct time frames for your specific needs. Because traders in different parts of the world see different times on their charts, the script includes a mechanism to convert between your local time and a "destination" time zone (such as the London or New York sessions).

It scans back through historical price data to identify exactly when the trading day began and ended for those specific zones. This ensures that if you are looking at European markets while living in Asia, the levels are calculated based on the European trading day rather than your local clock.

Key Functional Components

1. Price Data Collection Once the correct time boundaries are established, the script scans the price history to gather three critical pieces of information from the previous trading session:

  • The highest price reached (High)
  • The lowest price reached (Low)
  • The closing price (Close)

It also tracks the opening price and the real-time highs/lows of the current ongoing day.

2. Dynamic Level Calculations Using the data gathered from the previous session, the script automatically calculates several types of technical levels:

  • Pivot Points: It establishes a central "Pivot" level and several Support (S1, S2, S3) and Resistance (R1, R2, R3) levels. These are often used by traders to identify areas where the market might stall or reverse.
  • Fibonacci Levels: The script calculates various percentages (such as 38.2% and 61.8%) based on the total range of yesterday's price movement.
  • Camarilla Levels: These are specific levels derived from the closing price and the previous day's range, often used by breakout traders.
  • Midpoints & Sweet Spots: It can calculate the halfway points between various pivots and identify specific "Sweet Spots" based on current market pricing.

3. Visual Mapping The script then draws these levels directly onto your chart as horizontal lines. It handles all the heavy lifting of:

  • Drawing and moving the lines in real-time.
  • Labeling each line (e.g., "R1", "S2", "Yesterday's High") so you can identify them instantly.
  • Placing vertical markers to visually separate yesterday’s trading range from today's.

4. On-Screen Dashboard To provide a quick summary without cluttering the chart with too much text, the script generates a small data comment in the corner of your screen. This updates automatically to show you the price ranges in pips, the exact highs and lows for both yesterday and today, and the current closing price.

Summary for the User

In short, this tool automates the math required for advanced pivot analysis. By simply setting your time zones, the script does the "hunting" for the previous day's data and paints a roadmap of potential support and resistance levels on your chart, helping you visualize where key market boundaries lie based on global trading sessions.

Miscellaneous
It issuies visual alerts to the screen
10 Views
0 Downloads
0 Favorites
SDX-TzPivots_005
//+------------------------------------------------------------------+
//|                                                     TZ-Pivot.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright Shimodax"
#property link      "http://www.strategybuilderfx.com"

#property indicator_chart_window

/* Introduction:

   Calculation of pivot and similar levels based on time zones.
   If you want to modify the colors, please scroll down to line
   200 and below (where it says "Calculate Levels") and change
   the colors.  Valid color names can be obtained by placing
   the curor on a color name (e.g. somewhere in the word "Orange"
   and pressing F1).
   
   Time-Zone Inputs:

   LocalTimeZone: TimeZone for which MT4 shows your local time, 
                  e.g. 1 or 2 for Europe (GMT+1 or GMT+2 (daylight 
                  savings time).  Use zero for no adjustment.
                  
                  The MetaQuotes demo server uses GMT +2.
                  
   DestTimeZone:  TimeZone for the session from which to calculate
                  the levels (e.g. 1 or 2 for the European session
                  (without or with daylight savings time).  
                  Use zero for GMT
           
                  
   Example: If your MT server is living in the EST (Eastern Standard Time, 
            GMT-5) zone and want to calculate the levels for the London trading
            session (European time in summer GMT+1), then enter -5 for 
            LocalTimeZone, 1 for Dest TimeZone. 
            
            Please understand that the LocalTimeZone setting depends on the
            time on your MetaTrader charts (for example the demo server 
            from MetaQuotes always lives in CDT (+2) or CET (+1), no matter
            what the clock on your wall says.
           
            If in doubt, leave everything to zero.
*/


extern int LocalTimeZone= 0;
extern int DestTimeZone= 0;

extern int LineStyle= 2;
extern int LineThickness= 1;

extern bool ShowComment = true;
extern bool ShowHighLowOpen = true;
extern bool ShowSweetSpots = true;
extern bool ShowPivots = true;
extern bool ShowMidPitvot = false;
extern bool ShowFibos= false;
extern bool ShowCamarilla = false;
extern bool ShowLevelPrices = false;

extern int BarForLabels= 10;     // number of bars from right, where lines labels will be shown

extern bool DebugLogger = false;



/*
   The following doesn't work yet, please leave it to 0/24:
                  
   TradingHoursFrom: First hour of the trading session in the destination
                     time zone.
                     
   TradingHoursTo: Last hour of the trading session in the destination
                   time zone (the hour starting with this value is excluded,
                   i.e. 18 means up to 17:59 o'clock)
                   
   Example: If you are lving in the EST (Eastern Standard Time, GMT-5) 
            zone and want to calculate the levels for the London trading
            session (European time GMT+1, 08:00 - 17:00), then enter
            -5 for LocalTimeZone, 1 for Dest TimeZone, 8 for HourFrom
            and 17 for hour to.
*/

int TradingHoursFrom= 0;
int TradingHoursTo= 24;
       



//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   Print("Period= ", Period());
   return(0);
}

int deinit()
{
   int obj_total= ObjectsTotal();
   
   for (int i= obj_total; i>=0; i--) {
      string name= ObjectName(i);
    
      if (StringSubstr(name,0,7)=="[PIVOT]") 
         ObjectDelete(name);
   }
   
   return(0);
}
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   static datetime timelastupdate= 0;
   static datetime lasttimeframe= 0;
   
   datetime startofday= 0,
            startofyesterday= 0;

   double today_high= 0,
            today_low= 0,
            today_open= 0,
            yesterday_high= 0,
            yesterday_open= 0,
            yesterday_low= 0,
            yesterday_close= 0;

   int idxfirstbaroftoday= 0,
       idxfirstbarofyesterday= 0,
       idxlastbarofyesterday= 0;

   
   // no need to update these buggers too often   
   if (CurTime()-timelastupdate<60 && Period()==lasttimeframe)
      return (0);
      
   lasttimeframe= Period();
   timelastupdate= CurTime();
   
   //---- exit if period is greater than daily charts
   if(Period() > 1440) {
      Alert("Error - Chart period is greater than 1 day.");
      return(-1); // then exit
   }

   if (DebugLogger) {
      Print("Local time current bar:", TimeToStr(Time[0]));
      Print("Dest  time current bar: ", TimeToStr(Time[0]- (LocalTimeZone - DestTimeZone)*3600), ", tzdiff= ", LocalTimeZone - DestTimeZone);
   }


   // let's find out which hour bars make today and yesterday
   ComputeDayIndices(LocalTimeZone, DestTimeZone, idxfirstbaroftoday, idxfirstbarofyesterday, idxlastbarofyesterday);

   startofday= Time[idxfirstbaroftoday];  // datetime (x-value) for labes on horizontal bars
   startofyesterday= Time[idxfirstbarofyesterday];  // datetime (x-value) for labes on horizontal bars

   

   // 
   // walk forward through yestday's start and collect high/lows within the same day
   //
   yesterday_high= -99999;  // not high enough to remain alltime high
   yesterday_low=  +99999;  // not low enough to remain alltime low
   
   for (int idxbar= idxfirstbarofyesterday; idxbar>=idxlastbarofyesterday; idxbar--) {

      if (yesterday_open==0)  // grab first value for open
         yesterday_open= Open[idxbar];                      
      
      yesterday_high= MathMax(High[idxbar], yesterday_high);
      yesterday_low= MathMin(Low[idxbar], yesterday_low);
      
      // overwrite close in loop until we leave with the last iteration's value
      yesterday_close= Close[idxbar];
   }

   

   // 
   // walk forward through today and collect high/lows within the same day
   //
   today_open= Open[idxfirstbaroftoday];  // should be open of today start trading hour

   today_high= -99999; // not high enough to remain alltime high
   today_low=  +99999; // not low enough to remain alltime low
   for (int j= idxfirstbaroftoday; j>=0; j--) {
      today_high= MathMax(today_high, High[j]);
      today_low= MathMin(today_low, Low[j]);
   }
      
   
   
   // draw the vertical bars that marks the time span
   double level= (yesterday_high + yesterday_low + yesterday_close) / 3;
   SetTimeLine("YesterdayStart", "yesterday", idxfirstbarofyesterday, CadetBlue, level - 4*Point);
   SetTimeLine("YesterdayEnd", "today", idxfirstbaroftoday, CadetBlue, level - 4*Point);
   
   
   
   if (DebugLogger) 
      Print("Timezoned values: yo= ", yesterday_open, ", yc =", yesterday_close, ", yhigh= ", yesterday_high, ", ylow= ", yesterday_low, ", to= ", today_open);


   //
   //---- Calculate Levels
   //
   double p, q, d, r1,r2,r3, s1,s2,s3;
   
   d = (today_high - today_low);
   q = (yesterday_high - yesterday_low);
   p = (yesterday_high + yesterday_low + yesterday_close) / 3;
   
   r1 = (2*p)-yesterday_low;
   r2 = p+(yesterday_high - yesterday_low);              //	r2 = p-s1+r1;
	r3 = (2*p)+(yesterday_high-(2*yesterday_low));
   s1 = (2*p)-yesterday_high;
   s2 = p-(yesterday_high - yesterday_low);              //	s2 = p-r1+s1;
	s3 = (2*p)-((2* yesterday_high)-yesterday_low);


   //---- High/Low, Open
   if (ShowHighLowOpen) {
      SetLevel("Y\'s High", yesterday_high,  Orange, LineStyle, LineThickness, startofyesterday);
      SetLevel("T\'s Open", today_open,      Orange, LineStyle, LineThickness, startofday);
      SetLevel("Y\'s Low", yesterday_low,    Orange, LineStyle, LineThickness, startofyesterday);
   }

   //---- High/Low, Open
   if (ShowSweetSpots) {
      int ssp1, ssp2;
      double ds1, ds2;
      
      ssp1= Bid / Point;
      ssp1= ssp1 - ssp1%50;
      ssp2= ssp1 + 50;
      
      ds1= ssp1*Point;
      ds2= ssp2*Point;
      
      SetLevel(DoubleToStr(ds1,Digits), ds1,  Gold, LineStyle, LineThickness, Time[10]);
      SetLevel(DoubleToStr(ds2,Digits), ds2,  Gold, LineStyle, LineThickness, Time[10]);
   }

   //---- Pivot Lines
   if (ShowPivots==true) {
      SetLevel("R1", r1,      Blue, LineStyle, LineThickness, startofday);
      SetLevel("R2", r2,      Blue, LineStyle, LineThickness, startofday);
      SetLevel("R3", r3,      Blue, LineStyle, LineThickness, startofday);
      
      SetLevel("Pivot", p,    Magenta, LineStyle, LineThickness, startofday);

      SetLevel("S1", s1,      Red, LineStyle, LineThickness, startofday);
      SetLevel("S2", s2,      Red, LineStyle, LineThickness, startofday);
      SetLevel("S3", s3,      Red, LineStyle, LineThickness, startofday);
   }
   
   //---- Fibos of yesterday's range
   if (ShowFibos) {
      // .618, .5 and .382
      SetLevel("Low - 61.8%", yesterday_low - q*0.618,      Yellow, LineStyle, LineThickness, startofday);
      SetLevel("Low - 38.2%", yesterday_low - q*0.382,      Yellow, LineStyle, LineThickness, startofday);
      SetLevel("Low + 38.2%", yesterday_low + q*0.382,      Yellow, LineStyle, LineThickness, startofday);
      SetLevel("LowHigh 50%", yesterday_low + q*0.5,        Yellow, LineStyle, LineThickness, startofday);
      SetLevel("High - 38.2%", yesterday_high - q*0.382,    Yellow, LineStyle, LineThickness, startofday);
      SetLevel("High + 38.2%", yesterday_high + q*0.382,    Yellow, LineStyle, LineThickness, startofday);
      SetLevel("High + 61.8%", yesterday_high +  q*0.618,   Yellow, LineStyle, LineThickness, startofday);
   }


   //----- Camarilla Lines
   if (ShowCamarilla==true) {
      
      double h4,h3,l4,l3;
	   h4 = (q*0.55)+yesterday_close;
	   h3 = (q*0.27)+yesterday_close;
	   l3 = yesterday_close-(q*0.27);	
	   l4 = yesterday_close-(q*0.55);	
	   
      SetLevel("H3", h3,   Khaki, LineStyle, LineThickness, startofday);
      SetLevel("H4", h4,   Khaki, LineStyle, LineThickness, startofday);
      SetLevel("L3", l3,   Khaki, LineStyle, LineThickness, startofday);
      SetLevel("L4", l4,   Khaki, LineStyle, LineThickness, startofday);
   }


   //------ Midpoints Pivots 
   if (ShowMidPitvot==true) {
      // mid levels between pivots
      SetLevel("MR3", (r2+r3)/2,    Green, LineStyle, LineThickness, startofday);
      SetLevel("MR2", (r1+r2)/2,    Green, LineStyle, LineThickness, startofday);
      SetLevel("MR1", (p+r1)/2,     Green, LineStyle, LineThickness, startofday);
      SetLevel("MS1", (p+s1)/2,     Green, LineStyle, LineThickness, startofday);
      SetLevel("MS2", (s1+s2)/2,    Green, LineStyle, LineThickness, startofday);
      SetLevel("MS3", (s2+s3)/2,    Green, LineStyle, LineThickness, startofday);
   }


   //------ Comment for upper left corner
   if (ShowComment) {
      string comment= ""; 
      
      comment= comment + "-- Good luck with your trading! ---\n";
      comment= comment + "Range: Yesterday "+DoubleToStr(MathRound(q/Point),0)   +" pips, Today "+DoubleToStr(MathRound(d/Point),0)+" pips" + "\n";
      comment= comment + "Highs: Yesterday "+DoubleToStr(yesterday_high,Digits)  +", Today "+DoubleToStr(today_high,Digits) +"\n";
      comment= comment + "Lows:  Yesterday "+DoubleToStr(yesterday_low,Digits)   +", Today "+DoubleToStr(today_low,Digits)  +"\n";
      comment= comment + "Close: Yesterday "+DoubleToStr(yesterday_close,Digits) + "\n";
   // comment= comment + "Pivot: " + DoubleToStr(p,Digits) + ", S1/2/3: " + DoubleToStr(s1,Digits) + "/" + DoubleToStr(s2,Digits) + "/" + DoubleToStr(s3,Digits) + "\n" ;
   // comment= comment + "Fibos: " + DoubleToStr(yesterday_low + q*0.382, Digits) + ", " + DoubleToStr(yesterday_high - q*0.382,Digits) + "\n";
      
      Comment(comment); 
   }

   return(0);
}

 
//+------------------------------------------------------------------+
//| Compute index of first/last bar of yesterday and today           |
//+------------------------------------------------------------------+
void ComputeDayIndices(int tzlocal, int tzdest, int &idxfirstbaroftoday, int &idxfirstbarofyesterday, int &idxlastbarofyesterday)
{     
   int tzdiff= tzlocal - tzdest,
       tzdiffsec= tzdiff*3600,
       dayminutes= 24 * 60,
       barsperday= dayminutes/Period();
   
   int dayofweektoday= TimeDayOfWeek(Time[0] - tzdiffsec),  // what day is today in the dest timezone?
       dayofweektofind= -1; 

   //
   // due to gaps in the data, and shift of time around weekends (due 
   // to time zone) it is not as easy as to just look back for a bar 
   // with 00:00 time
   //
   
   idxfirstbaroftoday= 0;
   idxfirstbarofyesterday= 0;
   idxlastbarofyesterday= 0;
       
   switch (dayofweektoday) {
      case 6: // sat
      case 0: // sun
      case 1: // mon
            dayofweektofind= 5; // yesterday in terms of trading was previous friday
            break;
            
      default:
            dayofweektofind= dayofweektoday -1; 
            break;
   }
   
   if (DebugLogger) {
      Print("Dayofweektoday= ", dayofweektoday);
      Print("Dayofweekyesterday= ", dayofweektofind);
   }
       
       
   // search  backwards for the last occrrence (backwards) of the day today (today's first bar)
   for (int i=1; i<=barsperday+1; i++) {
      datetime timet= Time[i] - tzdiffsec;
      if (TimeDayOfWeek(timet)!=dayofweektoday) {
         idxfirstbaroftoday= i-1;
         break;
      }
   }
   

   // search  backwards for the first occrrence (backwards) of the weekday we are looking for (yesterday's last bar)
   for (int j= 0; j<=2*barsperday+1; j++) {
      datetime timey= Time[i+j] - tzdiffsec;
      if (TimeDayOfWeek(timey)==dayofweektofind) {  // ignore saturdays (a Sa may happen due to TZ conversion)
         idxlastbarofyesterday= i+j;
         break;
      }
   }


   // search  backwards for the first occurrence of weekday before yesterday (to determine yesterday's first bar)
   for (j= 1; j<=barsperday; j++) {
      datetime timey2= Time[idxlastbarofyesterday+j] - tzdiffsec;
      if (TimeDayOfWeek(timey2)!=dayofweektofind) {  // ignore saturdays (a Sa may happen due to TZ conversion)
         idxfirstbarofyesterday= idxlastbarofyesterday+j-1;
         break;
      }
   }


   if (DebugLogger) {
      Print("Dest time zone\'s current day starts:", TimeToStr(Time[idxfirstbaroftoday]), 
                                                      " (local time), idxbar= ", idxfirstbaroftoday);

      Print("Dest time zone\'s previous day starts:", TimeToStr(Time[idxfirstbarofyesterday]), 
                                                      " (local time), idxbar= ", idxfirstbarofyesterday);
      Print("Dest time zone\'s previous day ends:", TimeToStr(Time[idxlastbarofyesterday]), 
                                                      " (local time), idxbar= ", idxlastbarofyesterday);
   }
}


//+------------------------------------------------------------------+
//| Helper                                                           |
//+------------------------------------------------------------------+
void SetLevel(string text, double level, color col1, int linestyle, int thickness, datetime startofday)
{
   int digits= Digits;
   string labelname= "[PIVOT] " + text + " Label",
          linename= "[PIVOT] " + text + " Line",
          pricelabel; 

   // create or move the horizontal line   
   if (ObjectFind(linename) != 0) {
      ObjectCreate(linename, OBJ_TREND, 0, startofday, level, Time[0],level);
      ObjectSet(linename, OBJPROP_STYLE, linestyle);
      ObjectSet(linename, OBJPROP_COLOR, col1);
      ObjectSet(linename, OBJPROP_WIDTH, thickness);
   }
   else {
      ObjectMove(linename, 1, Time[0],level);
      ObjectMove(linename, 0, startofday, level);
   }
   

   // put a label on the line   
   if (ObjectFind(labelname) != 0) {
      ObjectCreate(labelname, OBJ_TEXT, 0, MathMin(Time[BarForLabels], startofday + 2*Period()*60), level);
   }
   else {
      ObjectMove(labelname, 0, MathMin(Time[BarForLabels], startofday+2*Period()*60), level);
   }

   pricelabel= " " + text;
   if (ShowLevelPrices && StrToInteger(text)==0) 
      pricelabel= pricelabel + ": "+DoubleToStr(level, Digits);
   
   ObjectSetText(labelname, pricelabel, 8, "Arial", White);
}
      

//+------------------------------------------------------------------+
//| Helper                                                           |
//+------------------------------------------------------------------+
void SetTimeLine(string objname, string text, int idx, color col1, double vleveltext) 
{
   string name= "[PIVOT] " + objname;
   int x= Time[idx];

   if (ObjectFind(name) != 0) 
      ObjectCreate(name, OBJ_TREND, 0, x, 0, x, 100);
   else {
      ObjectMove(name, 0, x, 0);
      ObjectMove(name, 1, x, 100);
   }
   
   ObjectSet(name, OBJPROP_STYLE, STYLE_DOT);
   ObjectSet(name, OBJPROP_COLOR, DarkGray);
   
   if (ObjectFind(name + " Label") != 0) 
      ObjectCreate(name + " Label", OBJ_TEXT, 0, x, vleveltext);
   else
      ObjectMove(name + " Label", 0, x, vleveltext);
            
   ObjectSetText(name + " Label", text, 8, "Arial", col1);
}

Comments