• Home
  • Forums
  • Trades
  • News
  • Calendar
  • Market
  • Brokers
  • Login
  • Join
  • User/Email: Password:
  • 7:56am
Menu
  • Forums
  • Trades
  • News
  • Calendar
  • Market
  • Brokers
  • Login
  • Join
  • 7:56am
Sister Sites
  • Metals Mine
  • Energy EXCH
  • Crypto Craft

Options

Bookmark Thread

First Page First Unread Last Page Last Post

Printable Version

Similar Threads

Useful trading tips (Recommended) 16 replies

I need some MQ4 help from a real MQ4 programmer 2 replies

Useful Indy to be modified 1 reply

Related and inversely related markets 1 reply

moutaki Mq4+fibo grid Mq4=profit+ease 39 replies

  • Platform Tech
  • /
  • Reply to Thread
  • Subscribe
  • 11
Attachments: Modified, useful MQ4 utilities, indicators, and related tips
Exit Attachments

Modified, useful MQ4 utilities, indicators, and related tips

  • Post #1
  • Quote
  • First Post: Edited Apr 25, 2020 3:08am May 7, 2017 12:36am | Edited Apr 25, 2020 3:08am
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Updated: April 24, 2020: Posted link to Hanover (actually b600 compatible) update of his Daily LinesBoxes(1).mq4 file.
Updated: April 17, 2020: Posted v4 of hanover --- extensible functions b600 (np).mqh in this post#1.

Updated: January 27, 2018: Posted v1 of my P4L Check_Price_Discounts.mq4 (Script) in this post#1.
Updated: July 11, 2017: Posted a link to my P4L ChangeTF-All charts.mq4 (Script)
Updated: May 6, 2017: Posted v3 of Hanover's Handy MQL4 utility functions in this post#1.
Updated: May 6, 2017: Posted a link to a b600 update of Hanover's Display Info All Pairs.mq4
Updated: May 6, 2017: Posted a link to a b600 update of Hanover's Daily LinesBoxes(1).mq4

A COLLECTION of modified, useful MQ4 utilities, indicators, and related tips.

A few other threads that I've started have some useful indicators that I made extensive modifications to, and those will remain in those threads.

Disclaimer: All such code (indicators, EA's, functions, etc.) here and elsewhere, are provided AS-IS, and for use at YOUR OWN RISK! No exceptions!

On occasion, I have some other code or indicators that I'm willing to share, but are best to post in this catch-all thread. I can update post #1 indefinitely with new code, or updates to existing versions. ALWAYS READ POST#1 (FULLY) and CHECK BACK HERE FOR UPDATES!

I don't expect that I will do much to support or make additional changes, unless I happen to find them personally useful and find the time to do so. (Rarely). People can always make suggestions regarding these indicators, or make the changes and post them to the thread. I might create links, or possibly, merge the changes and replace the attachments to this first post #1.

Updates to Hanover's Code:
Hanover has posted some great indicators and utilities over many years, however, for the most part, they are only compatible with MT4 b509, now several years old. The compiled .ex4 files are (still) mostly forward compatible to the latest version (b1065, 23 Mar 2017), but it is a hassle to make changes or updates in the old version with the old compiler. (For programmers only).

Hanover's Handy MQL4 utility functions

Most of his indicators make use of an extensive set of non-proprietary (np) functions which he has shared, but are for b509 only. I made a v2 update for b600+ in 2014, which "compiled", but still has some significant changes in behavior and was therefore not quite correct enough. I have a new v3 update! (May 2017). I found and fixed a simple bug but which had a profound impact on many other string functions. While still not fully tested, I did compile a few of his indicators with much better success.

NOTE: These functions are useful as they are. But to combine them with old source code by Hanover will almost certainly require a few additional changes to the main indicator source to be fully b600 compatible. It is also quite probable that there are still more bugs with this b600 utility code. The only way to uncover all of the changes since b509 is to actually use each function, and extensively test all behaviors, a task which I am unwilling to do! Nevertheless, the task is now much easier, and closer to a point of true b600 compatibility than before. In the "extensible functions" section, definitely read the "USAGE:" section for specific and necessary changes you must (or should) make to fix whatever main indicator code of his your are trying to compile. The list is incomplete. You keep compiling and fix all errors at a minimum. Some warnings you can ignore, but not always. Sometimes it will compile, but still won't work, and then it's harder. I have included a section (for programmers) for how to make simple changes in b509 code which you compile, and the output generates code for a b600 *script*, which will compare the b509 return values against the b600 values. Any differences are likely bugs.

2020-Apr-17: v4 released, of Hanover's b600+ utility functions (an #include file).

  1. Attached File
    File Type: mqh hanover --- extensible functions b600 (np).mqh   331 KB | 213 downloads | Uploaded Apr 17, 2020 5:18am
  2. Note: In v4, the 'function header' file was combined with the above 'extensible functions' file.

2017-May-06: v3 released, of Hanover's utility functions (#include files).

  1. Old v3 removed (851 downloads): hanover --- function header b600 (np).mqh
  2. Old v3 removed (834 downloads): hanover --- extensible functions b600 (np).mqh
  3. Attached File
    File Type: mqh hanover --- function header b509 (np).mqh   17 KB | 553 downloads
  4. Attached File
    File Type: mqh hanover --- extensible functions b509 (np).mqh   139 KB | 559 downloads
  5. Note, these pairs support both b600 and b509 versions, but they are simple variations of the same base code. (Search for "b600_b509"). These should function the same as the original, but it will be easier to maintain both if file differences are minimal.
  6. These are based on the b509 originals posted 2016-04-29 by hanover.
    PLEASE refer to Hanover's thread for more details on his Utility functions.

     

    1. hanover --- function header (np).mqh
    2. hanover --- extensible functions (np).mqh


2017-May-06: My b600 variation of Hanover's Display Info All Pairs.mq4 that uses the b600 utility (include) files above.

2017-May-06: My b600 variation of Hanover's Daily LinesBoxes(1).mq4 that uses the b600 utility (include) files above.
2020-Apr-24: NOTE: See Hanover (actually b600 compatible) update here.

2017-July-11: My variation of someone else's TF script: P4L ChangeTF-All charts.mq4 (Script)

2018-Jan-27: My script (below), P4L Check_Price_Discounts.mq4 (Script) to measure broker "discounts", the difference between Order Bid/Ask prices vs. those Chart Bid/Ask prices that display on a chart (Bid/Ask lines). For some brokers, due to spread "discounts", the prices differ, as discussed here.

Attached File
File Type: mq4 P4L Check_Price_Discounts.mq4   5 KB | 362 downloads | Uploaded Jan 27, 2018 9:55pm
  • Post #2
  • Quote
  • Edited at 3:10am May 7, 2017 1:37am | Edited at 3:10am
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Post #1 has the first two updates:

2017-May-06: v3 released, of Hanover's "Handy MQL4 utility functions" (include files).

  1. Files posted:

    1. hanover --- function header b600 (np).mqh
    2. hanover --- extensible functions b600 (np).mqh
    3. hanover --- function header b509 (np).mqh
    4. hanover --- extensible functions b509 (np).mqh


  2. PLEASE refer to Hanover's thread for more details on his original (b509) Utility functions.

    1. hanover --- function header (np).mqh
    2. hanover --- extensible functions (np).mqh



Hanover's Display Info All Pairs.mq4:
2017-May-06: My b600 variation of Hanover's "Display Info All Pairs.mq4" that uses the new b600 utility (include) files above, is posted here .

1
  • Post #3
  • Quote
  • May 7, 2017 2:50am May 7, 2017 2:50am
  •  hanover
  • Joined Sep 2006 | Status: ... | 8,081 Posts
P4L,

Many thanks for your time and effort, and for making this update publicly available. I expect that your updated MQH files will be widely used, as most programmers prefer to enjoy the benefits offered by the build >=600 MetaEditor/compiler and its facilities (I'm possibly the only programmer still using b509, LOL).

I have updated post #1 here with a link back to this thread. With your permission, I'll also include all four of your MQH files in post #1 as standard issue in the ZIP files that I've been posting with the source code. I will gradually get around to updating them all, whenever a new release for each such indicator gets posted.

Thanks again,
David
  • Post #4
  • Quote
  • May 7, 2017 3:05am May 7, 2017 3:05am
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Quoting hanover
Disliked
P4L, Many thanks for your time and effort, and for making this update publicly available. I expect that your updated MQH files will be widely used, as most programmers prefer to enjoy the benefits offered by the build >=600 MetaEditor/compiler and its facilities (I'm possibly the only programmer still using b509, LOL). I have updated post #1 here with a link back to this thread. With your permission, I'll also include all four of your MQH files in post #1 as standard issue in the...
Ignored
Hi David,

Sure, but the biggest thanks goes to you for providing so many useful original indicators and utilities! You may package my versions as best you see fit. The source of each of the 4 files has a URL for this thread, so no matter what, people can find post#1 of this thread (and of your utility functions thread of course).

And, zip files are very useful, so I insist, package them up!

However... try out these b600 libraries yourself, or, wait for the dust to settle on the few updates I've already posted. I am not certain all is working, because I am unfamiliar with the normal operation of some. If you compare a new b600 against the b509 .ex4, and see any differences, please point them out. There could well be further bug(s), but so far, I am encourage with the positive results to migrate a few so far.

Best regards,
Kent (pips4life)
  • Post #5
  • Quote
  • May 7, 2017 3:06am May 7, 2017 3:06am
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Post #1 has another update:

Hanover's Daily LinesBoxes(1).mq4:
2017-May-06: My b600 variation of Hanover's "Daily LinesBoxes(1).mq4" that uses the b600 utility (include) files above, is posted here .
  • Post #6
  • Quote
  • Sep 9, 2017 5:34pm Sep 9, 2017 5:34pm
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Hi David,

I just want to say THANKS, specifically for your "StrToDate" utility function! I used mask "MM/DD/YYYY MM:II" and delim " :/" to handle variable-width (1-or-2 digit Days/Months) to convert my string dates (from ForexFactory, actually) into datetime values.

The built-in MT4 StringToTime (or StrToTime) did not work, since standard format is YYYY/MM/DD hh:mm:ss It also handles a slight variation, DD/MM/YYYY hh:mm:ss but that's not the one I needed. (It converted 9/7/2017 as July 9, but I want Sep 7).

(Personally, I wish the whole world would use YYYY/MM/DD (most-significant "digit" to "least", like MT4) but that's not up to me ).

As you know, that would have been a pain for me to write from scratch, so I thank you!

I could have used "#include" as in:
#include <hanover --- function header b600 (np).mqh>
#include <hanover --- extensible functions b600 (np).mqh>

... but instead, I cut-and-pasted what I needed to keep my code independent, so really I'm using all of these:
StrToDate (requires also the ones below)
StringUpper
StringRightPad
StrToNumber
NumberToStr
stringSubstrOld
StringTrim
StringLeftTrim
StringRightTrim
StringRepeat
MathFix
MathSign
  • Post #7
  • Quote
  • Sep 10, 2017 5:28am Sep 10, 2017 5:28am
  •  hanover
  • Joined Sep 2006 | Status: ... | 8,081 Posts
Quoting pips4life
Disliked
Hi David, I just want to say THANKS, specifically for your "StrToDate" utility function! ......
Ignored
No problem, I'm glad you find it useful!
Quote
Disliked
Personally, I wish the whole world would use YYYY/MM/DD
I totally agree that YYYY/MM/DD is the most logical way to express dates, it makes life easy when it comes to sorting data chronologically. And exactly as you say, when you see 9/7/2017 it's not possible to know at first glance whether it's July 9 or Sept 7. Universal use of YYYY/MM/DD would remove this ambiguity.
  • Post #8
  • Quote
  • Apr 11, 2020 7:15am Apr 11, 2020 7:15am
  •  TraderWolf2
  • | Joined Apr 2020 | Status: Junior Member | 1 Post
I was initially looking for a mql easter sunday calculation and therefore glad to find one here.
After downloading different version of the files provided here I found out that non is compiling out of the box.
I corrected these files locally, maybe I did wrong, but also the easter caculation is not working, it's returning wrong results.
Can anybody gelp me further?
  • Post #9
  • Quote
  • Edited Apr 12, 2020 4:25pm Apr 11, 2020 7:01pm | Edited Apr 12, 2020 4:25pm
  •  hanover
  • Joined Sep 2006 | Status: ... | 8,081 Posts
Quoting TraderWolf2
Disliked
I was initially looking for a mql easter sunday calculation and therefore glad to find one here. After downloading different version of the files provided here I found out that non is compiling out of the box. I corrected these files locally, maybe I did wrong, but also the easter caculation is not working, it's returning wrong results. Can anybody gelp me further?
Ignored
If you want to get straight to the latest solution, please ignore my ramble in this post, and simply replace the YMDtoDate() and EasterDay() functions with the code posted in post #11. This will fix the bug in the EasterDay() calculation, and you should be good to go. Many thanks to pips4life for pointing out the bug. I will send pips4life an updated version of hanover --- extensible functions b600 (np).mqh (with the updated version of these functions) so that he can update post #1.
____________________________
Attached Image (click to enlarge)
Click to Enlarge

Name: PPI 920.png
Size: 309 KB
This appears to be caused by a bug in MT4. In the above screenshot, I have compared the results using the build 509 compiler with the current compiler.
The calculation function in both versions is exactly the same, as follows:
Inserted Code
//+------------------------------------------------------------------+
datetime EasterDay(int year)   {
//+------------------------------------------------------------------+
//   returns the MT4time value of Easter Sunday for the given (4 digit) year
//   e.g. DateToStr(EasterDay(2011),"M/D/Y") returns "04/24/2011"
  int result = MathMod(225-11*MathMod(year,19)-21,30)+21;
  if (result>48) result--;
  result = result+7-MathMod(year+MathInt(year/4)+result+1,7);
  result = YMDtoDate(year,3,1)+(result-1)*86400;
  return(result);
}
This is based on Carter's calculation formula, which I got from the website URL shown in the attached xls. Unfortunately the website no longer exists.
Attached File
File Type: xls Easter Day calculation.xls   148 KB | 76 downloads

You can run the following ex4 to verify the result displayed in the screenshot. It uses the above calculation and was compiled using build 509.
Attached File
File Type: ex4 test3 (script).ex4   23 KB | 65 downloads

If the math functions in MT4 are buggy, sorry but there's not much I can do about it.
____________________________________

[EDIT] Here is a 'brute force' approach that should give the correct result, from any year between 1971 and 2037:
Inserted Code
//+------------------------------------------------------------------+
datetime EasterSunday(int year)   {
//+------------------------------------------------------------------+
//   returns the MT4time value of Easter Sunday for the given (4 digit) year
//   e.g. DateToStr(EasterSunday(2011),"M/D/Y") returns "04/24/2011"
  int retval = 0;
  switch (year)  {
    case 1971 :  retval =   40176000;  break;    // 1971/04/11
    case 1972 :  retval =   71020800;  break;    // 1972/04/02
    case 1973 :  retval =  104284800;  break;    // 1973/04/22
    case 1974 :  retval =  135129600;  break;    // 1974/04/14
    case 1975 :  retval =  165369600;  break;    // 1975/03/30
    case 1976 :  retval =  198633600;  break;    // 1976/04/18
    case 1977 :  retval =  229478400;  break;    // 1977/04/10
    case 1978 :  retval =  259718400;  break;    // 1978/03/26
    case 1979 :  retval =  292982400;  break;    // 1979/04/15
    case 1980 :  retval =  323827200;  break;    // 1980/04/06
    case 1981 :  retval =  356486400;  break;    // 1981/04/19
    case 1982 :  retval =  387331200;  break;    // 1982/04/11
    case 1983 :  retval =  418176000;  break;    // 1983/04/03
    case 1984 :  retval =  451440000;  break;    // 1984/04/22
    case 1985 :  retval =  481680000;  break;    // 1985/04/07
    case 1986 :  retval =  512524800;  break;    // 1986/03/30
    case 1987 :  retval =  545788800;  break;    // 1987/04/19
    case 1988 :  retval =  576028800;  break;    // 1988/04/03
    case 1989 :  retval =  606873600;  break;    // 1989/03/26
    case 1990 :  retval =  640137600;  break;    // 1990/04/15
    case 1991 :  retval =  670377600;  break;    // 1991/03/31
    case 1992 :  retval =  703641600;  break;    // 1992/04/19
    case 1993 :  retval =  734486400;  break;    // 1993/04/11
    case 1994 :  retval =  765331200;  break;    // 1994/04/03
    case 1995 :  retval =  797990400;  break;    // 1995/04/16
    case 1996 :  retval =  828835200;  break;    // 1996/04/07
    case 1997 :  retval =  859680000;  break;    // 1997/03/30
    case 1998 :  retval =  892339200;  break;    // 1998/04/12
    case 1999 :  retval =  923184000;  break;    // 1999/04/04
    case 2000 :  retval =  956448000;  break;    // 2000/04/23
    case 2001 :  retval =  987292800;  break;    // 2001/04/15
    case 2002 :  retval = 1017532800;  break;    // 2002/03/31
    case 2003 :  retval = 1050796800;  break;    // 2003/04/20
    case 2004 :  retval = 1081641600;  break;    // 2004/04/11
    case 2005 :  retval = 1111881600;  break;    // 2005/03/27
    case 2006 :  retval = 1145145600;  break;    // 2006/04/16
    case 2007 :  retval = 1175990400;  break;    // 2007/04/08
    case 2008 :  retval = 1206230400;  break;    // 2008/03/23
    case 2009 :  retval = 1239494400;  break;    // 2009/04/12
    case 2010 :  retval = 1270339200;  break;    // 2010/04/04
    case 2011 :  retval = 1303603200;  break;    // 2011/04/24
    case 2012 :  retval = 1333843200;  break;    // 2012/04/08
    case 2013 :  retval = 1364688000;  break;    // 2013/03/31
    case 2014 :  retval = 1397952000;  break;    // 2014/04/20
    case 2015 :  retval = 1428192000;  break;    // 2015/04/05
    case 2016 :  retval = 1459036800;  break;    // 2016/03/27
    case 2017 :  retval = 1492300800;  break;    // 2017/04/16
    case 2018 :  retval = 1522540800;  break;    // 2018/04/01
    case 2019 :  retval = 1555804800;  break;    // 2019/04/21
    case 2020 :  retval = 1586649600;  break;    // 2020/04/12
    case 2021 :  retval = 1617494400;  break;    // 2021/04/04
    case 2022 :  retval = 1650153600;  break;    // 2022/04/17
    case 2023 :  retval = 1680998400;  break;    // 2023/04/09
    case 2024 :  retval = 1711843200;  break;    // 2024/03/31
    case 2025 :  retval = 1745107200;  break;    // 2025/04/20
    case 2026 :  retval = 1775347200;  break;    // 2026/04/05
    case 2027 :  retval = 1806192000;  break;    // 2027/03/28
    case 2028 :  retval = 1839456000;  break;    // 2028/04/16
    case 2029 :  retval = 1869696000;  break;    // 2029/04/01
    case 2030 :  retval = 1902960000;  break;    // 2030/04/21
    case 2031 :  retval = 1933804800;  break;    // 2031/04/13
    case 2032 :  retval = 1964044800;  break;    // 2032/03/28
    case 2033 :  retval = 1997308800;  break;    // 2033/04/17
    case 2034 :  retval = 2028153600;  break;    // 2034/04/09
    case 2035 :  retval = 2058393600;  break;    // 2035/03/25
    case 2036 :  retval = 2091657600;  break;    // 2036/04/13
    case 2037 :  retval = 2122502400;  break;    // 2037/04/05
    default   :  retval = 0;
  }
  return(retval);
}

Here is a useful URL for the dates from 1901 to 2078, that can be used to verify the result. It also includes another calculation algorithm near the bottom of the page.

=====================================================================

[EDIT 2]

Quoting hanover
Disliked
[EDIT] Here is a 'brute force' approach that should give the correct result, from any year between 1971 and 2037
Ignored
And for anybody who wants it, here is a version that will return Easter Sunday for any year between 1900 and 2099 (simply delete any lines that you don't require). There is no calculation formula; I simply sourced the dates directly from this URL. Note that the result must be returned as a string, as MT4 does not allow fore dates earlier than 1970/01/01 or where the datetime value exceeds the maximum allowed 4-byte integer value of 2,147,483,647 (which occurs at 2038/01/19 03:14:07).
Inserted Code
//+------------------------------------------------------------------+
string EasterSunday(int year)   {
//+------------------------------------------------------------------+
//  returns as a string yyyy.mm.dd of Easter Sunday for the given year (yyyy)
//  e.g. EasterSunday(2011) returns "2011.04.24"
  string retval = 0;
  switch (year)  {
    case 1900 :  retval = "1900.04.15";  break;    // Sun  15 Apr 1900
    case 1901 :  retval = "1901.04.07";  break;    // Sun  07 Apr 1901
    case 1902 :  retval = "1902.03.30";  break;    // Sun  30 Mar 1902
    case 1903 :  retval = "1903.04.12";  break;    // Sun  12 Apr 1903
    case 1904 :  retval = "1904.04.03";  break;    // Sun  03 Apr 1904
    case 1905 :  retval = "1905.04.23";  break;    // Sun  23 Apr 1905
    case 1906 :  retval = "1906.04.15";  break;    // Sun  15 Apr 1906
    case 1907 :  retval = "1907.03.31";  break;    // Sun  31 Mar 1907
    case 1908 :  retval = "1908.04.19";  break;    // Sun  19 Apr 1908
    case 1909 :  retval = "1909.04.11";  break;    // Sun  11 Apr 1909
    case 1910 :  retval = "1910.03.27";  break;    // Sun  27 Mar 1910
    case 1911 :  retval = "1911.04.16";  break;    // Sun  16 Apr 1911
    case 1912 :  retval = "1912.04.07";  break;    // Sun  07 Apr 1912
    case 1913 :  retval = "1913.03.23";  break;    // Sun  23 Mar 1913
    case 1914 :  retval = "1914.04.12";  break;    // Sun  12 Apr 1914
    case 1915 :  retval = "1915.04.04";  break;    // Sun  04 Apr 1915
    case 1916 :  retval = "1916.04.23";  break;    // Sun  23 Apr 1916
    case 1917 :  retval = "1917.04.08";  break;    // Sun  08 Apr 1917
    case 1918 :  retval = "1918.03.31";  break;    // Sun  31 Mar 1918
    case 1919 :  retval = "1919.04.20";  break;    // Sun  20 Apr 1919
    case 1920 :  retval = "1920.04.04";  break;    // Sun  04 Apr 1920
    case 1921 :  retval = "1921.03.27";  break;    // Sun  27 Mar 1921
    case 1922 :  retval = "1922.04.16";  break;    // Sun  16 Apr 1922
    case 1923 :  retval = "1923.04.01";  break;    // Sun  01 Apr 1923
    case 1924 :  retval = "1924.04.20";  break;    // Sun  20 Apr 1924
    case 1925 :  retval = "1925.04.12";  break;    // Sun  12 Apr 1925
    case 1926 :  retval = "1926.04.04";  break;    // Sun  04 Apr 1926
    case 1927 :  retval = "1927.04.17";  break;    // Sun  17 Apr 1927
    case 1928 :  retval = "1928.04.08";  break;    // Sun  08 Apr 1928
    case 1929 :  retval = "1929.03.31";  break;    // Sun  31 Mar 1929
    case 1930 :  retval = "1930.04.20";  break;    // Sun  20 Apr 1930
    case 1931 :  retval = "1931.04.05";  break;    // Sun  05 Apr 1931
    case 1932 :  retval = "1932.03.27";  break;    // Sun  27 Mar 1932
    case 1933 :  retval = "1933.04.16";  break;    // Sun  16 Apr 1933
    case 1934 :  retval = "1934.04.01";  break;    // Sun  01 Apr 1934
    case 1935 :  retval = "1935.04.21";  break;    // Sun  21 Apr 1935
    case 1936 :  retval = "1936.04.12";  break;    // Sun  12 Apr 1936
    case 1937 :  retval = "1937.03.28";  break;    // Sun  28 Mar 1937
    case 1938 :  retval = "1938.04.17";  break;    // Sun  17 Apr 1938
    case 1939 :  retval = "1939.04.09";  break;    // Sun  09 Apr 1939
    case 1940 :  retval = "1940.03.24";  break;    // Sun  24 Mar 1940
    case 1941 :  retval = "1941.04.13";  break;    // Sun  13 Apr 1941
    case 1942 :  retval = "1942.04.05";  break;    // Sun  05 Apr 1942
    case 1943 :  retval = "1943.04.25";  break;    // Sun  25 Apr 1943
    case 1944 :  retval = "1944.04.09";  break;    // Sun  09 Apr 1944
    case 1945 :  retval = "1945.04.01";  break;    // Sun  01 Apr 1945
    case 1946 :  retval = "1946.04.21";  break;    // Sun  21 Apr 1946
    case 1947 :  retval = "1947.04.06";  break;    // Sun  06 Apr 1947
    case 1948 :  retval = "1948.03.28";  break;    // Sun  28 Mar 1948
    case 1949 :  retval = "1949.04.17";  break;    // Sun  17 Apr 1949
    case 1950 :  retval = "1950.04.09";  break;    // Sun  09 Apr 1950
    case 1951 :  retval = "1951.03.25";  break;    // Sun  25 Mar 1951
    case 1952 :  retval = "1952.04.13";  break;    // Sun  13 Apr 1952
    case 1953 :  retval = "1953.04.05";  break;    // Sun  05 Apr 1953
    case 1954 :  retval = "1954.04.18";  break;    // Sun  18 Apr 1954
    case 1955 :  retval = "1955.04.10";  break;    // Sun  10 Apr 1955
    case 1956 :  retval = "1956.04.01";  break;    // Sun  01 Apr 1956
    case 1957 :  retval = "1957.04.21";  break;    // Sun  21 Apr 1957
    case 1958 :  retval = "1958.04.06";  break;    // Sun  06 Apr 1958
    case 1959 :  retval = "1959.03.29";  break;    // Sun  29 Mar 1959
    case 1960 :  retval = "1960.04.17";  break;    // Sun  17 Apr 1960
    case 1961 :  retval = "1961.04.02";  break;    // Sun  02 Apr 1961
    case 1962 :  retval = "1962.04.22";  break;    // Sun  22 Apr 1962
    case 1963 :  retval = "1963.04.14";  break;    // Sun  14 Apr 1963
    case 1964 :  retval = "1964.03.29";  break;    // Sun  29 Mar 1964
    case 1965 :  retval = "1965.04.18";  break;    // Sun  18 Apr 1965
    case 1966 :  retval = "1966.04.10";  break;    // Sun  10 Apr 1966
    case 1967 :  retval = "1967.03.26";  break;    // Sun  26 Mar 1967
    case 1968 :  retval = "1968.04.14";  break;    // Sun  14 Apr 1968
    case 1969 :  retval = "1969.04.06";  break;    // Sun  06 Apr 1969
    case 1970 :  retval = "1970.03.29";  break;    // Sun  29 Mar 1970
    case 1971 :  retval = "1971.04.11";  break;    // Sun  11 Apr 1971
    case 1972 :  retval = "1972.04.02";  break;    // Sun  02 Apr 1972
    case 1973 :  retval = "1973.04.22";  break;    // Sun  22 Apr 1973
    case 1974 :  retval = "1974.04.14";  break;    // Sun  14 Apr 1974
    case 1975 :  retval = "1975.03.30";  break;    // Sun  30 Mar 1975
    case 1976 :  retval = "1976.04.18";  break;    // Sun  18 Apr 1976
    case 1977 :  retval = "1977.04.10";  break;    // Sun  10 Apr 1977
    case 1978 :  retval = "1978.03.26";  break;    // Sun  26 Mar 1978
    case 1979 :  retval = "1979.04.15";  break;    // Sun  15 Apr 1979
    case 1980 :  retval = "1980.04.06";  break;    // Sun  06 Apr 1980
    case 1981 :  retval = "1981.04.19";  break;    // Sun  19 Apr 1981
    case 1982 :  retval = "1982.04.11";  break;    // Sun  11 Apr 1982
    case 1983 :  retval = "1983.04.03";  break;    // Sun  03 Apr 1983
    case 1984 :  retval = "1984.04.22";  break;    // Sun  22 Apr 1984
    case 1985 :  retval = "1985.04.07";  break;    // Sun  07 Apr 1985
    case 1986 :  retval = "1986.03.30";  break;    // Sun  30 Mar 1986
    case 1987 :  retval = "1987.04.19";  break;    // Sun  19 Apr 1987
    case 1988 :  retval = "1988.04.03";  break;    // Sun  03 Apr 1988
    case 1989 :  retval = "1989.03.26";  break;    // Sun  26 Mar 1989
    case 1990 :  retval = "1990.04.15";  break;    // Sun  15 Apr 1990
    case 1991 :  retval = "1991.03.31";  break;    // Sun  31 Mar 1991
    case 1992 :  retval = "1992.04.19";  break;    // Sun  19 Apr 1992
    case 1993 :  retval = "1993.04.11";  break;    // Sun  11 Apr 1993
    case 1994 :  retval = "1994.04.03";  break;    // Sun  03 Apr 1994
    case 1995 :  retval = "1995.04.16";  break;    // Sun  16 Apr 1995
    case 1996 :  retval = "1996.04.07";  break;    // Sun  07 Apr 1996
    case 1997 :  retval = "1997.03.30";  break;    // Sun  30 Mar 1997
    case 1998 :  retval = "1998.04.12";  break;    // Sun  12 Apr 1998
    case 1999 :  retval = "1999.04.04";  break;    // Sun  04 Apr 1999
    case 2000 :  retval = "2000.04.23";  break;    // Sun  23 Apr 2000
    case 2001 :  retval = "2001.04.15";  break;    // Sun  15 Apr 2001
    case 2002 :  retval = "2002.03.31";  break;    // Sun  31 Mar 2002
    case 2003 :  retval = "2003.04.20";  break;    // Sun  20 Apr 2003
    case 2004 :  retval = "2004.04.11";  break;    // Sun  11 Apr 2004
    case 2005 :  retval = "2005.03.27";  break;    // Sun  27 Mar 2005
    case 2006 :  retval = "2006.04.16";  break;    // Sun  16 Apr 2006
    case 2007 :  retval = "2007.04.08";  break;    // Sun  08 Apr 2007
    case 2008 :  retval = "2008.03.23";  break;    // Sun  23 Mar 2008
    case 2009 :  retval = "2009.04.12";  break;    // Sun  12 Apr 2009
    case 2010 :  retval = "2010.04.04";  break;    // Sun  04 Apr 2010
    case 2011 :  retval = "2011.04.24";  break;    // Sun  24 Apr 2011
    case 2012 :  retval = "2012.04.08";  break;    // Sun  08 Apr 2012
    case 2013 :  retval = "2013.03.31";  break;    // Sun  31 Mar 2013
    case 2014 :  retval = "2014.04.20";  break;    // Sun  20 Apr 2014
    case 2015 :  retval = "2015.04.05";  break;    // Sun  05 Apr 2015
    case 2016 :  retval = "2016.03.27";  break;    // Sun  27 Mar 2016
    case 2017 :  retval = "2017.04.16";  break;    // Sun  16 Apr 2017
    case 2018 :  retval = "2018.04.01";  break;    // Sun  01 Apr 2018
    case 2019 :  retval = "2019.04.21";  break;    // Sun  21 Apr 2019
    case 2020 :  retval = "2020.04.12";  break;    // Sun  12 Apr 2020
    case 2021 :  retval = "2021.04.04";  break;    // Sun  04 Apr 2021
    case 2022 :  retval = "2022.04.17";  break;    // Sun  17 Apr 2022
    case 2023 :  retval = "2023.04.09";  break;    // Sun  09 Apr 2023
    case 2024 :  retval = "2024.03.31";  break;    // Sun  31 Mar 2024
    case 2025 :  retval = "2025.04.20";  break;    // Sun  20 Apr 2025
    case 2026 :  retval = "2026.04.05";  break;    // Sun  05 Apr 2026
    case 2027 :  retval = "2027.03.28";  break;    // Sun  28 Mar 2027
    case 2028 :  retval = "2028.04.16";  break;    // Sun  16 Apr 2028
    case 2029 :  retval = "2029.04.01";  break;    // Sun  01 Apr 2029
    case 2030 :  retval = "2030.04.21";  break;    // Sun  21 Apr 2030
    case 2031 :  retval = "2031.04.13";  break;    // Sun  13 Apr 2031
    case 2032 :  retval = "2032.03.28";  break;    // Sun  28 Mar 2032
    case 2033 :  retval = "2033.04.17";  break;    // Sun  17 Apr 2033
    case 2034 :  retval = "2034.04.09";  break;    // Sun  09 Apr 2034
    case 2035 :  retval = "2035.03.25";  break;    // Sun  25 Mar 2035
    case 2036 :  retval = "2036.04.13";  break;    // Sun  13 Apr 2036
    case 2037 :  retval = "2037.04.05";  break;    // Sun  05 Apr 2037
    case 2038 :  retval = "2038.04.25";  break;    // Sun  25 Apr 2038
    case 2039 :  retval = "2039.04.10";  break;    // Sun  10 Apr 2039
    case 2040 :  retval = "2040.04.01";  break;    // Sun  01 Apr 2040
    case 2041 :  retval = "2041.04.21";  break;    // Sun  21 Apr 2041
    case 2042 :  retval = "2042.04.06";  break;    // Sun  06 Apr 2042
    case 2043 :  retval = "2043.03.29";  break;    // Sun  29 Mar 2043
    case 2044 :  retval = "2044.04.17";  break;    // Sun  17 Apr 2044
    case 2045 :  retval = "2045.04.09";  break;    // Sun  09 Apr 2045
    case 2046 :  retval = "2046.03.25";  break;    // Sun  25 Mar 2046
    case 2047 :  retval = "2047.04.14";  break;    // Sun  14 Apr 2047
    case 2048 :  retval = "2048.04.05";  break;    // Sun  05 Apr 2048
    case 2049 :  retval = "2049.04.18";  break;    // Sun  18 Apr 2049
    case 2050 :  retval = "2050.04.10";  break;    // Sun  10 Apr 2050
    case 2051 :  retval = "2051.04.02";  break;    // Sun  02 Apr 2051
    case 2052 :  retval = "2052.04.21";  break;    // Sun  21 Apr 2052
    case 2053 :  retval = "2053.04.06";  break;    // Sun  06 Apr 2053
    case 2054 :  retval = "2054.03.29";  break;    // Sun  29 Mar 2054
    case 2055 :  retval = "2055.04.18";  break;    // Sun  18 Apr 2055
    case 2056 :  retval = "2056.04.02";  break;    // Sun  02 Apr 2056
    case 2057 :  retval = "2057.04.22";  break;    // Sun  22 Apr 2057
    case 2058 :  retval = "2058.04.14";  break;    // Sun  14 Apr 2058
    case 2059 :  retval = "2059.03.30";  break;    // Sun  30 Mar 2059
    case 2060 :  retval = "2060.04.18";  break;    // Sun  18 Apr 2060
    case 2061 :  retval = "2061.04.10";  break;    // Sun  10 Apr 2061
    case 2062 :  retval = "2062.03.26";  break;    // Sun  26 Mar 2062
    case 2063 :  retval = "2063.04.15";  break;    // Sun  15 Apr 2063
    case 2064 :  retval = "2064.04.06";  break;    // Sun  06 Apr 2064
    case 2065 :  retval = "2065.03.29";  break;    // Sun  29 Mar 2065
    case 2066 :  retval = "2066.04.11";  break;    // Sun  11 Apr 2066
    case 2067 :  retval = "2067.04.03";  break;    // Sun  03 Apr 2067
    case 2068 :  retval = "2068.04.22";  break;    // Sun  22 Apr 2068
    case 2069 :  retval = "2069.04.14";  break;    // Sun  14 Apr 2069
    case 2070 :  retval = "2070.03.30";  break;    // Sun  30 Mar 2070
    case 2071 :  retval = "2071.04.19";  break;    // Sun  19 Apr 2071
    case 2072 :  retval = "2072.04.10";  break;    // Sun  10 Apr 2072
    case 2073 :  retval = "2073.03.26";  break;    // Sun  26 Mar 2073
    case 2074 :  retval = "2074.04.15";  break;    // Sun  15 Apr 2074
    case 2075 :  retval = "2075.04.07";  break;    // Sun  07 Apr 2075
    case 2076 :  retval = "2076.04.19";  break;    // Sun  19 Apr 2076
    case 2077 :  retval = "2077.04.11";  break;    // Sun  11 Apr 2077
    case 2078 :  retval = "2078.04.03";  break;    // Sun  03 Apr 2078
    case 2079 :  retval = "2079.04.23";  break;    // Sun  23 Apr 2079
    case 2080 :  retval = "2080.04.07";  break;    // Sun  07 Apr 2080
    case 2081 :  retval = "2081.03.30";  break;    // Sun  30 Mar 2081
    case 2082 :  retval = "2082.04.19";  break;    // Sun  19 Apr 2082
    case 2083 :  retval = "2083.04.04";  break;    // Sun  04 Apr 2083
    case 2084 :  retval = "2084.03.26";  break;    // Sun  26 Mar 2084
    case 2085 :  retval = "2085.04.15";  break;    // Sun  15 Apr 2085
    case 2086 :  retval = "2086.03.31";  break;    // Sun  31 Mar 2086
    case 2087 :  retval = "2087.04.20";  break;    // Sun  20 Apr 2087
    case 2088 :  retval = "2088.04.11";  break;    // Sun  11 Apr 2088
    case 2089 :  retval = "2089.04.03";  break;    // Sun  03 Apr 2089
    case 2090 :  retval = "2090.04.16";  break;    // Sun  16 Apr 2090
    case 2091 :  retval = "2091.04.08";  break;    // Sun  08 Apr 2091
    case 2092 :  retval = "2092.03.30";  break;    // Sun  30 Mar 2092
    case 2093 :  retval = "2093.04.12";  break;    // Sun  12 Apr 2093
    case 2094 :  retval = "2094.04.04";  break;    // Sun  04 Apr 2094
    case 2095 :  retval = "2095.04.24";  break;    // Sun  24 Apr 2095
    case 2096 :  retval = "2096.04.15";  break;    // Sun  15 Apr 2096
    case 2097 :  retval = "2097.03.31";  break;    // Sun  31 Mar 2097
    case 2098 :  retval = "2098.04.20";  break;    // Sun  20 Apr 2098
    case 2099 :  retval = "2099.04.12";  break;    // Sun  12 Apr 2099
    default   :  retval = "";
  }
  return(retval);
}

=====================================================================

[EDIT 3]

Or if you prefer more compact code, and don't mind installing the Easter Sunday.csv file (attached to post #11) into your ..../MQL4/Files folder:
Inserted Code
//+------------------------------------------------------------------+
string ReadWholeFile(string filename)  {
//+------------------------------------------------------------------+
  int handle = FileOpen(filename,FILE_READ|FILE_BIN);
  if (handle>=0) {
    string file_content = FileReadString(handle,FileSize(handle));
    FileClose(handle);
  }  
  return(file_content);
}
//+------------------------------------------------------------------+
string EasterSunday(int year)   {
//+------------------------------------------------------------------+
//  returns as a string yyyy.mm.dd of Easter Sunday for the given year (yyyy)
//  e.g. EasterSunday(2011) returns "2011.04.24"
  string retval = "";
  string content = ReadWholeFile("Easter Sunday.csv");
  int p = StringFind(content,NumberToStr(year,"4")+",");
  if (p>=0)
    retval = StringSubstr(content,p+5,10);
  return(retval);  
}
  • Post #10
  • Quote
  • Apr 12, 2020 3:16am Apr 12, 2020 3:16am
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Quoting hanover
Disliked
{quote}{image}This appears to be caused by a bug in MT4...
Ignored
Actually no. The root cause is a b600+ change of behavior for the hanover YMDtoDate function, which is based on your NumberToStr function, which is where the b600+ code error exists.

YMDtoDate(2020,3,1) returns the datetime for 2020.01.03. Obviously it should instead return datetime 2020.03.01.

Inside YMDtoDate is the line:
string dt = NumberToStr(yy,"4") + "." + NumberToStr(mm,"2") + "." + NumberToStr(dd,"2") + " 00:00:00";

The NumberToStr mask argument of "2" is supposed to return a string with leading, padded zeros. Instead, b600+ returns:
"2020. 3. 1 00:00:00" (with 2 unwanted embedded spaces), which when used as the argument for StrToTime(dt) returns the datetime for 2020.01.03 00:00:00

(And by the way, I have doubts that 'NumberToStr(yy,"4") ' is appropriate to use, since it's not going to work unless yy is a 4-digit year).


A fix for the EasterDay function is as follows:
Inserted Code
//+------------------------------------------------------------------+
datetime EasterDay(int year)   {
//+------------------------------------------------------------------+
//   returns the MT4time value of Easter Sunday for the given (4 digit) year
//   e.g. DateToStr(EasterDay(2011),"M/D/Y") returns "04/24/2011"
  if(year<70) year += 2000; // V4 update to handle 1-or-2-digit years: 0 to 69 as 2000+year, else 70 to 99 as 1900+year
  else if(year<100) year += 1900;
  int result = MathMod(225-11*MathMod(year,19)-21,30)+21;
  if (result>48) result--;
  result = result+7-MathMod(year+MathInt(year/4)+result+1,7);
  //BUG: result = YMDtoDate(year,3,1)+(result-1)*86400; // v3 BUG!  YMDtoDate(2020,3,1) => 2020.01.03 instead of 2020.03.01. A v3 bug in NumberToStr is the root cause.
  // Use instead the standard StringToTime. At this point, "year" must be 4-digits.
  result = StringToTime(year+".03.01")+(result-1)*86400;
  return(result);
}//end of EasterDay()

Hanover, when I converted your include files to b600+, I definitely did not do a thorough check of each function, to compare return values for b509 vs b600+.

I previously found one bug in NumberToStr that was a 1-line replacement change:
//string outstr = n; // CHANGE! In 600+, this does not assume 8 digits, and does not pad with any trailing zeros.
string outstr = DoubleToStr(n,8); // This seems to work like 509. (Or, DoubleToString ?? Is there any difference?)

Obviously there is still another bug with the b600+ for NumberToStr. Your "mask" code is quite clever, complex and unfamiliar to me. Any chance you want to tackle the update of that NumberToStr function? Your functions with the "string mask" argument are the most likely at risk of still having b600+ code bugs, with this one top of the list.

Kent

P.S.

A fix for YMDtoDate is as follows. It handles the leading padded zeros with IntegerToString.
It also handles 2-digit yy as well, assuming 70-99 means 1970-1999, and 0-69 means 2000-2069.
Inserted Code
//+------------------------------------------------------------------+
int YMDtoDate(int yy, int mm, int dd)  {
//+------------------------------------------------------------------+
// Converts a year, month and day value to a valid MT4 datetime value
  if(yy<70) yy += 2000; // V4 update to handle 1-or-2-digit years: 0 to 69 as 2000+yy, else 70 to 99 as 1900+yy
  else if(yy<100) yy += 1900;
  //string dt = NumberToStr(yy,"4") + "." + NumberToStr(mm,"2") + "." + NumberToStr(dd,"2") + " 00:00:00"; // A v3 bug in NumberToStr must be fixed.
  string dt = yy + "." + IntegerToString(mm,2,'0') + "." + IntegerToString(dd,2,'0') + " 00:00:00"; // A v4 update.
  return(StrToTime(dt));
}//end of YMDtoDate()
1
  • Post #11
  • Quote
  • Edited Apr 13, 2020 1:48am Apr 12, 2020 5:06am | Edited Apr 13, 2020 1:48am
  •  hanover
  • Joined Sep 2006 | Status: ... | 8,081 Posts
Quoting TraderWolf2
Disliked
I was initially looking for a mql easter sunday calculation and therefore glad to find one here. After downloading different version of the files provided here I found out that non is compiling out of the box. I corrected these files locally, maybe I did wrong, but also the easter caculation is not working, it's returning wrong results. Can anybody gelp me further?
Ignored
If you want to get straight to the latest solution, please ignore my ramble in post #9 and simply replace the YMDtoDate() and EasterDay() functions with those posted below. This will fix the bug in the EasterDay() calculation, and you should be good to go. Many thanks to pips4life for pointing out the bug. I will send pips4life an updated version of hanover --- extensible functions b600 (np).mqh so that he can update post #1.
___________________________
Quoting pips4life
Disliked
YMDtoDate(2020,3,1) returns the datetime for 2020.01.03. Obviously it should instead return datetime 2020.03.01. Inside YMDtoDate is the line: string dt = NumberToStr(yy,"4") + "." + NumberToStr(mm,"2") + "." + NumberToStr(dd,"2") + " 00:00:00"; The NumberToStr mask argument of "2" is supposed to return a string with leading, padded zeros.
Ignored
Kind sir,

Many thanks for your very prompt and comprehensive reply. A slight correction, however:

 NumberToStr(x,"n.d") mask right justifies the number and pads with spaces to the left.

 NumberToStr(x,"Zn.d") mask right justifies the number and pads with zeros to the left.

 NumberToStr(x,"Tn.d") mask performs no padding. If the integer portion > 8 digits, only the last 8 integer digits are printed. (You can include a ~ character anywhere in the mask and a ~ will print in the leftmost character, denoting overflow). If the integer part is <= 8 digits, then the field width is simply determined by the number of digits in the number.

All of this worked correctly in b509, as far as I'm aware. I used NumberToStr() extensively and experienced no problems.

However, I've fixed YMDtoDate().
It now looks like this:
Inserted Code
//+------------------------------------------------------------------+
int YMDtoDate(int yy, int mm, int dd)  {
//+------------------------------------------------------------------+
// Converts a year, month and day value to a valid MT4 datetime value
  if (yy<70) yy += 2000; // V4 update to handle 1-or-2-digit years: 0 to 69 as 2000+yy, else 70 to 99 as 1900+yy
  else if (yy<100) yy += 1900;
  string dt = NumberToStr(yy,"Z4") + "." + NumberToStr(mm,"Z2") + "." + NumberToStr(dd,"Z2") + " 00:00:00";
  return(StrToTime(dt));
}
i.e. string dt = NumberToStr(yy,"Z4") + "." + NumberToStr(mm,"Z2") + "." + NumberToStr(dd,"Z2") + " 00:00:00";
That was a careless oversight on my part, as I'm fairly certain that I'd intended to pad with zeros. But I somehow got away with the error in b509, only for it to surface when subjected to b600+.
And thanks for the code to correct any 2 digit year that's been input.

EasterDay() now looks like this:
Inserted Code
//+------------------------------------------------------------------+
datetime EasterDay(int year=0)   {
//+------------------------------------------------------------------+
//   returns the MT4time value of Easter Sunday for the given (4 digit) year
//   e.g. DateToStr(EasterDay(2011),"M/D/Y") returns "04/24/2011"
//   Leaving year blank causes it to default to the present year. Otherwise,
//   year must be between 1970 and 2037, because MQL4 can't handle dates
//   outside of this range. Use EasterSunday() to return Easter Sunday's
//   date for years outside of this range (works for 1700 thru 2099).
  if (year==0)
    year = Year();  // If no year specified, default value is the present year
  if (year<70)      // V4 update to handle 1-or-2-digit years: 0 to 69 as 2000+yy, else 70 to 99 as 1900+yy
    year += 2000;
  else if (year<100)
    year += 1900;
    
  if (year < 1970 || year > 2037)  {        // works only for years between 1970 and 2037 (MQL4 limitation)
    int result = 0;                         // if outside these years, simply return result of 0
  } else {
    /*  Use Carter's formula for calculating Easter Sunday:
         B = 225 – 11 * (Year MOD 19)
         D = ((B–21) MOD 30) + 21
         IF D > 48 THEN D = D - 1
         E = (Year + INT(Year/4) + D + 1) MOD 7
         Q = D + 7 – E
         IF Q<32 Result = March Q       } this is simply the number of days after the
         ELSE    Result = April Q-31    } last day in February (either 28th or 29th)
    */
    result = MathMod(225-11*MathMod(year,19)-21,30)+21;             // 'D' in Carter's formula (combines 2 steps: B = ..... and D = .....)
    if (result>48) result--;                                        // IF D > 48 THEN D = D - 1
    result = result+7-MathMod(year+MathInt(year/4)+result+1,7);     // 'Q' (combines 2 steps: E = ..... and Q = .....)
    result = YMDtoDate(year,3,1)+(result-1)*86400;                  // Convert result of [March 1 + (result-1) days] into MT4date
  }  
  return(result);
}
I've tested this across a year range of 1970 to 2037, and it seems to be generating the correct results now:
Attached Image (click to enlarge)
Click to Enlarge

Name: PPI 930.png
Size: 39 KB

I don't think there's anything in NumberToStr() that needs addressing? I've used it quite frequently in some of my recent b600+ conversions and haven't had any problems so far. But I haven't tested all of its options exhaustively. Here is a summary of all of the available options:
Inserted Code
//+------------------------------------------------------------------+
string NumberToStr(double n, string mask="")
//+------------------------------------------------------------------+
// Formats a number using a mask, and returns the resulting string
// Usage:    string result = NumberToStr(number,mask)
//
// Mask parameters:
// n = number of digits to output, to the left of the decimal point
// n.d = output n digits to left of decimal point; d digits to the right
// -n.d = floating minus sign at left of output
// n.d- = minus sign at right of output
// +n.d = floating plus/minus sign at left of output
//
// These characters may appear anywhere in the string:
//   ( or ) = enclose negative number in parentheses
//   $ or £ or ¥ or € = include floating currency symbol at left of output
//   % = include trailing % sign
//   , = use commas to separate thousands, millions, etc
//   Z or z = left fill with zeros instead of spaces
//   * = left fill with asterisks instead of spaces
//   R or r = round result in rightmost displayed digit
//   B or b = blank entire field if number is 0
//   ~ = show tilde in leftmost position if overflow occurs
//   ; = switch use of comma and period (European format)
//   L or l = left align final string
//   T ot t = trim (remove all spaces from) end result
Now I've spent close to 4 hours fixing a function that will probably seldom, if ever, be used. Not good time management.

Rather than post the mqh file here (which means there will be two versions, which could be confusing) I will email it to you after I've done some more testing. Then you can upload it to post #1 if/whenever you wish.

David
___________________________

[EDIT] Latest version of Easter Sunday.csv attached below. Allows processing from 1700 to 2299, for the sake of completeness, as I don't think fx markets existed in 1700, LOL.
Attached File
File Type: csv Easter Sunday.csv   20 KB | 54 downloads
___________________________

[EDIT 2] Ron Mallen's webpage is the most comprehensive material on the subject that I've been able to find. It displays Easter Sunday dates for the years 1700 to 2299, and includes an explanation on the necessary calculations, some history about how this all came about, and then an app written in BASIC to perform the calculation, which I rewrote in autohotkey for my own use.

Tom Larsen's webapage also includes dates from 1700 to 2299. I downloaded a xls from his page which I found useful for checking my work.

I've updated my own xls accoordingly. Copy attached below. Also a pdf that I found a while ago.
Attached Files
File Type: pdf Calendar notes - Easter calculation.pdf   271 KB | 79 downloads
File Type: xls Easter Day calculation.xls   2.4 MB | 64 downloads
  • Post #12
  • Quote
  • Edited Apr 18, 2020 4:03am Apr 17, 2020 5:41am | Edited Apr 18, 2020 4:03am
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
2020-Apr-17: v4 released, of Hanover's b600+ utility functions (an #include file).

A new v4 version of hanover --- extensible functions b600 (np).mqh is available in post #1

Note: With v4, there is no further need of the old v3 hanover --- function header b600 (np).mqh which has been combined.

Remove the "#include" statement of the function header file from your code, and just use a single "#include <hanover --- extensible functions b600 (np).mqh>"


Changes:
Inserted Code
v4 Updated on 2020-Apr-16 by pips4life (Kent); some edits by hanover combined here.
   NOTE: StrToColor *may* behave differently than b509!. Possibly, old CLR_NONE==0, but in b600+, CLR_NONE==4294967295
      Programs like Recent News expected a 0 for a blank string, now get CLR_NONE which is >0.
      Updated "USAGE:" section below to make a note of this.
   Combined into this file the content from the "<hanover --- function header b600 (np).mqh>" file.  
      NO "#include" of the header is necessary any longer.
      Note: Search for "b600_b509" to find lines which would need to be changed to work with b509. (No doubt, some
      newer sections may need additional changes that are not marked. OR, use the posted b509 versions).
      NOTE: Remove your "#include" of the old "function header" file to prevent compile warnings like "macro redefinition".
   New, or Updates, to functions (by hanover, or by pips4life):
      EasterDay - fixed v3 bug
      EasterSunday - new function that reads a .csv file of Easter Sunday dates. In the MT4 Data Folder (searched 1st), or
         in the MT4 Common Data Folder (if not found, searched 2nd), this file is read for the dates: "MQL4\Files\Easter Sunday.csv"
      ExtractBetween
      ReadWholeFile (hanover's version was modified by pips4life to read two locations, MT4 Data Folder 1st, then Common Data Folder)
      GetVisibility (minor updates for "MN1", and new support for argument "ALL")
      ListGlobals
      YMDtoDate (bug in v3 for b600+, fixed)
      StrReplace
      stringSubstrOld (The debugSubstr was true, now false. Error checking disabled, but ENABLE AGAIN if you see problems!)
      ReadWebPage is still uncommented here, as it was in v3. (Hanover may want it commented ??)
      iRegr (2 new arguments)
      log (unchanged, but hanover may want the output line commented out??)
2
  • Post #13
  • Quote
  • Apr 18, 2020 4:51pm Apr 18, 2020 4:51pm
  •  hanover
  • Joined Sep 2006 | Status: ... | 8,081 Posts
Quoting pips4life
Disliked
2020-Apr-17: v4 released, .........
Ignored
Hello sir,

Many thanks for the update.

I think I'll stay with my version (but won't post it publicly, to avoid confusion) as I don't fancy changing Plot News to accommodate the changes to ReadWholeFile(). I have some other functions that I'm planning on developing, when I get some time. It goes without saying that I'm happy to share them with you privately; it's then your choice as to whether you want to include (or modify) them in the 'official' version.

Keep up the great work.

David
  • Post #14
  • Quote
  • Apr 18, 2020 7:30pm Apr 18, 2020 7:30pm
  •  pips4life
  • Joined Apr 2007 | Status: Member | 696 Posts
Quoting hanover
Disliked
{quote} Hello sir, Many thanks for the update. I think I'll stay with my version (but won't post it publicly, to avoid confusion) as I don't fancy changing Plot News to accommodate the changes to ReadWholeFile()... David
Ignored
Your version is:
Inserted Code
//+------------------------------------------------------------------+
string ReadWholeFile(string filename)  {
//+------------------------------------------------------------------+
  int handle = FileOpen(filename,FILE_READ|FILE_BIN);
  if (handle>=0) {
    string file_content = FileReadString(handle,FileSize(handle));
    FileClose(handle);
  }  
  return(file_content);
}

To yours, I would suggest adding "|FILE_SHARE_READ" as in:
int handle = FileOpen(filename,FILE_READ|FILE_BIN|FILE_SHARE_READ);
I don't understand the full details, but when multiple instances of an indicator might want to read the same file, that option seems to be necessary.

My version's (below) default behavior is exactly the same as yours, so long as the file exists in the local MT4 MQL4\Files\ folder.
It's only when the local file does not exist that mine has an advantage -- IMO -- that it will check the alternative location in the *Common* Files\ folder.
Plus mine will "Print" an error if the file can't open from either location.

For the "EasterSunday" function, for example, the user needs only install the "Easter Sunday.csv" file once, in the common Data Folder (C:\users\your_name\AppData\Roaming\MetaQuotes\Terminal\Common\Files\ ), then it will be found by all MT4's on the PC. It won't hurt if the file is in the local Data Folder location (because it will be found 1st), but it's redundant, so long as the file is the same. It would be similar for Plot News opening a news.csv or newsXML.csv. The common Files would be fine, and more efficient too, but a local file would take precedence if found.

Since you prefer the original behavior of your "ReadWholeFile" function name, I can add two new functions. (ReadWholeLocalFile for your needs, if you choose. And ReadWholeCommonFile for completeness).

(And I'm happy to include any new functions you care to provide. Really, this is *your* functions file that you've graciously shared with us! It is helpful when we write our own code, yes, but most helpful just to get your various b509 .mq4 files converted to b600+, which means most functions should remain more-or-less compatible with whatever you did before).

Inserted Code
//+------------------------------------------------------------------+
string ReadWholeLocalFile(string filename) {
//+------------------------------------------------------------------+
   return( ReadWholeFile(filename,false,true) );
}
//+------------------------------------------------------------------+
string ReadWholeCommonFile(string filename) {
//+------------------------------------------------------------------+
   return( ReadWholeFile(filename,true,true) );
}
 
//+------------------------------------------------------------------+
string ReadWholeFile(string filename, bool checkForCommonFileFirst=false, bool checkOnlyFirstLocation=false)  {
//+------------------------------------------------------------------+
  int handle, FILE_LOC1=0, FILE_LOC2=FILE_COMMON;
  // Fyi, my Common data folder is:  C:\users\myname_here\AppData\Roaming\MetaQuotes\Terminal\Common\Files\
  // It so happens that all my MT4 installations are NOT under C:\Program Files (x86) but under C:\users\myname_here\
  // I doubt that my choice makes a difference where the common data folder is or not.  However, see MT4 documentation for what they say.
  
  if(checkForCommonFileFirst) { FILE_LOC1=FILE_COMMON; FILE_LOC2=0;}
  if(checkOnlyFirstLocation) FILE_LOC2=FILE_LOC1;
  static bool prtwarn=false;
  string file_content = "";
  
  handle = FileOpen(filename,FILE_LOC1|FILE_READ|FILE_BIN|FILE_SHARE_READ);
  if(handle<0 && !checkOnlyFirstLocation) handle = FileOpen(filename,FILE_LOC2|FILE_READ|FILE_BIN|FILE_SHARE_READ);
  
  if (handle>=0) {
    file_content = FileReadString(handle,FileSize(handle));
    FileClose(handle);
  }
  else if(!prtwarn)
  {
    prtwarn=true;
    string locationStr = " in location(s): ";
    if(FILE_LOC1 == FILE_COMMON || FILE_LOC2 == FILE_COMMON) locationStr = locationStr+TerminalInfoString(TERMINAL_COMMONDATA_PATH)+"\\File\\ ; ";
    if(FILE_LOC1 == 0 || FILE_LOC2 == 0) locationStr = locationStr+TerminalInfoString(TERMINAL_DATA_PATH)+"\\File\\ ; ";
    Print("ERROR. Cannot FileOpen for Read: '",filename,"'",locationStr);
  }  
  return(file_content);
}//end of ReadWholeFile()

P.S. For the record, my previous post that had suggested there is a bug with NumberToStr was wrong. Ultimately it was a bug with YMDtoDate which is fixed in v4.
  • Post #15
  • Quote
  • Last Post: Jan 16, 2021 7:58am Jan 16, 2021 7:58am
  •  JulienM2
  • | Joined Aug 2018 | Status: Trader | 89 Posts
Hello, i am happy to inform you that QChartist is MT4 friendly and 2038 friendly
Happy trading!
MT4, QChartist, Stooq, Alpha Vantage, TC 2000, TradingView, Yahoo Finance
  • Platform Tech
  • /
  • Modified, useful MQ4 utilities, indicators, and related tips
  • Reply to Thread
0 traders viewing now
Top of Page
  • Facebook
  • Twitter
About FF
  • Mission
  • Products
  • User Guide
  • Media Kit
  • Blog
  • Contact
FF Products
  • Forums
  • Trades
  • Calendar
  • News
  • Market
  • Brokers
  • Trade Explorer
FF Website
  • Homepage
  • Search
  • Members
  • Report a Bug
Follow FF
  • Facebook
  • Twitter

FF Sister Sites:

  • Metals Mine
  • Energy EXCH
  • Crypto Craft

Forex Factory® is a brand of Fair Economy, Inc.

Terms of Service / ©2021