9.6 SMA rule with volatility filter
We will consider the following rule:
- Buy every day when
- SMA30 SMA200 and
- standard deviation of close prices is less than its median over the last 50 days.
- Sell everything when
- SMA30 SMA200
The idea is that buy signal appears only when the price goes up with low volatility.
9.6.1 Step 1: Initialization
We first download data
from ="2009-01-01"
to ="2012-12-31"
symbols = c("IBM")
currency("USD")
getSymbols(symbols, from=from, to=to, adjust=TRUE)
stock(symbols, currency="USD", multiplier=1)
initEq=10^6
We first initialize the setup.
.blotter <-new.env()
.strategy <-new.env()
strategy.st <- "SMAv"
portfolio.st <- "SMAv"
account.st <- "SMAv"
rm.strat("SMAv")
initPortf(portfolio.st, symbols=symbols,
initDate=initDate, currency='USD')
initAcct(account.st, portfolios=portfolio.st,
initDate=initDate, currency='USD',
initEq=initEq)
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)
9.6.2 Step 2: Indicator
Besides SMA, we will need a new indicator to give buy signal. Since it is combination of SMA and volatility, we need to construct our own indicator, RB:
RB <- function(x,n,s,l){
sd <- runSD(x, n, sample= FALSE)
med <- runMedian(sd,n)
mavg <- SMA(x,n)
savg <- SMA(x,s)
lavg <- SMA(x,l)
signal <- ifelse(savg > lavg & sd < med,1,0)
colnames(signal) <- "RB"
reclass(signal,x)
}
Now we are ready to define our indicators:
add.indicator(
strategy.st, name="RB",
arguments=list(x=quote(Cl(mktdata)),
n=200, s=30, l=200),
label="RB")
add.indicator(
strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=30),
label="sma30")
add.indicator(
strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=200),
label="sma200")
9.6.3 Step 3: Signals
Now we add two signals: Buy signal appears when RB is greater than or equal to 1. Sell signals appears when SMA30 is less than SMA200.
Hence, this is different from simple trading rule. Here, we are going to do signal comparison. There are two price lists: sma200 and sma30. Then the relationship is greater than for buy and less than for less.
# Buy signal if RB>=1
add.signal(strategy.st,
name="sigThreshold",
arguments = list(threshold=1, column="RB",
relationship="gte",
cross=TRUE),
label="buy")
# Sell signal if SMA30<SMA200
add.signal(strategy.st,
name="sigComparison",
arguments=list(columns=c("sma30","sma200"),
relationship="lt"),
label="sell")
9.6.4 Step 4: Rules
We now consider buy and sell rules using market order. Note that this is the same as the case for simple SMA rule.
# Buy Rule
add.rule(strategy.st,
name='ruleSignal',
arguments = list(sigcol="buy",
sigval=TRUE,
orderqty=1000,
ordertype='market',
orderside='long',
pricemethod='market',
replace=FALSE),
type='enter',
path.dep=TRUE)
# Sell Rule
add.rule(strategy.st,
name='ruleSignal',
arguments = list(sigcol="sell",
sigval=TRUE,
orderqty='all',
ordertype='market',
orderside='long',
pricemethod='market',
replace=FALSE),
type='exit',
path.dep=TRUE)
9.6.5 Step 5: Evaluation
We first try to apply the trading rule.
out<-try(applyStrategy(strategy.st,
portfolios=portfolio.st))
## [1] "2011-07-14 08:00:00 IBM 1000 @ 169.919478248927"
## [1] "2011-08-08 08:00:00 IBM 1000 @ 162.813574456635"
## [1] "2012-07-06 08:00:00 IBM 1000 @ 189.765720727769"
## [1] "2012-07-26 08:00:00 IBM -3000 @ 192.283894241252"
## [1] "2012-08-14 08:00:00 IBM 1000 @ 197.425962200791"
## [1] "2012-11-19 08:00:00 IBM -1000 @ 190.350006"
Then we can update the accounts.
updatePortf(portfolio.st)
updateAcct(portfolio.st)
updateEndEq(account.st)
We can also plot the trading positions.
chart.Posn(Portfolio=portfolio.st,
Symbol="IBM",
log=TRUE)