8.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 first need to setup the working space.
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("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:
Porfolio: stores which stocks to be traded
Account: stores which money transactions
.blotter <-new.env()
rm("account.buyHold",pos=.blotter)
rm("portfolio.buyHold",pos=.blotter)
initPortf("buyHold", symbol=symbols)
initAcct("buyHold", portfolios = "buyHold",
initEq = initEq)
8.2.1 Buy and hold
To illustrate, we just consider buy and hold strategy on IBM:
- Buy on the first day at closing price
- Sell on the last day at closing price
We first get the price and timing data:
Buy.Date <- first(time(IBM))
Buy.Price <- as.numeric(Cl(IBM[Buy.Date,]))
Sell.Date <- last(time(IBM))
Sell.Price <- as.numeric(Cl(IBM[Sell.Date,]))
Qty <- initEq/Buy.Price
We first add buy transactions to the system using the function addTxn:
addTxn(Portfolio = "buyHold",
Symbol = "IBM",
TxnDate = Buy.Date,
TxnQty = Qty,
TxnPrice = Buy.Price,
TxnFees = 0)
Then we add the sell transactions:
addTxn(Portfolio = "buyHold",
Symbol = "IBM",
TxnDate = Sell.Date,
TxnQty = -Qty,
TxnPrice = 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 = "IBM")
We can see the trading statistics
out <- perTradeStats("buyHold", "IBM")
t(out)
## [,1]
## Start "2008-01-02 08:00:00"
## End "2012-12-28 08:00:00"
## Init.Qty "10446.77"
## Init.Pos "10446.77"
## Max.Pos "10446.77"
## End.Pos "0"
## Closing.Txn.Qty "-10446.77"
## Num.Txns "2"
## Max.Notional.Cost "1e+06"
## Net.Trading.PL "983110"
## MAE "-302740.5"
## MFE "1194663"
## Pct.Net.Trading.PL "0.98311"
## Pct.MAE "-0.3027405"
## Pct.MFE "1.194663"
## tick.Net.Trading.PL "9410.662"
## tick.MAE "-30274048"
## tick.MFE "119466318"
## duration "157420800 secs"
8.2.2 Buy Filter Rule
We use blotter package to apply simple filter rule
buy 1000 units signal if buy signal
hold otherwise
We first Download Data:
from ="2011-10-01"
to ="2012-12-31"
symbols = c("MSFT")
currency("USD")
getSymbols(symbols, from=from, to=to,
adjust=TRUE)
stock(symbols, currency="USD", multiplier=1)
initEq=10^6
Then setup the account and portfolio:
.blotter <-new.env()
rm("account.filter",pos=.blotter)
rm("portfolio.filter",pos=.blotter)
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)
}
}
We now update the account and do charting:
updatePortf(Portfolio = "filter")
updateAcct(name = "filter")
updateEndEq(Account = "filter")
chart.Posn("filter", Symbol = "MSFT")
Finally, we check the trading statistics:
out <- perTradeStats("filter", "MSFT")
t(out)
## [,1] [,2]
## Start "2011-10-05 08:00:00" "2012-01-04 08:00:00"
## End "2011-11-10 08:00:00" "2012-12-28 08:00:00"
## Init.Qty "1000" "1000"
## Init.Pos "1000" "1000"
## Max.Pos "1000" "6000"
## End.Pos " 0" "5000"
## Closing.Txn.Qty "-1000" "-5000"
## Num.Txns "2" "7"
## Max.Notional.Cost " 24989.77" "177548.89"
## Net.Trading.PL " 376.4411" "-17958.8999"
## MAE " 0.00" "-18858.89"
## MFE " 1370.625" "10321.156"
## Pct.Net.Trading.PL " 0.01506381" "-0.10114904"
## Pct.MAE " 0.000000" "-0.106218"
## Pct.MFE "0.05484743" "0.05813135"
## tick.Net.Trading.PL " 37.64411" "-299.31500"
## tick.MAE " 0" "-1885889"
## tick.MFE " 137062.5" "1032115.6"
## duration " 3110400 secs" "31017600 secs"