The Limit of ATR Order Sizing
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Before beginning this post, I’d like to notify readers that I have a webcast tomorrow (Wednesday, Sep. 3) at 4:30 EST for Big Mike’s Trading. Those that can follow the code and the analytics on this blog will see nothing new, but for those that effectively “nod and wait for the punchline” in the form of the equity curve, I’ll demonstrate how to build a strategy “in real time”.
Now onto the post:
While the last post showed how ATR did a better job than raw dollar positions of equalizing risk in the form of standard deviations across instruments, it isn’t the be-all, end-all method of order sizing. Something I learned about recently was portfolio component expected shortfall (along with portfolio component standard deviation). The rabbit hole on these methods runs very deep, including to a paper in the Journal of Risk. To give a quick summary of this computation, it’s one that takes into account not just the well-known mean and covariance, but also interactions between higher order moments, such as co-skewness, and co-kurtosis. The actual details of the math behind this is quite extensive, but luckily, it’s already programmed into the PerformanceAnalytics package, so computing it is as simple as calling a pre-programmed procedure. This demo will, along the way of making yet another comparison between ATR and dollar order sizes, demonstrate one way of doing this.
For those that are unfamiliar with the terminology, expected shortfall is also known as conditional value-at-risk (aka CVaR), which is a coherent risk measure, while regular value at risk is not (for instance, take the example of two bonds each with a default probability of less than 5%, say, 4.95% — the 5% VaR of either of them is 0, but the 5% VaR of the two bond portfolio is greater than zero (or less, depending on how you express the quantity–as a portfolio value, or loss value)).
In any case, here’s the code:
require(IKTrading) require(quantstrat) require(PerformanceAnalytics) initDate="1990-01-01" from="2003-01-01" to="2012-12-31" options(width=70) source("demoData.R") #trade sizing and initial equity settings tradeSize <- 100000 initEq <- tradeSize*length(symbols) strategy.st <- portfolio.st <- account.st <- "DollarVsATRos" 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 pctATR=.02 period=10 atrOrder <- TRUE nRSI <- 2 buyThresh <- 20 sellThresh <- 80 nSMA <- 200 add.indicator(strategy.st, name="lagATR", arguments=list(HLC=quote(HLC(mktdata)), n=period), label="atrX") add.indicator(strategy.st, name="RSI", arguments=list(price=quote(Cl(mktdata)), n=nRSI), label="rsi") add.indicator(strategy.st, name="SMA", arguments=list(x=quote(Cl(mktdata)), n=nSMA), label="sma") #signals add.signal(strategy.st, name="sigComparison", arguments=list(columns=c("Close", "sma"), relationship="gt"), label="filter") add.signal(strategy.st, name="sigThreshold", arguments=list(column="rsi", threshold=buyThresh, relationship="lt", cross=FALSE), label="rsiLtThresh") add.signal(strategy.st, name="sigAND", arguments=list(columns=c("filter", "rsiLtThresh"), cross=TRUE), label="longEntry") add.signal(strategy.st, name="sigThreshold", arguments=list(column="rsi", threshold=sellThresh, relationship="gt", cross=TRUE), label="longExit") add.signal(strategy.st, name="sigCrossover", arguments=list(columns=c("Close", "sma"), relationship="lt"), label="filterExit") #rules if(atrOrder) { 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) } else { add.rule(strategy.st, name="ruleSignal", arguments=list(sigcol="longEntry", sigval=TRUE, ordertype="market", orderside="long", replace=FALSE, prefer="Open", osFUN=osMaxDollar, tradeSize=tradeSize, maxSize=tradeSize), 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="filterExit", sigval=TRUE, orderqty="all", ordertype="market", orderside="long", 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) #Portfolio comparisons to SPY instRets <- PortfReturns(account.st) if(atrOrder) { atrSd <- StdDev(na.omit(instRets), portfolio_method="component") t1 <- Sys.time() atrES <- ES(na.omit(instRets), portfolio_method="component") t2 <- Sys.time() print(t2-t1) } else { dollarSd <- StdDev(na.omit(instRets), portfolio_method="component") t1 <- Sys.time() dollarES <- ES(na.omit(instRets), portfolio_method="component") t2 <- Sys.time() print(t2-t1) } if("atrSd" & "dollarSd" %in% ls()){ boxPlotFrame <- cbind(atrSd$pct_contrib_StdDev, atrES$pct_contrib_MES, dollarSd$pct_contrib_StdDev, dollarES$pct_contrib_MES) colnames(boxPlotFrame) <- c("atrSd", "atrES", "dollarSd", "dollarES") boxplot(boxPlotFrame) } rownames(boxPlotFrame) <- gsub(".DailyEndEq", "", rownames(boxPlotFrame))
This is the resulting image:
And the corresponding data which was used to generate the box plot:
> boxPlotFrame atrSd atrES dollarSd dollarES EFA 0.049378400 0.032829510 0.0412678995 0.0414725387 EPP 0.053737115 0.061714539 0.0509966059 0.0701035651 EWA 0.044784653 0.064515175 0.0510242998 0.0728805941 EWC 0.036487179 0.019929189 0.0439868019 0.0422535671 EWG 0.043172662 0.028698773 0.0455195612 0.0505451367 EWH 0.039433573 0.038858046 0.0449196754 0.0362996367 EWJ 0.030736566 0.037979817 0.0257488355 0.0257318748 EWS 0.041005553 0.016891054 0.0453268353 0.0240447623 EWT 0.029300684 0.058477463 0.0378874688 0.0599281716 EWU 0.043907517 0.025657106 0.0403600522 0.0366783005 EWY 0.039628602 0.028507044 0.0550089098 0.0370010120 EWZ 0.039586224 0.057278661 0.0721037108 0.0867982223 EZU 0.042050678 0.026106675 0.0412176610 0.0288231226 IEF 0.008465791 0.027757444 0.0008097627 0.0046390295 IGE 0.038329663 0.062596052 0.0487744244 0.0797431561 IYR 0.029283546 0.009068168 0.0299819881 -0.0088073708 IYZ 0.034378964 0.042472847 0.0265562205 0.0285952033 LQD 0.008845486 0.020600278 0.0013406959 0.0007059662 RWR 0.027775214 0.014710031 0.0301350434 -0.0063985075 SHY 0.007692137 0.026727026 0.0001618876 0.0009506367 TLT 0.008471822 0.015863044 0.0025502684 0.0031127512 XLB 0.037847498 0.069639008 0.0407311722 0.0788174726 XLE 0.034833476 0.040059687 0.0463448900 0.0602607692 XLF 0.036103344 0.031322842 0.0306424885 0.0337304540 XLI 0.036248065 0.003602306 0.0324606725 0.0018744509 XLK 0.039230708 0.022105404 0.0330037953 0.0276545899 XLP 0.029559398 0.006160133 0.0161629448 -0.0067567464 XLU 0.024703361 0.047065790 0.0191419001 0.0393038102 XLV 0.028872857 0.027564044 0.0168619029 0.0173169198 XLY 0.036149264 0.035242843 0.0289716256 0.0326969108
As can be seen in the image, which is a box plot of the various ways of computing the percentage of portfolio component risk for the two order types, ATR order sizing still does a better job than raw dollar order sizing in terms of controlling risk. However, as evidenced by the atrES box plot, there still is a somewhat wide distribution in terms of contributions to portfolio risk between the various instruments. However, even in this instance of portfolio component risk, it’s readily visible how the ATR order sizing improves on dollar order sizing. However, this also demonstrates how ATR order sizing isn’t the be-all, end-all method of portfolio allocations.
For future note, the application of portfolio component risk metrics is to optimize them in one of two ways–by minimizing the difference between them, or by striving to set them as close to equal to each other as possible (that is, portfolio component risk balance). The PortfolioAnalytics package provides methods on how to do that, which I’ll visit in the future.
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.