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.csvNext, 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.
Again, using a function from the library('EPFR.r'), compound.flows() compounds our daily percentage flow over the trailing lookback period for each country.
| 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.
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.
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.
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.
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.
7.2.3 Model
20-day flow percentage ranked into quintiles (computed only where forward returns are available)
| 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
| 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
| 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 |