[R-SIG-Finance] quantstrat - model transactions on specific dates

Mark Knecht markknecht at gmail.com
Thu Oct 9 23:43:24 CEST 2014


On Thu, Oct 9, 2014 at 2:16 PM, Brian G. Peterson <brian at braverock.com> wrote:
> On 10/09/2014 04:00 PM, Mark Knecht wrote:
>>
>> Best I can
>> tell the applyStrategy.rebalance function rebalances individual stocks
>> based on the last entry date of that stock but not, for instance, on a
>> specific date like the a calendar quarter. (I wasn't going to post
>> this all right now until I was really sure so don't take this too
>> seriously.) Anyway I want to write something like what Faber &
>> Richardson wrote about in 'The Ivy Portfolio' where the whole
>> portfolio is rebalanced on a given date, like end-of-month,
>> independent of whether I'm using the 10 month SMA or not. For that
>> reason I figured I might need a way to match indexes to dates going
>> though time.
>
>
> see the faber_rebal demo.
>
> The rebalance_on argument will call the rebalancing rule(s) on whatever
> periodicity you tell it to, you'll have to have something for them to do.
>
> In the demo, I just changed max order size, but there's no reason you
> couldn't write a (strategy specific) rebalancing rule that wouldn't read all
> the positions, and do transactions on the rebalance date.
>
>
> Regards,
>
> Brian

Brian,
   Yes, that's what I'm thinking I'll need to do. Josh's suggestion
about using sigTimestamp looks like it could also be part of that.

   The code below (for casual readers or people coming later) is based
on the faber_rebal demo and generates generates faberTxns which shows
all the stocks trades together in one place. They are being rebalanced
but the trades occur at different times which is what I want to play
with. Also, this code includes the index as a testable column (not
used but generated as a test) and I moved the start date on the SPY,
for comparison purposes, to be the first entry date of whatever stock
executes first.

Thanks,
Mark


#This code is based on the faber_rebal demo file
#Thanks to those who wrote and debugged it
require(quantstrat)

Sys.setenv(TZ="UTC")

portfolio.st = "faber"
account.st   = "faber"
strategy.st  = "faber"

# Try to clean up in case the demo was run previously
suppressWarnings(rm("account.faber","portfolio.faber",pos=.blotter))
suppressWarnings(rm("ltaccount", "ltportfolio", "ClosePrice",
"CurrentDate", "equity",
                    "GSPC", "stratFaber", "initDate", "initEq",
"Posn", "UnitSize", "verbose"))
suppressWarnings(rm("order_book.faber",pos=.strategy))

initDate='1997-12-31'
initEq=100000
currency("USD")
symbols = c("XLF", "XLP", "XLE", "XLY", "XLV", "XLI", "XLB", "XLK", "XLU")

xtsIndex = function(data){
  xtsIndex = reclass(index(data), match.to=data)
  colnames(xtsIndex)="xtsIndex"
  return(xtsIndex)
}

for(symbol in symbols){
  stock(symbol, currency="USD",multiplier=1)
}

getSymbols(symbols, src='yahoo', index.class=c("POSIXt","POSIXct"),
from='1999-01-01')
for(symbol in symbols) {
  if (symbol == symbols[1]){
    tmpData = Cl(get(symbol))
  }else{
    tmpData = cbind(tmpData, Cl(get(symbol)))
  }
}
#Find first common data date
tmpData = tmpData[complete.cases(tmpData)]
startDate = first(index(tmpData))
print(startDate)
#rm(tmpData)

for(symbol in symbols) {
  x<-get(symbol)
  x<-to.monthly(x,indexAt='lastof',drop.time=TRUE)
  indexFormat(x)<-'%Y-%m-%d'
  colnames(x)<-gsub("x",symbol,colnames(x))
#  x = x[paste0(startDate,"/")]
  assign(symbol,x)
}


initPortf(portfolio.st, symbols=symbols, initDate=initDate)
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, initEq=100000)
initOrders(portfolio=portfolio.st, initDate=initDate)

# set intial position limits
posval<-initEq/length(symbols)
for(symbol in symbols){
  pos<-round((posval/first(getPrice(get(symbol)))[,1]),-2)
  addPosLimit(portfolio.st,symbol,initDate, maxpos=pos,minpos=-pos)
}
print("setup completed")

# Initialize a strategy object
strategy(strategy.st, store=TRUE)


add.indicator(strategy.st, name = "SMA", arguments = list(x =
quote(Cl(mktdata)), n=10), label="SMA10")
add.indicator(strategy.st, name = "xtsIndex", arguments = list(data =
quote(mktdata)), label="Index")

add.signal(strategy.st,name="sigCrossover",arguments =
list(columns=c("Close","SMA10"),relationship="gte"),label="Cl.gt.SMA")
add.signal(strategy.st,name="sigCrossover",arguments =
list(columns=c("Close","SMA10"),relationship="lt"),label="Cl.lt.SMA")

add.rule(strategy.st, name='ruleSignal', arguments =
list(sigcol="Cl.gt.SMA", sigval=TRUE, orderqty=100000,
osFUN='osMaxPos', ordertype='market', orderside='long',
pricemethod='market',TxnFees=-5), type='enter', path.dep=TRUE)
#add.rule(strategy.st, name='ruleSignal', arguments =
list(sigcol="Cl.lt.SMA", sigval=TRUE, orderqty='all',
ordertype='market', orderside='long',
pricemethod='market',TxnFees=-5), type='exit', path.dep=TRUE)

# # add rebalancing rule
add.rule(strategy.st, 'rulePctEquity',
         arguments=list(rebalance_on='quarters',
                        trade.percent=1/length(symbols),

refprice=quote(last(getPrice(mktdata)[paste('::',as.character(curIndex),sep='')][,1])),
                        digits=0
         ),
         type='rebalance',
         label='rebalance'
)

# Process the strategy and generate trades
start_t<-Sys.time()
out<-applyStrategy.rebalancing(strategy=strategy.st , portfolios=portfolio.st)
#out<-applyStrategy(strategy=strategy.st , portfolios=portfolio.st)
end_t<-Sys.time()
print("Strategy Loop:")
print(end_t-start_t)


start_t<-Sys.time()
updatePortf(Portfolio=portfolio.st,Dates=paste('::',as.Date(Sys.time()),sep=''))
updateAcct(account.st)
end_t<-Sys.time()
print("trade blotter portfolio update:")
print(end_t-start_t)

# hack for new quantmod graphics, remove later
themelist<-chart_theme()
themelist$col$up.col<-'lightgreen'
themelist$col$dn.col<-'pink'

#dev.new() #Removed for RStudio
layout(mat=matrix(1:(length(symbols)+1),ncol=2))
for(symbol in symbols){
  chart.Posn(Portfolio=portfolio.st,Symbol=symbol,theme=themelist,TA="add_SMA(n=10,col='darkgreen')")
}

ret1 <- PortfReturns(portfolio.st)
ret1$total <- rowSums(ret1)

faber.stats<-tradeStats(portfolio.st)[,c('Net.Trading.PL','Max.Drawdown','Num.Trades','Profit.Factor','Std.Dev.Trade.PL','Largest.Winner','Largest.Loser','Max.Equity','Min.Equity')]
faber.stats = t(round(faber.stats,2))
View(faber.stats)

#Plot all the individual equities
par(mfrow=c(1,1))
plot.zoo(cumprod(1+ret1[,1:(ncol(ret1)-1)]), screens=1,
col=rainbow(n=ncol(ret1)-1))

#Get # of shares and txn prices

for (i in 1:length(symbols)){
  tmp1 = getTxns(portfolio.st,symbols[i])[,1:2]
  colnames(tmp1) = c(paste0(symbols[i],".sh"), paste0(symbols[i],".pr"))
#  print(tmp1)
  if (i == 1){
    faberTxns = tmp1
  }else{
    faberTxns = cbind(faberTxns, tmp1)
  }
}

View(faberTxns)

ComparisonDate = index(faberTxns)[2]

if("package:PerformanceAnalytics" %in% search() ||
require("PerformanceAnalytics",quietly=TRUE)){
  getSymbols("SPY", src='yahoo', index.class=c("POSIXt","POSIXct"),
from=ComparisonDate)
  SPY<-to.monthly(SPY, indexAt='lastof')
  SPY.ret <- Return.calculate(SPY$SPY.Close)
  #  dev.new() #Removed for RStudio
  charts.PerformanceSummary(cbind(ret1$total,SPY.ret),
geometric=FALSE, wealth.index=TRUE)
}



More information about the R-SIG-Finance mailing list