Just to save money is not enough, we
should keep our saving growing. Here is a very simple strategy: keep
investing on a regular basis.
We will use R to test this very simply
idea. Suppose that we start from 2004-05-10 and we keep investing
1000 to MDY every 20 business days. The transaction cost is 10/trade. The period is intentionally selected so that it can go through the financial crisis.
To estimate the annualized return of
this strategy, we will compare the final market value of our
investment to our total investment and use the formula :
(finalValue/initialInvetment) **(1/numYears)-1
(finalValue/initialInvetment) **(1/numYears)-1
Note that this formula will provide an
approximate estimation of the annualized return, because the time of
investment being in the market does not cover the whole period. The
test shows that we can get about 6% annualized return each year from
this very simply strategy.
The R script is attached at the end of
the post. The results of the strategy heavily depends on the
parameters of the algorithm and the studying period.
We can improve this strategy by making
it more flexible. For instance, when the market condition is not
good, we can try to invest more money to the equity market, believing
that the economy or the market will come back sooner or later.
------------------------------------------------------R script -------------------------------------------------------
library(tseries)
ustart <- "2004-05-10" # start date
uend <- "2014-08-08" # end date
ticker <- "mdy"
quote <- get.hist.quote(instrument=ticker,
start=ustart,
end=uend,
quote=c("AdjClose"),
provider="yahoo",
compression="d")
dates <- rownames(as.data.frame(quote))
quote <- as.double(quote)
# --------------------------------------------------
ptr <- 0
l <- length(quote)
amount <- 1000
investmentPeriod <- 20
transactionCost <- 10
totalInvestment <- 0
shares <- 0
totalInvestment_std <- 0
shares_std <- 0
dateIndex <- array()
annualizedReturn <- array()
annualizedReturn_std <- array()
count <- 0
level_low <- 0.03
level_high <- 0.05
extra_amount <- 250
while (ptr < l) {
ptr <- ptr + 1
if (ptr %% investmentPeriod == 0 ) {
count <- count + 1
dateIndex[count] <- ptr
if ((annualizedReturn[ptr-1] < level_low) && (count > 6)) {
extra_amount <- min(500,amount * (level_low - annualizedReturn[ptr-1]) * 15)
totalInvestment <- totalInvestment + amount + extra_amount
shares <- shares + (amount + extra_amount) /quote[ptr]
totalInvestment_std <- totalInvestment_std + amount
shares_std <- shares_std + amount / quote[ptr]
# } else if ((annualizedReturn[ptr-1] > level_high) && (count > 6)) {
# extra_amount <- max(-200, amount * (level_high - annualizedReturn[ptr-1]) * 2)
# totalInvestment <- totalInvestment + amount + extra_amount
# shares <- shares + (amount + extra_amount) /quote[ptr]
#
# totalInvestment_std <- totalInvestment_std + amount
# shares_std <- shares_std + amount / quote[ptr]
} else {
shares <- shares + amount / quote[ptr]
totalInvestment <- totalInvestment + amount
shares_std <- shares_std + amount / quote[ptr]
totalInvestment_std <- totalInvestment_std + amount
}
}
if ((totalInvestment == 0) || (count < 6)) {
annualizedReturn[ptr] <- 0
} else {
currentValue <- quote[ptr] * shares
currentValue_std <- quote[ptr] * shares_std
portionOfYear <- count * investmentPeriod / 252
aReturn <- ((currentValue - count * transactionCost)/totalInvestment) ** (1/portionOfYear) - 1
aReturn_std <- ((currentValue_std -count * transactionCost)/totalInvestment_std) ** (1/portionOfYear) - 1
annualizedReturn[ptr] <- aReturn
annualizedReturn_std[ptr] <- aReturn_std
}
}
# --------- plot ----------
plot(quote, type="l", ylab="", xlab="", xaxt="n")
uPoints <- cbind(dateIndex, quote[dateIndex])
points(uPoints, pch=17, col="blue")
par(new=TRUE)
plot(annualizedReturn, type="l", col="red", ylab="MDY",xlab="",xaxt="n", yaxt="n", ylim=c(-0.15,0.15))
lines(annualizedReturn_std, type="l", col="green", ylab="return",xlab="",xaxt="n",yaxt="n",ylim=c(-0.15,0.115))
lines(rep(level_low,l),type="l", col="lightgrey")
lines(rep(level_high,l),type="l", col="lightgrey")
legend("bottomright", legend=c("price","simple","aggressive"), col=c("black","green","red"), lty=1, cex=0.45)
y_grid <- c(-0.15,-0.1,-0.05,0,0.05,0.10,0.15)
axis(4,at=y_grid, label=y_grid)
nDates <- trunc(l / 252) * 4
cc <- trunc(l/nDates)
pos <- c(1:nDates) * cc
axis(1,at=pos, label=dates[pos],las=2)
title("Invest On a Monthly Basis")
# ---------- not important --------
annualizedReturn[l]
annualizedReturn_std[l]
(quote[l]/(mean(quote[1:15]))) ** (252 /l) - 1
ustart <- "2004-05-10" # start date
uend <- "2014-08-08" # end date
ticker <- "mdy"
quote <- get.hist.quote(instrument=ticker,
start=ustart,
end=uend,
quote=c("AdjClose"),
provider="yahoo",
compression="d")
dates <- rownames(as.data.frame(quote))
quote <- as.double(quote)
# --------------------------------------------------
ptr <- 0
l <- length(quote)
amount <- 1000
investmentPeriod <- 20
transactionCost <- 10
totalInvestment <- 0
shares <- 0
totalInvestment_std <- 0
shares_std <- 0
dateIndex <- array()
annualizedReturn <- array()
annualizedReturn_std <- array()
count <- 0
level_low <- 0.03
level_high <- 0.05
extra_amount <- 250
while (ptr < l) {
ptr <- ptr + 1
if (ptr %% investmentPeriod == 0 ) {
count <- count + 1
dateIndex[count] <- ptr
if ((annualizedReturn[ptr-1] < level_low) && (count > 6)) {
extra_amount <- min(500,amount * (level_low - annualizedReturn[ptr-1]) * 15)
totalInvestment <- totalInvestment + amount + extra_amount
shares <- shares + (amount + extra_amount) /quote[ptr]
totalInvestment_std <- totalInvestment_std + amount
shares_std <- shares_std + amount / quote[ptr]
# } else if ((annualizedReturn[ptr-1] > level_high) && (count > 6)) {
# extra_amount <- max(-200, amount * (level_high - annualizedReturn[ptr-1]) * 2)
# totalInvestment <- totalInvestment + amount + extra_amount
# shares <- shares + (amount + extra_amount) /quote[ptr]
#
# totalInvestment_std <- totalInvestment_std + amount
# shares_std <- shares_std + amount / quote[ptr]
} else {
shares <- shares + amount / quote[ptr]
totalInvestment <- totalInvestment + amount
shares_std <- shares_std + amount / quote[ptr]
totalInvestment_std <- totalInvestment_std + amount
}
}
if ((totalInvestment == 0) || (count < 6)) {
annualizedReturn[ptr] <- 0
} else {
currentValue <- quote[ptr] * shares
currentValue_std <- quote[ptr] * shares_std
portionOfYear <- count * investmentPeriod / 252
aReturn <- ((currentValue - count * transactionCost)/totalInvestment) ** (1/portionOfYear) - 1
aReturn_std <- ((currentValue_std -count * transactionCost)/totalInvestment_std) ** (1/portionOfYear) - 1
annualizedReturn[ptr] <- aReturn
annualizedReturn_std[ptr] <- aReturn_std
}
}
# --------- plot ----------
plot(quote, type="l", ylab="", xlab="", xaxt="n")
uPoints <- cbind(dateIndex, quote[dateIndex])
points(uPoints, pch=17, col="blue")
par(new=TRUE)
plot(annualizedReturn, type="l", col="red", ylab="MDY",xlab="",xaxt="n", yaxt="n", ylim=c(-0.15,0.15))
lines(annualizedReturn_std, type="l", col="green", ylab="return",xlab="",xaxt="n",yaxt="n",ylim=c(-0.15,0.115))
lines(rep(level_low,l),type="l", col="lightgrey")
lines(rep(level_high,l),type="l", col="lightgrey")
legend("bottomright", legend=c("price","simple","aggressive"), col=c("black","green","red"), lty=1, cex=0.45)
y_grid <- c(-0.15,-0.1,-0.05,0,0.05,0.10,0.15)
axis(4,at=y_grid, label=y_grid)
nDates <- trunc(l / 252) * 4
cc <- trunc(l/nDates)
pos <- c(1:nDates) * cc
axis(1,at=pos, label=dates[pos],las=2)
title("Invest On a Monthly Basis")
# ---------- not important --------
annualizedReturn[l]
annualizedReturn_std[l]
(quote[l]/(mean(quote[1:15]))) ** (252 /l) - 1