MARKETCAL2

MARKETCAL2( [Yr], [Nms] )
Yr
Optional. Year to generate the calendar for. If omitted, current year is used.
Nms
Optional. Any value will prevent the Holiday Names column from being displayed.

Generate a list of (currently) the ten Holidays the US Stock Market is closed. Can be used to provide the Holiday array for the NETWORKDAYS.INTL and WORKDAY.INTL functions.

jdellasala

Well-known Member
Joined
Dec 11, 2020
Messages
755
Office Version
  1. 365
Platform
  1. Windows
  2. Mobile
  3. Web
MARKETCAL2 will generate the days the market is closed for the year requested or the current year if that option is omitted, and is designed to work in conjunction with the MKTDAYS Lambda function to build an array of dates the market is open. It will generate a two column array with the name of the holiday in the first column, and the date in the second column. The optional second parameter can be any value and will omit the holiday name column.

This is the long overdue replacement for the MARKETCAL function mentioned in my MKTDAYS Lambda post and then had to have removed because it was very wrong!

Multiple years can be strung together using VSTACK. Here's the code:

Excel Formula:
LAMBDA([Yr],[Nms], 
LET( y, IF(ISOMITTED(Yr), YEAR(TODAY()), Yr), f, EDATE("1-1-" & y, 0),
    fs, f - WEEKDAY(f, 3), s, SEQUENCE(54, 7, fs), m, INDEX(s, , 1), 
    mm, MONTH(m), mlk, XLOOKUP(1, mm, m) + 14, wb, XLOOKUP(2, mm, m) + 14,
    gf, FLOOR("5/" & DAY(MINUTE(y / 38) / 2 + 56) & "/" & y, 7) - 36,
    md, XLOOKUP(5, mm, m, , , -1), jt, XLOOKUP(6, mm, m) + 14,
    ld, XLOOKUP(9, mm, m), th, INDEX(s, , 4),
    mth, MONTH(th), tgd, XLOOKUP(11, mth, th) + 21,
    xd, DATE(YEAR(f), {1; 7; 11; 12}, {1; 4; 11; 25}),
    wd, WEEKDAY(xd, 3), yd, IF(wd = 6, xd + 1, IF(wd = 5, xd - 1, xd)),
    sw, IFS( y<1998,
        SWITCH( SEQUENCE(8), 1, INDEX(yd, 1), 2, wb, 3, gf,
            4, md, 5, INDEX(yd, 2), 6, ld, 7, tgd, 8, INDEX(yd, 4)),
        y < 2022,
        SWITCH( 
            SEQUENCE(9), 1, INDEX(yd, 1), 2, mlk, 3, wb, 4, gf,
            5, md, 6, INDEX(yd, 2), 7, ld, 8, tgd, 9, INDEX(yd, 4)),
        TRUE,
        SWITCH(
            SEQUENCE(10), 1, INDEX(yd, 1), 2, mlk, 3, wb, 4, gf,
            5, md, 6, jt, 7, INDEX(yd, 2), 8, ld, 9, tgd, 10, INDEX(yd, 4))),
    hd, IFS( y < 1998,
        { "NewYear's Day"; "President's Day"; "Good Friday"; "Memorial Day";
            "Fourth of July"; "Labor Day"; "Thanksgiving Day"; "Christmas Day"},
        y < 2022,
        { "NewYear's Day"; "Martin Luther King Day"; "President's Day"; 
            "Good Friday"; "Memorial Day"; "Fourth of July"; "Labor Day";
            "Thanksgiving Day"; "Christmas Day" },
        TRUE,
        { "NewYear's Day"; "Martin Luther King Day"; "President's Day";
            "Good Friday"; "Memorial Day"; "Juneteenth"; "Fourth of July";
            "Labor Day"; "Thanksgiving Day";  "Christmas Day"}),
    IF(ISOMITTED(Nms), CHOOSE({1, 2}, hd, sw), sw)
)
Aside from its use with MKTDAYS, it can also be used for the Holidays options in the NETWORKDAYS.INTL and WORKDAY.INTL functions.

This was inspired and used a lot of the work of @Xlambda on his Lambda Post .
Also, I've been trying a way to stack a number of calendars more gracefully than just VSTACK(MARKETCAL2(2021),MARKETCAL2(2022),MARKETCAL2(2023)). Seems like there should be a shorter way to do it using SEQUENCE or something! Please post if you have a better solution!
 
Upvote 0
I have done the same with my function BACKTOTABLE(VSTACK(TOFILE(Table1),TOFILE(Table2))), but the only way I see of appending new tables with with an OfficeScript, which I have implemented using slice and concat.
 
Thank you for mentioning me @jdellasala✌️😉🙏
2 tiny obs. - formula missing leading "=" and trailing ")"
- returns some errors
Anyhow, after you fix the errors, here is a function for stacking, hope is what you wanted.
AMARKETCAL(y,[h]) Array Market Calendar
y: array of years, any shape or form, formula, constant array, vector or 2D array
[h]: if omitted vert stacking, if 1 horiz stacking + leading clm and headers
Book1
ABCDEFGHIJKLMNOPQ
1The errors
2h,omitted => good for holidays arrayh,1 => good for visualizing
3201820192020202120222023=AMARKETCAL({2021,2022,2023})=AMARKETCAL({2021,2022,2023},1)
401-01-1801-01-1901-01-2001-01-2131-12-2102-01-2301-01-21 202120222023
515-01-1821-01-1920-01-2018-01-2117-01-2216-01-2318-01-21NewYear's Day01-01-2131-12-2102-01-23
619-02-1818-02-1917-02-2015-02-2121-02-2220-02-2315-02-21Martin Luther King Day18-01-2117-01-2216-01-23
728-09-18#VALUE!#VALUE!25-06-21#VALUE!#VALUE!25-06-21President's Day15-02-2121-02-2220-02-23
828-05-1827-05-1925-05-2031-05-2130-05-2229-05-2331-05-21Good Friday25-06-21#VALUE!#VALUE!
904-07-1804-07-1903-07-2005-07-2120-06-2219-06-2305-07-21Memorial Day31-05-2130-05-2229-05-23
1003-09-1802-09-1907-09-2006-09-2104-07-2204-07-2306-09-21Fourth of July05-07-2120-06-2219-06-23
1122-11-1828-11-1926-11-2025-11-2105-09-2204-09-2325-11-21Labor Day06-09-2104-07-2204-07-23
1225-12-1825-12-1925-12-2024-12-2124-11-2223-11-2324-12-21Thanksgiving Day25-11-2105-09-2204-09-23
1326-12-2225-12-2331-12-21Christmas Day24-12-2124-11-2223-11-23
1417-01-22#N/A#N/A26-12-2225-12-23
1521-02-22
16#VALUE!
1730-05-22
1820-06-22
1904-07-22
2005-09-22
2124-11-22
2226-12-22
2302-01-23
2416-01-23
2520-02-23
26#VALUE!
2729-05-23
2819-06-23
2904-07-23
3004-09-23
3123-11-23
3225-12-23
Sheet2
Cell Formulas
RangeFormula
I3,M3I3=FORMULATEXT(I4)
F4:G13,B4:E12B4=MARKETCAL2(B3,1)
I4:I32I4=AMARKETCAL({2021,2022,2023})
M4:P14M4=AMARKETCAL({2021,2022,2023},1)
Dynamic array formulas.

Book1
ABCDEFGHIJKLMNOPQRSTU
1y: can be formula, vector or array
2
3formulavectorarray
4=AMARKETCAL(SEQUENCE(4,,2020))=AMARKETCAL(E6:E9)=AMARKETCAL(J6:K7)=AMARKETCAL(E6:E9,1)
501-01-20y01-01-20y01-01-20 2020202120222023
620-01-20202020-01-202020202120-01-20NewYear's Day01-01-2001-01-2131-12-2102-01-23
717-02-20202117-02-202022202317-02-20Martin Luther King Day20-01-2018-01-2117-01-2216-01-23
8#VALUE!2022#VALUE!#VALUE!President's Day17-02-2015-02-2121-02-2220-02-23
925-05-20202325-05-2025-05-20Good Friday#VALUE!25-06-21#VALUE!#VALUE!
1003-07-2003-07-2003-07-20Memorial Day25-05-2031-05-2130-05-2229-05-23
1107-09-2007-09-2007-09-20Fourth of July03-07-2005-07-2120-06-2219-06-23
1226-11-2026-11-2026-11-20Labor Day07-09-2006-09-2104-07-2204-07-23
1325-12-2025-12-2025-12-20Thanksgiving Day26-11-2025-11-2105-09-2204-09-23
1401-01-2101-01-2101-01-21Christmas Day25-12-2024-12-2124-11-2223-11-23
1518-01-2118-01-2118-01-21#N/A#N/A#N/A26-12-2225-12-23
1615-02-2115-02-2115-02-21
1725-06-2125-06-2125-06-21=AMARKETCAL(J6:K7,1)
1831-05-2131-05-2131-05-21 2020202120222023
1905-07-2105-07-2105-07-21NewYear's Day01-01-2001-01-2131-12-2102-01-23
2006-09-2106-09-2106-09-21Martin Luther King Day20-01-2018-01-2117-01-2216-01-23
2125-11-2125-11-2125-11-21President's Day17-02-2015-02-2121-02-2220-02-23
2224-12-2124-12-2124-12-21Good Friday#VALUE!25-06-21#VALUE!#VALUE!
2331-12-2131-12-2131-12-21Memorial Day25-05-2031-05-2130-05-2229-05-23
2417-01-2217-01-2217-01-22Fourth of July03-07-2005-07-2120-06-2219-06-23
2521-02-2221-02-2221-02-22Labor Day07-09-2006-09-2104-07-2204-07-23
26#VALUE!#VALUE!#VALUE!Thanksgiving Day26-11-2025-11-2105-09-2204-09-23
2730-05-2230-05-2230-05-22Christmas Day25-12-2024-12-2124-11-2223-11-23
2820-06-2220-06-2220-06-22#N/A#N/A#N/A26-12-2225-12-23
2904-07-2204-07-2204-07-22
3005-09-2205-09-2205-09-22
3124-11-2224-11-2224-11-22
3226-12-2226-12-2226-12-22
3302-01-2302-01-2302-01-23
3416-01-2316-01-2316-01-23
3520-02-2320-02-2320-02-23
36#VALUE!#VALUE!#VALUE!
3729-05-2329-05-2329-05-23
3819-06-2319-06-2319-06-23
3904-07-2304-07-2304-07-23
4004-09-2304-09-2304-09-23
4123-11-2323-11-2323-11-23
4225-12-2325-12-2325-12-23
43
Sheet3
Cell Formulas
RangeFormula
B4,P17,P4,M4,G4B4=FORMULATEXT(B5)
B5:B42B5=AMARKETCAL(SEQUENCE(4,,2020))
G5:G42G5=AMARKETCAL(E6:E9)
M5:M42M5=AMARKETCAL(J6:K7)
P5:T15P5=AMARKETCAL(E6:E9,1)
P18:T28P18=AMARKETCAL(J6:K7,1)
Dynamic array formulas.
 
AMARKETCAL(y,[h]) Array Market Calendar
y
: array of years, any shape or form, formula, constant array, vector or 2D array
[h]: if omitted vert stacking, if 1 horiz stacking + leading clm and headers
Excel Formula:
=LAMBDA(y, [h],
    LET(
        x, TAKE(MARKETCAL2(2000), , 1),
        r, REDUCE(0, y, LAMBDA(v, i, IF(h, HSTACK(v, MARKETCAL2(i, 1)), VSTACK(v, MARKETCAL2(i, 1))))),
        IF(h, VSTACK(HSTACK("", TOROW(y)), HSTACK(x, DROP(r, , 1))), DROP(r, 1))
    )
)
 
I know exactly what happened. I used the Advanced Formula Editor to format the code, but it doesn't include the =LAMBDA( or the closing ) for LAMBDA. I managed to remember adding LAMBDA( but as you pointed out forgot the leading = and trailing ). Thanks for the heads up as well as the exact problem. Here's the corrected M Code:
MARKETCAL2
Power Query:
=LAMBDA([Yr],[Nms],
LET( y, IF(ISOMITTED(Yr), YEAR(TODAY()), Yr), f, EDATE("1-1-" & y, 0),
    fs, f - WEEKDAY(f, 3), s, SEQUENCE(54, 7, fs), m, INDEX(s, , 1),
    mm, MONTH(m), mlk, XLOOKUP(1, mm, m) + 14, wb, XLOOKUP(2, mm, m) + 14,
    gf, FLOOR("5/" & DAY(MINUTE(y / 38) / 2 + 56) & "/" & y, 7) - 36,
    md, XLOOKUP(5, mm, m, , , -1), jt, XLOOKUP(6, mm, m) + 14,
    ld, XLOOKUP(9, mm, m), th, INDEX(s, , 4),
    mth, MONTH(th), tgd, XLOOKUP(11, mth, th) + 21,
    xd, DATE(YEAR(f), {1;7;11;12}, {1;4;11;25}),
    wd, WEEKDAY(xd, 3), yd, IF(wd = 6, xd + 1, IF(wd = 5, xd - 1, xd)),
    sw, IFS( y<1998,
        SWITCH( SEQUENCE(8), 1, INDEX(yd, 1), 2, wb, 3, gf,
            4, md, 5, INDEX(yd, 2), 6, ld, 7, tgd, 8, INDEX(yd, 4)),
        y < 2022,
        SWITCH(
            SEQUENCE(9), 1, INDEX(yd, 1), 2, mlk, 3, wb, 4, gf,
            5, md, 6, INDEX(yd, 2), 7, ld, 8, tgd, 9, INDEX(yd, 4)),
        TRUE,
        SWITCH(
            SEQUENCE(10), 1, INDEX(yd, 1), 2, mlk, 3, wb, 4, gf,
            5, md, 6, jt, 7, INDEX(yd, 2), 8, ld, 9, tgd, 10, INDEX(yd, 4))),
    hd, IFS( y < 1998,
        {"NewYear's Day";"President's Day";"Good Friday";"Memorial Day";"Fourth of July";"Labor Day";"Thanksgiving Day";"Christmas Day"},
        y < 2022,
        {"NewYear's Day";"Martin Luther King Day";"President's Day";"Good Friday";"Memorial Day";"Fourth of July";"Labor Day";"Thanksgiving Day";"Christmas Day"},
        TRUE,
        {"NewYear's Day";"Martin Luther King Day";"President's Day";"Good Friday";"Memorial Day";"Juneteenth";"Fourth of July";"Labor Day";"Thanksgiving Day";"Christmas Day"}),
    IF(ISOMITTED(Nms), CHOOSE({1,2}, hd, sw), sw))
I copied that from an active cell that was working!
AMARKETCAL is nice! That new holiday screws everything up though! Still a lot easier to make a nice, neat list of Market Closed dates for multiple years than just doing a VSTACK! Thanks.
 
A small point. Your function may be using date shortcut(s) that require USA Regional Settings.
see "gf, FLOOR("5/" & DAY(MINUTE(y / 38) / 2 + 56) & "/" & y, 7) - 36,"
I appreciate that your post is primarily for a USA based audience but there is a comment about International users.
 
A small point. Your function may be using date shortcut(s) that require USA Regional Settings.
see "gf, FLOOR("5/" & DAY(MINUTE(y / 38) / 2 + 56) & "/" & y, 7) - 36,"
I appreciate that your post is primarily for a USA based audience but there is a comment about International users.
Appreciate the feedback! That line determines the date for Good Friday. I see you're from Canada. Did the function give you yesterday as it should have?
If it didn't, I hope I can fix it!
Called without a parameter, it should return this (in US Date Format):
ZipTest.xlsm
AB
1NewYear's Day01/02/2023
2Martin Luther King Day01/16/2023
3President's Day02/20/2023
4Good Friday04/07/2023
5Memorial Day05/29/2023
6Juneteenth06/19/2023
7Fourth of July07/04/2023
8Labor Day09/04/2023
9Thanksgiving Day11/23/2023
10Christmas Day12/25/2023
Sheet3
Cell Formulas
RangeFormula
A1:B10A1=MARKETCAL2()
Dynamic array formulas.

BTW, my default Windows date format uses leading zeros.
 
Last edited:
"That line determines the date for Good Friday. I see you're from Canada. Did the function give you yesterday as it should have?"

That syntax would yield an error for systems that have the date format dd-mmm-yy.

More conventional code may be
gf, FLOOR(DATE(y, 5, DAY(MINUTE(y / 38) / 2 + 56)), 7) - 36,

I tried Advanced Formula Editor. It does not seem to install as an Add-in; I have to install it each time I want to use the feature.
Is this normal?
 
"That line determines the date for Good Friday. I see you're from Canada. Did the function give you yesterday as it should have?"

That syntax would yield an error for systems that have the date format dd-mmm-yy.

More conventional code may be
gf, FLOOR(DATE(y, 5, DAY(MINUTE(y / 38) / 2 + 56)), 7) - 36,

I tried Advanced Formula Editor. It does not seem to install as an Add-in; I have to install it each time I want to use the feature.
Is this normal?
I saw it a long time ago and don't think I ever got it fixed!
 

Forum statistics

Threads
1,223,575
Messages
6,173,148
Members
452,502
Latest member
PQCurious

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top