Gotobi days in USDJPY: how to compute them in MQL5 (with Japanese holidays)
Gotobi days ("5-10 days") are a well-known calendar idea in the yen market. Many Japanese companies settle payments on the 5th, 10th, 15th, 20th, 25th and on the last day of the month. On these days importers often need dollars before the Tokyo fixing at 09:55 Tokyo time, and some traders watch USDJPY in the first hours of the Tokyo session.
This post is not about whether the effect pays. It is about the part that many backtests get wrong: computing the dates correctly. A wrong calendar silently mixes normal days into the sample, and the test result then means little.
Three rules that are easy to miss
1. The day is the Tokyo day, not the broker day. With a broker on GMT+2/GMT+3, 08:00 Tokyo is 01:00 or 02:00 server time, and for the first hours of the Tokyo day the server date is still the previous day. Convert the server time to Tokyo time (GMT+9, no summer time) before you take the day of the month.
2. When the date falls on a non-business day, it usually moves to the previous business day. If the 10th is a Sunday, the settlement usually happens on Friday the 8th. Saturdays, Sundays and Japanese bank holidays all count as non-business days.
3. Japanese bank holidays are not only the national holidays. Banks are also closed from 1 to 3 January and on 31 December. National holidays have substitute days (a holiday on Sunday moves to Monday) and a "sandwich" rule (a day between two holidays is also a holiday). The simplest robust approach in an EA is a holiday list that the user can edit.
A function for MQL5
The code below works on Tokyo dates. It takes the list of holidays as a sorted array of dates (00:00 of each holiday).
// true if the date d (00:00, Tokyo time) is a Japanese bank business day
bool IsBusinessDay(datetime d, const datetime &holidays[])
{
MqlDateTime t; TimeToStruct(d, t);
if(t.day_of_week == 0 || t.day_of_week == 6) return false; // Sunday, Saturday
if(t.mon == 1 && t.day <= 3) return false; // 1-3 January
if(t.mon == 12 && t.day == 31) return false; // 31 December
for(int i = 0; i < ArraySize(holidays); i++)
if(holidays[i] == d) return false;
return true;
}
// last calendar day of the month of d
int LastDay(datetime d)
{
MqlDateTime t; TimeToStruct(d, t);
t.day = 1; t.mon++; if(t.mon == 13) { t.mon = 1; t.year++; }
t.hour = 0; t.min = 0; t.sec = 0;
MqlDateTime p; TimeToStruct(StructToTime(t) - 86400, p);
return p.day;
}
// true if the Tokyo date d (00:00) is a gotobi settlement day
bool IsGotobi(datetime d, const datetime &holidays[])
{
if(!IsBusinessDay(d, holidays)) return false;
MqlDateTime t; TimeToStruct(d, t);
int last = LastDay(d);
int targets[6] = {5, 10, 15, 20, 25, 0};
targets[5] = last;
for(int k = 0; k < 6; k++)
{
// the nominal date of this month, then back to the previous business day
MqlDateTime n = t; n.day = targets[k]; n.hour = 0; n.min = 0; n.sec = 0;
datetime s = StructToTime(n);
while(!IsBusinessDay(s, holidays)) s -= 86400;
if(s == d) return true;
}
return false;
} Edge cases such as one-off extended holidays that push a date across a month boundary are not covered.
How to use it in an EA: on each new Tokyo day, compute the Tokyo date from the server time with your broker's offset, call IsGotobi once, and keep the result for the day. Print the next gotobi date in the log when the EA starts: it is the quickest way to see that the calendar and the clock are right.
Checks before trusting a backtest
- Print all gotobi dates of one year and compare them with a Japanese calendar.
- Check the broker clock in winter and in summer: an hour of error moves the entry away from the fixing.
- Count the gotobi days the calendar gives per year: about 70 is the right order. If you see far more, the calendar is wrong.
- Use real ticks and the real spread of the Tokyo morning, which is wider than in London.
Questions or corrections are welcome in the comments.


