Hi,
I made an indicator which gives some information about the market, ie ADR, today's range, spread, swaps, remaining candle time etc.
Now I added an economic calendar to it. It works pretty good, but there are two issues I can't solve:
1) My profile contains about 20 chart windows and the MarketInfo indicator is in each of them. The indicator loads the data for the economic calendar from a website (thanks to deVries for his Grab Web) and saves the data as a csv-file in the files-folder. But I don't know how to avoid every single chart to load the website data and save as a csv-file. I need the data only once. A simple solution (sure not the best) is that I check if the current symbol is EURUSD. So only a EURUSD-chart window loads the website data and saves the csv-file. Maybe someone has a better solution for that?
2) That really gives me a headache! If you drag the indicator to a chart you see the information about this chart but no economic calendar. Only after changing the timeframe these data are printed on the screen. I have absolutely no idea why. Hopefully someone can tell me what the problem here is.
This is my code:
add 1) I am saving and reading the csv-file in one 'central' folder using Windows' kernel32.dll function.
add 2) It takes some time to load the information and OnInit() has finished meanwhile - you have to put it in OnTick() - I don't know whether a sleep can help.
Hi gooly,
add 1) Unfortunately, I am not a very experienced programmer. How can this be done? Also in an indicator? And how do you avoid that this is executed more than one time?
add 2) I tried to let Metatrader sleep 5-10 seconds but it doesn't work. I wanted to avoid putting it in OnTick() because it needn't be executed every tick because the data doesn't change. Maybe I must separate the calendar from the other information.
PS. When I open Metatrader I don't see the calendar. But when I compile it once again, everything works fine in all charts. But only after compiling or if I change the timeframe. But then only the chart I changed the timeframe shows the calendar.
hmm - you have to learn how to code! Start with google and the serach here for your problem: "mt4 kernel32.dll" and check whether Windws ..W(..) functions are used for mt4 b600++!
I think there is no other option than checking this in OnTick()!
Applying indicators or EA to a chart is something different than re-compiling or changing the timeframe - don't expect that the same happens: e.g. extern variables aren't reset if you re-compile an indicator being attached to a chart.
Ok, I think I have to live with the solution to let only the EURUSD chart load the data from the internet and save the csv-file. That's not the best but it works.
Now I want to read the file into the array in the OnInit(). Then I sort the data and print the objects in OnTick(). Now there are some compiling errors. The array is an "undeclared identifier" in OnTick(). As long as I use the declaration string DataArray[]; in the OnInit() I can't use the array in OnTick(). And when I declare it in the global part above the OnInit(), the OnInit() doesn't recognize the DataArray as an array. I know this has to do with the position of the declaration. But how can I feed an array in the OnInit() and use the data of this array in OnTick() ? How and where do I have to declare it that it can be used in the whole indicator?
Edit: I just read an article about global and local declarations. So my question could be how an array can be declared as global so that I can use it in all parts of the indicator?
Just in case I use a wrong terminology: I also read about 'initialization' instead of 'declaration'. I mean this:
string DataArray[];
=> Edit: I just read an article about global and local declarations. So my question could be how an array can be declared as global so that I can use it in all parts of the indicator?
It's all in the editor's reference and that means you don't have to wait:
Search either for "scope" or "Visibility"..
I'm not entirely following what you're trying to do but I suspect doing it OnInit is probably not your best option.
But to address your issue with the array... once you have declared your array with global scope you're going to need to:
1. Resize it (unless you've given it a size at declaration)
2. Fill it
3. Read it
Are you doing step 1?
@honest_knave:
I try to do the most what can be done in the OnInit(). For example reading the data from the internet, saving the csv-file to the MT4-folder, read this csv-file into an array and print the objects. These steps must only be done once when the indicator starts. To save the Metatrader from unnecessary calculation-time during the OnTick() I wanted to put everything what is only executed once into the OnInit(). Unfortunately, it only works when I do most of it in the OnTick(). But I use a flag (printNews) to make sure that the whole process of loading the file and filling the array is only executed once.
Here is the code which works fine now. The only thing I am not happy with is that I must be sure that the indicator is running in an EURUSD chart because this chart is loading the data from the internet and save it to a csv-file.
//+------------------------------------------------------------------+ //| MarketInfo.mq4 | //| Copyright 2015, Marcus Riemenschneider | //| http://www.facebook.com/riemenschneider.marcus | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Marcus Riemenschneider" #property link "http://www.facebook.com/riemenschneider.marcus" #property version "1.00" #property strict #property indicator_chart_window #import "Wininet.dll" int InternetOpenW(string, int, string, string, int); int InternetConnectW(int, string, int, string, string, int, int, int); int HttpOpenRequestW(int, string, string, int, string, int, string, int); int InternetOpenUrlW(int, string, string, int, int, int); int InternetReadFile(int, string, int, int& OneInt[]); int InternetCloseHandle(int); #import int FontSize = 8, xPos = 1300, yPos = 5, ySpace = 12; color col = clrBlack, colUpcoming = clrWhite, colPast = clrBlack; double Spread, ATR, DayRange, SpreadModifier, Swap = 0; string strTF, strTime, Today, ObjName, LocalTime, Currency, Event, Impact, DataArray[]; int dbl2pips, decimals, handle, Timeframe; bool printNews, NewsFileOK; //--- functions string TimeToStringNS(datetime when){ string withSep = TimeToStr(when), withOut = StringSubstr(withSep, 0, 4) + StringSubstr(withSep, 5, 2) + StringSubstr(withSep, 8, 2); return(withOut); } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if (MarketInfo(NULL, MODE_PROFITCALCMODE) == 0) { dbl2pips = (int)MathPow(10, Digits-1); SpreadModifier = 0.1; decimals = 1; } else if (MarketInfo(NULL, MODE_PROFITCALCMODE) == 1) { dbl2pips = 1; decimals = Digits; SpreadModifier = MathPow(10, -Digits); } else return(-1); //--- timeframe as string Timeframe = Period(); switch(Timeframe) { case PERIOD_MN1: strTF = "MN1"; break; case PERIOD_W1 : strTF = "W1"; break; case PERIOD_D1 : strTF = "D1"; break; case PERIOD_H4 : strTF = "H4"; break; case PERIOD_H1 : strTF = "H1"; break; case PERIOD_M30: strTF = "M30"; break; case PERIOD_M15: strTF = "M15"; break; case PERIOD_M5 : strTF = "M5"; break; case PERIOD_M1 : strTF = "M1"; break; } //--- analyse current chart size and place info-objects if (ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0) > 1000) { if (ChartGetInteger(0, CHART_SHIFT, 0)) { double ChartShift = ChartGetDouble(0, CHART_SHIFT_SIZE, 0); double ChartWidth = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0); xPos = (int)ChartWidth - (int)MathFloor(ChartWidth/100*ChartShift)+10; } } //--- objects (adr, swap, spread...) for (int i = ObjectsTotal(); i >= 0; i--) { if (StringFind(ObjectName(i), "[Market", 0) == 0) ObjectDelete(ObjectName(i)); } for (int i = 1; i <= 4; i++) { // 4 because I use 4 lines for adr, swap, spread, candle close... ObjName = "[MarketInfo] "+(string)i; ObjectCreate(0, ObjName, OBJ_LABEL, 0, 0, 0); ObjectSet(ObjName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSet(ObjName, OBJPROP_XDISTANCE, xPos); ObjectSet(ObjName, OBJPROP_YDISTANCE, yPos); yPos = yPos+ySpace; } yPos = yPos+ySpace; //--- Grab Web - Copyright © 2014, Tjipke de Vries if (Symbol() == "EURUSD") { // this avoids that all charts with this indicator read the information // from the website and save a csv-file. this csv-file must only be written // once and therefore i chose a pair most traders watch. string date = TimeToStringNS(TimeCurrent()); string URL = "http://calendar.forex-tsd.com/calendar.php?csv=1&date="+date+"&calendar[]=4&gmt=0"; int HttpOpen = InternetOpenW(" ", 0, " "," ",0 ); int HttpConnect = InternetConnectW(HttpOpen, "", 80, "", "", 3, 0, 1); int HttpRequest = InternetOpenUrlW(HttpOpen,URL, NULL, 0, 0, 0); int read[1]; string Buffer = " "; string NEWS = ""; string fileName = "FXCal.csv"; string xmlFileName = fileName; int xmlHandle=FileOpen(xmlFileName, FILE_READ); //File exists if FileOpen return >=0. if (xmlHandle >= 0) {FileClose(xmlHandle); FileDelete(xmlFileName);} xmlHandle=FileOpen(xmlFileName, FILE_CSV|FILE_WRITE, ';'); while (true) { InternetReadFile(HttpRequest, Buffer, StringLen(Buffer), read); if (read[0] > 0) NEWS = NEWS + StringSubstr(Buffer, 0, read[0]); else { FileWriteString(xmlHandle, NEWS); FileClose(xmlHandle); break; } } if (HttpRequest > 0) InternetCloseHandle(HttpRequest); if (HttpConnect > 0) InternetCloseHandle(HttpConnect); if (HttpOpen > 0) InternetCloseHandle(HttpOpen); } //--- csv-file check NewsFileOK = true; handle = FileOpen("FXCal.csv", FILE_READ|FILE_CSV, ';'); if (handle == -1) NewsFileOK = false; if (FileSize(handle) == 0) { FileClose(handle); NewsFileOK = false; } if (NewsFileOK) { printNews = true; } else { Comment(" NO CSV-FILE FOUND"); printNews = false; } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- if (printNews) { // news to be printed just one time while (!FileIsEnding(handle)) { string data = FileReadString(handle); Today = StringSubstr(data, 8, 2); if ((int)Today == Day()) { ArrayResize(DataArray, ArraySize(DataArray)+1); // if new date -> date is stored in the array DataArray[ArraySize(DataArray)-1] = data; // for (int i = 1; i <= 7; i++) { // store all data for this news item data = FileReadString(handle); // ArrayResize(DataArray, ArraySize(DataArray)+1); // DataArray[ArraySize(DataArray)-1] = data; // } //--- here a complete data set for one news item is loaded into the array //--- date, time, currency, news-event, impact (1-3), actual, forecast, previous //--- check timestamp. if missing, set timestamp to 00:00 //--- adjust GMT to local time if (TimeGMTOffset() < 0) { if (DataArray[ArraySize(DataArray)-7] == "") DataArray[ArraySize(DataArray)-7] = "00:00"; else DataArray[ArraySize(DataArray)-7] = TimeToStr(StrToTime(DataArray[ArraySize(DataArray)-7])-TimeGMTOffset(), TIME_MINUTES); } else if (TimeGMTOffset() > 0) { if (DataArray[ArraySize(DataArray)-7] == "") DataArray[ArraySize(DataArray)-7] = "00:00"; else DataArray[ArraySize(DataArray)-7] = TimeToStr(StrToTime(DataArray[ArraySize(DataArray)-7])+TimeGMTOffset(), TIME_MINUTES); } //--- check impact and print only high impact events if ((int)DataArray[ArraySize(DataArray)-4] == 3) { LocalTime= DataArray[ArraySize(DataArray)-7]; Currency = DataArray[ArraySize(DataArray)-6]; Event = DataArray[ArraySize(DataArray)-5]; StringToUpper(Event); ObjName = "[MarketNews] "+(string)Event; ObjectCreate(0, ObjName, OBJ_LABEL, 0, 0, 0); ObjectSet(ObjName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSet(ObjName, OBJPROP_XDISTANCE, xPos); ObjectSet(ObjName, OBJPROP_YDISTANCE, yPos); ObjectSetText(ObjName, LocalTime+" | "+Currency+" | "+Event, FontSize, "Arial", colPast); yPos = yPos+ySpace; } } } FileClose(handle); printNews = false; // news are printed } if (Period() <= PERIOD_D1) { datetime leftTime = (Period()*60)-(TimeCurrent()-Time[0]); strTime = strTF + " CANDLE CLOSES IN " + TimeToStr(leftTime, TIME_SECONDS) + " HRS"; } else strTime = ""; Spread = MarketInfo(Symbol(), MODE_SPREAD); ATR = iATR(NULL, PERIOD_D1, 5, 1); DayRange = iHigh(NULL, PERIOD_D1, 0) - iLow(NULL, PERIOD_D1, 0); ObjectSetText("[MarketInfo] 1", "ADR(5): " + DoubleToStr(ATR*dbl2pips, 2) +" | TODAY: " + DoubleToStr(DayRange*dbl2pips, 2) +" ("+DoubleToStr((DayRange / ATR)*100, 2)+"%)", FontSize, "Arial", col); ObjectSetText("[MarketInfo] 2", "SPREAD: "+DoubleToStr(Spread*SpreadModifier, decimals) +" | RATIO: "+DoubleToStr(Spread/ATR*100*Point, 2)+"%", FontSize, "Arial", col); ObjectSetText("[MarketInfo] 3", "SWAP ("+AccountCurrency() +"): LONG "+DoubleToStr((MarketInfo(NULL, MODE_SWAPLONG)*MarketInfo(NULL, MODE_TICKVALUE)), 2) +" | SHORT "+DoubleToStr((MarketInfo(NULL, MODE_SWAPSHORT)*MarketInfo(NULL, MODE_TICKVALUE)), 2), FontSize, "Arial", col); ObjectSetText("[MarketInfo] 4", strTime, FontSize, "Arial", col); //--- highlight the upcoming news for (int k = ObjectsTotal(); k >= 0; k--) { if (StringFind(ObjectName(k), "[MarketNews]", 0) == 0) { string ObjN = ObjectName(k); string ObjText = ObjectGetString(0, ObjN, OBJPROP_TEXT); string TimeText= StringSubstr(ObjText, 0, 5); color ObjCol = (color)ObjectGetInteger(0, ObjN, OBJPROP_COLOR); datetime RT = StrToTime(TimeText); if (TimeLocal() < RT) { if (ObjCol != colUpcoming) ObjectSet(ObjN, OBJPROP_COLOR, colUpcoming); } else { if (ObjCol != colPast) ObjectSet(ObjN, OBJPROP_COLOR, colPast); } } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Hello mar,
What about when the news calendar gets updated? Would you not rather run it on a timer?
Hey honest_knave,
you mean when it's updated within a day? Does that happen? Usually I only look in the morning at the high impact news which are published today and then I don't look again. So I can't say anything about the intra-day-updates of a news-calendar. Do you think it makes sense to load the data every full hour?
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
I made an indicator which gives some information about the market, ie ADR, today's range, spread, swaps, remaining candle time etc.
Now I added an economic calendar to it. It works pretty good, but there are two issues I can't solve:
1) My profile contains about 20 chart windows and the MarketInfo indicator is in each of them. The indicator loads the data for the economic calendar from a website (thanks to deVries for his Grab Web) and saves the data as a csv-file in the files-folder. But I don't know how to avoid every single chart to load the website data and save as a csv-file. I need the data only once. A simple solution (sure not the best) is that I check if the current symbol is EURUSD. So only a EURUSD-chart window loads the website data and saves the csv-file. Maybe someone has a better solution for that?
2) That really gives me a headache! If you drag the indicator to a chart you see the information about this chart but no economic calendar. Only after changing the timeframe these data are printed on the screen. I have absolutely no idea why. Hopefully someone can tell me what the problem here is.
This is my code: