7.2 Strategy Implementation

The final step is implementing this strategy to create a signal. Let’s begin by reading in the flow and return files to our R studio workspace.

x <- mat.read(flow.file) # GET FLOW PERCENTAGE C:\\EPFR\\daily\\FloPctCtry-B-daily.csv
y <- mat.read(ret.file) # TOTAL RETURN INDEX C:\\EPFR\\returns\\g10rates.csv

Next, we will need to ensure that the data structure in \(x\) and \(y\) are completely aligned, having the same column names in the same order. Below we will subset the columns of \(x\) to only use the G10 countries listed in y, and in the same date order as y \(y\).

x <- x[, is.element(dimnames(x)[[2]],dimnames(y)[[2]])] # SUBSET TO G10 COUNTRIES           
y <- y[,dimnames(x)[[2]]]           

* Note: subsetting can also be done when creating the flow and return files

7.2.1 Compounding Flows

Next, we set up a variable for our lookback period, which can also be called a flow window. This variable will be the window of time we use to create a trailing compounded daily percentage flow. The lookback period we choose for our demonstrations is 20 days.

lookback <- 20 # FLOW WINDOW (IN WEEKDAYS) - 20 day look back period

Again, using a function from the library('EPFR.r'), compound.flows() compounds our daily percentage flow over the trailing lookback period for each country.

x <- compound.flows(x, lookback, F) # COMPOUND FLOWS
AU CA CH DE GB JP NO NZ SE US
20220201 -0.0147356 0.0998440 -1.281829 -0.5176295 -0.4215695 0.8690703 -0.8346496 -1.086802 -0.6430788 -1.085531
20220202 -0.1436693 0.0422141 -1.566203 -0.4747096 -0.5748950 0.8112050 -0.9143912 -1.137833 -0.6976324 -1.079877
20220203 -0.1788996 0.0583401 -1.648158 -0.5788006 -0.6370636 0.7962985 -0.9826300 -1.174760 -0.7499326 -1.154433
20220204 -0.2867007 0.0322003 -1.957859 -0.6540758 -0.7560261 0.7889151 -1.1206663 -1.358382 -0.9953409 -1.232607
20220207 -0.4238226 0.0518056 -2.150644 -0.8875790 -0.8945644 0.7171231 -1.2435045 -1.439052 -1.2318519 -1.332639
20220208 -0.6638225 -0.1019379 -2.488187 -1.1557103 -1.0960234 0.5340066 -1.5090552 -1.721286 -1.6577818 -1.430017

7.2.2 Ranking Countries

Next, we sort each of the countries in our universe into five equal bins based on their compounded percentage flow values for the selected holding period. 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 10-year rates data for each G10 country. 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

Since EPFR data is published with a T+1 day lag and is released around 5:00 pm EST, we account for a T+2 day delay in our model. Users interested in more timely signals can also use the T+2 open prices for backtesting purposes. Alternatively, EPFR’s Premium Daily offering collects an earlier release of end-of-day data which includes a significant subset of its original fund-level flow information.

delay <- 2 # DELAY IN KNOWING DATA (IN WEEKDAYS) - data takes time to have

It is also important to note that this model will need to be re-balanced weekly. The day of the week the rebalancing occurs is at the user’s discretion. For this example we will set the day of the week to trade as Friday.

doW <- 5 # DAY OF THE WEEK YOU WILL TRADE ON (5 = FRIDAYS)

Additionally, we also evaluate the returns for different holding periods. The user can input the return horizons that they are interested in here. For this example, we define a return horizon for weekly, fortnightly, monthly, bi-monthly, quarterly, and semi-annual rebalancing.

hz <- c(5, 10, 20, 45, 65, 130) # RETURN HORIZON (IN WEEKDAYS) - holding periods

Now that we have defined all of our inputs, to rank the countries into quintiles by their 20-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, sprds = T)

7.2.3 Model

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

z[["bins"]]
AU CA CH DE GB JP NO NZ SE US
20220225 2 1 5 2 3 1 4 3 5 4
20220218 2 1 5 2 3 1 4 3 5 4
20220211 2 1 5 3 2 1 4 4 5 3
20220204 2 1 5 2 3 1 4 5 3 4

Quintile returns over the equal-weight universe

z[["rets"]]
Q1 Q2 Q3 Q4 Q5 TxB uRet
20220225 0.03595 -0.0168 0.04595 -0.06605 0.00095 0.0350 -0.17545
20220218 -0.02070 -0.0177 0.00480 0.02080 0.01280 -0.0335 0.02970
20220211 0.04895 -0.0203 -0.01255 0.00545 -0.02155 0.0705 -0.04445
20220204 -0.07860 0.0764 0.00390 -0.04060 0.03890 -0.1175 0.09410

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


7.2.4 Performance

Performance over all holding periods

fcn <- function(retW) {as.matrix(bbk(x, y, 1, retW, nBin, doW, T, 0, delay, sprds = T)$summ)} # DEFINE SUMMARY FUNCTION         

sapply(split(hz, hz), fcn, simplify = "array") # WRITE SUMMARIES            
Q1 Q2 Q3 Q4 Q5 TxB uRet
Weekly
AnnMn -0.1 0.0 -0.1 0.0 0.1 -0.2 -0.2
AnnSd 0.3 0.3 0.3 0.3 0.3 0.5 0.6
Sharpe -28.2 11.0 -32.1 -3.7 50.1 -50.1 -36.8
HitRate -1.0 0.1 -1.3 -0.3 6.4 -4.4 -4.2
Beta NA NA NA NA NA NA 1.0
Alpha NA NA NA NA NA NA 0.0
DrawDn -2.0 -0.8 -2.0 -0.8 -1.0 -4.3 -4.6
DDnBeg 20090417 20090619 20070615 20120914 20081226 20090605 20070706
DDnN 631 539 409 480 26 616 671
AnnTo 1443 2580 2876 2543 1518 2961 0
Fortnightly
AnnMn -0.1 0.1 0.0 -0.1 0.1 -0.2 -0.2
AnnSd 0.3 0.3 0.3 0.3 0.3 0.4 0.6
Sharpe -32.1 33.5 -14.6 -31.3 40.2 -45.0 -39.7
HitRate -3.6 2.4 0.3 -4.2 5.2 -5.4 -5.6
Beta NA NA NA NA NA NA 1.0
Alpha NA NA NA NA NA NA 0.0
DrawDn -2.2 -0.7 -1.3 -1.3 -0.8 -4.2 -4.6
DDnBeg 20090372 20110822 20070612 20095664 20081216 20085623 20070660
DDnN 326 65 111 310 14 336 339
AnnTo 1055 1568 1692 1650 1119 2174 0
Monthly
AnnMn -0.1 0.1 0.0 -0.1 0.1 -0.2 -0.2
AnnSd 0.3 0.3 0.3 0.2 0.3 0.4 0.6
Sharpe -27.6 24.3 -14.5 -28.6 41.7 -43.3 -39.4
HitRate -2.9 3.1 -2.7 -5.4 8.0 -5.3 -6.8
Beta NA NA NA NA NA NA 1.0
Alpha NA NA NA NA NA NA 0.0
DrawDn -2.0 -0.7 -1.2 -1.4 -0.7 -3.7 -4.6
DDnBeg 20087969 20098065 20100566 20083141 20093212 20087889 20070643
DDnN 162 68 94 122 29 163 170
AnnTo 740 924 977 953 785 1525 0
Bi-Monthly
AnnMn -0.1 0.0 0.0 0.0 0.1 -0.2 -0.2
AnnSd 0.3 0.3 0.3 0.2 0.3 0.4 0.6
Sharpe -27.5 5.7 4.6 -15.9 34.8 -39.9 -38.2
HitRate -5.9 -1.2 2.0 0.0 7.5 -7.1 -8.3
Beta NA NA NA NA NA NA 1.0
Alpha NA NA NA NA NA NA 0.0
DrawDn -1.8 -0.9 -0.8 -1.0 -0.6 -2.9 -4.5
DDnBeg 20084295 20102888 20091694 20109616 20118674 20077514 20071773
DDnN 64 38 24 24 17 65 75
AnnTo 365 430 445 434 373 738 0
Quarterly
AnnMn -0.1 0.0 0.0 0.0 0.1 -0.1 -0.2
AnnSd 0.2 0.2 0.3 0.2 0.2 0.4 0.6
Sharpe -23.3 -5.1 5.4 -8.7 36.3 -37.7 -38.0
HitRate -5.4 -2.1 2.0 -1.7 9.8 -6.4 -9.4
Beta NA NA NA NA NA NA 1.0
Alpha NA NA NA NA NA NA 0.0
DrawDn -1.5 -1.1 -0.8 -0.9 -0.5 -2.5 -4.4
DDnBeg 20089039 20102884 20102184 20114652 20108193 20089901 20070707
DDnN 44 33 21 27 9 45 52
AnnTo 256 300 303 307 261 518 0
Semi-Annual
AnnMn 0.0 0.0 0.0 0.0 0.1 -0.1 -0.2
AnnSd 0.2 0.2 0.2 0.2 0.2 0.4 0.6
Sharpe -13.8 -1.7 -2.5 -5.9 27.3 -25.9 -38.1
HitRate -4.0 -2.1 0.3 -2.8 8.5 -8.1 -9.7
Beta NA NA NA NA NA NA 1.0
Alpha NA NA NA NA NA NA 0.0
DrawDn -1.3 -0.9 -0.9 -0.8 -0.5 -2.2 -4.3
DDnBeg 20093350 20112889 20096066 20114543 20107167 20091428 20071216
DDnN 17 12 12 13 6 19 26
AnnTo 143 156 158 160 140 283 0

Annualized mean one-week returns

bbk(x, y, 1, hz[1], nBin, doW, T, 0, delay, sprds = T)$annSumm # DISPLAY CALENDAR-YEAR RETURNS
Q1 Q2 Q3 Q4 Q5 TxB uRet nPrds
2007 0.2 0.5 -0.4 -0.5 0.1 0.0 -0.5 29
2008 0.2 0.0 -0.9 0.1 0.6 -0.4 -1.4 52
2009 0.1 0.2 0.1 0.3 -0.7 0.8 0.7 52
2010 0.0 0.0 0.2 0.0 -0.1 0.0 -0.3 53
2011 -0.2 0.0 -0.6 0.3 0.5 -0.7 -1.3 52
2012 0.3 -0.4 -0.2 -0.1 0.3 0.0 -0.2 52
2013 -0.3 0.0 0.1 -0.1 0.2 -0.5 0.9 52
2014 -0.2 0.3 -0.4 0.0 0.2 -0.4 -1.1 52
2015 -0.1 0.0 0.1 -0.1 0.0 -0.1 -0.1 52
2016 -0.1 0.0 0.2 -0.2 0.0 -0.1 -0.2 53
2017 -0.4 -0.2 0.1 0.1 0.4 -0.7 0.0 52
2018 -0.6 0.0 0.2 0.3 0.1 -0.7 -0.1 52
2019 -0.1 -0.1 0.1 0.0 0.2 -0.3 -0.5 52
2020 0.1 0.1 0.0 -0.5 0.3 -0.2 -0.4 52
2021 0.0 0.2 -0.4 0.0 0.0 0.0 0.6 53
2022 -1.1 0.3 0.7 0.2 -0.1 -1.1 2.6 10