8.2 Strategy Implementation

To implementing this strategy, begin by reading in the flow files to our R studio workspace.

x <- mat.read(flow.file) # GET RGN FLOW PERCENTAGE C:\\EPFR\\PremDaily\\FloPctBond-US-PremDaily700.csv
y <- mat.read(ret.file) # TOTAL RETURN INDEX C:\\EPFR\\returns\\USBond_ETFS.txt

There is one date where we do not have daily flows published before 7am available which is on 20 Feb. 2023. For this date we will use the following code to fill in the missing day of data with the previous day’s flows, with the help of functions from library('EPFR.r').

# MISSING FLOW DATES (GETS PRIOR-DAY'S FLOW PERCENTAGE)
w <- dimnames(x)[[1]]
x <- map.rname(x, flowdate.seq(w[1], rev(w)[1]))
x <- fcn.mat.vec(fix.gaps, x, , T)

8.2.1 Total Return Index

We will then import our two total return files and modify them to become one data frame of total index returns indexed so that time moves forward. To do this, we will use the function ret.to.idx() from library('EPFR.r'). We will also use the functions map.rname() to ensure the row names of the matrices line up with our flow file, and ret.idx.gaps.fix() to replace any NA values. Please refer to the library documentation for the complete list of parameters for these functions (tip: ?ret.to.idx(),?ret.idx.gaps.fix() ).

# TOTAL-RETURN INDEX
y <- ret.to.idx(map.rname(y, dimnames(x)[[1]])) 
y <- ret.idx.gaps.fix(y)

8.2.2 Ranking Asset Classes

Next, we sort each of the asset classes in our universe into five equal bins based on their previous days percentage flow throughout history. To do this, we will use the function from library('EPFR.r'), called bbk(). This function will output a standardized backtest result.

The bbk() function requires our daily percentage flow data compounded over a desired period and the total return index data. Please refer to the library documentation for the complete list of parameters of this function (tip: ?bbk()).

The first parameter we add is the number of bins we want to use. For our case, we want to use 5 because our strategy is to go long the top fifth and short the bottom fifth.

nBin <- 5 # NUMBER OF BINS

EPFR’s Premium Daily flow data is published the next day before the market open, we will only need to account for a 1-day delay in our model.

delay <- 1 # DELAY IN KNOWING DATA (IN WEEKDAYS) - data is available before market opens

It is also important to note that this model will be re-balanced daily. The function requires an input for the day of the week to trade, we will put NULL.

doW <- NULL # DAY OF THE WEEK YOU WILL TRADE ON (NULL = DAILY)

Additionally, we want to evaluate the performance of the signal based on our holding period. The user can input the return horizons that they are interested in here. For this model, we define a return horizon for daily rebalancing or a 1 day holding period.

hz <- c(1) # RETURN HORIZON (IN WEEKDAYS) - holding periods

Now that we have defined all of our inputs, to rank the asset classes into quintiles by their 1-day percentage flow, we call the function bbk() for a one-week holding period.

z <- bbk(x, y, 1, hz[1], nBin, doW, T, 0, delay)

8.2.3 Model

1-day flow percentage ranked into quintiles (computed only where forward returns are available)

z[["bins"]]
Bank Loan High Yield Inflation Protected Intermediate Term Intermediate Term Corporate Intermediate Term Government Long Term Bond Long Term Corporate Long Term Government Mortgage Backed Short Term Bond Short Term Corporate Short Term Government Total Return
20230228 5 5 4 2 1 5 1 4 3 4 2 2 1 3
20230227 4 4 5 2 2 5 5 1 1 2 3 4 1 3
20230224 3 4 4 2 2 5 5 3 5 2 1 4 1 1
20230223 5 5 4 1 3 4 1 2 5 2 2 4 1 3
20230222 4 5 3 2 3 4 NA 5 1 2 NA 4 1 2
20230221 4 5 4 2 5 1 3 1 5 1 NA 3 2 3

Quintile returns over the equal-weight universe

z[["rets"]]
Q1 Q2 Q3 Q4 Q5 TxB uRet
20230228 -0.0419955 -0.0689486 0.1374004 0.1282479 -0.1089042 0.0669087 -0.1817861
20230227 -0.3599815 -0.0952014 0.0792846 0.3926506 0.0096758 -0.3696574 -0.2705314
20230224 -0.1165616 0.1505063 -0.1288016 0.0864855 -0.0345623 -0.0819993 0.1725353
20230223 0.0782963 -0.0066639 -0.0378932 -0.0693983 0.0230281 0.0552682 -0.2003083
20230222 -0.0085670 -0.0447315 -0.2822338 -0.0648286 0.4551409 -0.4637079 0.1091861
20230221 0.0224375 0.0850116 0.1011316 0.0144925 -0.1899052 0.2123428 -0.0648474

Def: TxB represents summary statistics for the long/short portfolio (top - bottom = Q1 - Q5 = overall portfolio returns)


8.2.4 Performance

Annualized mean one-day returns

bbk(x, y, 1, hz[1], nBin, doW, T, 0, delay)$annSumm # DISPLAY CALENDAR-YEAR RETURNS
Q1 Q2 Q3 Q4 Q5 TxB uRet nPrds
2019 1.7 0.5 -1.6 -2.7 1.2 0.5 5.2 219
2020 7.4 -1.4 -2.0 5.3 -7.4 14.8 3.8 251
2021 2.1 -2.1 1.1 1.7 -1.1 3.2 -2.6 251
2022 3.3 0.1 -1.3 2.6 -4.0 7.3 -15.8 251
2023 2.5 2.3 -3.1 0.8 -2.4 4.9 2.7 249