RPackage QuantStat
RPackage QuantStat
RPackage: Quanstrat
Since quantstrat is not standard package, we first learn how to install custom package.
We will illustrate the usage of the quantstrat package by showing how four different rules be
applied:
Since the coding is complicated, we first overview the structure of the code. There are five
parts:
1. Initialization
2. Indicator: filter rule/SMA rule
3. Signals: buy/sell signals
4. Rule: buy or sell? quantity?
5. Evaluation of results.
Before we start, let us make sure that we have installed the following four standard packages:
1. quantmod,
2. PerformanceAnalytics,
3. FinancialInstrument, and
4. foreach.
If your R does not have them, please run the following code:
install.packages("quantmod")
install.packages("FinancialInstrument")
install.packages("PerformanceAnalytics")
install.packages("foreach")
FinancialInstrument allows you to specify your assets class (e.g., stock, derivatives,
currency) and foreach is a package that allow fast computation (i.e., parallel computation).
2 Blotter Package
Since working through quanstrat package requires the blotter package, which is rather
complicated, we demostrate first how the blotter pacakge works first.
As we have seen, recording tranasction of stocks, keeping track of cash and stock holding, and
evaluate return is rather messy. The blotter package is mainly for this purpose.
We need to setup the currency and declare the data is the stock
(using FinancialInstrument package).
The multipler is always one for stock, and currency is USD for US stock.
options("getSymbols.warning4.0"=FALSE)
from ="2008-01-01"
to ="2012-12-31"
symbols = c("AAPL", "IBM")
currency("USD")
getSymbols(symbols, from=from, to=to,
adjust=TRUE)
stock(symbols, currency="USD", multiplier=1)
initEq=10^6
To start, we initialize account and portfolio where:
initPortf("buyHold", symbol=symbols)
initAcct("buyHold", portfolios = "buyHold",
initEq = initEq)
2.1 Buy and hold
To illustrate, we just consider buy and hold strategy:
addTxn(Portfolio = "buyHold",
Symbol = "IBM",
TxnDate = IBM.Buy.Date,
TxnQty = IBM.Qty,
TxnPrice = IBM.Buy.Price,
TxnFees = 0)
Then we add the sell transactions:
addTxn(Portfolio = "buyHold",
Symbol = "AAPL",
TxnDate = Apple.Sell.Date,
TxnQty = -Apple.Qty,
TxnPrice = Apple.Sell.Price,
TxnFees = 0)
addTxn(Portfolio = "buyHold",
Symbol = "IBM",
TxnDate = IBM.Sell.Date,
TxnQty = -IBM.Qty,
TxnPrice = IBM.Sell.Price,
TxnFees = 0)
Now we can update the account based on the added transactions:
updatePortf(Portfolio = "buyHold")
## [1] "buyHold"
updateAcct(name = "buyHold")
## [1] "buyHold"
updateEndEq(Account = "buyHold")
## [1] "buyHold"
We can chart our trading positions:
chart.Posn("buyHold", Symbol = "AAPL")
initPortf("filter", symbol=symbols)
initAcct("filter", portfolios = "filter",
initEq = initEq)
Here we generate trading indicator:
price <- Cl(MSFT)
r <- price/Lag(price) - 1
delta<-0.03
signal <-c(NA)
for (i in 2: length(price)){
if (r[i] > delta){
signal[i]<- 1
} else if (r[i]< -delta){
signal[i]<- -1
} else
signal[i]<- 0
}
signal<-reclass(signal,Cl(MSFT))
This convert trading indicator to trading signal:
trade <- Lag(signal)
trade <- na.fill(trade,0)
Now we are ready to apply trading signal into trading action:
for (i in 1:length(price)){
if (as.numeric(trade[i]) == 1){
addTxn(Portfolio = "filter",
Symbol = "MSFT",
TxnDate = time(price[i]),
TxnQty = 1000,
TxnPrice = price[i],
TxnFees = 0)
}
if (as.numeric(trade[i]) == -1){
addTxn(Portfolio = "filter",
Symbol = "MSFT",
TxnDate = time(price[i]),
TxnQty = -1000,
TxnPrice = price[i],
TxnFees = 0)
}
}
Finally, we update the account and do charting:
updatePortf(Portfolio = "filter")
updateAcct(name = "filter")
updateEndEq(Account = "filter")
chart.Posn("filter", Symbol = "MSFT")
3. Simple Filter Rule
3.1 Step 1: Initialization
We need to install standard packages and custom packages. After loading all the packages, we
initialize are variables and then download data.
Then we need to get the data and define initial variables.Download using getSybmols()
options("getSymbols.warning4.0"=FALSE)
from ="2003-01-01"
to ="2012-12-31"
symbols = c("MSFT", "IBM")
getSymbols(symbols, from=from, to=to,
adjust=TRUE)
Currency is USD for US stocks and the multiplier is always 1 for stocks.
currency("USD")
stock(symbols, currency="USD", multiplier=1)
We first define our strategy, portfolio and account name.
strategy.st <- "filter"
portfolio.st <- "filter"
account.st <- "filter"
Remove any old variables
rm.strat("filter")
After naming strategy, portfolio and account, we initialize them:
initEq=100000
initDate="1990-01-01"
initPortf(name=portfolio.st,
symbols=symbols,
initDate=initDate,
currency='USD')
initAcct(name=account.st,
portfolios=portfolio.st,
initDate=initDate,
currency='USD',
initEq=initEq)
initOrders(portfolio=portfolio.st,
symbols=symbols,
initDate=initDate)
strategy(strategy.st, store=TRUE)
In quantstrat, there are three ways one can use a signal. It is refer to as name:
The column refers to the data for calculation of signal. There are five possible relationship:
1. gt = greater than
2. gte = greater than or equal to
3. lt = less than
4. lte = less than or equal to
5. eq = equal to
Buy rule specifies that when a buy signal appears, place a buy market order with quantity size.
add.rule(strategy.st,
name='ruleSignal',
arguments = list(sigcol="filter.buy",
sigval=TRUE,
orderqty=1000,
ordertype='market',
orderside='long',
pricemethod='market',
replace=FALSE),
type='enter',
path.dep=TRUE)
Sell rule specifies that when a sell signal appears, place a sell market order with quantity size.
add.rule(strategy.st,
name='ruleSignal',
arguments = list(sigcol="filter.sell",
sigval=TRUE,
orderqty=-1000,
ordertype='market',
orderside='long',
pricemethod='market',
replace=FALSE),
type='enter',
path.dep=TRUE)
#Initial Setup
initPortf("buyHold", "SPY", initDate = initDate)
initAcct("buyHold", portfolios = "buyHold",
initDate = initDate, initEq = initEq)
initPortf(portfolio.st, symbols)
initAcct(account.st, portfolios=portfolio.st,
initEq = initEq)
initOrders(portfolio.st)
strategy(strategy.st, store=TRUE)
add.indicator(
strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=200),
label="sma200")
Here, we are going to do signal comparison so that we set name to sigComparison. We will
compare two signals: sma30 and sma200. Then the relationship is greater than for buy and
less than for less. We name the former to be a buy signal and the latter for a sell signal.
# Bull market if SMA30>SMA200
add.signal(
strategy.st,
name="sigComparison",
arguments=list(columns=c("sma30","sma200"),
relationship="gt"),
label="buy")
# 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)
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)
add.indicator(
strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=200),
label="sma200")
add.indicator(
strategy.st, name="RB",
arguments=list(x=quote(Cl(mktdata)), n=200),
label="RB")
# 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)