Trace_History

Download script
Author: Copyright � 2008, LEGRUPO.
Trace_History

This script functions as a visual data overlay for the MetaTrader 4 platform, designed to translate external economic news data into actionable visual cues on a trading chart. Rather than calculating mathematical trends based on price action alone, this tool focuses on "Event Correlation"—mapping out historical or scheduled economic announcements so that traders can see exactly where market-moving news occurred in relation to price movements.

Core Operational Logic

Data Integration and Filtering The script begins by reading an external CSV file (a spreadsheet of news events). It acts as a sophisticated filter, allowing the user to customize what information is displayed based on several criteria:

  • Date Range: Only news occurring between a specific start and end date is processed.
  • Impact Level: Users can choose to display only high-impact events (e.g., central bank decisions), medium-impact events, or low-impact events.
  • Currency Specificity: The script identifies which currencies are affected by an event (such as USD, EUR, or GBP) and will only show those icons on relevant charts.
  • Timeframe Visibility: It can be configured to hide or show data based on the specific chart period you are currently viewing (e.g., M15 vs. H4).

Visual Mapping and Organization Once the data passes through these filters, the script performs several automated actions to organize the visual layout:

  • Dynamic Positioning: If multiple news events occur at the exact same time, the script automatically offsets them vertically (spacing them out) so they do not overlap, ensuring every piece of data remains legible.
  • Iconography and Color Coding: The script assigns specific visual identities to events based on their severity. Typically, these are color-coded (e.g., Red for High Impact, Orange for Medium, Yellow for Low). It also uses unique symbols (Wingdings) to represent different currencies.
  • Data Labeling: For every event plotted, the script can display descriptive text, such as the description of the news event and specific data points like "Actual," "Forecast," and "Previous" values.

Automated Cleanup To maintain a clean workspace, the script includes a management routine that automatically removes all the drawn icons and text labels from the chart the moment the indicator is turned off or removed. This ensures that your chart remains uncluttered when the tool is not in active use.

Price Data Components
Series array that contains the lowest prices of each barSeries array that contains the highest prices of each bar
Miscellaneous
Implements a curve of type %1Uses files from the file systemIt reads information from a fileIt writes information to file
12 Views
0 Downloads
0 Favorites
Trace_History
//+------------------------------------------------------------------+
//|                                        _US-HEDGE_CloseOrders.mq4 |
//|                                       Copyright © 2008, LEGRUPO. |
//|                                           http://www.legrupo.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, LEGRUPO."
#property link      "http://www.legrupo.com"

#property indicator_chart_window

// NEWS.CSV file must exist in: \metatrader 4\experts\files
extern   string   FileName          = "gbpjpy_2007.csv";   // News file name
extern   int      VertSpacing       = 5;            // # pips spacing between symbols plotted against same bar
extern   int      SymbolSize        = 2;            // size of symbols being plotted on the chart

// Filters (set parameter to FALSE to suppress plot):
extern   datetime FromDate          = D'2007.12.01 00:00';
extern   datetime ThruDate          = D'2007.12.31 23:59';
extern   bool     Plot_High         = TRUE;         // High impact   = 3 (red plot)
extern   bool     Plot_Medium       = TRUE;         // Medium impact = 2 (orange plot)
extern   bool     Plot_Low          = TRUE;         // Low impact    = 1 (yellow plot)
extern   bool     Plot_USD          = TRUE;         // USD = 1 (wingding character #140)
extern   bool     Plot_CAD          = TRUE;         // CAD = 2 (wingding character #141)
extern   bool     Plot_EUR          = TRUE;         // EUR = 3 (wingding character #142)
extern   bool     Plot_GBP          = TRUE;         // GBP = 4 (wingding character #143)
extern   bool     Plot_CHF          = TRUE;         // CHF = 5 (wingding character #144)
extern   bool     Plot_JPY          = TRUE;         // JPY = 6 (wingding character #145)
extern   bool     Plot_AUD          = TRUE;         // AUD = 7 (wingding character #146)
extern   bool     Plot_NZD          = TRUE;         // NZD = 8 (wingding character #147)

int      handle;

int      eCount;              // Event counter
datetime eTime[9999];         // Event date/time, format = yyyy.mm.dd<space>hh:mm
int      eNumber[9999];       // Event seq# (same date/time use ascending seq#s)
int      eWingding[9999];     // Wingding code for implicated currency, as above
int      eImpact[9999];       // 1=low impact; 2=medium impact; 3=high impact
string   eCurrency[9999];     // Currency/ies on whose charts object will display; ALL = all currencies 
string   ePeriods[9999];      // Time period settings on which object will display (M1,M5,M15,M30,H1,H4,D1,W1,MTH; 0=no, 1=yes)
string   eText1[9999];        // First descr line, format = hh:mm XXX Y "event description"
                              //   where XXX=currency; Y=H/M/L impact
string   eText2[9999];        // Second descr line, shows Actual, Forecast, Previous values

//----
extern color color1 = Red;
extern color color2 = White;
extern color color3 = Red;
extern color color4 = White;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
SetIndexStyle(0,DRAW_HISTOGRAM, 0, 1, color1);
   SetIndexBuffer(0, ExtMapBuffer1);
   SetIndexStyle(1,DRAW_HISTOGRAM, 0, 1, color2);
   SetIndexBuffer(1, ExtMapBuffer2);
   SetIndexStyle(2,DRAW_HISTOGRAM, 0, 3, color3);
   SetIndexBuffer(2, ExtMapBuffer3);
   SetIndexStyle(3,DRAW_HISTOGRAM, 0, 3, color4);
   SetIndexBuffer(3, ExtMapBuffer4);
//----
   SetIndexDrawBegin(0,10);
   SetIndexDrawBegin(1,10);
   SetIndexDrawBegin(2,10);
   SetIndexDrawBegin(3,10);
//---- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexBuffer(2,ExtMapBuffer3);
   SetIndexBuffer(3,ExtMapBuffer4);
//---- initialization done

//---- indicators

   string objname, sym1, sym2, cmp1, cmp2;
   int    barno, dir1, h;
   double vertpos;

   handle = FileOpen(FileName, FILE_CSV|FILE_READ,',');          // Open NEWS.CSV
   if(handle < 1) {
      Comment("File "+FileName+" not found.");
   }
   double haOpen, haHigh, haLow, haClose;
   string output = "From "+TimeToStr(FromDate)+" to "+TimeToStr(ThruDate)+":\n";
   Comment("");
   while ( !FileIsEnding(handle)) 
   {
      string date = FileReadString(handle);
      string time = FileReadString(handle);
      double open = StrToDouble(FileReadString(handle));
      double high = StrToDouble(FileReadString(handle));
      double low  = StrToDouble(FileReadString(handle));
      double close = StrToDouble(FileReadString(handle));
      int volume  = StrToInteger(FileReadString(handle));
      //Comment(date,",",time,",",open,",",high,",",low,",",close,",",volume);
      haOpen=(ExtMapBuffer3[h+1]+ExtMapBuffer4[h+1])/2;
      haClose=(Open[h]+High[h]+Low[h]+Close[h])/4;
      haHigh=MathMax(High[h], MathMax(haOpen, haClose));
      haLow=MathMin(Low[h], MathMin(haOpen, haClose));
      //Comment(date,",",time,",",haOpen,",",haHigh,",",haLow,",",haClose,",",volume);
      
      // here we plot objects based on configuration
      //if ((StringFind(date, "11|12") > 0)) {
      if (StrToTime(date+" "+time) >= FromDate && StrToTime(date+" "+time) <= ThruDate) {
         output = output+ "Date: "+date+" ";
         output = output+ "Open: "+NormalizeDouble(open, Digits)+" ";
         output = output+ "High: "+NormalizeDouble(high, Digits)+" ";
         output = output+ "Low: "+NormalizeDouble(low, Digits)+" ";
         output = output+ "Close:  "+NormalizeDouble(close, Digits)+"\n";
         Comment(output);
      }
      
      
      if (haOpen<haClose) 
        {
         ExtMapBuffer1[h]=haLow;
         ExtMapBuffer2[h]=haHigh;
        } 
      else
        {
         ExtMapBuffer1[h]=haHigh;
         ExtMapBuffer2[h]=haLow;
        } 
      ExtMapBuffer3[h]=haOpen;
      ExtMapBuffer4[h]=haClose;
      h++;
   }
   FileClose(handle);

   /*for(eCount = 0; !FileIsEnding(handle); eCount++)              // Read from NEWS.CSV; one line per event
   {
      eTime[eCount]     = StrToTime(FileReadString(handle));     // Event date/time
      eNumber[eCount]   = StrToInteger(FileReadString(handle));  // Event seq# (same date/time have ascending seq#s)
      eWingding[eCount] = StrToInteger(FileReadString(handle));  // Wingding code denoting implicated currency
      eImpact[eCount]   = StrToInteger(FileReadString(handle));  // Impact: 1=low; 2=medium; 3=High
      eCurrency[eCount] = FileReadString(handle);                // Currency/ies on whose charts object will display; ALL = all currencies
      ePeriods[eCount]  = FileReadString(handle);                // Time period settings on which object will display (M1,M5,M15,M30,H1,H4,D1,W1,MTH; 0=no, 1=yes)
      eText1[eCount]    = FileReadString(handle);                // First line of description
      eText2[eCount]    = FileReadString(handle);                // Second line of description

      if (eNumber[eCount] == 0 )      continue;                  // Invalid entry, or EOF
//    if (eWingding[eCount] == 0 )    continue;
//    if (eImpact[eCount] == 0 )      continue;

      if (eTime[eCount] < FromDate) continue;                    // Skip if outside entered date range
      if (eTime[eCount] > ThruDate) continue;
      
      if (eImpact[eCount] == 1 && Plot_Low == FALSE)    continue;                     // Skip if impact outside entered values
      if (eImpact[eCount] == 2 && Plot_Medium == FALSE) continue;
      if (eImpact[eCount] == 3 && Plot_High == FALSE)   continue;
      
      if (eWingding[eCount] == 140 && Plot_USD == FALSE)   continue;                  // Skip if currency outside entered values
      if (eWingding[eCount] == 141 && Plot_CAD == FALSE)   continue;
      if (eWingding[eCount] == 142 && Plot_EUR == FALSE)   continue;
      if (eWingding[eCount] == 143 && Plot_GBP == FALSE)   continue;
      if (eWingding[eCount] == 144 && Plot_CHF == FALSE)   continue;
      if (eWingding[eCount] == 145 && Plot_JPY == FALSE)   continue;
      if (eWingding[eCount] == 146 && Plot_AUD == FALSE)   continue;
      if (eWingding[eCount] == 147 && Plot_NZD == FALSE)   continue;

      if ( StringSubstr(ePeriods[eCount],0,1) == "0" && Period() == PERIOD_M1  )   continue;    // Skip if not to be shown on this period's chart
      if ( StringSubstr(ePeriods[eCount],1,1) == "0" && Period() == PERIOD_M5  )   continue;
      if ( StringSubstr(ePeriods[eCount],2,1) == "0" && Period() == PERIOD_M15 )   continue;
      if ( StringSubstr(ePeriods[eCount],3,1) == "0" && Period() == PERIOD_M30 )   continue;
      if ( StringSubstr(ePeriods[eCount],4,1) == "0" && Period() == PERIOD_H1  )   continue;
      if ( StringSubstr(ePeriods[eCount],5,1) == "0" && Period() == PERIOD_H4  )   continue;
      if ( StringSubstr(ePeriods[eCount],6,1) == "0" && Period() == PERIOD_D1  )   continue;
      if ( StringSubstr(ePeriods[eCount],7,1) == "0" && Period() == PERIOD_W1  )   continue;
      if ( StringSubstr(ePeriods[eCount],8,1) == "0" && Period() == PERIOD_MN1 )   continue;

      bool skipflag = FALSE;                                                          // Skip if currency outside entered values
      if (eCurrency[eCount] != "ALL")
        {
          skipflag = TRUE;
          sym1 = StringSubstr(Symbol(),0,3);
          sym2 = StringSubstr(Symbol(),3,3);
          cmp1 = StringSubstr(eCurrency[eCount],0,3);
          if (StringLen(eCurrency[eCount]) > 3) 
          {
            cmp2 = StringSubstr(eCurrency[eCount],3,3);
            if ((cmp1 == "ALL" || cmp1 == sym1 || cmp1 == sym2) && (cmp2 == "ALL" || cmp2 == sym1 || cmp2 == sym2)) skipflag = FALSE;   
          }
          else
          {
            if (cmp1 == "ALL" || cmp1 == sym1 || cmp1 == sym2) skipflag = FALSE;   
          }  
        }
      if (skipflag == TRUE) continue;  

      objname = eText1[eCount];                                                       // Set object name = first descr line
      barno = iBarShift(NULL,0,eTime[eCount],FALSE);                                  // Number of bars back from current
//    if (eWingding[eCount] == 0) barno++;

      dir1 = 1;
      if (eNumber[eCount] < 0) dir1 = -1;
      
      if (VertSpacing * eNumber[eCount] > 0) 
        vertpos = iLow(NULL,0,barno) - VertSpacing * eNumber[eCount] * Point;         // Plot object VertSpacing pips x seq# below low of relevant bar
      else
        vertpos = iHigh(NULL,0,barno) - VertSpacing * (eNumber[eCount]+dir1) * Point;    // Plot object VertSpacing pips x seq# above high of relevant bar
      if (eWingding[eCount] == 0)
       {  
        ObjectCreate(objname,OBJ_TEXT,0,eTime[eCount],vertpos);                
        ObjectSet(objname,OBJPROP_ANGLE,0);
        ObjectSetText(objname,eText2[eCount],9,"Verdana",White);                      // Set object descr = second descr line
       } 
      else
       {
        ObjectCreate(objname,OBJ_ARROW,0,eTime[eCount],vertpos);                
        ObjectSet(objname,OBJPROP_ARROWCODE,eWingding[eCount]);                       // Set wingding code
        ObjectSet(objname,OBJPROP_WIDTH,SymbolSize);                                  // Set size of object
        ObjectSetText(objname,eText2[eCount]);                                        // Set object descr = second descr line
       } 
      ObjectSet(objname,OBJPROP_COLOR,White);                                         // Default color
      if (eImpact[eCount] == 1) ObjectSet(objname,OBJPROP_COLOR,Yellow);              // Low impact = yellow
      if (eImpact[eCount] == 2) ObjectSet(objname,OBJPROP_COLOR,Orange);              // Medium impact = orange
      if (eImpact[eCount] == 3) ObjectSet(objname,OBJPROP_COLOR,Red);                 // High impact = red
      if (eImpact[eCount] == 4) ObjectSet(objname,OBJPROP_COLOR,LimeGreen);           // Allow other primary colors
      if (eImpact[eCount] == 5) ObjectSet(objname,OBJPROP_COLOR,DodgerBlue);        
      if (eImpact[eCount] == 6) ObjectSet(objname,OBJPROP_COLOR,Magenta);        
      if (eImpact[eCount] == 7) ObjectSet(objname,OBJPROP_COLOR,Aqua);        
      if (eImpact[eCount] == 8) ObjectSet(objname,OBJPROP_COLOR,Goldenrod);        
      if (eImpact[eCount] == 9) ObjectSet(objname,OBJPROP_COLOR,Plum);        
      if (eImpact[eCount] == 10) ObjectSet(objname,OBJPROP_COLOR,Silver);        

   }
 
   int debug, i;
   debug=FileOpen("debug.txt", FILE_CSV|FILE_WRITE, '|');
   for( i=0; i<eCount; i++)
     FileWrite(debug,i,TimeToStr(eTime[i]),eNumber[i],eWingding[i],eImpact[i],eCurrency[i],eText1[i],eText2[i]);
   FileClose(debug);*/
//----
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
   int i;                                  // Delete created objects when indicator is removed
   for(i=0;i<eCount;i++)
     ObjectDelete(eText1[i]);
//----
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
//----

  
//----
   return(0);
}


Comments