FRAMA Part III: Avoiding Countertrend Trading — A First Attempt
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
This post will begin to experiment with long-term directional detection using relationships between two FRAMA indicators. By observing the relationship between two differently parametrized FRAMAs and the relationship by virtue of the ATR, it will be possible to avoid counter-trend trading on both sides. We will see this example later:
As with TVI, when the signals and rules were swapped for the short end, the equity curve was an unmitigated disaster. Unlike the flat-during-bull-runs-and-permanently-popping-up equity curve of ETFHQ, this equity curve was a disaster. For those that read the final TVI post, the equity curve looked almost identical to that–just a monotonous drawdown until the crisis, at which point the gains aren’t made up, and then the losses continue. In short, there’s no need to go into depth of those statistics.
As the link to ETFHQ suggests, we will use a longer-term FRAMA (the n=252, FC=40, SC=252 version). The market will be in an uptrend when the fast FRAMA (the FRAMA from the previous post) is above this slower FRAMA, and vice versa. Furthermore, in order to avoid some whipsaws, the fast FRAMA will have to be ascending (or descending, during a downtrend), and the entry signal will be when the price crosses over (under) the faster FRAMA, with the exit being the reverse.
In the interest of brevity, since the sample period was an uptrend, then a great deal of strategies will look good on the upside. The question is whether or not the strategy does well on the short side, as the litmus test in testing a confirming indicator is whether or not it can create a positive expectation in a strategy that is counter-trend to the dominant trend in the sample data. As this is a replication of an implied idea by ETFHQ (rather than my own particular idea), let’s look at the code for the strategy. In this instance, both the long and short end of this symmetric strategy are included, and in RStudio, commenting or uncommenting one half or the other is as simple as highlight+ctrl+shift+C.
Here’s the code.
require(DSTrading) require(IKTrading) require(quantstrat) require(PerformanceAnalytics) initDate="1990-01-01" from="2003-01-01" to="2010-12-31" options(width=70) #to rerun the strategy, rerun everything below this line source("demoData.R") #contains all of the data-related boilerplate. #trade sizing and initial equity settings tradeSize <- 10000 initEq <- tradeSize*length(symbols) strategy.st <- portfolio.st <- account.st <- "FRAMA_II" 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',initEq=initEq) initOrders(portfolio.st, initDate=initDate) strategy(strategy.st, store=TRUE) #parameters FCfast=4 SCfast=300 nFast=126 fastTriggerLag=1 FCslow=40 SCslow=252 nSlow=252 slowTriggerLag=1 period=10 pctATR=.02 #indicators #Have to add in this function first, since the word 'slow' gets picked up #by the HLC function as "low", which causes issues. add.indicator(strategy.st, name="lagATR", arguments=list(HLC=quote(HLC(mktdata)), n=period), label="atrX") add.indicator(strategy.st, name="FRAMA", arguments=list(HLC=quote(HLC(mktdata)), n=nFast, FC=FCfast, SC=SCfast, triggerLag=fastTriggerLag), label="fast") add.indicator(strategy.st, name="FRAMA", arguments=list(HLC=quote(HLC(mktdata)), n=nSlow, FC=FCslow, SC=SCslow, triggerLag=slowTriggerLag), label="slow") # #long signals # # #condition 1: our fast FRAMA is above our slow FRAMA # add.signal(strategy.st, name="sigComparison", # arguments=list(columns=c("FRAMA.fast", "FRAMA.slow"), relationship="gt"), # label="fastFRAMAaboveSlow") # # #condition 2: our fast FRAMA is rising # add.signal(strategy.st, name="sigComparison", # arguments=list(columns=c("FRAMA.fast", "trigger.fast"), relationship="gt"), # label="fastFRAMArising") # # #setup: price crosses above the fast FRAMA # add.signal(strategy.st, name="sigComparison", # arguments=list(columns=c("Close", "FRAMA.fast"), relationship="gte"), # label="CloseGteFastFRAMA") # # #wrap our conditions and our setup into one entry signal # add.signal(strategy.st, name="sigAND", # arguments=list(columns=c("fastFRAMAaboveSlow", "fastFRAMArising", "CloseGteFastFRAMA"), cross=TRUE), # label="longEntry") # # #our old exit signal # add.signal(strategy.st, name="sigCrossover", # arguments=list(columns=c("Close", "FRAMA.fast"), relationship="lt"), # label="longExit") # #long rules # add.rule(strategy.st, name="ruleSignal", # arguments=list(sigcol="longEntry", sigval=TRUE, ordertype="market", # orderside="long", replace=FALSE, prefer="Open", osFUN=osDollarATR, # tradeSize=tradeSize, pctATR=pctATR, atrMod="X"), # 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) #short signals add.signal(strategy.st, name="sigComparison", arguments=list(columns=c("FRAMA.fast", "FRAMA.slow"), relationship="lt"), label="fastFRAMAbelowSlow") #condition 2: our fast FRAMA is falling add.signal(strategy.st, name="sigComparison", arguments=list(columns=c("FRAMA.fast", "trigger.fast"), relationship="lt"), label="fastFRAMAfalling") #setup: price crosses below the fast FRAMA add.signal(strategy.st, name="sigCrossover", arguments=list(columns=c("Close", "FRAMA.fast"), relationship="lt"), label="CloseLtFastFRAMA") #wrap our conditions and our setup into one entry signal add.signal(strategy.st, name="sigAND", arguments=list(columns=c("fastFRAMAbelowSlow", "fastFRAMAfalling", "CloseLtFastFRAMA"), cross=TRUE), label="shortEntry") #our old exit signal add.signal(strategy.st, name="sigCrossover", arguments=list(columns=c("Close", "FRAMA.fast"), relationship="gt"), label="shortExit") #short rules add.rule(strategy.st, name="ruleSignal", arguments=list(sigcol="shortEntry", sigval=TRUE, ordertype="market", orderside="short", replace=FALSE, prefer="Open", osFUN=osDollarATR, tradeSize=-tradeSize, pctATR=pctATR, atrMod="X"), type="enter", path.dep=TRUE) add.rule(strategy.st, name="ruleSignal", arguments=list(sigcol="shortExit", sigval=TRUE, orderqty="all", ordertype="market", orderside="short", replace=FALSE, prefer="Open"), type="exit", path.dep=TRUE) #apply strategy t1 <- Sys.time() out <- applyStrategy(strategy=strategy.st,portfolios=portfolio.st) t2 <- Sys.time() print(t2-t1) #set up analytics updatePortf(portfolio.st) dateRange <- time(getPortfolio(portfolio.st)$summary)[-1] updateAcct(portfolio.st,dateRange) updateEndEq(account.st)
First, a quick little side-note: since many indicators look for the word “low”, my usage of the label “slow” would cause a bug if I added the lagATR indicator after that point. So try to avoid labels such as “high”, “low”, “open”, and “close” in your indicators, or at least declare all indicators that would look for the word “low” before declaring the indicator you label in part as “slow”, if you must go this route. Low is probably the easiest one for which to overlook this, since “slow” has so many applications to confirmatory indicators. (EG: SMA fast vs. SMA slow, etc.)
Again, to reiterate, the system will take a long position when price crosses over (under) a rising (falling) fast FRAMA that’s higher (lower) than the slow FRAMA, and exit that position when the price crosses back under (over) the fast FRAMA. The cross must happen when the other two conditions are intact, as opposed to a trade being entered when all three conditions come together, which may be in the middle of a trend.
As the majority of the sample data was in an uptrend (and the fact that the Andreas Clenow-inspired ATR order-sizing function pays enormous dividends in protecting for a limited time in a counter-trend), I decided to put the (slightly modified–with the one condition of rising in an uptrend or falling in a downtrend) system to the test by testing it on the non-dominant trend in the sample–that is, to see if the system can stay out at all points aside from the crisis.
Here are the (not-so-flattering) results:
Trade statistics:
EFA EPP EWA EWC EWG Num.Txns 88.00 80.00 84.00 60.00 70.00 Num.Trades 43.00 40.00 40.00 30.00 35.00 Net.Trading.PL -1393.99 -1585.91 981.89 875.47 -810.83 Avg.Trade.PL -32.42 -39.65 24.55 29.18 -23.17 Med.Trade.PL -106.64 -70.14 1.79 -74.83 -46.21 Largest.Winner 1238.56 775.14 1106.59 2195.51 449.23 Largest.Loser -661.04 -466.95 -552.10 -565.80 -547.09 Gross.Profits 4211.42 3301.63 3677.16 3856.57 2719.33 Gross.Losses -5605.42 -4887.54 -2695.27 -2981.10 -3530.16 Std.Dev.Trade.PL 344.67 284.29 263.92 462.93 226.75 Percent.Positive 32.56 30.00 50.00 26.67 48.57 Percent.Negative 67.44 70.00 50.00 73.33 51.43 Profit.Factor 0.75 0.68 1.36 1.29 0.77 Avg.Win.Trade 300.82 275.14 183.86 482.07 159.96 Med.Win.Trade 73.89 172.89 56.79 245.71 121.09 Avg.Losing.Trade -193.29 -174.55 -134.76 -135.50 -196.12 Med.Losing.Trade -156.80 -141.04 -88.56 -108.19 -187.47 Avg.Daily.PL -33.19 -39.65 24.55 29.18 -23.17 Med.Daily.PL -103.99 -70.14 1.79 -74.83 -46.21 Std.Dev.Daily.PL 337.33 284.29 263.92 462.93 226.75 Ann.Sharpe -1.56 -2.21 1.48 1.00 -1.62 Max.Drawdown -4696.67 -3090.61 -2193.20 -2032.07 -1990.83 Profit.To.Max.Draw -0.30 -0.51 0.45 0.43 -0.41 Avg.WinLoss.Ratio 1.56 1.58 1.36 3.56 0.82 Med.WinLoss.Ratio 0.47 1.23 0.64 2.27 0.65 Max.Equity 560.75 355.13 2236.74 1567.71 1030.36 Min.Equity -4135.91 -2881.48 -1702.76 -2019.64 -960.47 End.Equity -1393.99 -1585.91 981.89 875.47 -810.83 EWH EWJ EWS EWT EWU Num.Txns 48.00 102.00 74.00 56.00 82.00 Num.Trades 23.00 51.00 35.00 27.00 41.00 Net.Trading.PL -420.23 -951.54 1424.73 292.07 -1756.36 Avg.Trade.PL -18.27 -18.66 40.71 10.82 -42.84 Med.Trade.PL -42.63 -54.18 -15.44 3.83 -46.42 Largest.Winner 309.93 1704.54 1165.10 437.42 664.06 Largest.Loser -341.09 -460.39 -424.29 -367.22 -367.18 Gross.Profits 996.32 5137.50 4424.92 2072.64 2461.62 Gross.Losses -1416.55 -6089.05 -3000.19 -1780.57 -4217.98 Std.Dev.Trade.PL 135.68 358.27 328.50 180.94 227.57 Percent.Positive 39.13 39.22 42.86 51.85 34.15 Percent.Negative 60.87 60.78 57.14 48.15 65.85 Profit.Factor 0.70 0.84 1.47 1.16 0.58 Avg.Win.Trade 110.70 256.88 294.99 148.05 175.83 Med.Win.Trade 91.25 80.40 84.30 100.73 66.50 Avg.Losing.Trade -101.18 -196.42 -150.01 -136.97 -156.22 Med.Losing.Trade -92.50 -173.06 -141.06 -144.50 -146.70 Avg.Daily.PL -18.27 -18.66 40.71 10.82 -42.84 Med.Daily.PL -42.63 -54.18 -15.44 3.83 -46.42 Std.Dev.Daily.PL 135.68 358.27 328.50 180.94 227.57 Ann.Sharpe -2.14 -0.83 1.97 0.95 -2.99 Max.Drawdown -1330.17 -3187.00 -1855.03 -1440.36 -3674.50 Profit.To.Max.Draw -0.32 -0.30 0.77 0.20 -0.48 Avg.WinLoss.Ratio 1.09 1.31 1.97 1.08 1.13 Med.WinLoss.Ratio 0.99 0.46 0.60 0.70 0.45 Max.Equity 791.29 2235.46 2100.37 919.22 280.39 Min.Equity -974.85 -2116.00 -1230.08 -885.33 -3394.12 End.Equity -420.23 -951.54 1424.73 292.07 -1756.36 EWY EWZ EZU IEF IGE Num.Txns 82.00 58.00 90.00 47.00 96.00 Num.Trades 41.00 29.00 45.00 24.00 48.00 Net.Trading.PL 2644.53 434.29 -1639.77 -1071.52 -1826.08 Avg.Trade.PL 64.50 14.98 -36.44 -44.65 -38.04 Med.Trade.PL -36.18 -89.69 -70.13 -56.73 -79.30 Largest.Winner 2447.28 2495.03 1222.50 908.54 2146.42 Largest.Loser -392.38 -382.20 -455.60 -717.52 -297.67 Gross.Profits 5519.58 3649.15 3231.22 2332.00 3162.60 Gross.Losses -2875.04 -3214.86 -4870.99 -3403.52 -4988.68 Std.Dev.Trade.PL 441.24 521.49 282.42 339.58 349.80 Percent.Positive 48.78 24.14 37.78 41.67 20.83 Percent.Negative 51.22 75.86 62.22 58.33 79.17 Profit.Factor 1.92 1.14 0.66 0.69 0.63 Avg.Win.Trade 275.98 521.31 190.07 233.20 316.26 Med.Win.Trade 119.21 91.01 54.82 81.98 82.87 Avg.Losing.Trade -136.91 -146.13 -173.96 -243.11 -131.28 Med.Losing.Trade -97.92 -109.64 -155.51 -230.79 -113.58 Avg.Daily.PL 64.50 14.98 -36.44 -74.70 -38.04 Med.Daily.PL -36.18 -89.69 -70.13 -71.76 -79.30 Std.Dev.Daily.PL 441.24 521.49 282.42 312.88 349.80 Ann.Sharpe 2.32 0.46 -2.05 -3.79 -1.73 Max.Drawdown -1779.21 -3253.19 -3402.61 -3204.56 -3455.82 Profit.To.Max.Draw 1.49 0.13 -0.48 -0.33 -0.53 Avg.WinLoss.Ratio 2.02 3.57 1.09 0.96 2.41 Med.WinLoss.Ratio 1.22 0.83 0.35 0.36 0.73 Max.Equity 3319.81 2235.92 291.74 1170.92 255.57 Min.Equity -1779.21 -1280.22 -3110.88 -2033.64 -3200.25 End.Equity 2644.53 434.29 -1639.77 -1071.52 -1826.08 IYR IYZ LQD RWR SHY Num.Txns 106.00 108.00 43.00 114.00 33.00 Num.Trades 53.00 54.00 21.00 56.00 17.00 Net.Trading.PL -3809.10 -3010.91 1863.94 -3690.62 -3715.43 Avg.Trade.PL -71.87 -55.76 88.76 -65.90 -218.55 Med.Trade.PL -107.50 -94.91 -14.30 -95.48 -165.13 Largest.Winner 1714.13 2673.04 1618.71 1455.78 23.93 Largest.Loser -745.50 -463.08 -236.13 -476.51 -870.37 Gross.Profits 3465.76 3941.01 3050.21 2877.22 44.39 Gross.Losses -7274.86 -6951.92 -1186.26 -6567.84 -3759.82 Std.Dev.Trade.PL 316.10 412.75 387.67 256.76 226.14 Percent.Positive 22.64 22.22 47.62 19.64 11.76 Percent.Negative 77.36 77.78 52.38 80.36 88.24 Profit.Factor 0.48 0.57 2.57 0.44 0.01 Avg.Win.Trade 288.81 328.42 305.02 261.57 22.19 Med.Win.Trade 125.96 52.77 178.87 144.25 22.19 Avg.Losing.Trade -177.44 -165.52 -107.84 -145.95 -250.65 Med.Losing.Trade -151.10 -150.12 -97.91 -134.83 -210.93 Avg.Daily.PL -71.87 -55.76 80.29 -65.90 -223.39 Med.Daily.PL -107.50 -94.91 -33.90 -95.48 -188.03 Std.Dev.Daily.PL 316.10 412.75 395.74 256.76 232.64 Ann.Sharpe -3.61 -2.14 3.22 -4.07 -15.24 Max.Drawdown -4518.57 -4628.68 -1075.56 -4511.52 -4429.88 Profit.To.Max.Draw -0.84 -0.65 1.73 -0.82 -0.84 Avg.WinLoss.Ratio 1.63 1.98 2.83 1.79 0.09 Med.WinLoss.Ratio 0.83 0.35 1.83 1.07 0.11 Max.Equity 709.48 561.64 2649.32 820.90 714.45 Min.Equity -3809.10 -4067.04 -318.88 -3690.62 -3715.43 End.Equity -3809.10 -3010.91 1863.94 -3690.62 -3715.43 TLT XLB XLE XLF XLI Num.Txns 73.00 72.00 82.00 104.00 106.00 Num.Trades 37.00 36.00 41.00 52.00 53.00 Net.Trading.PL -2881.18 75.64 -738.57 -705.52 -1281.19 Avg.Trade.PL -77.87 2.10 -18.01 -13.57 -24.17 Med.Trade.PL -147.94 -45.01 -94.63 -71.06 -77.50 Largest.Winner 1425.91 1831.45 2087.67 1058.03 1218.87 Largest.Loser -486.72 -423.07 -299.82 -711.69 -480.88 Gross.Profits 3086.09 3723.24 3173.04 5277.71 4948.54 Gross.Losses -5967.27 -3647.61 -3911.61 -5983.23 -6229.73 Std.Dev.Trade.PL 338.67 369.57 371.02 313.49 307.17 Percent.Positive 24.32 36.11 14.63 34.62 30.19 Percent.Negative 75.68 63.89 85.37 65.38 69.81 Profit.Factor 0.52 1.02 0.81 0.88 0.79 Avg.Win.Trade 342.90 286.40 528.84 293.21 309.28 Med.Win.Trade 151.67 158.38 237.83 139.29 204.28 Avg.Losing.Trade -213.12 -158.59 -111.76 -175.98 -168.37 Med.Losing.Trade -195.66 -128.42 -96.70 -144.43 -147.64 Avg.Daily.PL -86.21 2.10 -18.01 -13.57 -24.17 Med.Daily.PL -149.61 -45.01 -94.63 -71.06 -77.50 Std.Dev.Daily.PL 339.60 369.57 371.02 313.49 307.17 Ann.Sharpe -4.03 0.09 -0.77 -0.69 -1.25 Max.Drawdown -3946.88 -2772.07 -2742.16 -2243.85 -2727.83 Profit.To.Max.Draw -0.73 0.03 -0.27 -0.31 -0.47 Avg.WinLoss.Ratio 1.61 1.81 4.73 1.67 1.84 Med.WinLoss.Ratio 0.78 1.23 2.46 0.96 1.38 Max.Equity 139.90 1411.59 335.20 1066.45 848.83 Min.Equity -3806.97 -1978.82 -2742.16 -1573.88 -2028.21 End.Equity -2881.18 75.64 -738.57 -705.52 -1281.19 XLK XLP XLU XLV XLY Num.Txns 94.00 84.00 86.00 62.00 66.00 Num.Trades 47.00 41.00 42.00 31.00 33.00 Net.Trading.PL -1651.16 -3264.51 -4665.83 -2093.02 507.06 Avg.Trade.PL -35.13 -79.62 -111.09 -67.52 15.37 Med.Trade.PL -99.55 -129.52 -90.84 -80.14 -100.97 Largest.Winner 2403.16 1008.09 174.64 1447.68 2090.68 Largest.Loser -526.85 -460.10 -419.92 -533.05 -352.17 Gross.Profits 4484.79 2660.58 600.44 2419.62 4101.12 Gross.Losses -6135.95 -5925.09 -5266.27 -4512.64 -3594.06 Std.Dev.Trade.PL 419.01 287.43 134.66 364.01 430.90 Percent.Positive 31.91 19.51 21.43 16.13 30.30 Percent.Negative 68.09 80.49 78.57 83.87 69.70 Profit.Factor 0.73 0.45 0.11 0.54 1.14 Avg.Win.Trade 298.99 332.57 66.72 483.92 410.11 Med.Win.Trade 106.63 84.26 46.23 86.14 202.57 Avg.Losing.Trade -191.75 -179.55 -159.58 -173.56 -156.26 Med.Losing.Trade -168.10 -161.95 -152.33 -128.20 -151.78 Avg.Daily.PL -35.13 -79.62 -111.09 -67.52 15.37 Med.Daily.PL -99.55 -129.52 -90.84 -80.14 -100.97 Std.Dev.Daily.PL 419.01 287.43 134.66 364.01 430.90 Ann.Sharpe -1.33 -4.40 -13.10 -2.94 0.57 Max.Drawdown -4435.53 -5189.24 -4665.83 -3779.96 -2264.20 Profit.To.Max.Draw -0.37 -0.63 -1.00 -0.55 0.22 Avg.WinLoss.Ratio 1.56 1.85 0.42 2.79 2.62 Med.WinLoss.Ratio 0.63 0.52 0.30 0.67 1.33 Max.Equity 861.83 1156.76 0.00 1686.94 2771.26 Min.Equity -3573.71 -4032.47 -4665.83 -2093.02 -613.72 End.Equity -1651.16 -3264.51 -4665.83 -2093.02 507.06 > (aggPF <- sum(tStats$Gross.Profits)/-sum(tStats$Gross.Losses)) [1] 0.7443694 > (aggCorrect <- mean(tStats$Percent.Positive)) [1] 31.708 > (numTrades <- sum(tStats$Num.Trades)) [1] 1166 > (meanAvgWLR <- mean(tStats$Avg.WinLoss.Ratio)) [1] 1.824333
In other words, we can already see that the proposed confirmatory indicator is a dud. To display the raw instrument daily stats at this point would also be uninteresting, so we’ll move past that.
Duration statistics:
durStats <- durationStatistics(Portfolio=portfolio.st, Symbols=sort(symbols)) print(t(durStats)) EFA EPP EWA EWC EWG EWH EWJ EWS EWT EWU EWY EWZ EZU IEF IGE IYR Min 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Q1 2 1 1 4 1 2 1 3 1 1 1 1 2 2 1 1 Med 4 4 4 8 5 4 4 5 5 4 3 5 4 5 5 3 Mean 10 8 9 13 10 7 9 11 13 8 10 11 8 10 9 7 Q3 7 8 7 16 10 6 8 10 10 10 7 8 7 8 8 7 Max 83 72 79 74 77 55 98 76 79 72 105 71 83 66 90 59 WMin 1 1 1 7 1 1 1 1 1 1 1 1 1 1 6 1 WQ1 3 2 1 14 1 3 1 4 2 1 1 4 2 7 8 6 WMed 10 6 6 23 5 6 2 10 10 4 3 8 4 8 18 9 WMean 21 14 13 26 13 11 13 18 22 13 16 24 11 20 26 15 WQ3 26 14 9 29 13 7 9 26 21 15 14 41 7 39 30 17 WMax 83 72 79 74 77 55 98 76 79 72 105 71 83 66 90 59 LMin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 LQ1 2 1 1 4 2 2 2 3 1 2 1 1 2 1 1 1 LMed 4 3 4 6 4 3 4 4 4 4 1 4 5 2 3 3 LMean 4 5 6 9 6 4 6 5 4 6 3 7 6 4 4 4 LQ3 6 6 6 12 8 6 8 5 5 7 3 7 7 6 6 5 LMax 21 23 22 33 21 14 25 32 8 29 12 68 26 10 14 36 IYZ LQD RWR SHY TLT XLB XLE XLF XLI XLK XLP XLU XLV XLY Min 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Q1 1 1 1 4 2 2 1 2 2 2 2 2 2 2 Med 5 3 3 6 4 6 4 5 4 3 4 4 5 5 Mean 9 9 6 9 8 12 10 13 9 9 8 6 8 14 Q3 7 5 6 12 7 14 7 18 11 10 7 6 8 11 Max 105 91 67 29 55 82 97 91 55 67 67 34 35 100 WMin 1 1 1 3 1 2 7 1 1 1 1 1 3 2 WQ1 3 3 8 4 2 7 9 3 3 2 4 1 7 7 WMed 8 5 10 6 6 17 22 20 10 15 15 4 17 26 WMean 21 17 18 6 18 23 40 26 17 20 22 9 19 35 WQ3 28 18 24 7 32 22 69 34 26 26 32 13 35 56 WMax 105 91 67 8 55 82 97 91 55 67 67 34 35 100 LMin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 LQ1 1 1 1 4 2 2 1 2 2 1 1 2 1 1 LMed 4 1 2 6 4 3 3 4 4 3 3 4 4 4 LMean 5 2 3 9 5 6 5 6 6 4 4 4 6 4 LQ3 7 3 5 12 7 8 6 8 10 5 6 5 7 6 LMax 29 7 15 29 19 29 40 21 19 21 20 16 30 13
Basically, we can see that there are some really long trades that win, but between this table and the previous trade stats output, that is more than swamped by the legions of losers. Here is the market exposure:
#market exposure tmp <- list() length(tmp) <- length(symbols) for(i in 1:nrow(dStats)) { totalDays <- nrow(get(rownames(dStats)[i])) mktExposure <- dStats$Total.Days[i]/totalDays tmp[[i]] <- c(rownames(dStats)[i], round(mktExposure, 3)) } mktExposure <- data.frame(do.call(rbind, tmp)) colnames(mktExposure) <- c("Symbol","MktExposure") print(mktExposure) Symbol MktExposure 1 EFA 0.168 2 EPP 0.125 3 EWA 0.149 4 EWC 0.15 5 EWG 0.133 6 EWH 0.063 7 EWJ 0.176 8 EWS 0.145 9 EWT 0.133 10 EWU 0.135 11 EWY 0.152 12 EWZ 0.126 13 EZU 0.147 14 IEF 0.102 15 IGE 0.168 16 IYR 0.152 17 IYZ 0.186 18 LQD 0.083 19 RWR 0.149 20 SHY 0.052 21 TLT 0.126 22 XLB 0.168 23 XLE 0.16 24 XLF 0.249 25 XLI 0.196 26 XLK 0.168 27 XLP 0.129 28 XLU 0.101 29 XLV 0.1 30 XLY 0.168
In other words, even though the market exposure is rather small, the system still manages to hemorrhage a great deal during those small exposures, which does not sing many praises for the proposed system.
Here is the code for a cash sharpe and the equity curve comparisons:
#portfolio cash PL portString <- paste0("portfolio.", portfolio.st) portPL <- .blotter[[portString]]$summary$Net.Trading.PL #Cash Sharpe (SharpeRatio.annualized(portPL, geometric=FALSE)) #Portfolio comparisons to SPY instRets <- PortfReturns(account.st) #Correlations instCors <- cor(instRets) diag(instRets) <- NA corMeans <- rowMeans(instCors, na.rm=TRUE) names(corMeans) <- gsub(".DailyEndEq", "", names(corMeans)) print(round(corMeans,3)) mean(corMeans) portfRets <- xts(rowMeans(instRets)*ncol(instRets), order.by=index(instRets)) portfRets <- portfRets[!is.na(portfRets)] cumPortfRets <- cumprod(1+portfRets) firstNonZeroDay <- as.character(index(portfRets)[min(which(portfRets!=0))]) getSymbols("SPY", from=firstNonZeroDay, to=to) SPYrets <- diff(log(Cl(SPY)))[-1] cumSPYrets <- cumprod(1+SPYrets) comparison <- cbind(cumPortfRets, cumSPYrets) colnames(comparison) <- c("strategy", "SPY") chart.TimeSeries(comparison, legend.loc = "topleft", colors=c("green","red"))
Which gives us the following results:
(SharpeRatio.annualized(portPL, geometric=FALSE)) Net.Trading.PL Annualized Sharpe Ratio (Rf=0%) -0.2687879
In short, the idea of using a “slower” FRAMA does not seem to hold much water. And here are the portfolio statistics to confirm it:
> SharpeRatio.annualized(portfRets) [,1] Annualized Sharpe Ratio (Rf=0%) -0.2950648 > Return.annualized(portfRets) [,1] Annualized Return -0.01560975 > maxDrawdown(portfRets) [1] 0.1551006
But why?
For that, we’ll look at a picture of the equity curve of an individual instrument, complete with overlaid indicators.
chart.Posn(portfolio.st, "XLF") tmp <- FRAMA(HLC(XLF), n=nFast, FC=FCfast, SC=SCfast, triggerLag=fastTriggerLag) add_TA(tmp$FRAMA, on=1, col="purple", lwd=3) add_TA(tmp$trigger, on=1, col="blue", lwd=0.5) tmp2 <- FRAMA(HLC(XLF), n=nSlow, FC=FCslow, SC=SCslow, triggerLag=slowTriggerLag) add_TA(tmp2$FRAMA, on=1, col="orange", lwd=3) tmp2 <- lagATR(HLC=HLC(XLF), n=period) add_TA(tmp2$atr, col="purple", lwd=2)
Which produces the following plot:
The primary indicator is in purple, while the confirmatory indicator is in orange. And now we see the reason why: because although the FRAMA (n=252, FC=40, SC=252) is a seemingly fine parametrization in and of itself, as a “big-picture/long-term-trend/greater smoothing” indicator, it does not seem like the best choice, at least in the conventional sense as using something such as the SMA200, ROC200 > 0, or RS Rank (see this post from SystemTraderSuccess).
Why? Because from my intuition, adaptive moving average indicators all aim to do the same thing–they aim to be a more accurate way of aggregating lots of data in order to tell you what is happening to as close as current time as they can get. That is, if you look at the presentation by Dr. John Ehlers (see this link), you’ll notice how similar all of the indicators are. All of them effectively aim to maximize near-term smoothness and eliminate as much lag as possible. That is, if you’re looking to make short-term momentum trades that last five days, if your indicator has a five-day lag (EG a 10-day running median), well, your indicator isn’t of much use in that case, because by the time you receive the signal, the opportunity is over!
However, while eliminating lag is usually desirable, in one case, it isn’t. To go off on a tangent, the Japanese trading system called Ichimoku Kinko Hyo (which may be investigated in the future), created by Goichi Hosoda, deliberately makes use of lagging current price action to create a cloud. That is, if you want a confirmatory indicator, you want something robust (especially to the heightened volatility during corrections, bear markets, downtrends, etc.), and something that *has* a bit of lag to it, to confirm the relationship between the more up-to-date indicator (E.G. an adaptive moving average, a short-term oscillator such as RSI2, etc.), and the overarching, long-term trend.
The failure to do so in this case results in problematic counter-trend trades before the financial crisis. While the trading during the financial crisis had a very choppy equity curve during the height of the crisis itself, this was for an individual instrument, and note, that by the end of the crisis, the strategy had indeed made money. The greater problem was that due to the similarities in kind of the confirmatory indicator with the one used for entries and exits, then occasionally, the confirmatory indicator would overtake the indicator it was supposed to confirm, even in a sideways or upwards market, which resulted in several disastrous trades.
And while the indicator used for entries and exits should be as up-to-date as possible so as to get in and out in as timely a fashion as possible, a confirmatory indicator, first and foremost, should not reverse the entire system’s understanding of the market mode on a whim, and secondly, should try to be more backward looking, so as to better do its job of confirmation. Thus, in my opinion, the recommendation of this “slower” FRAMA to be used as a confirmatory indicator by ETFHQ was rather ill-advised. Thus, the investigation will continue into finding a more suitable confirmatory indicator.
Thanks for reading.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.