Trace_History
Download scriptThis 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.
//+------------------------------------------------------------------+
//| _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