Given a particular month, I need to find the third Friday of that month. I just found out that there is a function called
dayofweekofmonth which basically does the reverse of what I want. You give it a date and it tells you that date is in fact the third Friday of the month (it returns 3).
For example, today is the second Monday of the month
I basically want to know if there is a shorthand for the inverse of this function (as in, something that returns the date itself) or if anybody has a cute trick to come up with it beyond running a boolean check on every date inside a given month.
When I’ll have an access to my computer I’ll write full code, but idea is the following
- Calculate day of the week for the first day of the month e.g. “2021-03-01”
- Calculate the distance to the nearest Friday (number in range 0:6)
- Add 14
- Add result to the first day of the month
dt = floor(Date(dt), Month)
dt |> dayofweek |>
(x -> 5 - x < 0 ? 12 - x : 5 - x) |>
(x -> x + 14) |>
(x -> dt + Day(x))
julia> dr = Date(2021):Month(1):Date(2022);
It should be efficient, I suppose, since it adds no allocations, pure arithmetic.
It was interesting to read
Dates documentation, there are interesting
toprev functions as well as
filter. So, if you are not afraid of iterations, at least they can be written in a very compact form
julia> tonext(x -> (dayofweek(x) == 5) && (dayofweekofmonth(x) == 3), Date("2020-03-01"))
julia> dr = Date(2021):Day(1):Date(2022)
julia> filter(dr) do x
(dayofweek(x) == 5) && (dayofweekofmonth(x) == 3)
Not sure this is particularly clever but here’s how I would do it:
julia> using Dates
julia> third_friday(dates) = dates[findfirst(x -> (dayofweek(x) == 5) && (dayofweekofmonth(x) == 3), dates)]
third_friday (generic function with 1 method)
julia> candidates = Date(2021,1,15):Day(1):Date(2021,1,21)
julia> [third_friday(candidates + Month(i)) for i ∈ 0:12]
This uses the fact that the third Friday must be between the 15th and 21st (which I suppose is a variation on the “find first Friday and add 14” theme above)
Here is another possibility:
function get_next_expiry(calc_date:: Date, month:: Integer; holidays:: AbstractArray = )
# get 3rd Wednesday of the corresponding month
expiry_date = Dates.tonext(calc_date + Month(month-1)) do x
Dates.dayofweek(x) == Dates.Friday && Dates.dayofweekofmonth(x) == 3
# move to next business day if the day is a holiday - not sure if you need this
Dates.tonext(expiry_date, same=true) do x
# get the next 300 3rd Fridays, shifted to next business day if required
expiry_dates = get_next_expiry.(START_DATE, 1:300; holidays=target_holidays)
Thanks for the responses. Extra points for @lungben for thinking ahead about business days (but I need them for the Eurex trading calendar, not sure that is built-in anywhere).
For most products, Eurex uses Target holiday calendar. Not sure if there is a free source, but it is available in Bloomberg or Reuters.
Thanks! I’ll take a look.
Have a look at BusinessDays.jl. This example uses an unexported function
findweekday. Find the first business day (TARGET2) on or after the first Friday of January 2021.
julia> using BusinessDays, Dates
findweekday(weekday_target::Integer, yy::Integer, mm::Integer, occurrence::Integer, ascending::Bool) → Date
Given a year yy and month mm, finds a date where a choosen weekday occurs.
weekday_target values are declared in module Base.Dates:
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday = 1,2,3,4,5,6,7.
If ascending is true, searches from the beginning of the month. If false,
searches from the end of the month.
If occurrence is 2 and weekday_target is Monday, searches the 2nd Monday of
the given month, and so on.
julia> dow = Dates.Friday; y = 2021; m = 1; occurence = 1
julia> tobday(:TARGET2, BusinessDays.findweekday(dow, y, m, occurence, true))
Ah I was aware of BusinessDays.jl but did not know about this function.