Thursday, September 24, 2015

Machine learning and commonly used trading indicators (part 1)

Portfolio trading comparison example - part 1

In the previous post, I reworked the tradingPortfolio() procedures to handle trading signals produced by both quantmod library based model and custom ones. As custom trading signal, I mean any trading signal whose syntax is a sequence of {-1,0,1} values respectively indicating {sell,hold,buy} action. That can be build by any user procedure following any criteria which makes sense.

In this post, first I build a quantmod based model which forecats next week close price to next week open price gain by taking into account last two weeks gains. The trading dates are chosen so that both trading strategies at the end determine a sell action. Signal thresholds are set to 0 to evaluate trading strategies signal issuing at their core. Also buy.all and sell.all flags are set to TRUE for the same reasons. The output portfolio will be referenced as machine learning based portfolio.

suppressPackageStartupMessages(library(quantmod))
suppressPackageStartupMessages(library(rpart))
suppressPackageStartupMessages(library(rpart.plot))
suppressPackageStartupMessages(library(knitr))

ticker <- "YHOO"
getSymbols(ticker, src='yahoo')
##     As of 0.4-0, 'getSymbols' uses env=parent.frame() and
##  auto.assign=TRUE by default.
## 
##  This  behavior  will be  phased out in 0.5-0  when the call  will
##  default to use auto.assign=FALSE. getOption("getSymbols.env") and 
##  getOptions("getSymbols.auto.assign") are now checked for alternate defaults
## 
##  This message is shown once per session and may be disabled by setting 
##  options("getSymbols.warning4.0"=FALSE). See ?getSymbols for more details.
## [1] "YHOO"
ticker = to.weekly(YHOO)

training.dates <- c('2012-01-01','2013-12-31')
trading.dates <- c('2014-01-01', '2015-02-20')

q.model <- specifyModel(Next(OpCl(ticker)) ~ (Lag(OpCl(ticker), 0:2)))

model.data <- modelData(q.model)
head(model.data)
##            Next.OpCl.ticker Lag.OpCl.ticker.0.2.Lag.0
## 2007-01-19      0.006822298              -0.074966535
## 2007-01-26      0.025668486               0.006822298
## 2007-02-02      0.037321242               0.025668486
## 2007-02-09      0.089450287               0.037321242
## 2007-02-16      0.009433931               0.089450287
## 2007-02-23     -0.072560947               0.009433931
##            Lag.OpCl.ticker.0.2.Lag.1 Lag.OpCl.ticker.0.2.Lag.2
## 2007-01-19               0.063176893               0.073114120
## 2007-01-26              -0.074966535               0.063176893
## 2007-02-02               0.006822298              -0.074966535
## 2007-02-09               0.025668486               0.006822298
## 2007-02-16               0.037321242               0.025668486
## 2007-02-23               0.089450287               0.037321242
model <- buildModel(q.model, method='rpart', training.per=training.dates,
                    control=rpart.control(minsplit=15))
rpart.plot(model@fitted.model)

signal.threshold <- c(0.00, 0.00)
control <- list("initial" = c("portfolio" = 0, 
                              "own.shares" = 0, 
                              "average.price"= 0, 
                              "buy.first" = TRUE, 
                              "sell.first" = FALSE),
                "available.funds" = 6000,
                "single.buy" = 0, 
                "buy.all" = TRUE, 
                "single.sell" = 0,
                "sell.all" = TRUE, 
                "signal.threshold" = signal.threshold)

res <- tradePortfolio(ticker, model, trading.dates, control)

portfolioTradingHistory <- res[[1]]

filt.col <- c("portfolio.Open", "portfolio.Close", "portfolio.Gain", "action", 
              "own.shares", "available.funds.Close")

portfolioTradingHistFilt <- subset(portfolioTradingHistory[,filt.col], action != "hold")
kable(portfolioTradingHistFilt, caption="Machine learning based portfolio trading history") 
Machine learning based portfolio trading history
portfolio.Open portfolio.Close portfolio.Gain action own.shares available.funds.Close
2014-01-10 0.000 6176.779 0.0000000 buy 149.8127 0.000
2014-01-31 5394.756 0.000 -10.0873935 sell 0.0000 5394.756
2014-02-07 0.000 5588.391 -10.0873935 buy 150.1045 0.000
2014-03-07 5809.045 0.000 -3.1825805 sell 0.0000 5809.045
2014-03-14 0.000 5654.157 -3.1825805 buy 150.3765 0.000
2014-03-28 5398.517 0.000 -10.0247097 sell 0.0000 5398.517
2014-04-11 0.000 5202.265 -10.0247097 buy 158.2679 0.000
2014-05-30 5483.982 0.000 -8.6002962 sell 0.0000 5483.982
2014-06-06 0.000 5678.427 -8.6002962 buy 158.0854 0.000
2014-06-13 5839.674 0.000 -2.6720938 sell 0.0000 5839.674
2014-06-20 0.000 5681.169 -2.6720938 buy 166.8478 0.000
2014-07-25 6026.544 0.000 0.4423964 sell 0.0000 6026.544
2014-08-01 0.000 5925.075 0.4423964 buy 166.3413 0.000
2014-08-15 6066.466 0.000 1.1077642 sell 0.0000 6066.466
2014-08-22 0.000 6271.046 1.1077642 buy 164.9841 0.000
2014-08-29 6353.538 0.000 5.8922980 sell 0.0000 6353.538
2014-09-05 0.000 6466.235 5.8922980 buy 163.3300 0.000
2014-10-24 7104.856 0.000 18.4142603 sell 0.0000 7104.856
2014-10-31 0.000 7554.343 18.4142603 buy 164.0465 0.000
2014-12-05 8364.733 0.000 39.4122196 sell 0.0000 8364.733
2014-12-12 0.000 8318.373 39.4122196 buy 165.5727 0.000
2014-12-26 8421.028 0.000 40.3504677 sell 0.0000 8421.028
2015-01-02 0.000 8337.931 40.3504677 buy 166.1936 0.000
2015-02-20 7330.799 0.000 22.1799786 sell 0.0000 7330.799

Afterwards, I build a portfolio based on the 10-weeks moving average indicator. The difference between the weekly closing price and its MA-10 moving average is used to trigger buy/sell actions. When such difference changes sign from negative to positive, a buy signal +1 is determined When on the contrary such difference changes sign from positive to negative, a sell signal -1 is determined. The output portfolio will be referenced as MA-10 based portfolio.

adj.trading.dates <- adjustTradingDate(ticker, trading.dates)
trading.window <- seq(from = adj.trading.dates[[1]], to = adj.trading.dates[[2]], by=1)

ticker.ma10 <- EMA(Cl(ticker), n = 10)
ticker.signal <- Cl(ticker) - ticker.ma10

ticker.trade <- ticker[trading.window]
len = nrow(ticker.trade)

signal <- rep(0, len)
trading.signal <- ticker.signal[trading.window]
for (i in 2:len) {
  if (trading.signal[i-1] <= 0 && trading.signal[i] > 0) {
    signal[i] <- 1
  } 
  if (trading.signal[i-1] >=0 && trading.signal[i] < 0) {
    signal[i] <- (-1)
  }
}

portfolioMaTradingHistory <- tradePortfolioWithSignal(ticker.trade, control, signal)

portfolioMaTradingHistFilt <- subset(portfolioMaTradingHistory[,filt.col], action != "hold")
kable(portfolioMaTradingHistFilt, caption="MA-10 based portfolio trading history") 
MA-10 based portfolio trading history
portfolio.Open portfolio.Close portfolio.Gain action own.shares available.funds.Close
2014-02-14 0.000 6036.316 0.0000000 buy 157.8947 0.000
2014-02-21 5887.895 0.000 -1.8684184 sell 0.0000 5887.895
2014-02-28 0.000 6115.629 -1.8684184 buy 158.1492 0.000
2014-03-14 5946.410 0.000 -0.8931703 sell 0.0000 5946.410
2014-04-17 0.000 6448.000 -0.8931703 buy 177.2402 0.000
2014-04-25 6111.243 0.000 1.8540564 sell 0.0000 6111.243
2014-05-02 0.000 6499.035 1.8540564 buy 176.2689 0.000
2014-05-09 5950.839 0.000 -0.8193557 sell 0.0000 5950.839
2014-06-06 0.000 6161.837 -0.8193557 buy 171.5434 0.000
2014-06-20 5841.051 0.000 -2.6491514 sell 0.0000 5841.051
2014-07-03 0.000 6043.389 -2.6491514 buy 167.2216 0.000
2014-07-18 5573.497 0.000 -7.1083889 sell 0.0000 5573.497
2014-07-25 0.000 6036.423 -7.1083889 buy 167.1213 0.000
2014-10-17 6425.816 0.000 7.0969342 sell 0.0000 6425.816
2014-10-24 0.000 7265.999 7.0969342 buy 167.0345 0.000
2015-01-16 7762.092 0.000 29.3681962 sell 0.0000 7762.092
2015-01-23 0.000 8120.419 29.3681962 buy 165.8921 0.000
2015-01-30 7297.594 0.000 21.6265674 sell 0.0000 7297.594

Saving both portfolio datasets for later analysis.

write.csv(portfolioTradingHistory, file = "portfolioTradingHistory.csv", row.names=TRUE)
write.csv(portfolioMaTradingHistory, file = "portfolioMaTradingHistory.csv", row.names=TRUE)

In my next post, I will comment on and perform graphic comparison of the results.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.