ffc.mq4 v3c1源码
//=============================================================================
// FFCal_v01.mq4
// Copyright © 2006, Derk Wehler
// Written in cooperation with: http://www.forexfactory.com
//
//
// This "indicator" calls DLLs to fetch a special XML file from the
// ForexFactory web site. It then parses it and writes it out as a .CSV
// file, which it places in the folder: experts/files so that IsNewsTime()
// can use that file to tell if it is near announcement time.
//
// It does this once when it starts up and once per hour in case there have
// been any updates to the annoucement calendar.
//
// In order for this to work correctly and synchronize with your broker's
// server time, you must enter the proper value for "TimeZone". This is
// entered relative to GMT. For example, my broker's server time is GMT+1,
// so I have the default set to 1. If your broker uses GMT+3, enter 3.
// If your broker uses GMT-2, then enter -2.
//
//
//
//=============================================================================
// OTHER CREDIT DUE
// (For GrebWeb and LogUtils functionality (see end of this flie)
//
// 2/14/2007: Robert Hill added code for using text objects instead
// of Comment() for easier reading
//
// 2/25/2007: Paul Hampton-Smith for his TimeZone DLL code
//
// 2/26/2007: Mike Nguyen added the following things (search text for Added by MN):
// -Connection test so that MT4 doesnt hang when there is no server connection
// -Fixed some minor syntax because was getting "too many files open error..."
// -Added vertical lines and vertical news text so that we have a
// visual reference of when the news happened.
// -Now supports and correctly draws two simultaneous news announcements
// -Added text to say "xx min SINCE event..." after the event as past
// -Clean up old Objects left behind on old news annoumcents
//
//=============================================================================
//+---------------------------------------------------------------------------+
//| WinInet.mqh |
//| Paul Hampton-Smith |
//| paul1000@pobox.com |
//| |
//| This include has been adapted from the groundbreaking GrabWeb script |
//| developed by Adbi that showed me how to import functions from wininet.dll |
//|---------------------------------------------------------------------------|
//| grabweb.mq4 |
//| Copyright © 2006, Abhi |
//| http://www.megadelfi.com/experts/ |
//| E-mail: grabwebexpert{Q)megadelfi.com |
//| fix my e-mail address before mailing me ;) |
//+---------------------------------------------------------------------------+
/*
IDEAS FOR ADDITIONS:
* A text lable of what the news was and when it was, e.g
"USD CPI m/m @ [broker time here]" at the top or bottom within the shaded area.
* Label the number of pips it went in its initial direction and how much it
retraced...of course you'd have to come up with a convention for measuring
movement. Or you could label what price was just prior to news then labels
the next two price exteremes. I think it would be nice to have the numbers
right under/over the candle that produced the extremes for whatever timeframe
you are in.
* Label the volume count for the candle that included the news in it...whatever
timeframe your in. So I could switch from 1 min. to 5 min. to 15 min.
timeframes and get different vol. counts for the bar that included the news.
*/
#property copyright "Copyright © 2006, Derk Wehler"
#property link "http://www.forexfactory.com"
#property indicator_chart_window
#property indicator_buffers 3
#define TITLE 0
#define COUNTRY 1
#define DATE 2
#define TIME 3
#define IMPACT 4
#define FORECAST 5
#define PREVIOUS 6
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
extern bool IncludeHigh = true;
extern bool IncludeMedium = true;
extern bool IncludeLow = false;
extern bool IncludeSpeaks = true; // news items with "Speaks" in them have different characteristics
extern int Alert1MinsBefore = -1; // Set to -1 for no Alert
extern int Alert2MinsBefore = -1; // Set to -1 for no Alert
extern bool EnableLogging = false; // Perhaps remove this from externs once its working well
extern bool ShowNextTwoEvents = true;
extern int TxtSize = 10;
extern color TxtColorTitle = LightGray;
extern color TxtColorNews = DeepSkyBlue;
extern color TxtColorImpact = Red;
extern color TxtColorPrevious = Orange;
extern color TxtColorForecast = Lime;
extern int VertTxtShift = 21; //how far away below the ask line we want to place our vertical news text
int DebugLevel = 2;
double ExtMapBuffer0[]; // Contains (minutes until) each news event
double ExtMapBuffer1[]; // Contains only most recent and next news event ([0] & [1])
double ExtMapBuffer2[]; // Contains impact value for most recent and next news event
string sUrl = "http://www.forexfactory.com/weekly_calendar.xml";
int xmlHandle;
int logHandle = -1;
int BoEvent, finalend, end, i;
int begin;
string mainData[100][7];
int minsTillNews;
string sData, csvoutput;
string commentStr;
int tmpMins;
int idxOfNext;
int dispMinutes[2];
string dispTitle[2],
dispCountry[2],
dispImpact[2],
dispForecast[2],
dispPrevious[2];
string dispSeparator1 = "===================";
static bool FirstRun = true;
static int PrevMinute = -1;
datetime LastTimeAlert1=0; //used to make sure we only draw something once per annoucement. Added by MN
int init()
{
Print("In Init()...\n");
SetIndexStyle(0, DRAW_NONE);
SetIndexBuffer(0, ExtMapBuffer0);
SetIndexStyle(1, DRAW_NONE);
SetIndexBuffer(1, ExtMapBuffer1);
IndicatorShortName("FFCal");
SetIndexLabel(0, "MinsBeforeNews");
SetIndexLabel(1, "MinsAfterNews");
return(0);
}
int deinit()
{
ObjectDelete("Sponsor");
ObjectDelete("Minutes");
ObjectDelete("Impact");
ObjectDelete("Previous");
ObjectDelete("Forecast");
ObjectDelete("Separator1");
ObjectDelete("Separator2");
ObjectDelete("Sponsor2");
ObjectDelete("Minutes2");
ObjectDelete("Impact2");
ObjectDelete("Previous2");
ObjectDelete("Forecast2");
ObjectsDeleteAll(0,OBJ_TEXT); //added by MN
ObjectsDeleteAll(0,OBJ_TREND); //added by MN
return(0);
}
int start()
{
int newsIdx = 0;
int nextNewsIdx = -1;
int next;
string myEvent;
bool skip;
datetime newsTime;
//check to 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;
commentStr = "Forex Factory Calendar";
string xmlFileName = Month() + "-" + Day() + "-" + Year() + "-" + "FFCal.xml";
//Print("STARTED");
// Refresh FF calendar on startup, and once at the top of each hour
if (FirstRun || Minute() == 0)
{
FirstRun = false;
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);
}
// Write the contents of the ForexFactory page to an .htm file
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ|FILE_WRITE);
if (xmlHandle < 1)
{
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("GetNewsFF Error - Web page download was not complete!");
return(false);
}
//-------------------------------------------------------------------------------//
}
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Perform remaining checks once per minute
if (Minute() == PrevMinute)
return (true);
PrevMinute = Minute();
Print("GetNewsFF 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
// Ave file length == ~7K, so 65536 should always read whole file
sData = FileReadString(xmlHandle, 65536);
//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;
string sTags[7] = { "", "", "", "", "", "", "" };
while (true)
{
BoEvent = StringFind(sData, "", BoEvent);
if (BoEvent == -1)
break;
BoEvent += 7;
next = StringFind(sData, "", BoEvent);
myEvent = StringSubstr(sData, BoEvent, next - BoEvent);
BoEvent = next;
begin = 0;
skip = false;
for (i=0; i < 7; i++)
{
mainData[newsIdx] = "";
next = StringFind(myEvent, sTags, 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); // Advance past the start tag
end = StringFind(myEvent, eTags, begin); // Find start of end tag
if (end > begin && end != -1)
{
// Get data between start and end tag
mainData[newsIdx] = StringSubstr(myEvent, begin, end - begin);
}
}
}
// for (i=6; i >= 0; i--)
// Print(sTags, " = ", mainData[newsIdx]);
// = - = = - = = - = = - = = - = = - = = - = = - = = - = = - =
// Test against filters that define whether we want to
// skip this particular annoucemnt
if (cntry1 != mainData[newsIdx][COUNTRY] && cntry2 != mainData[newsIdx][COUNTRY])
skip = true;
if (!IncludeHigh && mainData[newsIdx][IMPACT] == "3")
skip = true;
if (!IncludeMedium && mainData[newsIdx][IMPACT] == "2")
skip = true;
if (!IncludeLow && mainData[newsIdx][IMPACT] == "1")
skip = true;
if (!IncludeSpeaks && (StringFind(mainData[newsIdx][TITLE], "speaks") != -1 ||
StringFind(mainData[newsIdx][TITLE], "Speaks") != -1) )
skip = true;
if (mainData[newsIdx][TIME] == "All Day" ||
mainData[newsIdx][TIME] == "Tentative" ||
mainData[newsIdx][TIME] == "")
skip = true;
// = - = = - = = - = = - = = - = = - = = - = = - = = - = = - =
// If not skipping this event, then log it into the draw buffers
if (!skip)
{
// If we got this far then we need to calc the minutes until this event
//
// First, convert the announcement time to seconds, GMT
newsTime = StrToTime(MakeDateTime(mainData[newsIdx][DATE], mainData[newsIdx][TIME]));
// Now calculate the minutes until this announcement (may be negative)
minsTillNews = (newsTime - TimeGMT()) / 60;
//added by MN, if minsTillNews is zero, then its the time our news is hit.
if ( (minsTillNews == 0) && (LastTimeAlert1 != newsTime) )
{ //draw the 1st news event onto the chart vertically so we have a visual record of when it occured
DisplayVerticalNews(dispTitle[0], dispCountry[0], 0);
//if there is a 2nd simultaneous news event, display the 2nd news event
if (dispMinutes[0] == dispMinutes[1])
{
DisplayVerticalNews(dispTitle[1], dispCountry[1], 1);
}
//only draw once per announcement
LastTimeAlert1 = newsTime;
}
// 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 (Alert1MinsBefore != -1 && minsTillNews == Alert1MinsBefore)
Alert(Alert1MinsBefore, " minutes until news for ", pair, ": ", mainData[newsIdx][TITLE]);
if (Alert2MinsBefore != -1 && minsTillNews == Alert2MinsBefore)
Alert(Alert2MinsBefore, " 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++;
}
}
// 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] = 0;
ExtMapBuffer1[1] = 0;
ExtMapBuffer2[0] = 0;
ExtMapBuffer2[1] = 0;
string outNews = "Minutes until news events for " + pair + " : ";
for (i=0; i < newsIdx; i++)
{
outNews = outNews + ExtMapBuffer0 + ", ";
if (ExtMapBuffer0 > 0 && first)
{
first = false;
// Put the relevant info into the indicator buffers...
if (i > 0)
{
ExtMapBuffer1[0] = ExtMapBuffer0[i-1];
ExtMapBuffer2[0] = ImpactToNumber(mainData[i-1][IMPACT]);
}
ExtMapBuffer1[1] = ExtMapBuffer0;
ExtMapBuffer2[1] = ImpactToNumber(mainData[IMPACT]);
}
// Also use this loop to set which information to display
if (i == idxOfNext)
{
dispTitle[0] = mainData[TITLE];
dispCountry[0] = mainData[COUNTRY];
dispImpact[0] = mainData[IMPACT];
dispForecast[0] = mainData[FORECAST];
dispPrevious[0] = mainData[PREVIOUS];
dispMinutes[0] = ExtMapBuffer0;
}
if (i == idxOfNext + 1)
{
dispTitle[1] = mainData[TITLE];
dispCountry[1] = mainData[COUNTRY];
dispImpact[1] = mainData[IMPACT];
dispForecast[1] = mainData[FORECAST];
dispPrevious[1] = mainData[PREVIOUS];
dispMinutes[1] = ExtMapBuffer0;
}
}
// 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];
//ensures that we clean up so that we get old text left behind on old news annoumcents. Added by MN
ObjectDelete("Impact");
ObjectDelete("Previous");
ObjectDelete("Forecast");
ObjectDelete("Impact2");
ObjectDelete("Previous2");
ObjectDelete("Forecast2");
}
// 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]);
}
OutputToChart(dispMinutes[0]);
if (logHandle > 0)
{ FileClose(logHandle); }
return (0);
}
//Draws the news veritically on the Chart so that we have a visual reference of when it occurs. Added by MN
void DisplayVerticalNews(string dispTitle, string dispCountry, int shift)
{
if (shift == 0)
{
//draw a vertical line at the time of the news if it hasnt already been drawn
if(ObjectFind("vLine"+Time[2]) == -1)
{
//ObjectCreate("vLine"+Time[2], OBJ_TREND, 0, Time[0], 0, Time[0], 2*Point); //works
ObjectCreate("vLine"+Time[2], OBJ_TREND, 0, Time[0], 0, Time[0], High[0]); //experimental
ObjectSet("vLine"+Time[2], OBJPROP_COLOR, Yellow);
ObjectSet("vLine"+Time[2], OBJPROP_STYLE, STYLE_DOT);
ObjectSet("vLine"+Time[2], OBJPROP_BACK, true); //put object in the background behind any other object on the chart
}
//place our news if it hasnt already been placed on our chart
if(ObjectFind("Headline"+Time[2]) == -1)
{ //x value use Time[3], for y value find the lowest bar within the last 10 bars, subtract by VertTxtShift and used that as our y coordinate
ObjectCreate("Headline"+Time[2], OBJ_TEXT, 0, Time[3], Low[iLowest(NULL,0,MODE_LOW,10,0)]-VertTxtShift*Point);
ObjectSet("Headline"+Time[2], OBJPROP_ANGLE, 90); //rotate the text 90 degrees
ObjectSetText("Headline"+Time[2], "News: " + dispCountry + " " + dispTitle, 8, "Arial", Orange);
}
}
else //draw second news headline
{
//place our news if it hasnt already been placed on our chart
if(ObjectFind("Headline"+Time[3]) == -1)
{ //x value use Time[3], for y value find the lowest bar within the last 10 bars, subtract by VertTxtShift and used that as our y coordinate
ObjectCreate("Headline"+Time[3], OBJ_TEXT, 0, Time[3]+900, Low[iLowest(NULL,0,MODE_LOW,10,0)]-VertTxtShift*Point);
ObjectSet("Headline"+Time[3], OBJPROP_ANGLE, 90); //rotate the text 90 degrees
ObjectSetText("Headline"+Time[3], "News: " + dispCountry + " " + dispTitle, 8, "Arial", Orange);
}
}
//force a redraw of our chart
WindowRedraw();
return(0);
}
void OutputToChart(int dispMin)
{
// Added by Robert for using TxtSize and TxtColor for easier reading
int curY = 10;
ObjectCreate("Separator1", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Separator1", dispSeparator1, TxtSize, "Arial Bold", TxtColorTitle);
ObjectSet("Separator1", OBJPROP_CORNER, 0);
ObjectSet("Separator1", OBJPROP_XDISTANCE, 10);
ObjectSet("Separator1", OBJPROP_YDISTANCE, curY);
curY = curY + TxtSize + 4;
ObjectCreate("Sponsor", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Sponsor", commentStr, TxtSize, "Arial Bold", TxtColorTitle);
ObjectSet("Sponsor", OBJPROP_CORNER, 0);
ObjectSet("Sponsor", OBJPROP_XDISTANCE, 10);
ObjectSet("Sponsor", OBJPROP_YDISTANCE, curY);
curY = curY + TxtSize + 4;
ObjectCreate("Separator2", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Separator2", dispSeparator1, TxtSize, "Arial Bold", TxtColorTitle);
ObjectSet("Separator2", OBJPROP_CORNER, 0);
ObjectSet("Separator2", OBJPROP_XDISTANCE, 10);
ObjectSet("Separator2", OBJPROP_YDISTANCE, curY);
// curY = curY + TxtSize + 4;
// ObjectCreate("Minutes", OBJ_LABEL, 0, 0, 0);
// ObjectSetText("Minutes", dispMinutes[0] + " Mins until " + dispCountry[0] + ": " + dispTitle[0], TxtSize, "Arial Bold", TxtColorNews);
// ObjectSet("Minutes", OBJPROP_CORNER, 0);
// ObjectSet("Minutes", OBJPROP_XDISTANCE, 10);
// ObjectSet("Minutes", OBJPROP_YDISTANCE, curY);
//if the time is negative, we want to say xxx mins SINCE .... news event
if (dispMin < 0)
{
curY = curY + TxtSize + 4;
ObjectCreate("Minutes", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Minutes",dispMinutes[0] + " mins" + " since news of " + dispCountry[0] + ": " + dispTitle[0], TxtSize, "Arial Bold", TxtColorNews);
ObjectSet("Minutes", OBJPROP_CORNER, 0);
ObjectSet("Minutes", OBJPROP_XDISTANCE, 10);
ObjectSet("Minutes", OBJPROP_YDISTANCE, curY);
}
else
{ //otherwise, we say xxx until .... news event
curY = curY + TxtSize + 4;
ObjectCreate("Minutes", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Minutes",dispMinutes[0] + " mins" + " until " + dispCountry[0] + ": " + dispTitle[0], TxtSize, "Arial Bold", TxtColorNews);
ObjectSet("Minutes", OBJPROP_CORNER, 0);
ObjectSet("Minutes", OBJPROP_XDISTANCE, 10);
ObjectSet("Minutes", OBJPROP_YDISTANCE, curY);
}
curY = curY + TxtSize + 4;
ObjectCreate("Impact", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Impact", "Impact: " + dispImpact[0], TxtSize, "Arial Bold", TxtColorImpact);
ObjectSet("Impact", OBJPROP_CORNER, 0);
ObjectSet("Impact", OBJPROP_XDISTANCE, 10);
ObjectSet("Impact", OBJPROP_YDISTANCE, curY);
if (dispPrevious[0] != "")
{
curY = curY + TxtSize + 4;
ObjectCreate("Previous", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Previous", "Previous: " + dispPrevious[0], TxtSize, "Arial Bold", TxtColorPrevious);
ObjectSet("Previous", OBJPROP_CORNER, 0);
ObjectSet("Previous", OBJPROP_XDISTANCE, 10);
ObjectSet("Previous", OBJPROP_YDISTANCE, curY);
}
if (dispForecast[0] != "")
{
curY = curY + TxtSize + 4;
ObjectCreate("Forecast", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Forecast", "Forecast: " + dispForecast[0], TxtSize, "Arial Bold", TxtColorForecast);
ObjectSet("Forecast", OBJPROP_CORNER, 0);
ObjectSet("Forecast", OBJPROP_XDISTANCE, 10);
ObjectSet("Forecast", OBJPROP_YDISTANCE, curY);
}
// Do second news event
if (ShowNextTwoEvents)
{
curY = curY + TxtSize + 20;
ObjectCreate("Minutes2", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Minutes2", dispMinutes[1] + " mins until " + dispCountry[1] + ": " + dispTitle[1], TxtSize, "Arial Bold", TxtColorNews);
ObjectSet("Minutes2", OBJPROP_CORNER, 0);
ObjectSet("Minutes2", OBJPROP_XDISTANCE, 10);
ObjectSet("Minutes2", OBJPROP_YDISTANCE, curY);
curY = curY + TxtSize + 4;
ObjectCreate("Impact2", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Impact2", "Impact: " + dispImpact[1], TxtSize, "Arial Bold", TxtColorImpact);
ObjectSet("Impact2", OBJPROP_CORNER, 0);
ObjectSet("Impact2", OBJPROP_XDISTANCE, 10);
ObjectSet("Impact2", OBJPROP_YDISTANCE, curY);
if (dispPrevious[1] != "")
{
curY = curY + TxtSize + 4;
ObjectCreate("Previous2", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Previous2", "Previous: " + dispPrevious[1], TxtSize, "Arial Bold", TxtColorPrevious);
ObjectSet("Previous2", OBJPROP_CORNER, 0);
ObjectSet("Previous2", OBJPROP_XDISTANCE, 10);
ObjectSet("Previous2", OBJPROP_YDISTANCE, curY);
}
if (dispForecast[1] != "")
{
curY = curY + TxtSize + 4;
ObjectCreate("Forecast2", OBJ_LABEL, 0, 0, 0);
ObjectSetText("Forecast2", "Forecast: " + dispForecast[1], TxtSize, "Arial Bold", TxtColorForecast);
ObjectSet("Forecast2", OBJPROP_CORNER, 0);
ObjectSet("Forecast2", OBJPROP_XDISTANCE, 10);
ObjectSet("Forecast2", OBJPROP_YDISTANCE, curY);
}
}
}
int ImpactToNumber(string impact)
{
if (impact == "High")
return (3);
if (impact == "Medium")
return (2);
if (impact == "Low")
return (1);
else
return (0);
}
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, 2);
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;
}
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 = 13;
#import "wininet.dll"
#define INTERNET_FLAG_PRAGMA_NOCACHE 0x00000100 // Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
#define INTERNET_FLAG_NO_CACHE_WRITE 0x04000000 // Does not add the returned entity to the cache.
#define INTERNET_FLAG_RELOAD 0x80000000 // Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.
int InternetOpenA(
string sAgent,
int lAccessType,
string sProxyName="",
string sProxyBypass="",
int lFlags=0
);
int InternetOpenUrlA(
int hInternetSession,
string sUrl,
string sHeaders="",
int lHeadersLength=0,
int lFlags=0,
int lContext=0
);
int InternetReadFile(
int hFile,
string 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 = InternetOpenA(InternetAgent, Internet_Open_Type_Preconfig, "0", "0", 0);
hSession_Direct = InternetOpenA(InternetAgent, Internet_Open_Type_Direct, "0", "0", 0);
}
if (Direct)
{
return(hSession_Direct);
}
else
{
return(hSession_IEType);
}
}
bool GrabWeb(string strUrl, string& strWebPage)
{
int hInternet;
int iResult;
int lReturn[]={1};
string sBuffer="x";
int bytes;
hInternet = InternetOpenUrlA(hSession(FALSE), strUrl, "0", 0,
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_PRAGMA_NOCACHE |
INTERNET_FLAG_RELOAD, 0);
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: " + sBuffer);
if (iResult == 0)
return(false);
bytes = lReturn[0];
strWebPage = StringSubstr(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 + StringSubstr(sBuffer, 0, lReturn[0]);
}
Print("Closing URL web connection"); //added by MN
iResult = InternetCloseHandle(hInternet);
if (iResult == 0)
return(false);
/* if (bWinInetDebug)
{
Log("iResult: " + iResult);
int handle = FileOpen("Grabweb.htm",FILE_BIN|FILE_READ|FILE_WRITE);
FileWriteString(handle,strWebPage,StringLen(strWebPage));
FileClose(handle);
} */
return(true);
}
/*
string GetData(string strWebPage, int nStart, string strLeftTag, string strRightTag, int& nPos)
{
nPos = StringFind(strWebPage,strLeftTag,nStart);
if (nPos == -1)
{
if (bWinInetDebug) Log("GetData(WebPage,"+nStart+","+strLeftTag+","+strRightTag+"): not found, returning empty string and -1");
return("");
}
nPos += StringLen(strLeftTag);
int nEnd = StringFind(strWebPage,strRightTag,nPos+1);
string strData = StringTrimLeft(StringTrimRight(StringSubstr(strWebPage,nPos,nEnd-nPos)));
if (bWinInetDebug) Log("GetData(WebPage,"+nStart+","+strLeftTag+","+strRightTag+") returning "+strData+" and "+nPos);
return(strData);
}
void Goto(string strWebPage, int nStart, string strTag, int& nPos)
{
nPos = StringFind(strWebPage,strTag,nStart);
if (nPos == -1)
{
if (bWinInetDebug) Log("Goto("+nStart+","+strTag+") not found. Returning -1");
return;
}
nPos += StringLen(strTag);
if (bWinInetDebug) Log("Goto("+nStart+","+strTag+") returning "+nPos);
}
void SaveWebPage(string strWebPage, string strID)
{
string strFilename = strID+"_"+Year()+Pad(Month())+Pad(Day())+"-"+Pad(Hour())+Pad(Minute())+Pad(Seconds())+".htm";
int handle = FileOpen(strFilename,FILE_BIN|FILE_WRITE);
FileWriteString(handle,strWebPage,StringLen(strWebPage));
FileClose(handle);
}
string Pad(int n)
{
string strPad = "";
if (n <= 9) strPad = "0";
return(strPad+n);
}
*/
//=================================================================================================
//=================================================================================================
//=================================== 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
// Local timezone in hours, adjusting for daylight saving
double TimeZoneLocal()
{
int TZInfoArray[43];
switch(GetTimeZoneInformation(TZInfoArray))
{
case TIME_ZONE_ID_UNKNOWN:
Print("Error obtaining PC timezone from GetTimeZoneInformation in kernel32.dll. Returning 0");
return(0);
case TIME_ZONE_ID_STANDARD:
return(TZInfoArray[0]/(-60.0));
case TIME_ZONE_ID_DAYLIGHT:
return((TZInfoArray[0]+TZInfoArray[42])/(-60.0));
default:
Print("Unkown return value from GetTimeZoneInformation in kernel32.dll. Returning 0");
return(0);
}
}
// Server timezone in hours
double TimeZoneServer()
{
int ServerToLocalDiffMinutes = (TimeCurrent()-TimeLocal())/60;
// round to nearest 30 minutes to allow for inaccurate PC clock
int nHalfHourDiff = MathRound(ServerToLocalDiffMinutes/30.0);
ServerToLocalDiffMinutes = nHalfHourDiff*30;
return(TimeZoneLocal() + ServerToLocalDiffMinutes/60.0);
}
// Uses local PC time, local PC timezone, and server time to calculate GMT time at arrival of last tick
datetime TimeGMT()
{
// two ways of calculating
// 1. From PC time, which may not be accurate
// 2. From server time. Most accurate except when server is down on weekend
datetime dtGmtFromLocal = TimeLocal() - TimeZoneLocal()*3600;
datetime dtGmtFromServer = TimeCurrent() - TimeZoneServer()*3600;
// return local-derived value if server value is out by more than 5 minutes, eg during weekend
if (dtGmtFromLocal > dtGmtFromServer + 300)
{
return(dtGmtFromLocal);
}
else
{
return(dtGmtFromServer);
}
}
//=================================================================================================
//=================================================================================================
//================================= END IMPORTED FUNCTIONS =====================================
//=================================================================================================
//================================================================================================= |