", "", "", "", "", "", "", "", "", "" };
string sinceUntil, TimeStr,Sponsor, Minutes1, Minutes2, box1, box2, box3;
color TxtColorNews; //= White;
bool FLAG_deinit;
//+-----------------------------------------------------------------------------------------------+
//| Indicator Initialization |
//+-----------------------------------------------------------------------------------------------+
int init()
{
FLAG_deinit = false;
SetIndexBuffer(0, ExtMapBuffer0);
SetIndexBuffer(1, ExtMapBuffer1);
SetIndexBuffer(2, ExtMapBuffer2);
SetIndexStyle(0, DRAW_NONE);
SetIndexStyle(1, DRAW_NONE);
SetIndexStyle(2, DRAW_NONE);
IndicatorShortName("FFCal");
//SetIndexLabel(0, "MinsBeforeNews");
//SetIndexLabel(1, "MinsAfterNews");
MathSrand(TimeLocal());
RefreshMin = (MathRand() % 60);
RefreshHour = (MathRand() % 6);
if (DebugLevel > 0)
{
Print("In Init()...\n");
Print("RefreshMin == ", RefreshMin);
Print("RefreshHour == ", RefreshHour);
}
return(0);
}
//+-----------------------------------------------------------------------------------------------+
//| Indicator De-initialization |
//+-----------------------------------------------------------------------------------------------+
int deinit()
{
int obj_total= ObjectsTotal();
for (i= obj_total; i>=0; i--) {
string name= ObjectName(i);
if (StringSubstr(name,0,7)=="[FFCal]") {ObjectDelete(name);}}
//Fixed one case of divide by zero where multiple charts
//indicator is on was trying to overwrite the same file
xmlFileName = GetXmlFileName();
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ|FILE_WRITE);
//File does not exist if FileOpen return -1 or if GetLastError = ERR_CANNOT_OPEN_FILE (4103)
if (xmlHandle >= 0)
{
//Since file exists, Close what we just opened
FileClose(xmlHandle);
//Delete our news file and redownload a new one to prevent a remainder from zero divide error
if (!SaveXmlFiles) FileDelete(xmlFileName);
}
return(0);
}
string GetXmlFileName()
{
return (Month() + "-" + Day() + "-" + Year() + "-" + Symbol() + Period() + "-" + "FFCal.xml");
}
//+-----------------------------------------------------------------------------------------------+
//| Indicator Start |
//+-----------------------------------------------------------------------------------------------+
int start()
{
//Deinitialize once when turned off, not on every tick while off----------------------------
if(!Indicator_ON)
{
if (!FLAG_deinit) deinit(); FLAG_deinit = true; return(0);
}
FLAG_deinit = false;
//Clear variables to refresh labels. Then exit if "Off".
if (!Indicator_ON) {return(0);}
int newsIdx = 0;
int nextNewsIdx = -1;
int next;
string myEvent;
bool skip;
datetime newsTime;
//Make sure we are connected. Otherwise exit. Added by MN
if (!IsConnected()) {Print("News Indicator is disabled because NO CONNECTION to Broker!"); return(0);}
//If we are not logging, then do not output debug statements either
if (!EnableLogging) DebugLevel = 0;
//Added this section to check if the XML file already exists.
//If it does NOT, then we need to set a flag to go get it
xmlFileName = GetXmlFileName();
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ);
//File does not exist if FileOpen return -1 or if GetLastError = ERR_CANNOT_OPEN_FILE (4103)
//Since file exists, close what we just opened
if (xmlHandle >= 0) {FileClose(xmlHandle); NeedToGetFile = false;}
else NeedToGetFile = true;
//---------------------------------------------------------------------------------------------
//Set this to false when using in another EA or Chart, so that the multiple
//instances of the indicator don't fight with each other (added by MN).
if (AllowWebUpdates)
{
//New method: Use global variables so that when put on multiple charts, it
//will not update overly often; only first time and every 4 hours
if (DebugLevel > 1)
Print(GlobalVariableGet("LastUpdateTime") + " " + (TimeCurrent() - GlobalVariableGet("LastUpdateTime")));
if (NeedToGetFile || GlobalVariableCheck("LastUpdateTime") == false ||
(TimeCurrent() - GlobalVariableGet("LastUpdateTime")) > WebUpdateFreq)
{
if (DebugLevel > 1) Print("sUrl == ", sUrl);
if (DebugLevel > 0)Print("Grabbing Web, url = ", sUrl);
//THIS CALL WAS DONATED BY PAUL TO HELP FIX THE RESOURCE ERROR
GrabWeb(sUrl, sData);
if (DebugLevel > 0) {Print("Opening XML file...\n"); Print(sData);}
//Delete existing file
FileDelete(xmlFileName);
//Write the contents of the ForexFactory page to an .htm file
//If it is still open from the above FileOpen call, close it.
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_WRITE);
if (xmlHandle < 0)
{
if (DebugLevel > 0) Print("Can\'t open new xml file, the last error is ", GetLastError()); return(false);
}
FileWriteString(xmlHandle, sData, StringLen(sData));
FileClose(xmlHandle);
if (DebugLevel > 0) Print("Wrote XML file...\n");
//THIS BLOCK OF CODE DONATED BY WALLY TO FIX THE RESOURCE ERROR
//--- Look for the end XML tag to ensure that a complete page was downloaded ---//
end = StringFind(sData, "", 0);
if (end <= 0) {Alert("FFCal Error - Web page download was not complete!"); return(false);}
else {GlobalVariableSet("LastUpdateTime", TimeCurrent());} // set global to time of last update
}
}//end of allow web updates--------------------------------------------------------------------
//Perform remaining checks once per minute
if (!IsEA_Call && Minute() == PrevMinute) return (true);
PrevMinute = Minute();
//Print("FFCal NEW MINUTE...Refreshing News from XML file...");
//Open the log file (will not open if logging is turned off)
OpenLog("FFCal");
//Init the buffer array to zero just in case
ArrayInitialize(ExtMapBuffer0, 0);
ArrayInitialize(ExtMapBuffer1, 0);
//Open the XML file
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ);
if (xmlHandle < 0)
{
Print("Can\'t open xml file: ", xmlFileName, ". The last error is ", GetLastError()); return(false);
}
if (DebugLevel > 0) Print("XML file open must be okay");
//Read in the whole XML file
//Avg. file length == ~7K, so 65536 should always read whole file
//sData = FileReadString(xmlHandle, 65536);
//if (StringLen(sData) < FileSize(xmlHandle)) sData = sData + FileReadString(xmlHandle, FileSize(xmlHandle));
// Workaround for FileReadString limitation - added by euclid
sData="";
while (StringLen(sData) < NormalizeDouble(FileSize(xmlHandle),0))
sData = sData + FileReadString(xmlHandle, FileSize(xmlHandle)-StringLen(sData));
//Because MT4 build 202 complained about too many files open and MT4 hung. Added by MN
if (xmlHandle > 0) FileClose(xmlHandle);
//Get the currency pair, and split it into the two countries
string pair = Symbol();
string cntry1 = StringSubstr(pair, 0, 3);
string cntry2 = StringSubstr(pair, 3, 3);
if (DebugLevel > 0) Print("cntry1 = ", cntry1, " cntry2 = ", cntry2);
if (DebugLevel > 0) Log("Weekly calendar for " + pair + "\n\n");
//Parse the XML file looking for an event to report
tmpMins = 10080; // (a week)
BoEvent = 0;
while (true)
{
BoEvent = StringFind(sData, "", BoEvent);
if (BoEvent == -1) break;
BoEvent += 7;
next = StringFind(sData, "", BoEvent);
if (next == -1) break;
myEvent = StringSubstr(sData, BoEvent, next - BoEvent);
BoEvent = next;
begin = 0;
skip = false;
for (i=0; i < 7; i++)
{
mainData[newsIdx][i] = "";
next = StringFind(myEvent, sTags[i], begin);
// Within this event, if tag not found, then it must be missing; skip it
if (next == -1) continue;
else
{
// We must have found the sTag okay...
begin = next + StringLen(sTags[i]); // Advance past the start tag
end = StringFind(myEvent, eTags[i], begin); // Find start of end tag
//Get data between start and end tag
if (end > begin && end != -1) {mainData[newsIdx][i] = StringSubstr(myEvent, begin, end - begin);}
//check for CDATA tag - added by euclid
if (StringSubstr(mainData[newsIdx][i],0,9)==" 0)
{
Log("FOREX FACTORY\nTitle: " + mainData[newsIdx][TITLE] + "\n" + minsTillNews + "\n\n");
}
//Keep track of the most recent news announcement. Do that by saving each one until we get to the
//first annoucement that isn't in the past; i.e. minsTillNews > 0. Then, keep this one instead for
//display, but only once the minutes until the next news is SMALLER than the minutes since the last.
//Print("Mins till event: ", minsTillNews);
if (minsTillNews < 0 || MathAbs(tmpMins) > minsTillNews) {idxOfNext = newsIdx; tmpMins = minsTillNews;}
Log("Weekly calendar for " + pair + "\n\n");
if (DebugLevel > 0)
{
Log("FOREX FACTORY\nTitle: " + mainData[newsIdx][TITLE] +
"\nCountry: " + mainData[newsIdx][COUNTRY] +
"\nDate: " + mainData[newsIdx][DATE] +
"\nTime: " + mainData[newsIdx][TIME] +
"\nImpact: " + mainData[newsIdx][IMPACT] +
"\nForecast: " + mainData[newsIdx][FORECAST] +
"\nPrevious: " + mainData[newsIdx][PREVIOUS] + "\n\n");
}
//Do alert if user has enabled
if (Alert_Minutes_Before != 0 && minsTillNews == Alert_Minutes_Before && !IsEA_Call)
Alert(Alert_Minutes_Before, " minutes until news for ", pair, ": ", mainData[newsIdx][TITLE]);
//Buffers are set up as so:
//ExtMapBuffer0 contains the time UNTIL each announcement (can be negative)
//e.g. [0] = -372; [1] = 25; [2] = 450; [3] = 1768 (etc.)
//ExtMapBuffer1[0] has the mintutes since the last annoucement.
//ExtMapBuffer1[1] has the mintutes until the next annoucement.
ExtMapBuffer0[newsIdx] = minsTillNews;
newsIdx++;
}//End "skip" routine
}//End "while" routine
//Cycle through the events array and pick out the most recent past and the next coming event
//to put into ExtMapBuffer1. Put the corresponding impact for these two into ExtMapBuffer2.
bool first = true;
ExtMapBuffer1[0] = 99999;
ExtMapBuffer1[1] = 99999;
ExtMapBuffer2[0] = 0;
ExtMapBuffer2[1] = 0;
string outNews = "Minutes until news events for " + pair + " : ";
for (i=0; i < newsIdx; i++)
{
outNews = outNews + ExtMapBuffer0[i] + ", ";
if (ExtMapBuffer0[i] >= 0 && first)
{
first = false;
//Put the relevant info into the indicator buffers...
//Minutes SINCE - - - - - - - - - - - - - - - - - - - - - - - - -
//(does not apply if the first event of the week has not passed)
if (i > 0)
{
ExtMapBuffer1[0] = MathAbs(ExtMapBuffer0[i-1]);
ExtMapBuffer2[0] = ImpactToNumber(mainData[i-1][IMPACT]);
}
//Minutes UNTIL - - - - - - - - - - - - - - - - - - - - - - - - -
//Check if past the last event.
if (ExtMapBuffer0[i] > 0 || (ExtMapBuffer0[i] == 0 && ExtMapBuffer0[i+1] > 0))
{
ExtMapBuffer1[1] = ExtMapBuffer0[i];
}
ExtMapBuffer2[1] = ImpactToNumber(mainData[i][IMPACT]);
}
//Also use this loop to set which information to display
if (i == idxOfNext)
{
dispTitle[0] = mainData[i][TITLE];
dispCountry[0] = mainData[i][COUNTRY];
dispImpact[0] = mainData[i][IMPACT];
dispForecast[0] = mainData[i][FORECAST];
dispPrevious[0] = mainData[i][PREVIOUS];
dispMinutes[0] = ExtMapBuffer0[i];
}
if (i == idxOfNext + 1)
{
dispTitle[1] = mainData[i][TITLE];
dispCountry[1] = mainData[i][COUNTRY];
dispImpact[1] = mainData[i][IMPACT];
dispForecast[1] = mainData[i][FORECAST];
dispPrevious[1] = mainData[i][PREVIOUS];
dispMinutes[1] = ExtMapBuffer0[i];
}
}//End "for" loop
//If we are past all news events, then neither one will have been
//set, so set the past event to the last (negative) minutes
if (ExtMapBuffer1[0] == 0 && ExtMapBuffer1[1] == 0)
{
ExtMapBuffer1[0] = ExtMapBuffer0[i-1];
ExtMapBuffer1[1] = 999999;
}
//For debugging...Print the tines until news events, as a "Comment"
if (DebugLevel > 0)
{
Print(outNews);
Print("LastMins (ExtMapBuffer1[0]) = ", ExtMapBuffer1[0]);
Print("NextMins (ExtMapBuffer1[1]) = ", ExtMapBuffer1[1]);
}
if (ShowNewsText) OutputToChart();
if (logHandle > 0) {FileClose(logHandle); logHandle = -1;}
return (0);
}
//+-----------------------------------------------------------------------------------------------+
//| Indicator Routine For Normal Display |
//+-----------------------------------------------------------------------------------------------+
void OutputToChart()
{
//Set variables
TxtSize = TxtSize_8_9_10;
if (TxtSize <8 || TxtSize >10) {TxtSize = 9;}
TitleSpacer = 6;
EventSpacer = 6;
curX = 5;
curY = 5;
box1 = "[FFCal] Background1";
box2 = "[FFCal] Background2";
box3 = "[FFCal] Background3";
W = WindowsTotal( );
//Do background---------------------------------------------------------------------------------
if(TxtSize == 8)
{
Box= 45; x1= 0; y1= 0; x2=180+Widen_Background; y2= 0; x3= 180+ Widen_Background; y3= 0;
if(DisplayCorner==2 && Broker_Watermark && W ==1) {Box=53; x2=90+Widen_Background; x3= 187+ Widen_Background; y3= 0; curY = curY+12;}
}
if(TxtSize == 9)
{
//Box= 51; x1= 0; y1= 0; x2=140+Widen_Background; y2= 0;
Box= 47; x1= 0; y1= 0; x2=130+Widen_Background; y2= 0; x3= 252+ Widen_Background; y3= 0;
if(DisplayCorner==2 && Broker_Watermark && W ==1) {Box=55; x2=120+Widen_Background; x3= 220+ Widen_Background; y3= 0; curY = curY+11;}
}
if(TxtSize == 10)
{
Box= 51; x1= 0; y1= 0; x2=140+Widen_Background; y2= 0; x3= 244+ Widen_Background; y3= 0;
if(DisplayCorner==2 && Broker_Watermark && W ==1) {Box=57; x2=130+Widen_Background; x3= 220+ Widen_Background; y3= 0; curY = curY+10;}
}
if (DisplayCorner == 1 || DisplayCorner == 3) {x1= 1;}
if (DisplayCorner == 2 || DisplayCorner == 3) {y1= 1; y2= 1; y3= 1;}
if (ObjectFind(box1) == -1){
ObjectCreate(box1, OBJ_LABEL, DisplayWindow_0123, 0,0);
ObjectSetText(box1, "ggg", Box, "Webdings");
ObjectSet(box1, OBJPROP_CORNER, DisplayCorner);
ObjectSet(box1, OBJPROP_XDISTANCE, x1);
ObjectSet(box1, OBJPROP_YDISTANCE, y1);
ObjectSet(box1, OBJPROP_COLOR, Color_Background);
ObjectSet(box1, OBJPROP_BACK, false);}
else {ObjectMove(box1, DisplayWindow_0123, x1, y1);}
if (ObjectFind(box2) == -1){
ObjectCreate(box2, OBJ_LABEL, DisplayWindow_0123, 0,0);
ObjectSetText(box2, "ggg", Box, "Webdings");
ObjectSet(box2, OBJPROP_CORNER, DisplayCorner);
ObjectSet(box2, OBJPROP_XDISTANCE, x2);
ObjectSet(box2, OBJPROP_YDISTANCE, y2);
ObjectSet(box2, OBJPROP_COLOR, Color_Background);
ObjectSet(box2, OBJPROP_BACK, false);}
else {ObjectMove(box1, DisplayWindow_0123, x2, y2);}
if (ObjectFind(box3) == -1){
ObjectCreate(box3, OBJ_LABEL, DisplayWindow_0123, 0,0);
ObjectSetText(box3, "ggg", Box, "Webdings");
ObjectSet(box3, OBJPROP_CORNER, DisplayCorner);
ObjectSet(box3, OBJPROP_XDISTANCE, x3);
ObjectSet(box3, OBJPROP_YDISTANCE, y3);
ObjectSet(box3, OBJPROP_COLOR, Color_Background);
ObjectSet(box3, OBJPROP_BACK, false);}
else {ObjectMove(box3, DisplayWindow_0123, x3, y3);}
//Do labels------------------------------------------------------------------------------------
Title = "FOREX FACTORY CALENDAR HEADLINES:";
Sponsor = "[FFCal] Sponsor";
Minutes1 = "[FFCal] Minutes1";
Minutes2 = "[FFCal] Minutes2";
int index;
if (DisplayCorner < 2) //Code to display in upper corners
{
//Start with title------------------------------------------------------
if (ObjectFind(Sponsor) == -1){
ObjectCreate(Sponsor, OBJ_LABEL, DisplayWindow_0123, 0, 0);
ObjectSetText(Sponsor, Title, TxtSize_8_9_10, TxtStyle, FFCal_Title);
ObjectSet(Sponsor, OBJPROP_CORNER, DisplayCorner);
ObjectSet(Sponsor, OBJPROP_XDISTANCE, curX);
ObjectSet(Sponsor, OBJPROP_YDISTANCE, curY);}
else {ObjectMove(Sponsor, DisplayWindow_0123, curX, curY);}
//Then do first news event description line & Impact---------------------
//If time is 0 or negative, we want to say "xxx mins SINCE ... news event", else say "UNTIL ... news event"
sinceUntil = "until ";
dispMins = dispMinutes[0];
if (dispMinutes[0] <= 0) {sinceUntil = "since "; dispMins *= -1;} //"*= -1" = multiply by "-1"
if (dispMins < 60) {TimeStr = dispMins + " mins ";}
else // time is 60 minutes or more
{
Hours = MathRound(dispMins / 60);
Mins = dispMins % 60;
if (Hours < 24) // less than a day: show hours and minutes
{
TimeStr = Hours + " hrs " + Mins + " mins ";
}
else // days, hours, and minutes
{
Days = MathRound(Hours / 24);
Hours = Hours % 24;
TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
}
}
index = StringFind(TimeStr+sinceUntil+dispCountry[0], "since mins", 0);
if(index == -1)
{
curY = curY + TxtSize + TitleSpacer;
TxtColorNews = ImpactToColor(dispImpact[0]);
ObjectDelete(Minutes1);
if (ObjectFind(Minutes1) == -1){
ObjectCreate(Minutes1, OBJ_LABEL, DisplayWindow_0123, 0, 0);
//if(index != -1){
if (sinceUntil == "since " && dispMins > WebUpdateFreq + 1) {TxtColorNews = News_Impact_None;
ObjectSetText(Minutes1, "Event 1: No H/M impact events currently scheduled", TxtSize_8_9_10, TxtStyle, TxtColorNews);}
else {
ObjectSetText(Minutes1, TimeStr + sinceUntil + dispCountry[0] + ": " + dispTitle[0], TxtSize_8_9_10, TxtStyle, TxtColorNews);}
ObjectSet(Minutes1, OBJPROP_CORNER, DisplayCorner);
ObjectSet(Minutes1, OBJPROP_XDISTANCE, curX);
ObjectSet(Minutes1, OBJPROP_YDISTANCE, curY);}
else {ObjectMove(Minutes1, DisplayWindow_0123, curX, curY);}
}
//Finish with second news event description line------------------------
sinceUntil = "until ";
dispMins = dispMinutes[1];
if (dispMinutes[1] <= 0) {sinceUntil = "since "; dispMins *= -1;}
if (dispMins < 60) {TimeStr = dispMins + " mins ";}
else // time is 60 minutes or more
{
Hours = MathRound(dispMins / 60);
Mins = dispMins % 60;
if (Hours < 24) // less than a day: show hours and minutes
{
TimeStr = Hours + " hrs " + Mins + " mins ";
}
else // days, hours, and minutes
{
Days = MathRound(Hours / 24);
Hours = Hours % 24;
TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
}
}
index = StringFind(TimeStr+sinceUntil+dispCountry[1], "since mins", 0);
if(index == -1)
{
curY = curY+ TxtSize + EventSpacer;
TxtColorNews = ImpactToColor(dispImpact[1]);
ObjectDelete(Minutes2);
if (ObjectFind(Minutes2) == -1){
ObjectCreate(Minutes2, OBJ_LABEL, DisplayWindow_0123, 0, 0);
if(index != -1){
ObjectSetText(Minutes2, "Event 2: No events currently scheduled", TxtSize_8_9_10, TxtStyle, TxtColorNews);}
else {
ObjectSetText(Minutes2, TimeStr + "until " + dispCountry[1] + ": " + dispTitle[1], TxtSize_8_9_10, TxtStyle, TxtColorNews);}
ObjectSet(Minutes2, OBJPROP_CORNER, DisplayCorner);
ObjectSet(Minutes2, OBJPROP_XDISTANCE, curX);
ObjectSet(Minutes2, OBJPROP_YDISTANCE, curY);}
else {ObjectMove(Minutes2, DisplayWindow_0123, curX, curY);}
}
}//End display code for upper corners
//---------------------------------------------------------------------------------------------
else if (DisplayCorner > 1) //Code to display in lower corners
{
//Do second event description line-----------------------------------
sinceUntil = "until ";
dispMins = dispMinutes[1];
if (dispMinutes[1] <= 0) {sinceUntil = "since "; dispMins *= -1;} //"*= -1" = multiply by "-1"
if (dispMins < 60) {TimeStr = dispMins + " mins ";}
else // time is 60 minutes or more
{
Hours = MathRound(dispMins / 60);
Mins = dispMins % 60;
if (Hours < 24) // less than a day: show hours and minutes
{
TimeStr = Hours + " hrs " + Mins + " mins ";
}
else // days, hours, and minutes
{
Days = MathRound(Hours / 24);
Hours = Hours % 24;
TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
}
}
index = StringFind(TimeStr+sinceUntil+dispCountry[1], "since mins", 0);
TxtColorNews = ImpactToColor(dispImpact[1]);
ObjectDelete(Minutes2);
if (ObjectFind(Minutes2) == -1){
ObjectCreate(Minutes2, OBJ_LABEL, DisplayWindow_0123, 0, 0);
if(index != -1){
ObjectSetText(Minutes2, "Event 2: Additional events not currently scheduled", TxtSize_8_9_10, TxtStyle, TxtColorNews);}
else {
ObjectSetText(Minutes2, TimeStr + "until " + dispCountry[1] + ": " + dispTitle[1], TxtSize_8_9_10, TxtStyle, TxtColorNews);}
ObjectSet(Minutes2, OBJPROP_CORNER, DisplayCorner);
ObjectSet(Minutes2, OBJPROP_XDISTANCE, curX);
ObjectSet(Minutes2, OBJPROP_YDISTANCE, curY);}
else {ObjectMove(Minutes2, DisplayWindow_0123, curX, curY);}
curY = curY + TxtSize + EventSpacer;
//Do first event description line------------------------------------
//If time is 0 or negative, we want to say "xxx mins SINCE ... news event", else say "UNTIL ... news event"
sinceUntil = "until ";
dispMins = dispMinutes[0];
if (dispMinutes[0] <= 0) {sinceUntil = "since "; dispMins *= -1;}
if (dispMins < 60) {TimeStr = dispMins + " mins ";}
else // time is 60 minutes or more
{
Hours = MathRound(dispMins / 60);
Mins = dispMins % 60;
if (Hours < 24) // less than a day: show hours and minutes
{
TimeStr = Hours + " hrs " + Mins + " mins ";
}
else // days, hours, and minutes
{
Days = MathRound(Hours / 24);
Hours = Hours % 24;
TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
}
}
index = StringFind(TimeStr+sinceUntil+dispCountry[0], "since mins", 0); //Comment (index);
TxtColorNews = ImpactToColor(dispImpact[0]);
ObjectDelete(Minutes1);
if (ObjectFind(Minutes1) == -1){
ObjectCreate(Minutes1, OBJ_LABEL, DisplayWindow_0123, 0, 0);
//if(index != -1) {
if (sinceUntil == "since " && dispMins > WebUpdateFreq + 1) {TxtColorNews = News_Impact_None;
ObjectSetText(Minutes1, "Event 1: Additional events not currently scheduled", TxtSize_8_9_10, TxtStyle, TxtColorNews);}
else
{
ObjectSetText(Minutes1, TimeStr + sinceUntil + dispCountry[0] + ": " + dispTitle[0], TxtSize_8_9_10, TxtStyle, TxtColorNews);
}
ObjectSet(Minutes1, OBJPROP_CORNER, DisplayCorner);
ObjectSet(Minutes1, OBJPROP_XDISTANCE, curX);
ObjectSet(Minutes1, OBJPROP_YDISTANCE, curY);}
else {ObjectMove(Minutes1, DisplayWindow_0123, curX, curY);}
curY = curY + TxtSize + TitleSpacer;
//Finish with title--------------------------------------------------
if (ObjectFind(Sponsor) == -1){
ObjectCreate(Sponsor, OBJ_LABEL, DisplayWindow_0123, 0, 0);
ObjectSetText(Sponsor, Title, TxtSize_8_9_10, TxtStyle, FFCal_Title);
ObjectSet(Sponsor, OBJPROP_CORNER, DisplayCorner);
ObjectSet(Sponsor, OBJPROP_XDISTANCE, curX);
ObjectSet(Sponsor, OBJPROP_YDISTANCE, curY);}
else {ObjectMove(Sponsor, DisplayWindow_0123, curX, curY);}
}//End display code for lower corners
return;
}
//+-----------------------------------------------------------------------------------------------+
//| Indicator Subroutine For Impact Color |
//+-----------------------------------------------------------------------------------------------+
double ImpactToColor (string impact)
{
if (impact == "High") return (News_Impact_High);
else {if (impact == "Medium") return (News_Impact_Medium);
else {if (impact == "Low") return (News_Impact_Low);
else {return (News_Impact_None);} }}
//else return (0);
}
//+-----------------------------------------------------------------------------------------------+
//| Indicator Subroutine For Impact Number |
//+-----------------------------------------------------------------------------------------------+
double ImpactToNumber(string impact)
{
if (impact == "High") return (3);
if (impact == "Medium") return (2);
if (impact == "Low") return (1);
else return (0);
}
//+-----------------------------------------------------------------------------------------------+
//| Indicator Subroutine For Date/Time |
//+-----------------------------------------------------------------------------------------------+
string MakeDateTime(string strDate, string strTime)
{
//Print("Converting Forex Factory Time into Metatrader time..."); //added by MN
//Converts forexfactory time & date into yyyy.mm.dd hh:mm
int n1stDash = StringFind(strDate, "-");
int n2ndDash = StringFind(strDate, "-", n1stDash+1);
string strMonth = StringSubstr(strDate, 0, 2);
string strDay = StringSubstr(strDate, 3, 2);
string strYear = StringSubstr(strDate, 6, 4);
//strYear = "20" + strYear;
int nTimeColonPos = StringFind(strTime, ":");
string strHour = StringSubstr(strTime, 0, nTimeColonPos);
string strMinute = StringSubstr(strTime, nTimeColonPos+1, 2);
string strAM_PM = StringSubstr(strTime, StringLen(strTime)-2);
int nHour24 = StrToInteger(strHour);
if ((strAM_PM == "pm" || strAM_PM == "PM") && nHour24 != 12) {nHour24 += 12;}
if ((strAM_PM == "am" || strAM_PM == "AM") && nHour24 == 12) {nHour24 = 0;}
string strHourPad = "";
if (nHour24 < 10) strHourPad = "0";
return(StringConcatenate(strYear, ".", strMonth, ".", strDay, " ", strHourPad, nHour24, ":", strMinute));
}
//=================================================================================================
//==================================== GrabWeb Functions ======================================
//=================================================================================================
// Main Webscraping function
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// bool GrabWeb(string strUrl, string& strWebPage)
// returns the text of any webpage. Returns false on timeout or other error
//
// Parsing functions
// ~~~~~~~~~~~~~~~~~
// string GetData(string strWebPage, int nStart, string strLeftTag, string strRightTag, int& nPos)
// obtains the text between two tags found after nStart, and sets nPos to the end of the second tag
//
// void Goto(string strWebPage, int nStart, string strTag, int& nPos)
// Sets nPos to the end of the first tag found after nStart
bool bWinInetDebug = false;
int hSession_IEType;
int hSession_Direct;
int Internet_Open_Type_Preconfig = 0;
int Internet_Open_Type_Direct = 1;
int Internet_Open_Type_Proxy = 3;
int Buffer_LEN = 80;
#import "wininet.dll"
//Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
#define INTERNET_FLAG_PRAGMA_NOCACHE 0x00000100
//Does not add the returned entity to the cache.
#define INTERNET_FLAG_NO_CACHE_WRITE 0x04000000
//Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.
#define INTERNET_FLAG_RELOAD 0x80000000
#define HTTP_QUERY_CONTENT_LENGTH 0x00000005
#define HTTP_QUERY_FLAG_NUMBER 0x20000000
//----
#define INTERNET_OPEN_TYPE_DIRECT 0
#define INTERNET_OPEN_TYPE_PRECONFIG 0x00000000 // use registry configuration
//int InternetConnectW(int,string,int,string,string,int,int,int);
int InternetOpenW( string sAgent, int lAccessType, string sProxyName, string sProxyBypass, int lFlags );
int InternetOpenUrlW(int hInternetSession,string sUrl,string sHeaders="",int lHeadersLength=0,int lFlags=0,int lContext=0);
int InternetReadFile(int hFile, uchar &sBuffer[],int lNumBytesToRead,int &lNumberOfBytesRead[]);
int InternetCloseHandle(int hInet);
#import
//-----------------------------------------------------------------------------------------------
int hSession(bool Direct)
{
string InternetAgent;
if (hSession_IEType == 0)
{
InternetAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)";
hSession_IEType = InternetOpenW(InternetAgent, Internet_Open_Type_Preconfig, "0", "0", 0);
hSession_Direct = InternetOpenW(InternetAgent, Internet_Open_Type_Direct, "0", "0", 0);
}
if (Direct) {return(hSession_Direct);}
else {return(hSession_IEType);}
}
//------------------------------------------------------------------------------------------------
bool GrabWeb(string strUrl, string& strWebPage)
{
uint hInternet;
int iResult;
int lReturn[] = {1};
//string sBuffer = " "; // 255 spaces
uchar sBuffer[1024];
int bytes;
uint flags=INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
hInternet = InternetOpenUrlW(hSession(FALSE), strUrl, NULL, 0,flags);
if (bWinInetDebug) Log("hInternet: " + hInternet);
if (hInternet == 0) return(false);
Print("Reading URL: " + strUrl); //added by MN
iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);
if (bWinInetDebug) Log("iResult: " + iResult);
if (bWinInetDebug) Log("lReturn: " + lReturn[0]);
if (bWinInetDebug) Log("iResult: " + iResult);
if (bWinInetDebug) Log("sBuffer: " + CharArrayToString(sBuffer, 0, lReturn[0]));
if (iResult == 0) return(false);
bytes = lReturn[0];
strWebPage = CharArrayToString(sBuffer, 0, lReturn[0]);
//If there's more data then keep reading it into the buffer
while (lReturn[0] != 0)
{
iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);
if (lReturn[0]==0) break;
bytes = bytes + lReturn[0];
strWebPage = strWebPage + CharArrayToString(sBuffer, 0, lReturn[0]);
}
Print("Closing URL web connection"); //added by MN
iResult = InternetCloseHandle(hInternet);
if (iResult == 0) return(false);
return(true);
}
//=================================== LogUtils Functions ======================================
void OpenLog(string strName)
{
if (!EnableLogging) return;
if (logHandle <= 0)
{
string strMonthPad = "";
string strDayPad = "";
if (Month() < 10) strMonthPad = "0";
if (Day() < 10) strDayPad = "0";
string strFilename = StringConcatenate(strName, "_", Year(), strMonthPad, Month(), strDayPad, Day(), "_log.txt");
logHandle = FileOpen(strFilename,FILE_CSV|FILE_READ|FILE_WRITE);
Print("logHandle =================================== ", logHandle);
}
if (logHandle > 0) {FileFlush(logHandle); FileSeek(logHandle, 0, SEEK_END);}
}
//------------------------------------------------------------------------------------------------
void Log(string msg)
{
if (!EnableLogging) return;
if (logHandle <= 0) return;
msg = TimeToStr(TimeCurrent(),TIME_DATE|TIME_MINUTES|TIME_SECONDS) + " " + msg;
FileWrite(logHandle,msg);
}
//=================================== Timezone Functions ======================================
#import "kernel32.dll"
int GetTimeZoneInformation(int& TZInfoArray[]);
#import
#define TIME_ZONE_ID_UNKNOWN 0
#define TIME_ZONE_ID_STANDARD 1
#define TIME_ZONE_ID_DAYLIGHT 2
int TZInfoArray[43];
datetime timeGMT()
{
int DST = GetTimeZoneInformation(TZInfoArray);
if (DST == 1) DST = 3600;
else DST = 0;
return( TimeLocal() + DST + (Offset_Hours * 3600) + (TZInfoArray[0] + TZInfoArray[42]) * 60 );
}
//=================================================================================================
//================================= END IMPORTED FUNCTIONS =====================================
//=================================================================================================
//+-----------------------------------------------------------------------------------------------+
//| Indicator End |
//+-----------------------------------------------------------------------------------------------+