Portfolio Trading
In the previous post, we see how to define a trading prediction model based on historical data by using the quantmod package. We also notice why it is necessary to introduce a new function able to fulfill the need of implementing and verifying the success of a portfolio trading strategy based upon the model just produced. My portfolio trading strategy will use the following basic information:
- initial portfolio status
- available funds
- parameters driving how/when the buy orders should be issued
- parameters driving how/when the sell orders should be issued
All those parameters can be collected into a control structure given as input to our trading portfolio function together with the ticker OHLC object, the trading interval and the quantmod model.
As output, I like to have a dataframe reporting with the same frequency used for model building, the following:
- portfolio.Open, the money value of our portfolio at open market time
- portfolio.Close, the money value of our portfolio at close market time
- portfolio.Gain, the percentage gain of our portfolio to date
- own.shares, the ticker shares in our portfolio to date
- average.price, the ticker shares buy average price
- available.funds.Open, the available funds at open market time
- available.funds.Close, the available funds at close market time
- action, the trading action to date, one between hold, buy, sell
- quantity, the quantity of shares bought, sold in the case within the day
- trade.value, the money value of our daily trade
All those parameters allow for a basic understanding of the performance of our trading strategy. Of course the following aspects should be considered:
- I am driving a basic scenario of trading having in mind general-purpose investor needs
- I am not including other important details of the trading, to mention some:
- bid ask spread
- required price
- the actual value the share is bought or sold
However, to keep it simple let us start with the requirements above mentioned. It is possible to detail it later once we have gain confidence in what I am going to show you.
Preliminary behavior to the tradePortfolio() function call is:
- download ticker OHLC data
- update OHLC data frequency, I mean change it from daily to weekly for example
- define some trading strategy, I mean next ticker gain forecast model
- specify quantmod model
- extract quantmod model correspoding data
- quantmod model build
- quantmod model dump and plot
Herein some example code. Required libraries are quantmod, rpart and rpart.plot.
setwd("~/R/aroundrblog/Finance")
suppressPackageStartupMessages(library(quantmod))
suppressPackageStartupMessages(library(rpart))
suppressPackageStartupMessages(library(rpart.plot))
suppressPackageStartupMessages(library(knitr))
Herein below, I download OHLC ticker data and convert it to weekly frequency. Then I specify a model which aim to forecast the next weekly ticker gain based on the last two weekly Close/Open price ratio. Then model is build using as all 2013 year data for training purpose. Model dump and plot are shown.
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)
q.model <- specifyModel(Next(OpCl(ticker)) ~ (Lag(OpCl(ticker),0:1)))
model.data <- modelData(q.model)
head(model.data)
## Next.OpCl.ticker Lag.OpCl.ticker.0.1.Lag.0
## 2007-01-12 -0.074966535 0.063176893
## 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
## Lag.OpCl.ticker.0.1.Lag.1
## 2007-01-12 0.073114120
## 2007-01-19 0.063176893
## 2007-01-26 -0.074966535
## 2007-02-02 0.006822298
## 2007-02-09 0.025668486
## 2007-02-16 0.037321242
model <- buildModel(q.model, method='rpart', training.per=c('2013-02-01','2013-12-31'),
control=rpart.control(minsplit=5))
model@fitted.model
## n= 48
##
## node), split, n, deviance, yval
## * denotes terminal node
##
## 1) root 48 4.782837e-02 0.014575700
## 2) Lag.OpCl.ticker.0.1.Lag.1< 0.004439411 19 1.171213e-02 0.001198999
## 4) Lag.OpCl.ticker.0.1.Lag.1>=-0.0108401 9 5.612584e-03 -0.011584030
## 8) Lag.OpCl.ticker.0.1.Lag.1< -0.00537906 4 7.223112e-04 -0.023542240 *
## 9) Lag.OpCl.ticker.0.1.Lag.1>=-0.00537906 5 3.860680e-03 -0.002017452
## 18) Lag.OpCl.ticker.0.1.Lag.1>=-0.000755803 3 1.426650e-03 -0.020017440 *
## 19) Lag.OpCl.ticker.0.1.Lag.1< -0.000755803 2 4.033451e-06 0.024982530 *
## 5) Lag.OpCl.ticker.0.1.Lag.1< -0.0108401 10 3.305307e-03 0.012703720
## 10) Lag.OpCl.ticker.0.1.Lag.1< -0.01312584 8 2.547570e-03 0.008457823
## 20) Lag.OpCl.ticker.0.1.Lag.1>=-0.0295945 2 5.817894e-04 -0.011050870 *
## 21) Lag.OpCl.ticker.0.1.Lag.1< -0.0295945 6 9.508757e-04 0.014960720 *
## 11) Lag.OpCl.ticker.0.1.Lag.1>=-0.01312584 2 3.663088e-05 0.029687310 *
## 3) Lag.OpCl.ticker.0.1.Lag.1>=0.004439411 29 3.048901e-02 0.023339750
## 6) Lag.OpCl.ticker.0.1.Lag.1>=0.04632919 9 2.201388e-03 0.000771833
## 12) Lag.OpCl.ticker.0.1.Lag.0>=-0.00898223 7 3.375160e-04 -0.003288263 *
## 13) Lag.OpCl.ticker.0.1.Lag.0< -0.00898223 2 1.344614e-03 0.014982170 *
## 7) Lag.OpCl.ticker.0.1.Lag.1< 0.04632919 20 2.164111e-02 0.033495310
## 14) Lag.OpCl.ticker.0.1.Lag.1< 0.03258854 15 1.556012e-02 0.026400750
## 28) Lag.OpCl.ticker.0.1.Lag.1>=0.02455003 5 6.339454e-03 0.006100402
## 56) Lag.OpCl.ticker.0.1.Lag.0< -0.009535946 2 2.498836e-03 -0.006493894 *
## 57) Lag.OpCl.ticker.0.1.Lag.0>=-0.009535946 3 3.311897e-03 0.014496600 *
## 29) Lag.OpCl.ticker.0.1.Lag.1< 0.02455003 10 6.129883e-03 0.036550920
## 58) Lag.OpCl.ticker.0.1.Lag.1< 0.01598028 6 4.137488e-03 0.026186960
## 116) Lag.OpCl.ticker.0.1.Lag.1>=0.007428941 3 5.346758e-04 0.006895524 *
## 117) Lag.OpCl.ticker.0.1.Lag.1< 0.007428941 3 1.369857e-03 0.045478390 *
## 59) Lag.OpCl.ticker.0.1.Lag.1>=0.01598028 4 3.812181e-04 0.052096870 *
## 15) Lag.OpCl.ticker.0.1.Lag.1>=0.03258854 5 3.061020e-03 0.054779010
## 30) Lag.OpCl.ticker.0.1.Lag.1>=0.03570818 3 2.092971e-03 0.045361740 *
## 31) Lag.OpCl.ticker.0.1.Lag.1< 0.03570818 2 3.029117e-04 0.068904920 *
rpart.plot(model@fitted.model)
Next step is to define some control strategy for our portfolio trading simulation, the following ones:s
- signal threshold for sell and buy
- trading dates
- control structure reporting:
- the initial portfolio status, comprising:
- portfolio money value,
- owned shares and their average buy price
- if we want to do first a buy trading action or a sell trading action
- the available funds
- the money amount of a single buy
- a flag specifying if a buy trading position should engage all available current funds
- the money amount of a single sell
- a flag specifying if a sell trading position should engage all available portfolio shares
- the signal thresholds for sell and buy as percentage of price variation against our model prediction
- the initial portfolio status, comprising:
Here is an example:
signal.threshold <- c(-0.02, 0.05)
dates <- c('2014-01-01', '2014-12-24')
control <- list("initial" = c("portfolio" = 0,
"own.shares" = 0,
"average.price"= 0,
"buy.first" = TRUE,
"sell.first" = FALSE
),
"available.funds" = 6000,
"single.buy" = 2000,
"buy.all" = FALSE,
"single.sell" = 0,
"sell.all" = TRUE,
"signal.threshold" = signal.threshold)
What aboveshown means that the investor intends:
- to sell when model forecasted price variation is below or equal 2%
- to buy when model forecasted price variation is above or equal 5%
- to trade from 2014-01-01 up to 2014-12-24
- to have an initial empty portfolio
- to open a long position first (buy), it cannot be else starting from an empty portfolio and being not allowed for uncovered short positions
- to have $6,000 available for trading
- to open long position (buy) of $2,000 per day
- not to engage all available funds in a single buy order
- to sell all owned shares by a single sell order
- the signal threshold as above explained
At this point, I can show you the tradePortfolio() function I have in mind. You can see I have also defined a couple of utility functions, searchTradingDay() and adjustTradingDate() to adjust the investor specified start and end trading dates with the closest actual trading ones.
searchTradingDay <- function(ticker, date, nextd) {
trading.date <- index(ticker)
if (nextd == TRUE) {
compare <- (date < trading.date)
} else {
compare <- (date > trading.date)
}
is.trading <- which(compare == nextd)
return (trading.date[is.trading[1]])
}
adjustTradingDate <- function(ticker, trade.date) {
price <- coredata(ticker[trade.date[[1]]])
if (length(price) == 0) {
work.date.1 <- searchTradingDay(ticker, trade.date[[1]], TRUE)
} else {
work.date.1 <- as.Date(trade.date[[1]])
}
price <- coredata(ticker[trade.date[[2]]])
if (length(price) == 0) {
work.date.2 <- searchTradingDay(ticker, trade.date[[2]], FALSE)
} else {
work.date.2 <- as.Date(trade.date[[2]])
}
return (c(work.date.1, work.date.2))
}
# tradePortfolio() function which implements our trading strategy against the ticker OHLC historical data
tradePortfolio <- function(ticker, model, dates, control) {
adj.trade.dates <- adjustTradingDate(ticker, dates)
ticker.trade <- ticker[seq(from = adj.trade.dates[[1]], to = adj.trade.dates[[2]], by=1)]
buy.first <- ifelse(is.null(control$initial) | control$initial["buy.first"], TRUE, FALSE)
sell.first <- ifelse(is.null(control$initial) == FALSE &
control$available.funds > control$single.buy &
control$initial["sell.first"], TRUE, FALSE)
# using some of the tradeModel code
quantmod <- getModelData(model);
model.data <- modelData(quantmod,adj.trade.dates);
fitted.zoo <- predict(quantmod@fitted.model, model.data)
if(class(fitted.zoo) != "zoo") {
fitted.zoo <- zoo(as.vector(fitted.zoo),index(model.data))
}
signal.threshold <- control$signal.threshold
signal.zoo <- ifelse(fitted.zoo < signal.threshold[1] | fitted.zoo > signal.threshold[2],
ifelse(fitted.zoo > 0, 1, -1), 0)
market.zoo <- model.data[,1]
signal.zoo <- merge(market.zoo,signal.zoo)
index(signal.zoo) <- index(signal.zoo);
# starting loop on signal
len <- nrow(ticker.trade)
portfolio.Open <- rep(control$initial["portfolio"], len)
portfolio.Close <- rep(control$initial["portfolio"], len)
portfolio.Gain <- rep(0, len)
own.shares <- rep(control$initial["own.shares"], len)
average.price <- rep(control$initial["average.price"], len)
available.funds.Open <- rep(0, len)
available.funds.Close <- rep(0, len)
action <- rep(NA, len)
quantity <- rep(0,len)
trade.value <- rep(0,len)
portfolio.df <- data.frame(portfolio.Open,
portfolio.Close,
portfolio.Gain,
own.shares,
average.price,
available.funds.Open,
available.funds.Close,
action,
quantity,
trade.value,
Op(ticker.trade),
Cl(ticker.trade),
Lo(ticker.trade),
Hi(ticker.trade))
cn <- colnames(portfolio.df)
l <- length(cn)
colnames(portfolio.df)[(l-3):l] <- c("ticker.Open", "ticker.Close", "ticker.Low", "ticker.High")
buy.todo <- buy.first
sell.todo <- sell.first
for (i in 1:len) {
ifelse (i > 1, portfolio.df[i, "available.funds.Open"] <- portfolio.df[i-1, "available.funds.Close"],
portfolio.df[i, "available.funds.Open"] <- control$available.funds)
if (signal.zoo[i,2] == 1 &&
sell.todo == FALSE &&
portfolio.df[i, "available.funds.Open"] >= control$single.buy) {
action <- "buy"
trade.value <- as.numeric(coredata(Op(ticker.trade)[i]))
if (control$buy.all == TRUE) {
quantity <- portfolio.df[i, "available.funds.Open"]/trade.value
} else {
quantity <- floor(control$single.buy/trade.value)
}
value.close <- quantity*as.numeric(coredata(Cl(ticker.trade)[i]))
portfolio.df[i, "portfolio.Open"] <- ifelse(i==1, 0, portfolio.df[i-1, "portfolio.Close"])
portfolio.df[i, "portfolio.Close"] <- ifelse(i==1,
value.close,
portfolio.df[i-1, "portfolio.Close"] + value.close)
portfolio.df[i, "portfolio.Gain"] <- ifelse(i==1, 0, portfolio.df[i-1, "portfolio.Gain"])
portfolio.df[i, "own.shares"] <- ifelse(i==1, quantity, portfolio.df[i-1, "own.shares"] + quantity)
temp <- portfolio.df[i-1, "own.shares"] * portfolio.df[i-1, "average.price"]
portfolio.df[i, "average.price"] <- ifelse(i==1,
trade.value,
(temp + trade.value * quantity)/portfolio.df[i, "own.shares"])
portfolio.df[i, "available.funds.Close"] <- portfolio.df[i, "available.funds.Open"] -
trade.value * quantity
portfolio.df[i, "action"] <- action
portfolio.df[i, "quantity"] <- quantity
portfolio.df[i, "trade.value"] <- trade.value
buy.todo = FALSE
} else if (signal.zoo[i,2] == -1 &&
buy.todo == FALSE &&
portfolio.df[i-1, "portfolio.Close"] > 0) {
action <- "sell"
trade.value <- as.numeric(coredata(Cl(ticker.trade)[i]))
portfolio.df[i, "action"] <- action
portfolio.df[i, "trade.value"] <- trade.value
portfolio.df[i, "portfolio.Open"] <- portfolio.df[i-1, "own.shares"] * trade.value
if (control$sell.all == TRUE) {
quantity <- portfolio.df[i-1, "own.shares"]
} else {
quantity <- min(portfolio.df[i-1, "own.shares"], floor(control$single.sell/trade.value))
}
portfolio.df[i, "own.shares"] <- portfolio.df[i-1, "own.shares"] - quantity
portfolio.df[i, "available.funds.Close"] <- portfolio.df[i, "available.funds.Open"] +
trade.value * quantity
portfolio.df[i, "portfolio.Close"] <- portfolio.df[i, "own.shares"]*trade.value
portfolio.df[i, "available.funds.Close"] <- portfolio.df[i, "available.funds.Open"] +
trade.value * quantity
portfolio.df[i, "portfolio.Gain"] <- 100*((portfolio.df[i, "available.funds.Close"]/control$available.funds)-1)
portfolio.df[i, "quantity"] <- quantity
value.close <- trade.value*quantity
if (portfolio.df[i, "own.shares"] == 0) {
portfolio.df[i, "average.price"] <- 0
} else {
temp <- portfolio.df[i-1, "own.shares"] * portfolio.df[i-1, "average.price"]
portfolio.df[i, "average.price"] <- (temp - trade.value * quantity)/portfolio.df[i, "own.shares"]
}
sell.todo <- FALSE
} else if (i > 1) {
share.price <- as.numeric(coredata(Op(ticker.trade)[i]))
portfolio.df[i, "portfolio.Open"] <- portfolio.df[i-1, "own.shares"]*share.price
portfolio.df[i, "own.shares"] <- portfolio.df[i-1, "own.shares"]
if (portfolio.df[i, "portfolio.Open"] == 0) {
portfolio.df[i, "average.price"] <- 0
} else {
portfolio.df[i, "average.price"] <- portfolio.df[i-1, "average.price"]
}
share.price <- as.numeric(coredata(Cl(ticker.trade)[i]))
portfolio.df[i, "portfolio.Close"] <- portfolio.df[i-1, "own.shares"]*share.price
portfolio.df[i, "portfolio.Gain"] <- portfolio.df[i-1, "portfolio.Gain"]
portfolio.df[i, "available.funds.Open"] <- portfolio.df[i-1, "available.funds.Close"]
portfolio.df[i, "available.funds.Close"] <- portfolio.df[i, "available.funds.Open"]
portfolio.df[i, "action"] <- "hold"
} else if (i == 1) {
share.price <- as.numeric(coredata(Op(ticker.trade)[i]))
portfolio.df[i, "action"] <- "hold"
portfolio.df[i, "available.funds.Close"] <- portfolio.df[i, "available.funds.Open"]
}
}
list(portfolio.df, signal.zoo)
}
And here is an example of tradePortfolio() call and corresponding results dump.
res <- tradePortfolio(ticker, model, dates, control)
porfolioTradingHistory <- res[[1]]
signalHistory <- res[[2]]
kable(porfolioTradingHistory, caption = "Portfolio trading history")
portfolio.Open | portfolio.Close | portfolio.Gain | own.shares | average.price | available.funds.Open | available.funds.Close | action | quantity | trade.value | ticker.Open | ticker.Close | ticker.Low | ticker.High | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2014-01-03 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 40.46 | 40.12 | 39.31 | 40.58 |
2014-01-10 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 40.05 | 41.23 | 39.75 | 41.72 |
2014-01-17 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 41.16 | 40.01 | 39.47 | 41.31 |
2014-01-24 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 39.98 | 37.91 | 37.62 | 40.40 |
2014-01-31 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 37.60 | 36.01 | 34.45 | 38.32 |
2014-02-07 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 35.94 | 37.23 | 34.66 | 37.27 |
2014-02-14 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 38.00 | 38.23 | 37.25 | 38.91 |
2014-02-21 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 38.31 | 37.29 | 37.22 | 38.59 |
2014-02-28 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 37.23 | 38.67 | 36.82 | 39.38 |
2014-03-07 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 37.65 | 38.70 | 37.43 | 40.15 |
2014-03-14 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 38.63 | 37.60 | 36.45 | 38.78 |
2014-03-21 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 39.00 | 37.94 | 37.42 | 39.94 |
2014-03-28 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 38.00 | 35.90 | 35.05 | 38.04 |
2014-04-04 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 36.46 | 34.26 | 33.83 | 36.86 |
2014-04-11 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 34.11 | 32.87 | 32.15 | 35.00 |
2014-04-17 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 33.55 | 36.38 | 32.64 | 37.30 |
2014-04-25 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 36.60 | 34.48 | 34.29 | 36.85 |
2014-05-02 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 34.67 | 36.87 | 33.65 | 37.12 |
2014-05-09 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 36.68 | 33.76 | 33.41 | 37.17 |
2014-05-16 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 33.99 | 33.41 | 33.10 | 34.69 |
2014-05-23 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 33.41 | 35.02 | 33.28 | 35.08 |
2014-05-30 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 35.00 | 34.65 | 34.13 | 35.17 |
2014-06-06 | 0.00 | 0.00 | 0.0000000 | 0 | 0.00000 | 6000.00000 | 6000.00000 | hold | 0 | 0.00 | 34.69 | 35.92 | 34.26 | 36.08 |
2014-06-13 | 0.00 | 2031.70 | 0.0000000 | 55 | 35.86000 | 6000.00000 | 4027.69994 | buy | 55 | 35.86 | 35.86 | 36.94 | 35.54 | 37.06 |
2014-06-20 | 1925.00 | 1872.75 | 0.0000000 | 55 | 35.86000 | 4027.69994 | 4027.69994 | hold | 0 | 0.00 | 35.00 | 34.05 | 33.97 | 35.49 |
2014-06-27 | 1877.15 | 1883.75 | 0.0000000 | 55 | 35.86000 | 4027.69994 | 4027.69994 | hold | 0 | 0.00 | 34.13 | 34.25 | 33.02 | 34.55 |
2014-07-03 | 1987.70 | 0.00 | 0.2566648 | 0 | 0.00000 | 4027.69994 | 6015.39989 | sell | 55 | 36.14 | 34.93 | 36.14 | 34.85 | 36.15 |
2014-07-11 | 0.00 | 1948.65 | 0.2566648 | 55 | 36.15000 | 6015.39989 | 4027.14978 | buy | 55 | 36.15 | 36.15 | 35.43 | 34.10 | 36.23 |
2014-07-18 | 1969.00 | 1833.15 | 0.2566648 | 55 | 36.15000 | 4027.14978 | 4027.14978 | hold | 0 | 0.00 | 35.80 | 33.33 | 32.93 | 35.95 |
2014-07-25 | 1834.25 | 1986.60 | 0.2566648 | 55 | 36.15000 | 4027.14978 | 4027.14978 | hold | 0 | 0.00 | 33.35 | 36.12 | 33.16 | 36.55 |
2014-08-01 | 1992.65 | 1959.10 | 0.2566648 | 55 | 36.15000 | 4027.14978 | 4027.14978 | hold | 0 | 0.00 | 36.23 | 35.62 | 35.31 | 36.99 |
2014-08-08 | 1964.05 | 1975.05 | 0.2566648 | 55 | 36.15000 | 4027.14978 | 4027.14978 | hold | 0 | 0.00 | 35.71 | 35.91 | 35.40 | 36.66 |
2014-08-15 | 1985.50 | 2005.85 | 0.2566648 | 55 | 36.15000 | 4027.14978 | 4027.14978 | hold | 0 | 0.00 | 36.10 | 36.47 | 35.15 | 36.57 |
2014-08-22 | 2022.35 | 2090.55 | 0.2566648 | 55 | 36.15000 | 4027.14978 | 4027.14978 | hold | 0 | 0.00 | 36.77 | 38.01 | 36.75 | 38.20 |
2014-08-29 | 2090.55 | 4093.07 | 0.2566648 | 107 | 37.11710 | 4027.14978 | 2043.86983 | buy | 52 | 38.14 | 38.14 | 38.51 | 37.54 | 38.72 |
2014-09-05 | 4162.30 | 4236.13 | 0.2566648 | 107 | 37.11710 | 2043.86983 | 2043.86983 | hold | 0 | 0.00 | 38.90 | 39.59 | 38.69 | 39.80 |
2014-09-12 | 4236.13 | 6337.25 | 0.2566648 | 156 | 38.12942 | 2043.86983 | 67.20983 | buy | 49 | 40.34 | 40.34 | 42.88 | 40.26 | 43.20 |
2014-09-19 | 6860.88 | 6385.08 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 43.98 | 40.93 | 39.55 | 44.01 |
2014-09-26 | 6204.12 | 6342.96 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 39.77 | 40.66 | 37.90 | 40.80 |
2014-10-03 | 6303.96 | 6400.68 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 40.41 | 41.03 | 39.69 | 41.69 |
2014-10-10 | 6427.20 | 6177.60 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 41.20 | 39.60 | 39.59 | 41.73 |
2014-10-17 | 6165.12 | 5998.20 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 39.52 | 38.45 | 36.20 | 40.07 |
2014-10-24 | 6001.32 | 6786.00 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 38.47 | 43.50 | 38.25 | 43.65 |
2014-10-31 | 6756.36 | 7183.80 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 43.31 | 46.05 | 43.29 | 46.52 |
2014-11-07 | 7183.80 | 7573.80 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 46.05 | 48.55 | 45.74 | 48.67 |
2014-11-14 | 7612.80 | 8073.00 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 48.80 | 51.75 | 48.10 | 51.95 |
2014-11-21 | 8085.48 | 7962.24 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 51.83 | 51.04 | 50.00 | 52.62 |
2014-11-28 | 7995.00 | 8071.44 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 51.25 | 51.74 | 51.07 | 52.26 |
2014-12-05 | 8023.08 | 7954.44 | 0.2566648 | 156 | 38.12942 | 67.20983 | 67.20983 | hold | 0 | 0.00 | 51.43 | 50.99 | 49.66 | 51.43 |
2014-12-12 | 7837.44 | 0.00 | 31.7441691 | 0 | 0.00000 | 67.20983 | 7904.65014 | sell | 156 | 50.24 | 50.52 | 50.24 | 48.29 | 51.17 |
2014-12-19 | 0.00 | 0.00 | 31.7441691 | 0 | 0.00000 | 7904.65014 | 7904.65014 | hold | 0 | 0.00 | 50.42 | 50.88 | 48.81 | 51.47 |
2014-12-26 | 0.00 | 0.00 | 31.7441691 | 0 | 0.00000 | 7904.65014 | 7904.65014 | hold | 0 | 0.00 | 50.99 | 50.86 | 49.93 | 51.60 |
Let us dump only active trading records to ease the post trading analysis.
portfolioTradingHistFIlt <- subset(porfolioTradingHistory, action != "hold")
kable(portfolioTradingHistFIlt, caption = "Filtered Portfolio trading history")
portfolio.Open | portfolio.Close | portfolio.Gain | own.shares | average.price | available.funds.Open | available.funds.Close | action | quantity | trade.value | ticker.Open | ticker.Close | ticker.Low | ticker.High | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2014-06-13 | 0.00 | 2031.70 | 0.0000000 | 55 | 35.86000 | 6000.00000 | 4027.69994 | buy | 55 | 35.86 | 35.86 | 36.94 | 35.54 | 37.06 |
2014-07-03 | 1987.70 | 0.00 | 0.2566648 | 0 | 0.00000 | 4027.69994 | 6015.39989 | sell | 55 | 36.14 | 34.93 | 36.14 | 34.85 | 36.15 |
2014-07-11 | 0.00 | 1948.65 | 0.2566648 | 55 | 36.15000 | 6015.39989 | 4027.14978 | buy | 55 | 36.15 | 36.15 | 35.43 | 34.10 | 36.23 |
2014-08-29 | 2090.55 | 4093.07 | 0.2566648 | 107 | 37.11710 | 4027.14978 | 2043.86983 | buy | 52 | 38.14 | 38.14 | 38.51 | 37.54 | 38.72 |
2014-09-12 | 4236.13 | 6337.25 | 0.2566648 | 156 | 38.12942 | 2043.86983 | 67.20983 | buy | 49 | 40.34 | 40.34 | 42.88 | 40.26 | 43.20 |
2014-12-12 | 7837.44 | 0.00 | 31.7441691 | 0 | 0.00000 | 67.20983 | 7904.65014 | sell | 156 | 50.24 | 50.52 | 50.24 | 48.29 | 51.17 |
So, no trading activity until June 13th when a buy order is issued. Sell order is issued on July13th as the prediction model foresees a loss higher than the specified sell threshold. At that time, no remarkable portfolio gain is achieved. Then other three buy orders are issued and the overall portfolio is closed on December 12th. The sell performed define a satisfactory portfolio gain percentage.
To inspect the signal values, we can dump:
signalHistory
## Next.OpCl.ticker signal.zoo
## 2014-01-03 0.029463197 0
## 2014-01-10 -0.027939796 -1
## 2014-01-17 -0.051775888 0
## 2014-01-24 -0.042287236 0
## 2014-01-31 0.035893184 0
## 2014-02-07 0.006052632 0
## 2014-02-14 -0.026624901 0
## 2014-02-21 0.038678431 0
## 2014-02-28 0.027888418 0
## 2014-03-07 -0.026663292 0
## 2014-03-14 -0.027179513 0
## 2014-03-21 -0.055263105 0
## 2014-03-28 -0.060340128 0
## 2014-04-04 -0.036353033 0
## 2014-04-11 0.084351776 0
## 2014-04-17 -0.057923446 0
## 2014-04-25 0.063455469 0
## 2014-05-02 -0.079607470 0
## 2014-05-09 -0.017063900 0
## 2014-05-16 0.048189165 0
## 2014-05-23 -0.009999943 0
## 2014-05-30 0.035456876 0
## 2014-06-06 0.030117066 -1
## 2014-06-13 -0.027142886 1
## 2014-06-20 0.003515939 0
## 2014-06-27 0.034640681 0
## 2014-07-03 -0.019917067 -1
## 2014-07-11 -0.068994332 1
## 2014-07-18 0.083058506 0
## 2014-07-25 -0.016836903 0
## 2014-08-01 0.005600700 0
## 2014-08-08 0.010249391 0
## 2014-08-15 0.033723089 0
## 2014-08-22 0.009701075 0
## 2014-08-29 0.017737737 1
## 2014-09-05 0.062964824 0
## 2014-09-12 -0.069349704 1
## 2014-09-19 0.022378677 0
## 2014-09-26 0.015342712 0
## 2014-10-03 -0.038835023 1
## 2014-10-10 -0.027074873 0
## 2014-10-17 0.130751205 0
## 2014-10-24 0.063264787 0
## 2014-10-31 0.054288818 0
## 2014-11-07 0.060450841 0
## 2014-11-14 -0.015242156 0
## 2014-11-21 0.009561015 0
## 2014-11-28 -0.008555279 0
## 2014-12-05 -0.005542320 0
## 2014-12-12 0.009123424 -1
## 2014-12-19 -0.002549539 -1
## 2014-12-26 -0.009867772 0
You can see now the difference with the tradeModel() function. Even though -1 signals are raised first, no actual gain against the market is accounted as the portfolio does not yet hold any shares. When June 13th +1 signal is raised, a correspondingly buy order is issued and recorded in our portfolio history table. And so on. Now we can match our model signals with concrete portfolio related trading actions and record consequent gains or losses.
You can play with different signal thresholds and buy/sell options to see how the results remarkably change in terms of loss or gain. Therefore you are advised. Please do not think to win all the times against the market with this or any other trading strategy you may want to define. Greed is good, yes...however...
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.