Quantstrat重新平衡 - 非常长时间运行

时间:2015-06-18 06:50:53

标签: r quantmod quantitative-finance quantstrat

在得到各位成员的帮助后,我终于在quantstrat中建立了自己的样本策略。该代码在< 100种股票的世界中运行良好且快速(约1分钟),但是当宇宙扩展到例如500种股票时,运行时间急剧增加到(> 5小时)。经过一些测试后,我发现增加运行时间的关键是applyStrategy。重新平衡。当我消除重新平衡这个词时,一切都很快。

但是,我希望保持再平衡选项以维持一定的股权与现金比率。任何关于大大增加运行时间和可能的解决方案的想法将不胜感激。

为了解释更多,我的策略相当简单。每个月,投资组合将出售投资组合中的所有股票,并回购排名前20位的股票。资金平均分配给20只股票。

具有更大Universe的数据文件: (请编辑代码中的路径)

http://www.filedropper.com/data7
http://www.filedropper.com/data72

我的代码:(在小样本下运行良好)

library(lattice)
library(quantstrat)


quotes.file <- "Data7.csv"   #Need Editing

quotes.file2 <- "Data72.csv"   #Need Editing

#
# 1. Instrument: read csv file into xts object
#
code  <- read.csv(quotes.file2,head=TRUE)
data2 <- read.csv(quotes.file, head=TRUE)
code=apply(code,1,"toString")
matsplitter<-function(M, r, c) {
    rg <- (row(M)-1)%/%r+1
    cg <- (col(M)-1)%/%c+1
    rci <- (rg-1)*max(cg) + cg
    N <- prod(dim(M))/r/c
    cv <- unlist(lapply(1:N, function(x) M[rci==x]))
    dim(cv)<-c(r,c,N)
    cv
} 

data=matsplitter(data2[,-1],nrow(data2),4)
colnames(data)=c("close","pe","pe_avg","pe_sd")
dates <- as.Date(data2$Date,"%d/%m/%Y")
C=list()
i=1
for (i in 1:(dim(data)[3])){
    C[[i]] <- xts(x=data[,,i], order.by=dates)
}


#
# 2. Support Functions
#

osFixedDollar <- function(timestamp,orderqty, portfolio, symbol, ruletype, ...)
{
  updatePortf(qs.portfolio, Symbols=code, Dates=paste('::',as.Date(Sys.time()),sep=''))
  cumPL=0
  for (o in (1: length(code))){
      cumPL <- cumPL+sum(getPortfolio(portfolio)$symbols[[code[o]]]$posPL$Net.Trading.PL)
  }
  ClosePrice <- as.numeric((mktdata[timestamp,"close"]))
  orderqty <- round(((initEq+cumPL)/topchoice)/ClosePrice,-2)
  return(orderqty)
}

pause <- function() {
  cat ("Press [enter] to continue")
  line <- readline()
}

Zscore <- function(x0,y0,z0) {
  x <- as.numeric(x0)
  y <- as.numeric(y0)
  z <- as.numeric(z0)
  res <- (x-y)/z
  res
}



for (i in 1:(dim(data)[3])){
    C[[i]]$Zscore <-Zscore(C[[i]]$pe,C[[i]]$pe_avg,C[[i]]$pe_sd)
}


for (j in  1:(nrow(data))){
    temp=0
    for (i in 1:(dim(data)[3])){    
        temp=c(temp,C[[i]][j,"Zscore"])
    }
    temp=temp[-1]
    temp=as.numeric(-temp)
    temp2=rank(temp)
    for (i in 1:(dim(data)[3])){
        C[[i]]$ranking[j]=temp2[i]
    }   
}

for (i in 1:(dim(data)[3])){
    assign(code[i],C[[i]])
}

#
# 3. Initializations
#

# Currency:
currency("HKD")

# Instrument:
big.point.value <- 1
for (i in 1:(dim(data)[3])){
    stock(code[i], currency="HKD", multiplier=big.point.value)
}

# Strategy, portfolio and account names:
qs.strategy <- "PE.on.HKex"
qs.portfolio <- "Equities"
qs.account <- "My.account"

# Remove previous strategy, portfolio and account:
suppressWarnings(rm(list = c(paste("account", qs.account, sep='.'), paste("portfolio", qs.portfolio, sep='.')), pos=.blotter))
suppressWarnings(rm(list = c(qs.strategy, paste("order_book", qs.portfolio, sep='.')), pos=.strategy))
rm.strat(qs.strategy) # remove strategy etc. if this is a re-run

# Portfolio:
initDate <- '2013-12-15'
initPortf(qs.portfolio, code, initDate=initDate, currency='HKD')

# Account:
initEq <- 100000
initAcct(qs.account, portfolios=qs.portfolio, initDate=initDate, currency='HKD', initEq=initEq)

# Orders:
initOrders(portfolio=qs.portfolio, initDate=initDate)

# Strategy:
strategy(qs.strategy, store=TRUE)

#
# 4. Functions indicating buy, sell short, sell and buy to cover
#

nb.bars.with.no.trade <- 0
topchoice=20

buy.function <- function(x) {
  N <- nrow(x) 
  buy.signals <- numeric(N)
  # buy.signals[1:nb.bars.with.no.trade]<- 0
  for (i in (nb.bars.with.no.trade+1):N) {
    if ( (x[i]<=topchoice)
         && (index(x)[i] < index(get(code[1]))[nrow(data)]) && (index(x)[i] > index(get(code[1]))[1]) # trick to avoid an open trade at the end
         ) {
      buy.signals[i] <- 1
    } else {
      buy.signals[i] <- 0
    }
  }

  xts(x=buy.signals, order.by=index(x))
}

sell.function <- function(x) {
  N <- nrow(x)
  sell.signals <- numeric(N)
  #sell.signals[1:nb.bars.with.no.trade]<- 0
  for (i in (nb.bars.with.no.trade+1):N) {

    if (x[i]>topchoice){
        sell.signals[i] <- 1
    }
  }

  xts(x=sell.signals, order.by=index(x))
}



#
# 5. Indicators for buy, sell short, sell and buy to cover
#

add.indicator(strategy = qs.strategy,
              name = "buy.function",
              arguments = list(x = quote(mktdata[,"ranking"])),
              label="Buy")

add.indicator(strategy = qs.strategy,
              name = "sell.function",
              arguments = list(x = quote(mktdata[,"ranking"])),
              label="Sell")

#
# 6. Signals for buy, sell short, sell and buy to cover
#

add.signal(qs.strategy,
           name="sigFormula",
           arguments = list(formula="X1.Buy == 1"),
           label="Buy",
           cross=FALSE)

add.signal(qs.strategy,
           name="sigFormula",
           arguments = list(formula="X1.Sell == 1"),
           label="Sell",
           cross=FALSE)

# 
# 7. Rules for buy, sell short, sell and buy to cover
# 

nb.contracts <- 2
round.trip.commission.for.one.contract <- 6
round.trip.commission.for.total.contracts <- round.trip.commission.for.one.contract * nb.contracts

add.rule(qs.strategy,
         name='ruleSignal',
         arguments = list(sigcol="Sell", 
                          sigval=TRUE,
                          orderqty='all',
                          ordertype='market',
                          orderside='long',
                          pricemethod='market',
                          replace=FALSE,TxnFees=-0),
         type='exit',
         label="LongExit")

add.rule(qs.strategy,
         name='ruleSignal',
         arguments = list(sigcol="Buy",
                          sigval=TRUE,
                          orderqty=100000000,
                          ordertype='market',
                          orderside='long',osFUN='osMaxPos',
                          replace=FALSE),     
         type='enter',
         label="LongEntry")

add.rule(qs.strategy, 'rulePctEquity',
        arguments=list(rebalance_on='years',
                       trade.percent=(1/topchoice)*0.9,
                       refprice=quote(last(getPrice(mktdata)[paste('::',curIndex,sep='')])),
                       digits=0
        ),
        type='rebalance',
        label='rebalance'
)





posval<-initEq/topchoice
for(symbol in code){
    pos<-round((posval/first(get(symbol)[,1])[,1]),0)
    addPosLimit(qs.portfolio,symbol,initDate, maxpos=pos,minpos=-pos)
}



#
# 8. Apply Strategy to Porfolio
#
tradeSize <- initEq/topchoice




applyStrategy.rebalancing(strategy = qs.strategy,
              portfolios = qs.portfolio)

updatePortf(qs.portfolio, Symbols=code, Dates=paste('::',as.Date(Sys.time()),sep=''))
updateAcct(qs.account)
updateEndEq(qs.account)

0 个答案:

没有答案