A positive batting average trend follower? Introducing Trend Vigor.

Since this is the first post on this blog, a quick start up for those who may be reading this who don’t have my exact technical background: this blog will mostly use R, and backtesting will be done in the quantstrat package.

For those of you who follow me from a non-technical background, send me a message, and I’ll help you get started. For those simply not acquainted with the quantstrat package, this is the link to the definitive, comprehensive guide on quantstrat.

http://www.rinfinance.com/agenda/2013/workshop/Humme+Peterson.pdf

To motivate this post, consider some common wisdom about both mean-reverting and trend-following strategies. Mean reverting strategies often sport a high percentage of positive trades, but the few negative trades can hammer the equity curve. On the other side of the equation, trend-following strategies run on a philosophy of “let your winners run and cut your losers”, resulting in many small losses and a few wins that make up for them. However, what if there were an indicator that behaved like the best of both worlds? That is, capitalize on trends, while cutting out a good portion of whipsaws?

The Trend Vigor Indicator, or TVI as I call it in my DSTrading package, available on my github (see my about page for the link), created by Dr. John Ehlers (whom I thank for providing the completed code), attempts to do just that. Here’s a link to the original presentation (code incomplete):

http://www.mesasoftware.com/Seminars/Trend%20Modes%20and%20Cycle%20Modes.pdf

As Dr. Ehlers says on the fifth slide, correctly identifying market mode means a great deal. Something I noticed is that the plot for the trend vigor index seems to be very smooth in general, so when the trend vigor rises, it generally doesn’t whipsaw around very much about any particular quantity (at least at the daily resolution), so there may be a strategy to take advantage of this possible property.

Here’s the corresponding function from the DSTrading package, which I will use in the following demo. There may also be a trend vigor calculation with one of Dr. Ehlers’s adaptive period computation algorithms built in. In any case, the way it works is this: it takes in a time series, and two parameters: a period, which is identical to the n parameter in indicators such as SMA and so on, and a delta, which is a trigonometric parameter to adjust the computation of the bandpass filter (I am not overly familiar with the rationale behind signal processing, so I’ll leave the commentary on the finer points of this parameter to someone more experienced in this field).

TVI then outputs a time series of a 0-centered trend vigor indicator, along with a pair of oscillators (signal and lead), which I may touch on in the future.

"TVI" <- function(x, period = 20, delta = 0.2, triggerLag = 1, ...) {
    if (period != 0) {
        # static, length-1 period
        beta <- cos(2 * pi/period)
        gamma <- 1/cos(4 * pi * delta/period)
        alpha <- gamma - sqrt(gamma * gamma - 1)
        BP <- 0.5 * (1 - alpha) * (x - lag(x, 2))
        BP[1] <- BP[2] <- 0
        BP <- filter(BP, c(beta * (1 + alpha), -1 * alpha), method = "recursive")
        BP <- xts(BP, order.by = index(x))
        signal <- BP - lag(BP, round(period/2))
        lead <- 1.4 * (BP - lag(BP, round(period/4)))

        BP2 <- BP * BP
        LBP2 <- lag(BP2, round(period/4))
        power <- runSum(BP2, period) + runSum(LBP2, period)
        RMS <- sqrt(power/period)
        PtoP <- 2 * sqrt(2) * RMS

        a1 <- exp(-sqrt(2) * pi/period)
        b1 <- 2 * a1 * cos(sqrt(2) * pi/period)
        coef2 <- b1
        coef3 <- -a1 * a1
        coef1 <- 1 - coef2 - coef3
        trend <- coef1 * (x - lag(x, period))
        trend[is.na(trend)] <- 0
        trend <- filter(trend, c(coef2, coef3), method = "recursive")
        trend <- xts(trend, order.by = index(x))
        vigor <- trend/PtoP
        vigor[vigor > 2] <- 2
        vigor[vigor < -2] <- -2
        trigger <- lag(vigor, triggerLag)
        out <- cbind(vigor, signal, lead, trigger)
        colnames(out) <- c("vigor", "signal", "lead", "trigger")
        return(out)
    } else {
        stop("Dynamic period computation not implemented yet.")
        # TODO -- DYNAMIC PERIOD TREND VIGOR
    }
}

So in order to test this indicator, I wrote a quantstrat demo to test its momentum properties. First, we will fetch the data, which consists of some ETFs that have been trading since before 2003. This is the data file I will source for this demo (called demoData.R), along with many others.

require(DSTrading)
require(quantstrat)
options(width=80)
source("demoData.R") #contains all of the data-related boilerplate.

Here are the exact contents of demoData.R

options("getSymbols.warning4.0"=FALSE)
rm(list=ls(.blotter), envir=.blotter)
initDate='1990-12-31'

currency('USD')
Sys.setenv(TZ="UTC")

symbols <- c("XLB", #SPDR Materials sector
             "XLE", #SPDR Energy sector
             "XLF", #SPDR Financial sector
             "XLP", #SPDR Consumer staples sector
             "XLI", #SPDR Industrial sector
             "XLU", #SPDR Utilities sector
             "XLV", #SPDR Healthcare sector
             "XLK", #SPDR Tech sector
             "XLY", #SPDR Consumer discretionary sector
             "RWR", #SPDR Dow Jones REIT ETF
             
             "EWJ", #iShares Japan
             "EWG", #iShares Germany
             "EWU", #iShares UK
             "EWC", #iShares Canada
             "EWY", #iShares South Korea
             "EWA", #iShares Australia
             "EWH", #iShares Hong Kong
             "EWS", #iShares Singapore
             "IYZ", #iShares U.S. Telecom
             "EZU", #iShares MSCI EMU ETF
             "IYR", #iShares U.S. Real Estate
             "EWT", #iShares Taiwan
             "EWZ", #iShares Brazil
             "EFA", #iShares EAFE
             "IGE", #iShares North American Natural Resources
             "EPP", #iShares Pacific Ex Japan
             "LQD", #iShares Investment Grade Corporate Bonds
             "SHY", #iShares 1-3 year TBonds
             "IEF", #iShares 3-7 year TBonds
             "TLT" #iShares 20+ year Bonds
)

#SPDR ETFs first, iShares ETFs afterwards
if(!"XLB" %in% ls()) { 
  suppressMessages(getSymbols(symbols, from="2003-01-01", to="2010-12-31", src="yahoo", adjust=TRUE))  
}

stock(symbols, currency="USD", multiplier=1)

The reason I’m using these symbols is fairly simple: they’re representative of a fairly broad aspect of both the U.S. economy and other developed economies abroad (E.G. Japan, Germany), and contain a fair amount of “staple” ETFs (SPDR sectors, EFA, internationals, etc.).

Let’s begin the demo. The strategy will be simple–the indicator will be the trend vigor calculation, and the strategy will go long on the next open when the trend vigor crosses above 1, sell the next open when it crosses below 1.4, and will stop out on the next open when the trend vigor crosses under 1 if it never crossed 1.4 within the duration of the position.

The general syntax of indicators, signals, and rules in quantstrat (for the uninitiated) is fairly straightforward:

add.indicator/add.signal/add.rule is a function which takes in the name of the strategy as the first argument (which I always use strategy.st for), a name of an R function in the name argument, the arguments to the function as the argument to arguments (that is, arguments=list(x=quote(Cl(mktdata)), period=100, delta=0.2) is the argument to the TVI function which is the value for the name argument in the add.indicator function), and finally, a label. While the labels may seem like so much window dressing, they are critical in terms of linking indicators to signals, signals to rules, and everything to any optimization/robustness testing you may deecide to do. Do not forget them.

While I kept Dr. Ehlers’s default period setting, I found that the strategy works best starting at 60 days for the period, and has a solid performance until the mid-hundreds, at which point it generates too few trades per instrument to really be able to look at any individual statistics.

Here’s the strategy.

#To rerun the strategy, re-run everything from this line down.

strategy.st <- portfolio.st <- account.st <- "TVItrendFollowingLong"
rm.strat(portfolio.st)
rm.strat(strategy.st)
initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD')
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD')
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)

#indicator

add.indicator(strategy.st, name="TVI", arguments=list(x=quote(Cl(mktdata)), period=100, delta=0.2), label="TVI")

#signals

add.signal(strategy.st, name="sigThreshold", 
           arguments=list(threshold=1, column="vigor.TVI", relationship="gte", cross=TRUE),
           label="longEntry")

add.signal(strategy.st, name="sigThreshold",
           arguments=list(threshold=1.4, column="vigor.TVI", relationship="lt", cross=TRUE),
           label="longExit")

add.signal(strategy.st, name="sigThreshold",
           arguments=list(threshold=1, column="vigor.TVI", relationship="lt", cross=TRUE),
           label="wrongExit")

#rules

add.rule(strategy.st, name="ruleSignal", 
         arguments=list(sigcol="longEntry", sigval=TRUE, orderqty=100, 
                        ordertype="market", orderside="long", replace=FALSE, prefer="Open"), 
         type="enter", path.dep=TRUE)

add.rule(strategy.st, name="ruleSignal", 
         arguments=list(sigcol="longExit", sigval=TRUE, orderqty="all", 
                        ordertype="market", orderside="long", replace=FALSE, prefer="Open"), 
         type="exit", path.dep=TRUE)

add.rule(strategy.st, name="ruleSignal", 
         arguments=list(sigcol="wrongExit", sigval=TRUE, orderqty="all", 
                        ordertype="market", orderside="long", replace=FALSE, prefer="Open"), 
         type="exit", path.dep=TRUE)

The strategy is then run with the applyStrategy call. I set verbose to FALSE for the purpose of not displaying the order log in this blog post, but by default, quantstrat will start printing out trades at this point. Printing out trades serves two purposes (in my experience): first off, you know your strategy is actually doing something, and secondly, even if it is, the attentive eye will also see if the strategy is not behaving intuitively (that is, is it loading up more lots when you thought it should only be trading 1 lot at a time? This happens often with strategies that crisscross above and below a threshold, such as with simple RSI strategies.)

#apply strategy

t1 <- Sys.time()
out <- applyStrategy(strategy=strategy.st,portfolios=portfolio.st, verbose=FALSE)
t2 <- Sys.time()
print(t2-t1)

 #tradeStats

updatePortf(portfolio.st)
dateRange <- time(getPortfolio(portfolio.st)$summary)[-1]
updateAcct(portfolio.st,dateRange)
updateEndEq(account.st)

The last four lines are some more “accounting boilerplate” that are necessary for the following analytics.

Here are the trade statistics:

tStats <- tradeStats(Portfolios = portfolio.st, use = "trades", inclZeroDays = FALSE)
print(data.frame(t(tStats[, -c(1:2)])))

Here’s the output:

                          EFA      EPP      EWA       EWC      EWG      EWH
 Num.Txns              11.000   11.000   11.000   13.0000   11.000   15.000
 Num.Trades             6.000    6.000    6.000    7.0000    6.000    8.000
 Net.Trading.PL      2565.775 1969.314 1286.254  467.3296  814.737  606.872
 Avg.Trade.PL         427.629  328.219  214.376   66.7614  135.789   75.859
 Med.Trade.PL         406.141  187.906  133.158  134.4598   32.897   98.591
 Largest.Winner       848.301  907.877  599.901  349.9296  591.163  180.214
 Largest.Loser          0.000 -124.794  -95.424 -256.5205  -59.893  -95.641
 Gross.Profits       2565.775 2163.065 1393.249  992.6210  942.630  703.020
 Gross.Losses           0.000 -193.750 -106.995 -525.2914 -127.893  -96.148
 Std.Dev.Trade.PL     353.537  461.074  285.169  239.4493  257.994   92.620
 Percent.Positive     100.000   66.667   66.667   57.1429   66.667   75.000
 Percent.Negative       0.000   33.333   33.333   42.8571   33.333   25.000
 Profit.Factor            Inf   11.164   13.022    1.8897    7.370    7.312
 Avg.Win.Trade        427.629  540.766  348.312  248.1553  235.658  117.170
 Med.Win.Trade        406.141  584.662  330.518  254.1158  175.014  109.259
 Avg.Losing.Trade         NaN  -96.875  -53.498 -175.0971  -63.947  -48.074
 Med.Losing.Trade          NA  -96.875  -53.498 -143.9421  -63.947  -48.074
 Avg.Daily.PL         494.769  407.654  230.788   42.4390  176.547   86.768
 Med.Daily.PL         571.279  289.949  134.004    4.8155   64.354  105.539
 Std.Dev.Daily.PL     349.896  467.346  315.644  252.6538  265.974   94.326
 Ann.Sharpe            22.447   13.847   11.607    2.6665   10.537   14.603
 Max.Drawdown       -1035.238 -817.160 -519.809 -765.6489 -442.170 -529.427
 Profit.To.Max.Draw     2.478    2.410    2.474    0.6104    1.843    1.146
 Avg.WinLoss.Ratio        NaN    5.582    6.511    1.4172    3.685    2.437
 Med.WinLoss.Ratio         NA    6.035    6.178    1.7654    2.737    2.273
 Max.Equity          3154.421 2386.521 1330.685  536.1786 1115.907  947.518
 Min.Equity            -1.416   -5.738    0.000 -229.4703  -10.326   -7.227
 End.Equity          2565.775 1969.314 1286.254  467.3296  814.737  606.872

                          EWJ       EWS        EWT      EWU        EWY       EWZ
 Num.Txns             15.0000   15.0000   13.00000   15.000    13.0000    13.000
 Num.Trades            8.0000    8.0000    7.00000    8.000     7.0000     7.000
 Net.Trading.PL      126.0921  527.5159  352.38231  496.885  3903.4781  5650.267
 Avg.Trade.PL         15.7615   65.9395   50.34033   62.111   557.6397   807.181
 Med.Trade.PL         -4.8031   48.6563   15.20059   53.201   507.7895   425.888
 Largest.Winner      211.4631  287.4863  181.33002  170.439  1911.0697  3090.026
 Largest.Loser      -109.4557 -183.5601  -98.93976  -26.825  -645.4187  -762.177
 Gross.Profits       369.6269  746.4612  536.96182  572.167  4548.8968  6431.642
 Gross.Losses       -243.5348 -218.9453 -184.57951  -75.282  -645.4187  -781.375
 Std.Dev.Trade.PL    105.5657  156.0082  121.48260   84.271   766.8694  1323.564
 Percent.Positive     37.5000   75.0000   57.14286   62.500    85.7143    71.429
 Percent.Negative     62.5000   25.0000   42.85714   37.500    14.2857    28.571
 Profit.Factor         1.5178    3.4094    2.90911    7.600     7.0480     8.231
 Avg.Win.Trade       123.2090  124.4102  134.24045  114.433   758.1495  1286.328
 Med.Win.Trade        99.0951   70.0932  170.21560  138.704   522.5712   533.596
 Avg.Losing.Trade    -48.7070 -109.4727  -61.52650  -25.094  -645.4187  -390.687
 Med.Losing.Trade    -29.1036 -109.4727  -70.52540  -25.206  -645.4187  -390.687
 Avg.Daily.PL          9.5748   69.4619   32.17724   74.305   585.8121   944.911
 Med.Daily.PL         -5.6972   56.0302    0.04312   63.148   522.5712   479.742
 Std.Dev.Daily.PL    112.4465  168.1641  122.22309   83.050   836.0858  1393.859
 Ann.Sharpe            1.3517    6.5571    4.17923   14.203    11.1226    10.761
 Max.Drawdown       -355.7105 -255.8450 -466.69819 -307.027 -1576.6419 -1600.155
 Profit.To.Max.Draw    0.3545    2.0619    0.75505    1.618     2.4758     3.531
 Avg.WinLoss.Ratio     2.5296    1.1365    2.18183    4.560     1.1747     3.292
 Med.WinLoss.Ratio     3.4049    0.6403    2.41354    5.503     0.8097     1.366
 Max.Equity          422.7339  547.8001  369.07717  650.692  4695.6618  6644.273
 Min.Equity            0.0000  -27.7323  -97.62103  -29.595  -106.6402   -58.404
 End.Equity          126.0921  527.5159  352.38231  496.885  3903.4781  5650.267

                         EZU       IEF        IGE      IYR       IYZ       LQD
 Num.Txns             13.000   16.0000      13.00   11.000   19.0000   12.0000
 Num.Trades            7.000    8.0000       7.00    6.000   10.0000    6.0000
 Net.Trading.PL     1182.003  727.7658 -3.733e+01 1925.684  174.6551  -83.6846
 Avg.Trade.PL        168.858   90.9707 -5.333e+00  320.947   17.4655  -13.9474
 Med.Trade.PL        116.812   60.5784  1.500e+02  310.430  -36.2849  -43.9321
 Largest.Winner      706.295  356.5054  6.172e+02  807.768  447.8273  257.6271
 Largest.Loser       -21.553 -224.7938 -1.047e+03 -294.785 -158.5646 -278.1925
 Gross.Profits      1256.372 1093.0415  1.342e+03 2220.469  707.1572  447.8795
 Gross.Losses        -74.369 -365.2757 -1.380e+03 -294.785 -532.5021 -531.5641
 Std.Dev.Trade.PL    255.791  211.5468  5.380e+02  367.789  179.1449  206.1184
 Percent.Positive     71.429   75.0000  5.714e+01   83.333   40.0000   33.3333
 Percent.Negative     28.571   25.0000  4.286e+01   16.667   60.0000   66.6667
 Profit.Factor        16.894    2.9924  9.729e-01    7.533    1.3280    0.8426
 Avg.Win.Trade       251.274  182.1736  3.356e+02  444.094  176.7893  223.9397
 Med.Win.Trade       126.562  168.8602  2.875e+02  328.352  113.7095  223.9397
 Avg.Losing.Trade    -37.184 -182.6379 -4.598e+02 -294.785  -88.7504 -132.8910
 Med.Losing.Trade    -37.184 -182.6379 -1.881e+02 -294.785  -82.9667 -121.9668
 Avg.Daily.PL        205.803   90.9707 -6.897e+01  336.975    1.5594  -13.9474
 Med.Daily.PL        121.687   60.5784  2.740e+00  328.352  -39.9546  -43.9321
 Std.Dev.Daily.PL    258.938  211.5468  5.598e+02  408.851  182.3684  206.1184
 Ann.Sharpe           12.617    6.8265 -1.956e+00   13.084    0.1357   -1.0742
 Max.Drawdown       -756.388 -753.7337 -1.189e+03 -977.604 -415.3754 -648.4695
 Profit.To.Max.Draw    1.563    0.9655 -3.139e-02    1.970    0.4205   -0.1290
 Avg.WinLoss.Ratio     6.758    0.9975  7.297e-01    1.507    1.9920    1.6851
 Med.WinLoss.Ratio     3.404    0.9246  1.529e+00    1.114    1.3705    1.8361
 Max.Equity         1650.980 1400.1652  4.661e+02 1932.684  332.9343  251.3202
 Min.Equity          -27.256 -321.9691 -7.230e+02 -190.088 -335.9970 -397.1493
 End.Equity         1182.003  727.7658 -3.733e+01 1925.684  174.6551  -83.6846

                          RWR      SHY        TLT      XLB        XLE      XLF
 Num.Txns              11.000   13.000    14.0000   15.000    17.0000   12.000
 Num.Trades             6.000    7.000     7.0000    8.000     9.0000    6.000
 Net.Trading.PL      1995.629 1142.519  1442.2875  980.284  -456.6602  323.884
 Avg.Trade.PL         332.605  163.217   206.0411  122.536   -50.7400   53.981
 Med.Trade.PL         335.682   61.755   269.8718  113.830  -152.9856  100.260
 Largest.Winner       773.739  901.261   809.9610  661.063  1136.1168  223.785
 Largest.Loser       -292.223  -41.231  -484.5142 -323.312 -1360.1798 -189.485
 Gross.Profits       2287.852 1183.751  1926.8017 1620.063  2243.5774  575.037
 Gross.Losses        -292.223  -41.231  -484.5142 -639.779 -2700.2376 -251.153
 Std.Dev.Trade.PL     379.963  330.145   388.5266  334.521   723.7411  153.249
 Percent.Positive      83.333   85.714    85.7143   62.500    44.4444   66.667
 Percent.Negative      16.667   14.286    14.2857   37.500    55.5556   33.333
 Profit.Factor          7.829   28.710     3.9768    2.532     0.8309    2.290
 Avg.Win.Trade        457.570  197.292   321.1336  324.013   560.8943  143.759
 Med.Win.Trade        359.312   63.647   295.1517  357.324   484.7987  142.446
 Avg.Losing.Trade    -292.223  -41.231  -484.5142 -213.260  -540.0475 -125.577
 Med.Losing.Trade    -292.223  -41.231  -484.5142 -229.386  -339.2491 -125.577
 Avg.Daily.PL         327.263  179.497   206.0411   88.994  -130.5507   53.981
 Med.Daily.PL         312.051   39.657   269.8718   49.687  -198.6073  100.260
 Std.Dev.Daily.PL     424.560  358.565   388.5266  346.489   730.1456  153.249
 Ann.Sharpe            12.237    7.947     8.4185    4.077    -2.8384    5.592
 Max.Drawdown       -1078.974 -176.880 -1935.3483 -782.001 -2802.9605 -286.089
 Profit.To.Max.Draw     1.850    6.459     0.7452    1.254    -0.1629    1.132
 Avg.WinLoss.Ratio      1.566    4.785     0.6628    1.519     1.0386    1.145
 Med.WinLoss.Ratio      1.230    1.544     0.6092    1.558     1.4290    1.134
 Max.Equity          2007.629 1177.262  3079.6926  983.284  1605.9939  591.275
 Min.Equity          -387.039  -63.396  -660.0092  -43.384 -1196.9666  -75.179
 End.Equity          1995.629 1142.519  1442.2875  980.284  -456.6602  323.884

                         XLI      XLK       XLP      XLU        XLV      XLY
 Num.Txns             11.000   13.000   11.0000   13.000   15.00000    9.000
 Num.Trades            6.000    7.000    6.0000    7.000    8.00000    5.000
 Net.Trading.PL     1711.104  803.342  323.3662 1004.075   30.93792 1211.524
 Avg.Trade.PL        285.184  114.763   53.8944  143.439    3.86724  242.305
 Med.Trade.PL        326.887  105.678   65.8982    7.115   -9.87414  147.312
 Largest.Winner      519.577  438.553  356.5055  681.636  288.56124  761.154
 Largest.Loser         0.000 -107.612 -210.7667 -295.709 -187.12589  -82.008
 Gross.Profits      1711.104  972.832  591.8219 1349.316  466.45591 1293.532
 Gross.Losses          0.000 -169.490 -268.4557 -345.241 -435.51798  -82.008
 Std.Dev.Trade.PL    194.940  190.582  188.6608  346.799  146.85429  330.468
 Percent.Positive    100.000   57.143   66.6667   57.143   50.00000   80.000
 Percent.Negative      0.000   42.857   33.3333   42.857   50.00000   20.000
 Profit.Factor           Inf    5.740    2.2045    3.908    1.07104   15.773
 Avg.Win.Trade       285.184  243.208  147.9555  337.329  116.61398  323.383
 Med.Win.Trade       326.887  214.301   96.6660  330.282   68.64046  247.765
 Avg.Losing.Trade        NaN  -56.497 -134.2278 -115.080 -108.87950  -82.008
 Med.Losing.Trade         NA  -34.689 -134.2278  -27.216  -94.01504  -82.008
 Avg.Daily.PL        317.385  116.277   46.7108  171.065   -5.57699  293.669
 Med.Daily.PL        405.014   81.035   41.9843   60.238  -60.36201  247.765
 Std.Dev.Daily.PL    199.312  208.726  210.0097  371.366  155.97459  357.804
 Ann.Sharpe           25.279    8.843    3.5308    7.312   -0.56760   13.029
 Max.Drawdown       -359.821 -431.415 -309.4029 -577.717 -418.76748 -496.847
 Profit.To.Max.Draw    4.755    1.862    1.0451    1.738    0.07388    2.438
 Avg.WinLoss.Ratio       NaN    4.305    1.1023    2.931    1.07104    3.943
 Med.WinLoss.Ratio        NA    6.178    0.7202   12.135    0.73010    3.021
 Max.Equity         1713.104  852.989  332.3662 1332.267  174.64061 1464.480
 Min.Equity            0.000 -124.148 -177.2952 -105.827 -399.20704 -100.523
 End.Equity         1711.104  803.342  323.3662 1004.075   30.93792 1211.524

Looking at the statistics on a per-trade basis on a 100-share trade size, the majority of configurations come away with a clear profit. While I did not set any transaction costs/slippage, as this strategy is a long to medium term horizon strategy, I wouldn’t worry too much over it. The statistics that impress me are the percentage correct and the profit factor. Looking at EWJ, even when the percentage correct is less than 50%, the strategy still manages to eke out a profit (profit factor 1.5). A few instruments lose), but on a whole, for an indicator that’s supposed to be a mere filter, this isn’t a particularly bad start.

For those wondering about the annualized “Sharpe Ratio” as it is calculated with trade statistics, this is my interpretation of it: if you aggregated every single trade’s profit and loss into one day apiece, averaged them, and divided by the standard error, which is the standard deviation divided by the square root of 252 (trading days in a year).

Here are the daily statistics:

dStats <- dailyStats(Portfolios = portfolio.st, use = "Equity")
rownames(dStats) <- gsub("\\.DailyEndEq", "", rownames(dStats))
print(data.frame(t(dStats[, -1])))
                          EFA       EPP      EWA      EWC      EWG      EWH
 Total.Days            886.00    669.00   636.00   566.00   675.00   842.00
 Winning.Days          490.00    370.00   359.00   300.00   370.00   442.00
 Losing.Days           396.00    299.00   277.00   266.00   305.00   400.00
 Avg.Day.PL              2.90      2.94     2.02     0.83     1.21     0.72
 Med.Day.PL              5.96      5.06     4.63     2.26     1.81     1.65
 Largest.Winner        196.41    164.03   123.88   113.03    99.29   120.60
 Largest.Loser        -275.87   -234.28  -135.60  -126.79  -117.34  -122.37
 Gross.Profits       19050.85  13211.44  8517.36  6635.32  7027.38  7348.06
 Gross.Losses       -16485.08 -11242.12 -7231.10 -6167.99 -6212.64 -6741.19
 Std.Dev.Daily.PL       54.62     50.83    34.68    30.69    27.08    24.61
 Percent.Positive       55.30     55.31    56.45    53.00    54.81    52.49
 Percent.Negative       44.70     44.69    43.55    47.00    45.19    47.51
 Profit.Factor           1.16      1.18     1.18     1.08     1.13     1.09
 Avg.Win.Day            38.88     35.71    23.73    22.12    18.99    16.62
 Med.Win.Day            30.35     26.11    17.14    16.54    14.44    11.84
 Avg.Losing.Day        -41.63    -37.60   -26.11   -23.19   -20.37   -16.85
 Med.Losing.Day        -28.57    -23.21   -15.90   -15.08   -13.21   -11.00
 Avg.Daily.PL            2.90      2.94     2.02     0.83     1.21     0.72
 Med.Daily.PL            5.96      5.06     4.63     2.26     1.81     1.65
 Std.Dev.Daily.PL.1     54.62     50.83    34.68    30.69    27.08    24.61
 Ann.Sharpe              0.84      0.92     0.93     0.43     0.71     0.46
 Max.Drawdown        -1035.24   -817.16  -519.81  -765.65  -442.17  -529.43
 Profit.To.Max.Draw      2.48      2.41     2.47     0.61     1.84     1.15
 Avg.WinLoss.Ratio       0.93      0.95     0.91     0.95     0.93     0.99
 Med.WinLoss.Ratio       1.06      1.12     1.08     1.10     1.09     1.08
 Max.Equity           3154.42   2386.52  1330.69   536.18  1115.91   947.52
 Min.Equity             -1.42     -5.74     0.00  -229.47   -10.33    -7.23
 End.Equity           2565.77   1969.31  1286.25   467.33   814.74   606.87

                         EWJ      EWS      EWT      EWU       EWY       EWZ
 Total.Days           569.00   970.00   597.00   763.00    989.00   1075.00
 Winning.Days         298.00   536.00   316.00   410.00    546.00    605.00
 Losing.Days          271.00   434.00   281.00   353.00    443.00    470.00
 Avg.Day.PL             0.22     0.54     0.59     0.65      3.95      5.26
 Med.Day.PL             1.87     1.61     1.67     1.68      9.35      7.49
 Largest.Winner        44.31    67.76    72.61    67.65    389.70    563.64
 Largest.Loser        -57.97   -84.06  -116.84   -98.01   -354.19   -623.29
 Gross.Profits       3238.75  4779.24  4216.67  5613.57  30944.68  38572.35
 Gross.Losses       -3112.66 -4251.73 -3864.29 -5116.69 -27041.21 -32922.08
 Std.Dev.Daily.PL      14.18    13.75    18.17    18.65     82.68    102.52
 Percent.Positive      52.37    55.26    52.93    53.74     55.21     56.28
 Percent.Negative      47.63    44.74    47.07    46.26     44.79     43.72
 Profit.Factor          1.04     1.12     1.09     1.10      1.14      1.17
 Avg.Win.Day           10.87     8.92    13.34    13.69     56.68     63.76
 Med.Win.Day            8.64     6.00    11.02    11.24     40.88     36.97
 Avg.Losing.Day       -11.49    -9.80   -13.75   -14.49    -61.04    -70.05
 Med.Losing.Day        -8.87    -6.43   -10.08   -10.41    -40.22    -40.02
 Avg.Daily.PL           0.22     0.54     0.59     0.65      3.95      5.26
 Med.Daily.PL           1.87     1.61     1.67     1.68      9.35      7.49
 Std.Dev.Daily.PL.1    14.18    13.75    18.17    18.65     82.68    102.52
 Ann.Sharpe             0.25     0.63     0.52     0.55      0.76      0.81
 Max.Drawdown        -355.71  -255.84  -466.70  -307.03  -1576.64  -1600.16
 Profit.To.Max.Draw     0.35     2.06     0.76     1.62      2.48      3.53
 Avg.WinLoss.Ratio      0.95     0.91     0.97     0.94      0.93      0.91
 Med.WinLoss.Ratio      0.97     0.93     1.09     1.08      1.02      0.92
 Max.Equity           422.73   547.80   369.08   650.69   4695.66   6644.27
 Min.Equity             0.00   -27.73   -97.62   -29.59   -106.64    -58.40
 End.Equity           126.09   527.52   352.38   496.89   3903.48   5650.27

                          EZU      IEF       IGE       IYR      IYZ      LQD
 Total.Days            661.00   670.00    510.00    582.00   715.00   561.00
 Winning.Days          366.00   339.00    272.00    307.00   362.00   290.00
 Losing.Days           295.00   331.00    238.00    275.00   353.00   271.00
 Avg.Day.PL              1.79     1.09     -0.07      3.31     0.24    -0.15
 Med.Day.PL              4.40     0.88      3.76      6.55     0.86     1.63
 Largest.Winner        173.19   171.24    215.52    235.32    70.10   109.77
 Largest.Loser        -269.85  -159.58   -227.11   -251.01  -102.91  -125.10
 Gross.Profits       12212.18 10589.20  10077.87  15816.00  5627.62  7328.19
 Gross.Losses       -11030.18 -9861.44 -10115.20 -13890.32 -5452.96 -7411.88
 Std.Dev.Daily.PL       48.55    41.28     53.89     65.85    20.72    34.60
 Percent.Positive       55.37    50.60     53.33     52.75    50.63    51.69
 Percent.Negative       44.63    49.40     46.67     47.25    49.37    48.31
 Profit.Factor           1.11     1.07      1.00      1.14     1.03     0.99
 Avg.Win.Day            33.37    31.24     37.05     51.52    15.55    25.27
 Med.Win.Day            26.82    23.78     31.78     44.00    12.42    19.64
 Avg.Losing.Day        -37.39   -29.79    -42.50    -50.51   -15.45   -27.35
 Med.Losing.Day        -24.40   -22.30    -30.05    -38.11   -11.24   -21.70
 Avg.Daily.PL            1.79     1.09     -0.07      3.31     0.24    -0.15
 Med.Daily.PL            4.40     0.88      3.76      6.55     0.86     1.63
 Std.Dev.Daily.PL.1     48.55    41.28     53.89     65.85    20.72    34.60
 Ann.Sharpe              0.58     0.42     -0.02      0.80     0.19    -0.07
 Max.Drawdown         -756.39  -753.73  -1189.16   -977.60  -415.38  -648.47
 Profit.To.Max.Draw      1.56     0.97     -0.03      1.97     0.42    -0.13
 Avg.WinLoss.Ratio       0.89     1.05      0.87      1.02     1.01     0.92
 Med.WinLoss.Ratio       1.10     1.07      1.06      1.15     1.10     0.90
 Max.Equity           1650.98  1400.17    466.12   1932.68   332.93   251.32
 Min.Equity            -27.26  -321.97   -723.05   -190.09  -336.00  -397.15
 End.Equity           1182.00   727.77    -37.33   1925.68   174.66   -83.68

                          RWR      SHY       TLT       XLB       XLE      XLF
 Total.Days            574.00  1190.00    614.00    780.00    727.00   471.00
 Winning.Days          309.00   668.00    321.00    429.00    398.00   246.00
 Losing.Days           265.00   522.00    293.00    351.00    329.00   225.00
 Avg.Day.PL              3.48     0.96      2.35      1.26     -0.63     0.69
 Med.Day.PL              5.92     1.00      6.03      4.30      8.25     1.82
 Largest.Winner        269.45    32.68    471.43    129.97    416.59    83.33
 Largest.Loser        -293.03   -43.49   -333.98   -162.54   -350.68  -156.62
 Gross.Profits       17031.46  4452.86  19634.89  11099.37  22312.96  4470.08
 Gross.Losses       -15035.83 -3310.34 -18192.61 -10119.09 -22769.62 -4146.20
 Std.Dev.Daily.PL       72.55     8.62     86.91     36.57     88.11    24.85
 Percent.Positive       53.83    56.13     52.28     55.00     54.75    52.23
 Percent.Negative       46.17    43.87     47.72     45.00     45.25    47.77
 Profit.Factor           1.13     1.35      1.08      1.10      0.98     1.08
 Avg.Win.Day            55.12     6.67     61.17     25.87     56.06    18.17
 Med.Win.Day            45.43     5.03     40.71     21.69     39.10    13.76
 Avg.Losing.Day        -56.74    -6.34    -62.09    -28.83    -69.21   -18.43
 Med.Losing.Day        -45.55    -4.93    -45.35    -19.65    -46.93   -12.94
 Avg.Daily.PL            3.48     0.96      2.35      1.26     -0.63     0.69
 Med.Daily.PL            5.92     1.00      6.03      4.30      8.25     1.82
 Std.Dev.Daily.PL.1     72.55     8.62     86.91     36.57     88.11    24.85
 Ann.Sharpe              0.76     1.77      0.43      0.55     -0.11     0.44
 Max.Drawdown        -1078.97  -176.88  -1935.35   -782.00  -2802.96  -286.09
 Profit.To.Max.Draw      1.85     6.46      0.75      1.25     -0.16     1.13
 Avg.WinLoss.Ratio       0.97     1.05      0.99      0.90      0.81     0.99
 Med.WinLoss.Ratio       1.00     1.02      0.90      1.10      0.83     1.06
 Max.Equity           2007.63  1177.26   3079.69    983.28   1605.99   591.27
 Min.Equity           -387.04   -63.40   -660.01    -43.38  -1196.97   -75.18
 End.Equity           1995.63  1142.52   1442.29    980.28   -456.66   323.88

                         XLI      XLK      XLP      XLU      XLV      XLY
 Total.Days           703.00   806.00   453.00   845.00   632.00   641.00
 Winning.Days         396.00   452.00   247.00   469.00   316.00   348.00
 Losing.Days          307.00   354.00   206.00   376.00   316.00   293.00
 Avg.Day.PL             2.43     1.00     0.71     1.19     0.05     1.89
 Med.Day.PL             3.53     2.90     1.91     2.71     0.01     2.96
 Largest.Winner       117.17    98.93    76.23    91.19    78.78   165.94
 Largest.Loser       -105.71   -93.48   -67.43  -144.31   -97.34  -127.92
 Gross.Profits       7981.67  7157.63  2899.29  8376.04  5328.55  7759.21
 Gross.Losses       -6270.56 -6354.29 -2575.92 -7371.96 -5297.62 -6547.68
 Std.Dev.Daily.PL      26.72    22.19    15.94    25.64    21.81    30.39
 Percent.Positive      56.33    56.08    54.53    55.50    50.00    54.29
 Percent.Negative      43.67    43.92    45.47    44.50    50.00    45.71
 Profit.Factor          1.27     1.13     1.13     1.14     1.01     1.19
 Avg.Win.Day           20.16    15.84    11.74    17.86    16.86    22.30
 Med.Win.Day           16.69    12.37     9.31    14.55    14.23    18.28
 Avg.Losing.Day       -20.43   -17.95   -12.50   -19.61   -16.76   -22.35
 Med.Losing.Day       -15.22   -12.58    -9.61   -12.72   -13.16   -15.99
 Avg.Daily.PL           2.43     1.00     0.71     1.19     0.05     1.89
 Med.Daily.PL           3.53     2.90     1.91     2.71     0.01     2.96
 Std.Dev.Daily.PL.1    26.72    22.19    15.94    25.64    21.81    30.39
 Ann.Sharpe             1.45     0.71     0.71     0.74     0.04     0.99
 Max.Drawdown        -359.82  -431.41  -309.40  -577.72  -418.77  -496.85
 Profit.To.Max.Draw     4.76     1.86     1.05     1.74     0.07     2.44
 Avg.WinLoss.Ratio      0.99     0.88     0.94     0.91     1.01     1.00
 Med.WinLoss.Ratio      1.10     0.98     0.97     1.14     1.08     1.14
 Max.Equity          1713.10   852.99   332.37  1332.27   174.64  1464.48
 Min.Equity             0.00  -124.15  -177.30  -105.83  -399.21  -100.52
 End.Equity          1711.10   803.34   323.37  1004.07    30.94  1211.52

Looking at the daily statistics, while the statistics aren’t exactly spectacular on the daily time frame, keep in mind that these configurations are ones that hold for very long periods of time, and thus are subject to the usual sloshings of the individual securities over a long period of time. The thing to see here is that this indicator does a good job of creating an edge in most instruments.

Continuing–let’s look at the equity curve of XLB.

tmp <- TVI(Cl(XLB), period = 100)
add_TA(tmp$vigor)

XLB Equity Curve

Something to note is that the exits I programmed aren’t exactly the best, and suffer from the same weaknesses as the usual trend followers–namely, that unsophisticated trend-following strategies tend to “give back their profts” as the trend they were following winds down. However, looking at the plot of the indicator at the bottom, and given how it does not seem to be something very prone to whipsaws, a potential trading strategy going forward may be to do something Dr. Ehlers has done in another one of his presentations, and create signals on the relationship of the signal compared to its 1-day lagged version.

Finally, out of a tagential interest, let’s look at some portfolio statistics. Note that this probably makes the least sense out of anything presented here since there is no intelligent asset allocation scheme at work here.

portPL <- .blotter$portfolio.TVItrendFollowingLong$summary$Net.Trading.PL
(SharpeRatio.annualized(portPL, geometric=FALSE))

                                 Net.Trading.PL
Annualized Sharpe Ratio (Rf=0%)          0.623

plot(cumsum(portPL)["2003::"])

Portfolio Equity Curve

From a returns perspective, this doesn’t make too much sense, as there’s no initial equity, but it exists to just get a perspective of the strategy’s performance at a portfolio level. Overall, it seems the system is profitable, but drawdowns come quickly, meaning that as a strategy in and of itself, Trend Vigor is definitely worth looking at. That stated, its original use was as a filter, and odds are, there exist indicators that are probably more dedicated to trend following such as the FRAMA, ichimoku, and so on.

So, overall, this blog post has shown a few things:

1) It is possible to create a trend-following strategy with a win percentage greater than that of 50%.

2) While the trend vigor indicator is a filter, it may be possible to put a dedicated trend-following filter on top of it (such as the FRAMA–more on that in the future), to possibly get even better results.

3) This is (definitely) not a complete trading system. The exit logic definitely leaves something to be desired (for instance, if the trend vigor reaches its maximum (2)–which seems to be every time, waiting for it to drop under 1.4 is definitely suboptimal), and it seems more improvements can be made.

Furthermore, there is more to investigate in the study of this indicator:

1) In this case, given the smoothness of the trend vigor, is it possible to be more aggressive with it? For instance, although it avoided the financial crisis completely, it did not re-enter the market until late 2009, missing a chunk of the trend, and furthermore, it also managed to give back most of those profits (but not all). Can this be rectified?

2) How does the strategy perform on the short end?

3) What can be done to keep strategies built on this indicator from “giving back open equity”?

While I myself have more indicators to write about, I also feel that input from readers may be worth testing as well.

Thanks for reading.

Advertisements

5 thoughts on “A positive batting average trend follower? Introducing Trend Vigor.

  1. Hello,

    Interesting article, what frequency is the first results table where the sharpe ratios are > 10?
    Generally in R when I get sharpe ratios this high i’ve got some look forward bug in my code, possibly quantstrat passing values from the future into your indicator.

    Thanks
    G

    • Hey GQ,

      First off, thanks for finding my blog.

      Second of all, it’s not a bug. It’s just the way the Sharpe Ratio is computed, since it’s there to work with high frequency trades. Its computation is the mean of your trade PL aggregated to days (which is meaningless if your trades last longer than a day) divided by your standard deviation of your trade PL, multiplied by the square root of 252.

      Basically, it’s a statistic that can be safely ignored when working at the daily+ level, I think. I’m of the opinion that it’s a lot more meaningful once you get into intraday and higher frequency time scales.

  2. Hi, thanks for your efforts for putting forward this wonderful piece of work, though when i am running the complete program, the “out” for applyStrategy function – it’s giving me an error as : Error in orderqty == 0 : comparison (1) is possible only for atomic and list types, could you please guide me the reason i am getting this error and how to overcome this error.

    Thanks,
    Abhishek

      • Hi, well i got that executed, thanks, had some issue with RStudio, i restart the R studio and got that done. Thanks,really appreciate your work, keep it up.

        Abhishek

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s