Introduction
LIBOR will transition to an alternative reference rate. The SOFR(Secured Overnight Financing Rate) is the risk-free alternative reference rates for USD and is an in-arrears rate. Unlike LIBOR, SOFR is a secured overnight rate, not a forward looking term rate. SOFR Averages (30-, 90-, and 180-calendar days) are constructed by the geometric average of the daily rates. There are two method to make them. The first is to use the daily rate directly and the second is to use the SOFR index.
Before going into SOFR Averages, we will calculate SOFR Index at first. The following pages are the information regarding the SOFR.
Additional Information about Reference Rates Administered by the New York Fed (https://www.newyorkfed.org/markets/reference-rates/additional-information-about-reference-rates#sofr_ai_calculation_methodology)
SOFR Averages and Index Data (https://www.newyorkfed.org/markets/reference-rates/sofr-averages-and-index#historical-search)
Daily SOFR rates can be downloaded at the following page.
Secured Overnight Financing Rate (SOFR) (https://fred.stlouisfed.org/series/SOFR)We try to replicate the SOFR index from the following page.
Daily indicative SOFR averages and index (Apr. 2018 - Feb. 2020) (https://www.newyorkfed.org/medialibrary/media/markets/historical_indicative_sofr_avg_ind_data.xlsx)The above excel file have the following form (to get all visible rows of averages, some selected rows are hidden)
Before going into the detail, It is important to distinguish between publication date and value date (date of rate). SOFR rate available at publication date is the rate which is determined at previous business date(value date). If there is no holiday and weekend in between, the publiation date is the time \(t\) and the previous business date is the time \(t-1\).
The SOFR Index measures the cumulative index of compounding the SOFR on a unit of investment over time, with the initial value set to 1.00000000 on April 2, 2018, the first value date of the SOFR. The Index is compounded by the value of each SOFR thereafter.
\[\begin{align} \text{SOFR Index at time t} = \prod_{i=April, 3, 2018}^{t} \left( 1 + \frac{SOFR_i \times n_i }{ 360}\right) \end{align}\] Here, \(i\) denotes a sequential business day from April, 3, 2018 to \(t\). \(SOFR_i\) is the SOFR applicable on business day i and \(n_i\) is the number of calendar days for which \(SOFR_i\) applies.
From this SOFR Index, SOFR averages can be calculated using the following formula.
\[\begin{align} &\text{SOFR Average between x and y} \\ &= \left(\frac{\text{SOFR Index_y}}{\text{SOFR Index_x}} -1 \right) \times \left(\frac{360}{dc} \right) \end{align}\]
Here, \(x\) and \(y\) are the start and end date of calculation period respectively. \(dc\) is the number of calendar dates in the calculation period.
We can calculate the SOFR index from the daily SOFR rates using the following R code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #=========================================================================# # Financial Econometrics & Derivatives, ML/DL using R, Python, Tensorflow # by Sang-Heon Lee #-------------------------------------------------------------------------# # Calculation of SOFR Index from Daily SOFR Rates #=========================================================================# # construction of data frame df <- data.frame(rbind( c("2018-04-02", 1.00000000, 1.80), c("2018-04-03", 1.00005000, 1.83), c("2018-04-04", 1.00010084, 1.74), c("2018-04-05", 1.00014917, 1.75), c("2018-04-06", 1.00019779, 1.75), c("2018-04-09", 1.00034365, 1.75), c("2018-04-10", 1.00039228, 1.75), c("2018-04-11", 1.00044091, 1.76), c("2018-04-12", 1.00048982, 1.73), c("2018-04-13", 1.00053790, 1.72), c("2018-04-16", 1.00068131, 1.77), c("2018-04-17", 1.00073051, 1.76), c("2018-04-18", 1.00077944, 1.75), c("2018-04-19", 1.00082809, 1.73), c("2018-04-20", 1.00087618, 1.72), c("2018-04-23", 1.00101964, 1.70))) colnames(df) <- c("Pub_Date","SOFR_Index", "SOFR_Rate") # string to date format df$Pub_Date <- as.Date(df$Pub_Date) df$SOFR_Index <- as.numeric(df$SOFR_Index) df$SOFR_Rate <- as.numeric(df$SOFR_Rate) for(i in 1:nrow(df)) { if (i==1) { df$Calc_Index[i] = 1 } else { ni = as.numeric(df$Pub_Date[i] - df$Pub_Date[i-1]) df$Calc_Index[i] = df$Calc_Index[i-1]* (1+df$SOFR_Rate[i-1]/100*ni/360) } } # rounding at 8-decimal df$Calc_Index <- round(df$Calc_Index,8) # print df print(df) | cs |
In the above R code, data.frame (df) have all data as string formats because Pub_Date is of a string type. Therefore type recast is applied. The content of rest of code is the implementation of the SOFR Index by its formula. The following result shows that Calc_Index (the right most column of df) is the same as the SOFR_Index.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | > print(df) Pub_Date SOFR_Index SOFR_Rate Calc_Index 1 2018-04-02 1.000000 1.80 1.000000 2 2018-04-03 1.000050 1.83 1.000050 3 2018-04-04 1.000101 1.74 1.000101 4 2018-04-05 1.000149 1.75 1.000149 5 2018-04-06 1.000198 1.75 1.000198 6 2018-04-09 1.000344 1.75 1.000344 7 2018-04-10 1.000392 1.75 1.000392 8 2018-04-11 1.000441 1.76 1.000441 9 2018-04-12 1.000490 1.73 1.000490 10 2018-04-13 1.000538 1.72 1.000538 11 2018-04-16 1.000681 1.77 1.000681 12 2018-04-17 1.000731 1.76 1.000731 13 2018-04-18 1.000779 1.75 1.000779 14 2018-04-19 1.000828 1.73 1.000828 15 2018-04-20 1.000876 1.72 1.000876 16 2018-04-23 1.001020 1.70 1.001020 > | cs |
Next time, we will make SOFR averages from the SOFR index. After that, we try to get the same results from the direct use of SOFR rates successively. \(\blacksquare\)
pls make a workout how to valuate a OIS swap based on float rate of sofr o/n
ReplyDeleteThese days I am working on other issue not derivatives. After my works are completed, I will deal with that issue.
Delete