Synopsis

This document utilizes the “QuantMod”, and “PerformanceAnalytics”, R packages for Backtesting of Automated Trading Stategies, and Holt-Winters Filtering for Price Prediction.


Working Directory, and Required Packages

# Set Working Directory
# setwd(" ")

# Required Packages
# if (!require("quantmod")) { install.packages("quantmod"); require("quantmod") }
# if (!require("PerformanceAnalytics")) { install.packages("PerformanceAnalytics"); require("PerformanceAnalytics") }
# if (!require("rgl")) { install.packages("rgl"); require("rgl") }
# if (!require("rugarch")) { install.packages("rugarch"); require("rugarch") }

library(RCurl)
library(xts)
library(zoo)
library(tseries)
library(forecast)
library(quantmod) # data, plotting, quant modelling
library(PerformanceAnalytics) # performance and risk management
library(knitr)


Downloading Stock Ticker Data from Yahoo Finances

# Import Original data
ticker_lookup <- getSymbols("TWTR", auto.assign=F,
                            from="2014-01-01", to="2016-01-01")

ticker_lookup2 <- as.data.frame(cbind(ticker_lookup[,1], ticker_lookup[,2], ticker_lookup[,3], ticker_lookup[,4], ticker_lookup[,5], ticker_lookup[,6]))

ticker_data <-  as.data.frame(cbind(date = rownames(ticker_lookup2), ticker_lookup2))

colnames(ticker_data) <- c("date","open","high ","low ","close ","volume ","adjusted")

rownames(ticker_data) <- NULL


First Trading Strategy Backtest

daysSinceHigh <- function(x, n){
   apply(embed(x, n), 1, which.max)-1
}

myStrat <- function(x, nHold=100, nHigh=200) {
    position <- ifelse(daysSinceHigh(x, nHigh)<=nHold,1,0)
    c(rep(0,nHigh-1),position)
}

getSymbols('TWTR', from='2011-01-01')
## [1] "TWTR"
myStock <- Cl(TWTR)
myPosition <- myStrat(myStock,40,45)
bmkReturns <- dailyReturn(myStock, type = "arithmetic")
myReturns <- bmkReturns*Lag(myPosition,1)
myReturns[1] <- 0

names(bmkReturns) <- 'TWTR'
names(myReturns) <- 'Me'

charts.PerformanceSummary(cbind(bmkReturns,myReturns))

Performance <- function(x) {
    cumRetx = Return.cumulative(x)
    annRetx = Return.annualized(x, scale=252)
    sharpex = SharpeRatio.annualized(x, scale=252)
    winpctx = length(x[x > 0])/length(x[x != 0])
    annSDx = sd.annualized(x, scale=252)
    
    DDs <- findDrawdowns(x)
    maxDDx = min(DDs$return)
    maxLx = max(DDs$length)

    Perf = c(cumRetx, annRetx, sharpex, winpctx, annSDx, maxDDx, maxLx)
    names(Perf) = c("Cumulative Return", "Annual Return","Annualized Sharpe Ratio",
        "Win %", "Annualized Volatility", "Maximum Drawdown", "Max Length Drawdown")
    return(Perf)
}

cbind(Me=Performance(myReturns),TWTR=Performance(bmkReturns))
##                                  Me        TWTR
## Cumulative Return        -0.4741291  -0.5721604
## Annual Return            -0.2042218  -0.2604865
## Annualized Sharpe Ratio  -0.4538231  -0.4605472
## Win %                     0.4947146   0.4899713
## Annualized Volatility     0.4500032   0.5656021
## Maximum Drawdown         -0.7053375  -0.8088937
## Max Length Drawdown     479.0000000 676.0000000
testStrategy <- function(myStock, nHold=100, nHigh=200) {
    myPosition <- myStrat(myStock,nHold,nHigh)
    bmkReturns <- dailyReturn(myStock, type = "arithmetic")
    myReturns <- bmkReturns*Lag(myPosition,1)
    myReturns[1] <- 0
    names(bmkReturns) <- 'TWTR'
    names(myReturns) <- 'Me'
    
    charts.PerformanceSummary(cbind(bmkReturns,myReturns))
    cbind(Me=Performance(myReturns),Index=Performance(bmkReturns))
}

getSymbols('TWTR', from='2014-01-01')
## [1] "TWTR"
testStrategy(na.omit(TWTR),40,45)

##                                  Me       Index
## Cumulative Return        -0.5258818  -0.7044616
## Annual Return            -0.2441119  -0.3668884
## Annualized Sharpe Ratio  -0.8429806  -0.6657829
## Win %                     0.4077670   0.4833837
## Annualized Volatility     0.2895819   0.5510632
## Maximum Drawdown         -0.6016240  -0.7969565
## Max Length Drawdown     595.0000000 671.0000000


Second Trading Strategy Backtest

tickerData.xts <- xts(as.numeric(Cl(ticker_data)),
                      order.by=as.Date(ticker_data$date))
tickerData.z = zoo(x=Cl(ticker_data), order.by=as.Date(ticker_data$date))

# Specify the prices and store our models
prices <- tickerData.xts[,1]

# Create indicator
sma <- SMA(tickerData.xts, n=1)

# Calculate the indicators we need for our strategy
CCI20 <- CCI(prices, 20)
RSI3 <- RSI(prices, 3)
DEMA10 <- DEMA(prices, n = 10, v = 1, wilder = FALSE)
DEMA10c <- prices - DEMA10  
DEMA10c <- DEMA10c/.0001

buy.signal <- ifelse(RSI3 < 30 & CCI20 > -290 & CCI20 < -100 & DEMA10c > -40 & DEMA10c < 750, 1, NA)

# Construct trading rule
sig <- Lag(ifelse(sma$SMA < buy.signal, 1, -1))

# The trading rules/equity curve
retSMA <- ROC(tickerData.xts) * sig

chartSeries(ticker_lookup, theme = chartTheme('white'),
            TA=c(addVo(),addBBands(), addMACD()))

ticker_dataTS <- ts(ticker_data$close, start=c(2014, 1, 1), end=c(2016, 1, 1), frequency=250)

plot.ts(ticker_dataTS, col="blue", main="Time Series of TWTR")

# Seasonal decomposition
fit <- stl(ticker_dataTS, s.window="period")
plot(fit, main="Seasonal Decomposition of TWTR")

monthplot(ticker_dataTS, col="green", main="Month Plot of TWTR, Seasonal Adjustment")

seasonplot(ticker_dataTS, main="Season Plot of TwTR, Seasonal Adjustment")


20 Day Forecasting of TWTR Price

# simple exponential - models level
fit <- HoltWinters(ticker_dataTS, beta=FALSE, gamma=FALSE)
plot(fit, main="Holt-Winters Filtering, Models Level")

# double exponential - models level and trend
fit <- HoltWinters(ticker_dataTS, gamma=FALSE)
plot(fit, main="Holt-Winters Filtering, Models Level + Trend")

# triple exponential - models level, trend, and seasonal components
fit <- HoltWinters(ticker_dataTS)
plot(fit, main="Holt-Winters Filtering, Models Level + Trend + Seasonal Components")

# predict next three future values
TWTRForecast <- forecast(fit, 20)
plot(TWTRForecast, main="TWTR Price Forecast (20 Days) from Holt-Winters Filtering")