Chapter 12 Analyzing Results
portfolio.st <- "Port.Luxor"
account.st <- "Acct.Luxor"
strategy.st <- "Strat.Luxor"
cwd <- getwd()
setwd("./_data/")
load.strategy(strategy.st)
setwd(cwd)
rm.strat(portfolio.st)
rm.strat(account.st)
initPortf(name = portfolio.st,
symbols = symbols,
initDate = init_date)
## [1] "Port.Luxor"
initAcct(name = account.st,
portfolios = portfolio.st,
initDate = init_date,
initEq = init_equity)
## [1] "Acct.Luxor"
initOrders(portfolio = portfolio.st,
initDate = init_date)
12.1 Apply Strategy
# Results hidden to save space
applyStrategy(strategy.st, portfolios = portfolio.st)
checkBlotterUpdate(portfolio.st, account.st, verbose = TRUE)
## [1] TRUE
updatePortf(portfolio.st)
## [1] "Port.Luxor"
updateAcct(account.st)
## [1] "Acct.Luxor"
updateEndEq(account.st)
## [1] "Acct.Luxor"
12.2 Chart Positions
for(symbol in symbols) {
chart.Posn(portfolio.st, Symbol = symbol,
TA = "add_SMA(n = 10, col = 4); add_SMA(n = 30, col = 2)")
}
12.3 Trade Statistics
tstats <- tradeStats(portfolio.st)
kable(t(tstats))
IWM | QQQ | SPY | |
---|---|---|---|
Portfolio | Port.Luxor | Port.Luxor | Port.Luxor |
Symbol | IWM | QQQ | SPY |
Num.Txns | 23 | 21 | 23 |
Num.Trades | 11 | 10 | 11 |
Net.Trading.PL | 2501.460 | 1070.748 | 2251.207 |
Avg.Trade.PL | 211.1204 | 101.8385 | 200.5545 |
Med.Trade.PL | 51.52684 | -45.13684 | -120.63947 |
Largest.Winner | 2109.166 | 1287.017 | 2927.862 |
Largest.Loser | -428.1350 | -355.5896 | -891.9164 |
Gross.Profits | 3724.335 | 2463.680 | 5705.846 |
Gross.Losses | -1402.011 | -1445.295 | -3499.746 |
Std.Dev.Trade.PL | 732.3649 | 515.1777 | 1149.6862 |
Percent.Positive | 63.63636 | 50.00000 | 45.45455 |
Percent.Negative | 36.36364 | 50.00000 | 54.54545 |
Profit.Factor | 2.656424 | 1.704621 | 1.630360 |
Avg.Win.Trade | 532.0479 | 492.7360 | 1141.1692 |
Med.Win.Trade | 152.6189 | 351.7958 | 909.5703 |
Avg.Losing.Trade | -350.5026 | -289.0589 | -583.2910 |
Med.Losing.Trade | -352.4492 | -300.4438 | -726.2925 |
Avg.Daily.PL | 211.1204 | 101.8385 | 200.5545 |
Med.Daily.PL | 51.52684 | -45.13684 | -120.63947 |
Std.Dev.Daily.PL | 732.3649 | 515.1777 | 1149.6862 |
Ann.Sharpe | 4.576179 | 3.138017 | 2.769194 |
Max.Drawdown | -1691.308 | -1343.709 | -2942.752 |
Profit.To.Max.Draw | 1.4790094 | 0.7968602 | 0.7650008 |
Avg.WinLoss.Ratio | 1.517957 | 1.704621 | 1.956432 |
Med.WinLoss.Ratio | 0.4330239 | 1.1709206 | 1.2523471 |
Max.Equity | 2961.741 | 1893.009 | 3482.502 |
Min.Equity | -678.91818 | -52.69256 | -2053.06787 |
End.Equity | 2501.460 | 1070.748 | 2251.207 |
12.3.3 Averages
tab.wins <- tstats %>%
select(Avg.Trade.PL, Avg.Win.Trade, Avg.Losing.Trade, Avg.WinLoss.Ratio)
kable(t(tab.wins))
IWM | QQQ | SPY | |
---|---|---|---|
Avg.Trade.PL | 211.120398 | 101.838522 | 200.554528 |
Avg.Win.Trade | 532.047851 | 492.735974 | 1141.169162 |
Avg.Losing.Trade | -350.502644 | -289.058929 | -583.291000 |
Avg.WinLoss.Ratio | 1.517957 | 1.704621 | 1.956432 |
12.3.4 Performance Summary
rets <- PortfReturns(Account = account.st)
rownames(rets) <- NULL
charts.PerformanceSummary(rets, colorset = bluefocus)
12.3.5 Per Trade Statistics
for(symbol in symbols) {
pts <- perTradeStats(portfolio.st, Symbol = symbol)
kable(pts, booktabs = TRUE, caption = symbol)
}
kable(pts)
Start | End | Init.Pos | Max.Pos | Num.Txns | Max.Notional.Cost | Net.Trading.PL | MAE | MFE | Pct.Net.Trading.PL | Pct.MAE | Pct.MFE | tick.Net.Trading.PL | tick.MAE | tick.MFE |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2008-02-27 | 2008-03-07 | 100 | 100 | 2 | 13261.463 | -881.91636 | -881.91636 | 0.00000 | -0.0665022 | -0.0665022 | 0.0000000 | -881.91636 | -881.91636 | 0.00000 |
2008-03-07 | 2008-04-02 | -100 | -100 | 2 | -12385.273 | -725.99029 | -725.99029 | 168.92951 | -0.0586172 | -0.0586172 | 0.0136395 | -725.99029 | -725.99029 | 168.92951 |
2008-04-02 | 2008-06-03 | 100 | 100 | 2 | 13144.834 | 99.74852 | -395.16121 | 575.47610 | 0.0075884 | -0.0300621 | 0.0437796 | 99.74852 | -395.16121 | 575.47610 |
2008-06-03 | 2008-08-06 | -100 | -100 | 2 | -13235.450 | 807.57595 | -267.13716 | 1572.93130 | 0.0610161 | -0.0201835 | 0.1188423 | 807.57595 | -267.13716 | 1572.93130 |
2008-08-06 | 2008-09-08 | 100 | 100 | 2 | 12392.260 | -151.38610 | -436.70758 | 207.19458 | -0.0122162 | -0.0352404 | 0.0167197 | -151.38610 | -436.70758 | 207.19458 |
2008-09-11 | 2008-12-17 | -100 | -100 | 2 | -11759.376 | 2937.86161 | -394.74462 | 4444.47045 | 0.2498314 | -0.0335685 | 0.3779512 | 2937.86161 | -394.74462 | 4444.47045 |
2008-12-17 | 2009-01-21 | 100 | 100 | 2 | 8921.423 | -706.59467 | -1046.72109 | 214.09136 | -0.0792020 | -0.1173267 | 0.0239974 | -706.59467 | -1046.72109 | 214.09136 |
2009-02-05 | 2009-03-24 | -100 | -100 | 2 | -7823.378 | -110.63947 | -689.54812 | 1166.48465 | -0.0141422 | -0.0881394 | 0.1491024 | -110.63947 | -689.54812 | 1166.48465 |
2009-03-24 | 2009-06-26 | 100 | 100 | 2 | 8100.427 | 991.08945 | -344.57932 | 1258.95869 | 0.1223503 | -0.0425384 | 0.1554188 | 991.08945 | -344.57932 | 1258.95869 |
2009-07-06 | 2009-07-23 | -100 | -100 | 2 | -8804.437 | -863.21910 | -863.21910 | 97.01343 | -0.0980436 | -0.0980436 | 0.0110187 | -863.21910 | -863.21910 | 97.01343 |
2009-07-23 | 2009-11-04 | 100 | 100 | 2 | 9516.246 | 919.57028 | 0.00000 | 1403.96276 | 0.0966316 | 0.0000000 | 0.1475333 | 919.57028 | 0.00000 | 1403.96276 |
2009-11-16 | 2009-12-31 | 100 | 100 | 1 | 10978.893 | 165.10760 | -94.49099 | 293.10750 | 0.0150386 | -0.0086066 | 0.0266974 | 165.10760 | -94.49099 | 293.10750 |
12.3.6 Performance Statistics
tab.perf <- table.Arbitrary(rets,
metrics=c(
"Return.cumulative",
"Return.annualized",
"SharpeRatio.annualized",
"CalmarRatio"),
metricsNames=c(
"Cumulative Return",
"Annualized Return",
"Annualized Sharpe Ratio",
"Calmar Ratio"))
kable(tab.perf)
IWM.DailyEndEq | QQQ.DailyEndEq | SPY.DailyEndEq | |
---|---|---|---|
Cumulative Return | 0.2317202 | 0.1002049 | 0.1306882 |
Annualized Return | 0.1095999 | 0.0488073 | 0.0632089 |
Annualized Sharpe Ratio | 0.5363315 | 0.4537899 | 0.1979763 |
Calmar Ratio | 0.6821284 | 0.3825050 | 0.2385090 |
12.3.7 Risk Statistics
tab.risk <- table.Arbitrary(rets,
metrics=c(
"StdDev.annualized",
"maxDrawdown",
"VaR",
"ES"),
metricsNames=c(
"Annualized StdDev",
"Max DrawDown",
"Value-at-Risk",
"Conditional VaR"))
kable(tab.risk)
IWM.DailyEndEq | QQQ.DailyEndEq | SPY.DailyEndEq | |
---|---|---|---|
Annualized StdDev | 0.2043511 | 0.1075549 | 0.3192751 |
Max DrawDown | 0.1606735 | 0.1275992 | 0.2650170 |
Value-at-Risk | -0.0194849 | -0.0103564 | -0.0310188 |
Conditional VaR | -0.0266399 | -0.0163183 | -0.0522518 |
12.3.8 Buy and Hold Performance
rm.strat("buyHold")
# initialize portfolio and account
initPortf("buyHold", "SPY", initDate = init_date)
## [1] "buyHold"
initAcct("buyHold", portfolios = "buyHold",
initDate = init_date, initEq = init_equity)
## [1] "buyHold"
# place an entry order
CurrentDate <- time(getTxns(Portfolio = portfolio.st, Symbol = "SPY"))[2]
equity = getEndEq("buyHold", CurrentDate)
ClosePrice <- as.numeric(Cl(SPY[CurrentDate,]))
UnitSize = as.numeric(trunc(equity/ClosePrice))
addTxn("buyHold", Symbol = "SPY", TxnDate = CurrentDate, TxnPrice = ClosePrice,
TxnQty = UnitSize, TxnFees = 0)
## [1] "2008-02-27 00:00:00 SPY 75 @ 131.917425267632"
# place an exit order
LastDate <- last(time(SPY))
LastPrice <- as.numeric(Cl(SPY[LastDate,]))
addTxn("buyHold", Symbol = "SPY", TxnDate = LastDate, TxnPrice = LastPrice,
TxnQty = -UnitSize , TxnFees = 0)
## [1] "2009-12-31 00:00:00 SPY -75 @ 111.440002"
# update portfolio and account
updatePortf(Portfolio = "buyHold")
## [1] "buyHold"
updateAcct(name = "buyHold")
## [1] "buyHold"
updateEndEq(Account = "buyHold")
## [1] "buyHold"
chart.Posn("buyHold", Symbol = "SPY")
12.3.9 Strategy vs. Market
rets <- PortfReturns(Account = account.st)
rets.bh <- PortfReturns(Account = "buyHold")
returns <- cbind(rets, rets.bh)
charts.PerformanceSummary(returns, geometric = FALSE, wealth.index = TRUE,
main = "Strategy vs. Market")
12.3.10 Risk/Return Scatterplot
chart.RiskReturnScatter(returns, Rf = 0, add.sharpe = c(1, 2),
main = "Return vs. Risk", colorset = c("red", "blue"))
12.3.11 Relative Performance
for(n in 1:(ncol(returns) - 1)) {
chart.RelativePerformance(returns[, n], returns[, ncol(returns)],
colorset = c("red", "blue"), lwd = 2,
legend.loc = "topleft")
}
12.3.12 Portfolio Summary
#' Error
pf <- getPortfolio(portfolio.st)
xyplot(pf$summary, type = "h", col = 4)
12.3.13 Order Book
ob <- getOrderBook(portfolio.st)
12.3.14 Maximum Adverse Excursion
for(symbol in symbols) {
chart.ME(Portfolio = portfolio.st, Symbol = symbol, type = "MAE",
scale = "percent")
}
12.3.15 Maximum Favorable Excursion
for(symbol in symbols) {
chart.ME(Portfolio = portfolio.st, Symbol = symbol, type = "MFE",
scale = "percent")
}
12.4 Account Summary
a <- getAccount(account.st)
xyplot(a$summary, type = "h", col = 4)
12.4.1 Equity Curve
equity <- a$summary$End.Eq
plot(equity, main = "Equity Curve")
12.4.2 Account Performance Summary
ret <- Return.calculate(equity, method = "log")
charts.PerformanceSummary(ret, colorset = bluefocus,
main = "Strategy Performance")
12.4.3 Cumulative Returns
rets <- PortfReturns(Account = account.st)
chart.CumReturns(rets, colorset = rich10equal, legend.loc = "topleft",
main="SPDR Cumulative Returns")
12.4.4 Distribution Analysis
chart.Boxplot(rets, main = "SPDR Returns", colorset= rich10equal)
12.4.5 Annualized Returns
(ar.tab <- table.AnnualizedReturns(rets))
## IWM.DailyEndEq QQQ.DailyEndEq SPY.DailyEndEq
## Annualized Return 0.1096 0.0488 0.0632
## Annualized Std Dev 0.2044 0.1076 0.3193
## Annualized Sharpe (Rf=0%) 0.5363 0.4538 0.1980
12.4.6 Performance Scatter Plot
max.risk <- max(ar.tab["Annualized Std Dev",])
max.return <- max(ar.tab["Annualized Return",])
chart.RiskReturnScatter(rets,
main = "SPDR Performance", colorset = rich10equal,
xlim = c(0, max.risk * 1.1), ylim = c(0, max.return))
12.4.7 Notional Costs
#quantstratII pp. 67/69
mnc <- pts$Max.Notional.Cost
pe <- sapply(pts$Start,getEndEq, Account = account.st)/3
barplot(rbind(pe,mnc),beside=T,col=c(2,4),names.arg=format(pts$Start,"%m/%d/%y"),
ylim=c(0,1.5e5),ylab="$",xlab="Trade Date")
legend(x="topleft",legend=c("(Portfolio Equity)/9","Order Size"),
pch=15,col=c(2,4),bty="n")
title("Percent of Portfolio Equity versus Trade Size for XLU")