R/trickFun.R

#' alpha portfolio demo data
#'
#' part of index EI000905's alpha portfolio data set.
#' @format A data frame with 1149 rows and 3 variables.
"portdemo"


#' assets return demo dataset.
#'
#' A dataset containing stock index(000985.CSI), bond index(037.CS) and commodity(GC00.CMX) daily return data since 2009.
#'
#' @format A data frame with 2865 rows and 4 variables:
#' \describe{
#'   \item{date}{date type}
#'   \item{stock}{stock index return}
#'   \item{bond}{bond index return}
#'   \item{commodity}{commodity index return}
#' }
"rtndemo"



# ===================== xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ======================
# ===================== series of quant report functions  ===========================
# ===================== xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ======================




#' bank rotation
#'
#' This is a bank stocks rotation strategy.Its idea comes from
#' \url{https://www.jisilu.cn/question/50176}.
#' @name bankrotation
#' @author Andrew Dow
#' @param begT is strategy's begin date
#' @param endT is strategy's end date
#' @param chgBar is rotation's bar
#' @param fee is trading cost
#' @return a list of bank factorscore and strategy's historical return.
#' @examples
#' begT <- as.Date('2014-01-03')
#' endT <- Sys.Date()-1
#' chgBar <- 0.2
#' bankport <- bank.rotation(begT,endT,chgBar)
#' FactorLists <- list(
#'   buildFactorList(factorFun='gf.PB_mrq'),
#'   buildFactorList(factorFun='gf.ROE_ttm'))
#' re <- bank.rotationV2(begT,endT,FactorLists=FactorLists)
#' @export
bank.rotation <- function(begT,endT=Sys.Date()-1,chgBar=0.2,fee=0.003,
                             pbfun=c('gf.PB_lyr','gf.PB_mrq'),
                             roefun=c('gf.ROE_ttm','gf.ROE','gf.F_ROE')){
  pbfun <- match.arg(pbfun)
  roefun <- match.arg(roefun)

  rebDates <- getRebDates(begT,endT,rebFreq = 'day')
  TS <- getTS(rebDates,indexID = 'ES33480000')
  qr <- paste("select ID 'stockID',ListedDate from SecuMain where ID in",brkQT(unique(TS$stockID)))
  ipo <- queryAndClose.dbi(db.local('main'),qr)
  ipo$ListedDate <- intdate2r(ipo$ListedDate)
  TS <- left_join(TS,ipo,by='stockID')
  TS <- na.omit(TS)
  TS <- TS[TS$date>TS$ListedDate,c('date','stockID'),]
  TS <- rm_suspend(TS,0)

  TSF <- getRawFactor(TS,pbfun)
  tmp <- getRawFactor(TS,roefun)
  tmp <- tmp[,c('date','stockID','factorscore')]
  if(substr(roefun,4,4)!='F'){
    tmp$factorscore <- tmp$factorscore/100
  }
  TSF <- left_join(TSF,tmp,by=c('date','stockID'))
  colnames(TSF) <- c("date","stockID","PB","ROE")
  TSF <- na.omit(TSF)
  TSF$factorscore <- log(TSF$PB*2,base=(1+TSF$ROE))
  TSF <- dplyr::arrange(TSF,date,factorscore)

  #get bank
  dates <- unique(TSF$date)
  bankPort <- TSF[1,c('date','stockID')]
  for(i in 2:length(dates)){
    oldstock <- tail(bankPort$stockID,1)
    tmp <- TSF[TSF$date==dates[i],c('date','stockID',"factorscore")]
    if(oldstock %in% tmp$stockID){
      newscore <- tmp[1,'factorscore']
      oldscore <- tmp[tmp$stockID==oldstock,'factorscore']*(1-chgBar)
      if(newscore<oldscore){
        bankPort <- rbind(bankPort,tmp[1,c("date","stockID")])
        next
      }
    }
    bankPort <- rbind(bankPort,data.frame(date=dates[i],stockID=oldstock))
  }

  #get bank daily return
  qr <- paste("SELECT TradingDay 'date',ID 'stockID'
              ,PrevClosePrice 'pre_close',OpenPrice 'open'
              ,ClosePrice 'close',DailyReturn 'pct_chg'
              FROM QT_DailyQuote
              where ID in",brkQT(unique(bankPort$stockID)),
              " and TradingDay>=",rdate2int(min(bankPort$date)),
              " and TradingDay<=",rdate2int(max(bankPort$date)),
              " order by TradingDay,ID")
  re <- queryAndClose.odbc(db.quant(),qr,stringsAsFactors=F)
  re <- transform(re,date=intdate2r(date))

  TSR <- left_join(bankPort,re,by = c("date", "stockID"))

  for(i in 1:nrow(TSR)){
    if(i==1){
      TSR$pct_chg[i] <- 0
      next
    }
    if(i==2){
      TSR$pct_chg[i] <- TSR$close[i]/TSR$open[i]-1-fee
      next
    }

    if(TSR$stockID[i]!=TSR$stockID[i-1]){
      TSR$pct_chg[i] <- re[re$stockID==TSR$stockID[i-1] & re$date==TSR$date[i],'pct_chg']
    }else if(TSR$stockID[i]==TSR$stockID[i-1] & TSR$stockID[i-1]!=TSR$stockID[i-2]){
      tmp.open <- re[re$stockID==TSR$stockID[i-2] & re$date==TSR$date[i],'open']
      tmp.close <- re[re$stockID==TSR$stockID[i-2] & re$date==TSR$date[i-1],'close']
      tmp.rtn <- tmp.open/tmp.close-1-fee
      TSR$pct_chg[i] <- tmp.rtn+TSR$close[i]/TSR$open[i]-1-fee
    }
  }

  #get bench mark return
  bench <- getIndexQuote('EI801780',min(TSR$date),max(TSR$date),variables = c('pre_close','close'),datasrc = 'jy')
  bench$indexRtn <- bench$close/bench$pre_close-1
  bench <- bench[,c("date","indexRtn")]

  rtn <- left_join(bench,TSR[,c('date','pct_chg')],by='date')
  colnames(rtn) <- c("date","indexRtn","bankRtn")
  rtn <- na.omit(rtn)
  rtn <- xts::xts(rtn[,-1],order.by = rtn[,1])

  bankPort$mark <- 'hold'
  TSF <- left_join(TSF,bankPort,by=c('date','stockID'))
  TSF$stockName <- stockID2name(TSF$stockID)
  TSF <- TSF[,c("date", "stockID",'stockName',"PB","ROE","factorscore",'mark')]
  return(list(TSF=TSF,rtn=rtn))
}


#' @rdname bankrotation
#' @export
bank.rotationV2 <- function(begT,endT,FactorLists,chgBar,fee=0.003,
                             sectorID='ES33480000',prefer=FALSE){

  #get factorscore
  rebDates <- getRebDates(begT,endT,rebFreq = 'day')
  TS <- getTS(rebDates,indexID = sectorID)
  ipo <- data.frame(stockID=unique(TS$stockID),stringsAsFactors = FALSE)
  ipo <- transform(ipo,ListedDate=trday.IPO(stockID))

  TS <- TS %>% left_join(ipo,by='stockID') %>% filter(!is.na(ListedDate)) %>%
    filter(date>ListedDate+365) %>% select(date,stockID)

  TSF <- getRawMultiFactor(TS,FactorLists)
  colnames(TSF) <- c("date","stockID","PB","ROE")
  if(median(TSF$ROE,na.rm = TRUE)>1){
    TSF <- transform(TSF,ROE=ROE/100)
  }
  TSF <- TSF %>% mutate(factorscore=log(PB*2,base=(1+ROE))) %>%
   filter(!is.na(factorscore)) %>% arrange(date,factorscore)


  #get bench mark return
  bench <- getIndexQuote('EI801780',as.Date('2005-01-04'),max(TS$date),variables = c('pre_close','close'),datasrc = 'jy')
  bench <- bench %>% mutate(indexRtn=close/pre_close-1) %>% select(date,indexRtn)

  #if missing change bar, set change bar by historical vol.
  if(missing(chgBar)){
    indexVol <- xts::xts(bench[,-1],order.by = bench[,1])
    indexVol <- zoo::rollapply(indexVol, 22, sd)
    indexVol <- na.omit(indexVol)
    indexVol <- TTR::runPercentRank(indexVol,250,cumulative = TRUE)
    indexVol <- data.frame(date=zoo::index(indexVol),vol=zoo::coredata(indexVol))
    indexVol <- indexVol[250:nrow(indexVol),]
    chgBardf <- indexVol %>% mutate(bar=ifelse(vol<1/3,0.1,ifelse(vol<2/3,0.15,0.2))) %>%
      select(-vol)
  }

  #get bank
  dates <- unique(TSF$date)
  bankPort <- data.frame()
  for(i in 1:length(dates)){
    TSF_ <- TSF[TSF$date==dates[i],]
    TS_ <- TSF_[,c('date','stockID')]
    TS_ <- rm_suspend(TS_,0)
    if(nrow(TS_)<nrow(TSF_)){
      TSF_ <- TS_ %>% left_join(TSF_,by=c('date','stockID'))
    }

    if(prefer){
      TSF_ <- TSF_ %>% arrange(desc(ROE)) %>% slice(1:round(n()/3*2)) %>% arrange(factorscore)
    }

    if(i==1){
      bankPort_ <- TSF_[1,c('date','stockID')]

    }else{
      if(missing(chgBar)){
        chgBar <- chgBardf[chgBardf$date==dates[i],'bar']
      }

      oldstock <- tail(bankPort$stockID,1)
      bankPort_ <- data.frame(date=dates[i],stockID=oldstock)
      if(oldstock %in% TSF_$stockID && oldstock !=TSF_$stockID[1]){
        newscore <- TSF_[1,'factorscore']
        oldscore <- TSF_[TSF_$stockID==oldstock,'factorscore']*(1-chgBar)
        if(newscore<oldscore){
          bankPort_ <- TSF_[1,c("date","stockID")]
        }
      }
    }
    bankPort <- rbind(bankPort,bankPort_)
  }

  #get bank daily return
  qr <- paste("SELECT TradingDay 'date',ID 'stockID'
              ,PrevClosePrice 'pre_close',OpenPrice 'open'
              ,ClosePrice 'close',DailyReturn 'pct_chg'
              FROM QT_DailyQuote
              where ID in",brkQT(unique(bankPort$stockID)),
              " and TradingDay>=",rdate2int(min(bankPort$date)),
              " and TradingDay<=",rdate2int(max(bankPort$date)),
              " order by TradingDay,ID")
  re <- queryAndClose.odbc(db.quant(),qr,stringsAsFactors=F)
  re <- transform(re,date=intdate2r(date))

  TSR <- left_join(bankPort,re,by = c("date", "stockID"))
  for(i in 1:nrow(TSR)){
    if(i==1){
      TSR$pct_chg[i] <- 0
      next
    }
    if(i==2){
      TSR$pct_chg[i] <- TSR$close[i]/TSR$open[i]-1-fee
      next
    }

    if(TSR$stockID[i]!=TSR$stockID[i-1]){
      TSR$pct_chg[i] <- re[re$stockID==TSR$stockID[i-1] & re$date==TSR$date[i],'pct_chg']
    }else if(TSR$stockID[i]==TSR$stockID[i-1] & TSR$stockID[i-1]!=TSR$stockID[i-2]){
      tmp.open <- re[re$stockID==TSR$stockID[i-2] & re$date==TSR$date[i],'open']
      tmp.close <- re[re$stockID==TSR$stockID[i-2] & re$date==TSR$date[i-1],'close']
      tmp.rtn <- tmp.open/tmp.close-1-fee
      TSR$pct_chg[i] <- tmp.rtn+TSR$close[i]/TSR$open[i]-1-fee
    }
  }



  rtn <- left_join(TSR[,c('date','pct_chg')],bench,by='date')
  colnames(rtn) <- c("date","bankRtn","indexRtn")
  rtn <- na.omit(rtn)
  rtn <- as.data.frame(rtn)
  rtn <- xts::xts(rtn[,-1],order.by = rtn[,1])

  bankPort$mark <- 'hold'
  TSF <- left_join(TSF,bankPort,by=c('date','stockID'))
  TSF$stockName <- stockID2name(TSF$stockID)
  TSF <- TSF[,c("date", "stockID",'stockName',"PB","ROE","factorscore",'mark')]
  return(list(TSF=TSF,rtn=rtn))
}









# ===================== ~ index valuation  ====================
#' lcdb.build.QT_IndexValuation
#'
#' @name index_valuation
#' @rdname index_valuation
#' @export
#' @examples
#' lcdb.build.QT_IndexValuation()
lcdb.build.QT_IndexValuation<- function(indexID=c('EI399006','EI000933'),addIndex=FALSE){
  qr <- paste("select 'EI'+s.SecuCode 'indexID',s.SecuAbbr 'indexName',
              convert(varchar(8),i.PubDate,112) 'begT'
              from LC_IndexBasicInfo i,SecuMain s
              where i.IndexCode=s.InnerCode and s.SecuCode in",brkQT(substr(indexID,3,8)))
  indexDate <- queryAndClose.odbc(db.jy(),qr,stringsAsFactors=FALSE)
  indexDate <- transform(indexDate,begT=intdate2r(ifelse(begT<20050104,20050104,begT)),
                              endT=Sys.Date()-1)
  con <- db.local('main')
  if(addIndex){
    old <- dbGetQuery(con,"select distinct indexID from QT_IndexValuation")
    indexID <- setdiff(indexID,c(old$indexID))
    if(length(indexID)==0){
      return('Already in database!')
    }
    endT <- dbGetQuery(con,"select max(date) 'date' from QT_IndexValuation")
    indexDate <- indexDate[indexDate$indexID %in% indexID,]
    indexDate$endT <- intdate2r(endT$date)
  }

  re <- QT_IndexValuation_subfun(indexDate)
  if(addIndex){
    dbWriteTable(con,'QT_IndexValuation',re,overwrite=FALSE,append=TRUE,row.names=FALSE)
  }else{
    dbWriteTable(con,'QT_IndexValuation',re,row.names=FALSE)
  }

  dbDisconnect(con)
  return('Done!')
}

#inner function
QT_IndexValuation_subfun <- function(indexDate){

  #get index component
  qr <- paste("select 'EI'+s1.SecuCode 'indexID','EQ'+s2.SecuCode 'stockID',
              convert(varchar(8),l.InDate,112) 'InDate',
              convert(varchar(8),l.OutDate,112) 'OutDate'
              from LC_IndexComponent l
              LEFT join SecuMain s1 on l.IndexInnerCode=s1.InnerCode
              LEFT join SecuMain s2 on l.SecuInnerCode=s2.InnerCode
              where s1.SecuCode in",brkQT(substr(indexDate$indexID,3,8)),
              " order by s1.SecuCode,l.InDate")
  indexComp <- queryAndClose.odbc(db.jy(),qr,stringsAsFactors=FALSE)
  con <- db.local('main')
  dbWriteTable(con, name="amtao_tmp", value=indexComp, row.names = FALSE, overwrite = TRUE)

  #correct begT
  tmpdate <- plyr::ddply(indexComp,'indexID',plyr::summarise,mindate=intdate2r(min(InDate)))
  indexDate <- indexDate %>% dplyr::left_join(tmpdate,by='indexID') %>%
    dplyr::mutate(begT=as.Date(ifelse(begT<mindate,mindate,begT),origin='1970-01-01')) %>% dplyr::select(-mindate)

  #get bigTS
  bigTS <- data.frame()
  tmpdate <- data.frame(date=rdate2int(getRebDates(min(indexDate$begT),max(indexDate$endT),'day')))
  dbWriteTable(con, name="yrf_tmp", value=tmpdate, row.names = FALSE, overwrite = TRUE)
  for(i in 1:nrow(indexDate)){
    qr <- paste("SELECT a.date as date, b.stockID from yrf_tmp a, amtao_tmp b
                where b.IndexID=", QT(indexDate$indexID[i]),
                "and b.InDate<=a.date and (b.OutDate>a.date or b.OutDate IS NULL) and a.date>=",rdate2int(indexDate$begT[i]))
    TS_ <- dbGetQuery(con,qr)
    TS_ <- transform(TS_,date=intdate2r(date),indexID=indexDate$indexID[i])
    bigTS <- rbind(bigTS,TS_)
  }

  #get pe pb data
  TS <- dplyr::distinct(bigTS,date,stockID)
  pedata <- getTSF(TS,factorFun = 'gf.PE_ttm',factorPar = list(fillna = FALSE))
  pbdata <- getTSF(TS,factorFun = 'gf.PB_mrq',factorPar = list(fillna = FALSE))
  pedata <- dplyr::rename(pedata,pettm=factorscore)
  pbdata <- dplyr::rename(pbdata,pbmrq=factorscore)
  alldata <- dplyr::left_join(bigTS,pedata,by=c('date','stockID'))
  alldata <- dplyr::left_join(alldata,pbdata,by=c('date','stockID'))

  pemeanfun <- function(factorscore){
    #pe mean
    factorscore <- factorscore[!is.na(factorscore)]
    factorscore <- factorscore[factorscore>0 & factorscore<1000]
    outlier_u <- mean(factorscore)+3*sd(factorscore)
    outlier_l <- mean(factorscore)-3*sd(factorscore)
    factorscore[factorscore > outlier_u] <- outlier_u
    factorscore[factorscore < outlier_l] <- outlier_l
    return(mean(factorscore))
  }

  pbmeanfun <- function(factorscore){
    factorscore <- factorscore[!is.na(factorscore)]
    factorscore <- factorscore[factorscore>0 & factorscore<100]
    outlier_u <- mean(factorscore)+3*sd(factorscore)
    outlier_l <- mean(factorscore)-3*sd(factorscore)
    factorscore[factorscore > outlier_u] <- outlier_u
    factorscore[factorscore < outlier_l] <- outlier_l
    return(mean(factorscore))
  }

  #summarize
  indexvalue <- alldata %>% dplyr::group_by(date,indexID) %>% dplyr::summarise(PE_median=median(pettm,na.rm = TRUE),
                                                                                PE_mean=pemeanfun(pettm),
                                                                                PB_median=median(pbmrq,na.rm = TRUE),
                                                                                PB_mean=pbmeanfun(pbmrq))
  indexvalue <- tidyr::gather(indexvalue,key = "key", value = "value",-date,-indexID)
  indexvalue <- tidyr::separate(indexvalue,key,c('valtype','caltype'))
  indexvalue <- dplyr::left_join(indexvalue,indexDate[,c('indexID','indexName')],by='indexID')
  indexvalue <- indexvalue[,c("indexID","indexName","date","value","valtype","caltype")]
  indexvalue <- transform(indexvalue,date=rdate2int(date))
  dbDisconnect(con)
  return(indexvalue)
}

QT_IndexValuation_subfunF <- function(indexDate){
  require(WindR)
  w.start(showmenu = FALSE)
  indexValue <- data.frame()
  for(i in 1:nrow(indexDate)){
    indexValue_<-w.wsd(indexDate$indexID[i],"pe_ttm,pb_lf",indexDate$begT[i],indexDate$endT[i])[[2]]
    indexValue_ <- transform(indexValue_,indexID=indexDate$indexID[i],indexName=indexDate$indexName[i])
    indexValue <- rbind(indexValue,indexValue_)
  }

  indexValue <- indexValue[!is.nan(indexValue$PE_TTM),]
  indexpe <- reshape2::dcast(indexValue,DATETIME~indexID,value.var = 'PE_TTM',fill = NA)
  indexpb <- reshape2::dcast(indexValue,DATETIME~indexID,value.var = 'PB_LF',fill = NA)
  indexpe <- zoo::na.locf(indexpe)
  indexpb <- zoo::na.locf(indexpb)
  indexpe <- reshape2::melt(indexpe,id='DATETIME',variable.name = "indexID",value.name = "PE_TTM",na.rm = TRUE)
  indexpb <- reshape2::melt(indexpb,id='DATETIME',variable.name = "indexID",value.name = "PB_LF",na.rm = TRUE)
  indexValue <- left_join(indexpe,indexpb)
  indexValue <- reshape2::melt(indexValue,id=c('DATETIME','indexID'),variable.name = "valtype",value.name = "value")
  indexValue <- transform(indexValue,date=rdate2int(as.Date(DATETIME)),
                          valtype=ifelse(valtype=='PE_TTM','PE','PB'),
                          caltype='median')
  indexValue <- left_join(indexValue,indexDate[,c('indexID','indexName')])
  indexValue <- indexValue[,c("indexID","indexName","date","value","valtype","caltype")]
  return(indexValue)
}


#' lcdb.update.QT_IndexValuation
#'
#' @rdname index_valuation
#' @author Andrew Dow
#' @examples
#' lcdb.update.QT_IndexValuation()
#' @export
lcdb.update.QT_IndexValuation<- function(begT,endT=Sys.Date()-1){
  con <- db.local('main')
  if(missing(begT)){
    begT <- dbGetQuery(con,"select max(date) 'date' from QT_IndexValuation")
    begT <- trday.nearby(intdate2r(begT$date),by=1)
  }

  if(begT<=endT){
    qr <- paste("delete from QT_IndexValuation where date>=",rdate2int(begT)," and date<=",rdate2int(endT))
    dbSendQuery(con,qr)

    indexDate <- dbGetQuery(con,"select distinct indexID,indexName from QT_IndexValuation")
    indexDate <- transform(indexDate,begT=begT,endT=endT)
    indexDateA <- indexDate[!(stringr::str_sub(indexDate$indexID,-3,-1) %in% c('.GI','.HI')),]
    indexDateF <- indexDate[stringr::str_sub(indexDate$indexID,-3,-1) %in% c('.GI','.HI'),]
    re <- QT_IndexValuation_subfun(indexDateA)
    if(begT!=Sys.Date() || endT!=Sys.Date()){
      reF <- QT_IndexValuation_subfunF(indexDateF)
      re <- rbind(re,reF)
    }

    dbWriteTable(con,'QT_IndexValuation',re,overwrite=FALSE,append=TRUE,row.names=FALSE)
  }
  dbDisconnect(con)
  return('Done!')
}

#' lcdb.build.QT_IndexValuation_SW
#'
#' @rdname index_valuation
#' @author Andrew Dow
#' @examples
#' lcdb.build.QT_IndexValuation_SW()
#' @export
lcdb.build.QT_IndexValuation_SW <- function(endT=as.Date('2017-12-31')){
  require(WindR)
  w.start(showmenu = FALSE)
  indexID <- w.wset('sectorconstituent',date=endT,'sectorid=a39901011g000000')[[2]]
  indexID <- indexID %>% select(wind_code,sec_name)

  indexvalue <- data.frame()
  for(i in 1:nrow(indexID)){
    indexvalue_<-w.wsd(indexID$wind_code[i],"pe_ttm,pb_lf","2005-01-04",endT)[[2]]
    indexvalue_ <- indexvalue_ %>% mutate(id=indexID$wind_code[i],name=indexID$sec_name[i]) %>%
      rename(date=DATETIME,indexID=id,indexName=name) %>% select(date,indexID,indexName,everything())
    indexvalue <- rbind(indexvalue,indexvalue_)
  }
  indexvalue <- indexvalue %>% filter(!is.nan(PE_TTM)) %>% filter(!is.nan(PB_LF)) %>%
    mutate(date=rdate2int(date))

  con <- db.local('main')
  dbWriteTable(con,'QT_IndexValuation_SW',indexvalue,row.names=FALSE)
  dbDisconnect(con)
  return('Done!')
}

#' lcdb.update.QT_IndexValuation_SW
#'
#' @rdname index_valuation
#' @author Andrew Dow
#' @examples
#' lcdb.update.QT_IndexValuation_SW()
#' @export
lcdb.update.QT_IndexValuation_SW <- function(begT,endT=Sys.Date()-1){
  con <- db.local('main')
  if(missing(begT)){
    begT <- dbGetQuery(con,"select max(date) 'date' from QT_IndexValuation_SW")
    begT <- trday.nearby(intdate2r(begT$date),by=1)
  }

  if(begT<=endT){
    require(WindR)
    w.start(showmenu = FALSE)
    indexID <- w.wset('sectorconstituent',date=endT,'sectorid=a39901011g000000')[[2]]
    indexID <- indexID %>% select(wind_code,sec_name)

    indexvalue <- data.frame()
    for(i in 1:nrow(indexID)){
      indexvalue_<-w.wsd(indexID$wind_code[i],"pe_ttm,pb_lf",begT,endT)[[2]]
      indexvalue_ <- indexvalue_ %>% mutate(id=indexID$wind_code[i],name=indexID$sec_name[i]) %>%
        rename(date=DATETIME,indexID=id,indexName=name) %>% select(date,indexID,indexName,everything())
      indexvalue <- rbind(indexvalue,indexvalue_)
    }
    indexvalue <- indexvalue %>% filter(!is.nan(PE_TTM)) %>% filter(!is.nan(PB_LF)) %>%
      mutate(date=rdate2int(date))

    dbWriteTable(con,'QT_IndexValuation_SW',indexvalue,overwrite=FALSE,append=TRUE,row.names=FALSE)
  }
  dbDisconnect(con)
  return('Done!')
}




#' @rdname index_valuation
#' @export
#' @examples
#' re <- getIndexValuation()
#' #get newest valuation
#' re <- getIndexValuation(begT = Sys.Date(),endT = Sys.Date())
getIndexValuation <- function(valtype=c('PE','PB'),caltype='median',
                  begT=as.Date('2001-01-04'),endT=Sys.Date()-1){

  if(begT==Sys.Date() && endT==Sys.Date()){
    lcdb.update.QT_IndexValuation(begT,endT)
  }

  con <- db.local('main')
  qr <- paste("select * from QT_IndexValuation where date<=",rdate2int(endT),
              " and valtype in",brkQT(valtype)," and caltype in",brkQT(caltype),sep="")
  re <- dbGetQuery(con,qr)
  re <- re %>% mutate(date=intdate2r(date),value=round(value,digits = 2)) %>% tidyr::unite(type,valtype,caltype)
  Nindex <- unique(re[,c('indexID','indexName')])
  re <- reshape2::dcast(re,date+indexID+indexName~type,value.var = 'value')
  re <- dplyr::arrange(re,indexID,date)

  result <- data.frame()
  for(i in 1:nrow(Nindex)){
    Data <- re %>% dplyr::filter(indexID==Nindex$indexID[i]) %>% dplyr::select(-indexID,-indexName)

    for(j in 2:ncol(Data)){
      Datats <- xts::xts(Data[,j],order.by = Data[,1])
      Datats <- TTR::runPercentRank(Datats, n = 250, cumulative = TRUE, exact.multiplier = 0.5)
      Datats <-  data.frame(date=zoo::index(Datats),indexID=Nindex$indexID[i],
                            indexName=Nindex$indexName[i],
                            value=round(zoo::coredata(Datats),4),stringsAsFactors = FALSE)
      Datats <- Datats[251:nrow(Datats),]
      colnames(Datats) <- c('date','indexID','indexName',paste('per',colnames(Data)[j],sep = ''))
      if(j==2){
        result_ <- Datats
      }else{
        result_ <- dplyr::left_join(result_,Datats,by=c('date','indexID','indexName'))
      }
    }
    result <- rbind(result,result_)
  }

  result <- result %>% dplyr::filter(date>=begT,date<=endT) %>%
    left_join(re,by=c('date','indexID','indexName')) %>%
    dplyr::arrange(date,indexID)

  if(begT==Sys.Date() && endT==Sys.Date()){
    qr <- paste("delete from QT_IndexValuation where date=",rdate2int(Sys.Date()))
    dbSendQuery(con,qr)
  }
  dbDisconnect(con)
  return(result)
}

#' @rdname index_valuation
#' @export
#' @examples
#' re <- getIndexValuation_SW()
getIndexValuation_SW <- function(begT=as.Date('2001-01-04'),endT=Sys.Date()-1){

  con <- db.local('main')
  qr <- paste("select * from QT_IndexValuation_SW where date<=",rdate2int(endT),
              " and date>= ",rdate2int(begT),sep="")
  re <- dbGetQuery(con,qr)
  dbDisconnect(con)
  re <- re %>% mutate(date=intdate2r(date))
  Nindex <- unique(re[,c('indexID','indexName')])

  result <- data.frame()
  for(i in 1:nrow(Nindex)){
    Data <- re %>% dplyr::filter(indexID==Nindex$indexID[i]) %>% dplyr::select(-indexID,-indexName)

    for(j in 2:ncol(Data)){
      Datats <- xts::xts(Data[,j],order.by = Data[,1])
      Datats <- TTR::runPercentRank(Datats, n = 250, cumulative = TRUE, exact.multiplier = 0.5)
      Datats <-  data.frame(date=zoo::index(Datats),indexID=Nindex$indexID[i],
                            indexName=Nindex$indexName[i],
                            value=round(zoo::coredata(Datats),4),stringsAsFactors = FALSE)
      Datats <- Datats[251:nrow(Datats),]
      colnames(Datats) <- c('date','indexID','indexName',paste('per',colnames(Data)[j],sep = ''))
      if(j==2){
        result_ <- Datats
      }else{
        result_ <- dplyr::left_join(result_,Datats,by=c('date','indexID','indexName'))
      }
    }
    result <- rbind(result,result_)
  }

  result <- result %>% dplyr::filter(date>=begT,date<=endT) %>%
    left_join(re,by=c('date','indexID','indexName')) %>%
    dplyr::arrange(date,desc(perPE_TTM+perPB_LF))

  return(result)
}


#' get_univ_valuation
#'
#' @rdname index_valuation
#' @examples
#' indlist <- CT_industryList(std = 3,level=1)
#' univID <- indlist$IndustryID
#' TSV <- get_univ_valuation(univID)
#' re <- calc_univ_valueper(TSV)
#' @export
get_univ_valuation <- function(univID,begT,endT=Sys.Date()-1,freq='week',
                                valtype=c('PE','PB','eps','bps'),caltype=c('median','total','mean'),rmoutlier=FALSE,rmneg=FALSE,rmST=FALSE){

  valtype <- match.arg(valtype)
  caltype <- match.arg(caltype)

  if(missing(begT)){
    begT <- as.Date('2005-01-04')
  }

  RebDates <- getRebDates(begT,endT,rebFreq = freq)
  TS <- data.frame()
  for(i in 1:length(univID)){
    TS_ <- getTS(RebDates,univID[i])
    TS_ <- TS_ %>% mutate(sector=univID[i])
    TS <- rbind(TS,TS_)
  }

  if(rmST){
    TS <- is_st(TS)
    TS <- TS %>% filter(is_st==FALSE) %>% select(-is_st)
  }

  TS_dis <- distinct(TS,date,stockID)

  if(caltype=='total'){
    tsbasic <- getTech(TS_dis,variables=c("close","total_shares"))
    tsbasic <- tsbasic %>% mutate(total_shares=total_shares/1e4,cap=close*total_shares)
  }

  if(valtype %in% c('PE','PB')){
    if(caltype %in% c('median','mean')){
      #TSF_ <- gf.PE_ttm(TS_,fillna = FALSE)
      if(valtype=='PE'){
        TSF <- gf_lcfs(TS_dis,'F000005')
      }else{
        TSF <- gf_lcfs(TS_dis,'F000006')
      }
      TSF <- TSF %>% mutate(factorscore=1/factorscore)
      TSF <- TS %>% left_join(TSF,by=c('date','stockID')) %>% filter(!is.na(factorscore))
    }else if(caltype=='total'){
      if(valtype=='PE'){
        tslower <- gf.netprofit(TS_dis)
      }else{
        tslower <- gf.netbookvalue(TS_dis)
      }
      tslower <- tslower %>% rename(lower=factorscore) %>% select(-rptDate)
      TSF <- tsbasic %>% select(date,stockID,cap) %>% rename(upper=cap) %>%
        left_join(tslower,by=c('date','stockID'))
      TSF <- TS %>% left_join(TSF,by=c('date','stockID')) %>% filter(!is.na(upper),!is.na(lower))
    }

  }else if(valtype %in% c('eps','bps')){
    if(caltype %in% c('median','mean')){
      if(valtype=='eps'){
        TSF <- gf.eps(TS_dis)
      }else{
        TSF <- gf.bps(TS_dis)
      }
      TSF <- TS %>% left_join(TSF,by=c('date','stockID')) %>% filter(!is.na(factorscore))

    }else if(caltype=='total'){
      if(valtype=='eps'){
        tsupper <- gf.netprofit(TS_dis)
      }else{
        tsupper <- gf.netbookvalue(TS_dis)
      }

      tsupper <- tsupper %>% rename(upper=factorscore) %>% select(-rptDate)
      TSF <- tsbasic %>% select(date,stockID,total_shares) %>% rename(lower=total_shares) %>%
        left_join(tsupper,by=c('date','stockID'))
      TSF <- TS %>% left_join(TSF,by=c('date','stockID')) %>% filter(!is.na(upper),!is.na(lower))
    }

  }

  if(caltype %in% c('median','mean')){
    if(rmoutlier){
      TSF <- factor_outlier(TSF, method = "mad", par = 1.5,sectorAttr = 'existing')
    }

    if(caltype=='median'){
      TSFsum <- TSF %>% group_by(date,sector) %>% summarise(value=median(factorscore,na.rm = TRUE)) %>% ungroup()
    }else if(caltype=='mean'){
      TSFsum <- TSF %>% group_by(date,sector) %>% summarise(value=mean(factorscore,na.rm = TRUE)) %>% ungroup()
    }

  }else if(caltype=='total'){

    if(valtype %in% c('PE','PB') && rmneg){
      TSF <- TSF %>% filter(lower>0)
    }else if(valtype %in% c('eps','bps') && rmneg){
      TSF <- TSF %>% filter(upper>0)
    }
    TSFsum <- TSF %>% group_by(date,sector) %>% summarise(value=sum(upper,na.rm = TRUE)/sum(lower,na.rm = TRUE)) %>% ungroup()
  }


  TSFsum <- data.frame(TSFsum)
  return(TSFsum)
}


#' calc_univ_valueper
#' @rdname index_valuation
#' @export
calc_univ_valueper <- function(TSV,nwin=50,cumula = TRUE){
  require(TTR)
  TSV <- TSV %>% filter(!is.na(value))
  TSV <- reshape2::dcast(TSV,date~sector,value.var = 'value')
  TSVmat <- as.matrix(TSV[,-1])
  result <- apply(TSVmat, 2,runPercentRank,n = nwin, cumulative = cumula, exact.multiplier = 0.5)
  result <- data.frame(date=TSV[,1],result)
  result <- result %>% slice((nwin+1):n())
  result <- reshape2::melt(result,id="date",variable.name="sector",value.name = 'value',factorsAsStrings=FALSE)
  return(result)
}


gf.eps <- function(TS){
  funchar <-  '"factorscore",Last12MData(Rdate,9900000)'
  re <- TS.getFin_by_rptTS(TS,fun="rptTS.getFin_ts",funchar= funchar)
  return(re)
}

gf.bps <- function(TS){
  funchar <-  '"factorscore",Last12MData(Rdate,9900003)'
  re <- TS.getFin_by_rptTS(TS,fun="rptTS.getFin_ts",funchar= funchar)
  return(re)
}

gf.netprofit <- function(TS){
  funchar <-  '"factorscore",Last12MData(Rdate,46033)'
  re <- TS.getFin_by_rptTS(TS,fun="rptTS.getFin_ts",funchar= funchar)
  re$factorscore <- re$factorscore/1e8
  return(re)
}

gf.netbookvalue <- function(TS){
  funchar <-  '"factorscore",Last12MData(Rdate,44111)'
  re <- TS.getFin_by_rptTS(TS,fun="rptTS.getFin_ts",funchar= funchar)
  re$factorscore <- re$factorscore/1e8
  return(re)
}





# ===================== ~ index timing  ====================


#' LLT timing
#'
#'
#' @author Andrew Dow
#' @examples
#' re <- LLT()
#' @export
LLT <- function(indexID='EI000300',begT=as.Date('2005-01-04'),d=60,trancost=0.001,type=c('LLT','SMA')){
  type <- match.arg(type)

  endT <- Sys.Date()-1
  variables <- c("open","close","pct_chg")
  indexQuote <- getIndexQuote(indexID,begT,endT,variables,datasrc="jy")
  indexQuote$stockID <- NULL

  if(type=='LLT'){
    alpha <- 2/(1+d)

    indexQuote$LLT <- c(indexQuote$close[1:2],rep(0,nrow(indexQuote)-2))
    for(i in 3:nrow(indexQuote)){
      indexQuote$LLT[i] <- (alpha-alpha^2/4)* indexQuote$close[i]+
        (alpha^2/2)*indexQuote$close[i-1]-(alpha-3*alpha^2/4)*indexQuote$close[i-2]+
        2*(1-alpha)*indexQuote$LLT[i-1]-(1-alpha)^2*indexQuote$LLT[i-2]
    }
    indexQuote <- indexQuote[d:nrow(indexQuote),]
    rownames(indexQuote) <- seq(1,nrow(indexQuote))

    indexQuote$pos <- c(0)
    indexQuote$signal <- c('')
    indexQuote$tmp <- indexQuote$pct_chg
    for(i in 3:nrow(indexQuote)){
      if(indexQuote$LLT[i-1]>indexQuote$LLT[i-2] && indexQuote$pos[i-1]==0){
        indexQuote$pos[i] <- 1
        indexQuote$tmp[i] <- indexQuote$close[i]/indexQuote$open[i]-1-trancost
      }else if(indexQuote$LLT[i-1]>indexQuote$LLT[i-2] && indexQuote$pos[i-1]==1){
        indexQuote$pos[i] <- 1
      }else if(indexQuote$LLT[i-1]<indexQuote$LLT[i-2] && indexQuote$pos[i-1]==1){
        indexQuote$pos[i] <- 0
        indexQuote$tmp[i] <- indexQuote$open[i]/indexQuote$close[i-1]-1-trancost
      }

      if(indexQuote$LLT[i]>indexQuote$LLT[i-1] && indexQuote$pos[i]==0){
        indexQuote$signal[i] <- 'buy'
      }else if(indexQuote$LLT[i]>indexQuote$LLT[i-1] && indexQuote$pos[i]==1){
        indexQuote$signal[i] <- 'hold'
      }else if(indexQuote$LLT[i]<indexQuote$LLT[i-1] && indexQuote$pos[i]==1){
        indexQuote$signal[i] <- 'sell'
      }

    }

  }else{
    indexQuote$MA <- TTR::SMA(indexQuote$close,d)
    indexQuote <- indexQuote[d:nrow(indexQuote),]
    rownames(indexQuote) <- seq(1,nrow(indexQuote))

    indexQuote$pos <- c(0)
    indexQuote$signal <- c('')
    indexQuote$tmp <- indexQuote$pct_chg
    for(i in 2:nrow(indexQuote)){
      if(indexQuote$close[i-1]>indexQuote$MA[i-1] && indexQuote$pos[i-1]==0){
        indexQuote$pos[i] <- 1
        indexQuote$tmp[i] <- indexQuote$close[i]/indexQuote$open[i]-1-trancost
      }else if(indexQuote$close[i-1]>indexQuote$MA[i-1] && indexQuote$pos[i-1]==1){
        indexQuote$pos[i] <- 1
      }else if(indexQuote$close[i-1]<indexQuote$MA[i-1] && indexQuote$pos[i-1]==1){
        indexQuote$pos[i] <- 0
        indexQuote$tmp[i] <- indexQuote$open[i]/indexQuote$close[i-1]-1-trancost
      }

      if(indexQuote$close[i]>indexQuote$MA[i] && indexQuote$pos[i]==0){
        indexQuote$signal[i] <- 'buy'
      }else if(indexQuote$close[i]>indexQuote$MA[i] && indexQuote$pos[i]==1){
        indexQuote$signal[i] <- 'hold'
      }else if(indexQuote$close[i]<indexQuote$MA[i] && indexQuote$pos[i]==1){
        indexQuote$signal[i] <- 'sell'
      }
    }
  }

  indexQuote$strRtn <- indexQuote$tmp*indexQuote$pos
  indexQuote <- subset(indexQuote,select=-c(pos,tmp))
  return(indexQuote)

}



#' getIndustryMA
#'
#'
#' @author Andrew Dow
#' @examples
#' re <- getIndustryMA(begT=as.Date('2014-01-04'))
#' @export
getIndustryMA <- function(begT=as.Date('2005-01-04'),endT=Sys.Date()-1){
  qr <- "select 'EI'+s.SecuCode 'stockID',c.MS 'industryName'
  from LC_CorrIndexIndustry l,SecuMain s,CT_SystemConst c
  where l.IndustryStandard=24 and s.SecuMarket=83 and s.SecuCode like '80%'
  and l.IndexCode=s.InnerCode and l.IndustryCode=c.DM
  and c.LB=1804 and c.IVALUE=1"
  indexName <- queryAndClose.odbc(db.jy(),qr,stringsAsFactors=FALSE)

  indexQT <- getIndexQuote(indexName$stockID,begT,endT,variables='close',datasrc="jy")
  indexQT <- indexQT %>% arrange(stockID,date) %>% group_by(stockID) %>%
    mutate(MA1=TTR::SMA(close,8),MA2=TTR::SMA(close,13),
           MA3=TTR::SMA(close,21),MA4=TTR::SMA(close,34),
           MA5=TTR::SMA(close,55),MA6=TTR::SMA(close,89),
           MA7=TTR::SMA(close,144),MA8=TTR::SMA(close,233)) %>% ungroup()
  indexQT <- reshape2::melt(indexQT,id=c("stockID","date","close"),
                               variable.name = "MAtype", na.rm = TRUE, value.name = "MAclose")
  indexQT <- indexQT %>% mutate(upMA=ifelse(close>MAclose,1,0)) %>%
    group_by(stockID,date) %>% summarise(n=n(),score=sum(upMA)) %>% ungroup() %>%
    filter(n==max(n)) %>% mutate(stockID=as.character(stockID)) %>%
    left_join(indexName,by='stockID') %>%
    select(date,stockID,industryName,score) %>%
    arrange(date,desc(score))

  return(indexQT)
}


#' index.rotation
#'
#' @examples
#' indexID <-  CT_industryList(33,1)
#' indexID <-  sectorID2indexID(indexID$IndustryID)
#' re <- index.rotation(indexID)
#' @export
index.rotation <- function(indexID=c('EI000016','EI000905','EI000852'),begT=as.Date('2005-01-04'),
                           endT=Sys.Date(),MApara=20,fee=0.001,sell_count=1){

  rawdata <- getIndexQuote(indexID,begT = begT,endT = endT,variables = c('pre_close','open','close','pct_chg'),datasrc = 'jy')

  # fill zz500 rawdata
  if(begT<as.Date("2007-01-15") && 'EI000905' %in% indexID){
    require(WindR)
    w.start(showmenu = FALSE)
    rawdata_ <- w.wsd("000905.SH","pre_close,open,close,pct_chg",begT,as.Date("2007-01-15"))[[2]]
    rawdata_[is.na(rawdata_)] <- NA
    rawdata_ <- rawdata_ %>% mutate(stockID='EI000905',PCT_CHG=PCT_CHG/100) %>% select(stockID,everything())
    colnames(rawdata_) <- colnames(rawdata)
    rawdata <- rawdata[!(rawdata$date<=as.Date("2007-01-15") & rawdata$stockID=='EI000905'),]
    rawdata <- rbind(rawdata,rawdata_)
    rawdata <- dplyr::arrange(rawdata,stockID,date)
  }

  #get MA data
  indexClose <- reshape2::dcast(rawdata,date~stockID,value.var = 'close')
  quoteMA <- apply(indexClose[,-1], 2, TTR::SMA, n=MApara)
  quoteMA <- cbind(data.frame(date=as.Date(indexClose$date)),quoteMA)
  quoteMA <- quoteMA[MApara:nrow(quoteMA),]
  quoteMA <- reshape2::melt(quoteMA,id.vars='date',variable.name='stockID',value.name='MA')
  quote <- dplyr::left_join(quoteMA,rawdata[,c("date","stockID","close")],by=c("date","stockID"))

  #reshape index rtn
  indexrtn <- rawdata %>% dplyr::group_by(stockID) %>%
    dplyr::mutate(next_open=lead(open),pct_chg_buy=close/open-1-fee,
                  pct_chg_sell=next_open/pre_close-1-fee) %>%
    dplyr::ungroup() %>% dplyr::select(-next_open,-open,-pre_close,-close)


  quote <- quote %>% mutate(tag=ifelse(close>MA,1,0),trade='')
  for(j in indexID){
    quote_ <- quote[quote$stockID==j,]
    pos <- 0
    ncount <- 0
    for(i in 2:nrow(quote_)){
      #buy
      if(pos==0 && quote_[i-1,'tag']==1){
        quote_[i,'trade'] <- 'buy'
        pos <- 1
        if(quote_[i,'tag']==0){
          ncount <- 1
        }
        next
      }

      #hold
      if(pos==1 && quote_[i,'tag']==1){
        quote_[i,'trade'] <- 'hold'
        next
      }

      #sell
      if(pos==1 && quote_[i,'tag']==0){
        if(quote_[i-1,'tag']!=0){
          ncount <- 0
        }
        ncount <- ncount+1
        if(ncount==sell_count){
          quote_[i,'trade'] <- 'sell'
          pos <- 0
          ncount <- 0
        }else{
          quote_[i,'trade'] <- 'hold'
        }
      }# sell end
    } # inner for loop end
    quote <- quote[quote$stockID!=j,]
    quote <- rbind(quote,quote_)
  }

  #reduct fee from index return
  indexrtn_adj <- dplyr::left_join(quote,indexrtn,by=c('date','stockID'))
  indexrtn_adj <- transform(indexrtn_adj,pct_chg=ifelse(trade=='buy',pct_chg_buy,ifelse(trade=='sell',pct_chg_sell,pct_chg)))
  indexrtn_adj <- reshape2::dcast(indexrtn_adj,date~stockID,value.var = 'pct_chg')
  indexrtn_adj <- transform(indexrtn_adj,cash=0)

  #get daily wgt
  wgt <- quote %>% mutate(trade=ifelse(trade %in% c('buy','sell','hold'),1,0)) %>% select(date,stockID,trade)
  wgt_index <- wgt %>% arrange(date,stockID) %>% group_by(date) %>%
    mutate(trade=trade/sum(trade)) %>% ungroup()
  wgt_index[is.nan(wgt_index$trade),'trade'] <- 0
  wgt_cash <- wgt_index %>% group_by(date) %>% summarise(trade=1-sum(trade)) %>% ungroup() %>%
    mutate(stockID='cash') %>% select(date,stockID,trade)
  wgt <- rbind(as.data.frame(wgt_index),as.data.frame(wgt_cash))
  wgt <- reshape2::dcast(wgt,date~stockID,value.var = 'trade')
  wgt <- wgt[,colnames(indexrtn_adj)]

  wgt <- transform(wgt,tag=0)
  for(i in 1:nrow(wgt)){
    if(i==1){
      wgt$tag[i] <- 1
    }else{
      if(!all(wgt[i,2:(ncol(wgt)-1)]==wgt[i-1,2:(ncol(wgt)-1)])){
        wgt$tag[i] <- 1
      }
    }
  }
  wgt <- wgt[wgt$tag==1,]
  wgt$tag <- NULL

  wgt <- xts::xts(wgt[,-1],wgt[,1])
  indexrtn_adj <- xts::xts(indexrtn_adj[,-1],order.by = indexrtn_adj[,1])
  #get return
  re <- Return.backtesting(indexrtn_adj,weights = wgt)
  return(re)
}





# ===================== ~ get data  ====================

#' private offering fund
#'
#'
#' get private offering fund daily nav and premium and discount ration info
#' @author Andrew Dow
#' @examples
#' re <- POFund(fundID,begT,endT)
#' @export
POFund <- function(fundID,begT,endT){
  tmp <- brkQT(fundID)
  con <- db.jy()
  qr <- paste("SELECT s.SecuCode+'.OF' 'fundID',s.SecuAbbr 'fundName',
              convert(varchar(8),mf.EndDate,112) 'date',mf.UnitNV 'NAV',q.ClosePrice 'close'
              FROM MF_NetValue mf,SecuMain s,QT_DailyQuote q
              where mf.InnerCode=s.InnerCode and mf.InnerCode=q.InnerCode and mf.EndDate=q.TradingDay
              and mf.EndDate>=",QT(begT)," and mf.EndDate<=",QT(endT),
              " and s.SecuCode in ",tmp," order by s.SecuCode,mf.EndDate")
  fund <- sqlQuery(con,qr)
  fund$pre <- fund$close/fund$NAV-1
  fund$date <- intdate2r(fund$date)
  odbcClose(con)
  return(fund)
}







#' getIndexFuturesSpread
#'
#'
#' @author Andrew Dow
#' @examples
#' re <- getIFSpread()
#' @export
getIFSpread <- function(begT=as.Date('2010-04-16'),endT=Sys.Date()-1){
  qr <- paste("select convert(varchar,t.TradingDay,112) 'date',
              t.ContractCode 'stockID',t.ClosePrice 'close',t.BasisValue 'spread',
              convert(varchar,f.EffectiveDate,112) 'effectiveDate',
              convert(varchar,f.LastTradingDate,112) 'lastTradingDate'
              from Fut_TradingQuote t,Fut_ContractMain f
              where t.ContractInnerCode=f.ContractInnerCode and t.ContractCode like 'I%'
              and t.TradingDay>=",QT(begT),
              " and t.TradingDay<=",QT(endT),
              "ORDER by t.TradingDay,t.ContractCode")
  con <- db.jy()
  IFData <- sqlQuery(con,qr)
  odbcClose(con)
  IFData <- transform(IFData,date=intdate2r(date),
                      effectiveDate=intdate2r(effectiveDate),
                      lastTradingDate=intdate2r(lastTradingDate))
  tmp1 <- IFData[substr(IFData$stockID,3,4)=='0Y',c("date","stockID","close","spread")]
  colnames(tmp1) <- c("dateCon","stockIDCon","closeCon","spreadCon")
  tmp2 <- IFData[substr(IFData$stockID,3,4)!='0Y',c("date","stockID","close","spread","effectiveDate","lastTradingDate")]
  IFData <- cbind(tmp1,tmp2)
  if(sum(IFData$dateCon!=IFData$date)>0 | sum(IFData$closeCon- IFData$close)>1 |
     sum(IFData$spreadCon-IFData$spread)>1) stop('cbind fail!')
  IFData <- IFData[,c("date","stockIDCon","stockID","effectiveDate","lastTradingDate","close","spread")]

  IFData$spreadPct <- IFData$spread/(IFData$close-IFData$spread)
  IFData$spreadPctAna <- sign(IFData$spreadPct)*((1+abs(IFData$spreadPct))^(365/as.numeric(IFData$lastTradingDate- IFData$date))-1)
  IFData[IFData$date==IFData$lastTradingDate,'spreadPctAna'] <- 0
  IFData <- IFData[,c("date","stockIDCon","stockID","effectiveDate","lastTradingDate",
                      "close","spread","spreadPct","spreadPctAna")]
  return(IFData)

}


# ===================== ~ grid trading  ====================

#' grid trading with index futures
#'
#'
#' @author Andrew Dow
#' @examples
#' indexID <- 'EI000905'
#' begT <- as.Date('2015-09-01')
#' endT <- Sys.Date()-1
#' para <- list(total=5e6,initPos=2,posChg=1,bar=0.1,tradeCost=1/1000)
#' re <- gridTrade.IF(indexID,begT,endT,para)
#' @export
gridTrade.IF <- function(indexID,begT,endT=Sys.Date()-1,para){

  getData <- function(indexID,begT,endT){
    if(indexID=='EI000300'){
      tmp <- 'IF1%'
    }else if(indexID=='EI000905'){
      tmp <- 'IC1%'
    }else if(indexID=='EI000016'){
      tmp <- 'IH1%'
    }

    #get index future quote
    qr <- paste("select convert(varchar(10),t.TradingDay,112) 'date',
                t.ContractCode 'stockID',
                convert(varchar(10),c.EffectiveDate,112) 'effectiveDate',
                convert(varchar(10),c.LastTradingDate,112) 'lastTradingDate',
                t.ClosePrice 'close'
                from Fut_TradingQuote t,Fut_ContractMain c
                where t.ContractInnerCode=c.ContractInnerCode and
                t.ContractCode like ",QT(tmp),
                " and t.TradingDay>=",QT(begT)," and t.TradingDay<=",QT(endT),
                " order by t.TradingDay,t.ContractCode")
    con <- db.jy()
    indexData <- sqlQuery(con,qr,stringsAsFactors =F)
    odbcClose(con)
    indexData <- transform(indexData,date=intdate2r(date),effectiveDate=intdate2r(effectiveDate),
                           lastTradingDate=intdate2r(lastTradingDate))
    indexData$lastTradingDate <- trday.nearby(indexData$lastTradingDate,by=-1)

    # keep the next quarter contract
    indexData$tmp <- c(0)
    shiftData <- data.frame()
    for(i in 1:nrow(indexData)){
      if(i==1){
        IF.ID <- indexData$stockID[4]
        IF.lastDay <- indexData$lastTradingDate[4]
      }
      if(indexData$stockID[i]==IF.ID && indexData$date[i]<IF.lastDay){
        indexData$tmp[i] <- 1
      }else if(indexData$stockID[i]==IF.ID && indexData$date[i]==IF.lastDay){
        shiftData <- rbind(shiftData,indexData[i,c("date","stockID","close")])
        tmp <- indexData[indexData$date==indexData$date[i],]
        IF.ID <- tmp$stockID[4]
        IF.lastDay <- tmp$lastTradingDate[4]
      }
    }
    indexData <- indexData[indexData$tmp==1,c("date","stockID","close")]

    #get index quote
    tmp <- getIndexQuote(indexID,begT,endT,variables='close',datasrc="jy")
    tmp$stockID <- NULL
    colnames(tmp) <- c("date","benchClose")

    indexData <- merge(indexData,tmp,by='date',all.x=T)
    alldata <- list(indexData=indexData,shiftData=shiftData)
    return(alldata)
  }


  calcData <- function(indexData,shiftData,para){
    if(substr(indexData$stockID[1],1,2) %in% c('IF','IH')){
      multiplier <- 300
    }else if(substr(indexData$stockID[1],1,2)=='IC'){
      multiplier <- 200
    }

    indexData <- transform(indexData,benchPct=benchClose/indexData$benchClose[1]-1,
                           pos=c(0),mv=c(0),cost=c(0),cash=c(0),rtn=c(0),totalasset=c(0),remark=NA)
    for(i in 1:nrow(indexData)){
      #initial
      if(i==1){
        indexData$pos[i] <-para$initPos
        indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
        indexData$cost[i] <-para$tradeCost*indexData$mv[i]
        indexData$cash[i] <-para$total-indexData$mv[i]-indexData$cost[i]
        indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
        indexData$rtn[i] <- indexData$totalasset[i]/para$total-1
        indexData$remark[i] <-'initial'
        next
      }

      # shift positions
      if(indexData$stockID[i]!=indexData$stockID[i-1]){
        tmp <- subset(shiftData,stockID==indexData$stockID[i-1] & date==indexData$date[i],select=close)
        indexData$pos[i] <-indexData$pos[i-1]
        indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
        indexData$cost[i] <-para$tradeCost*(indexData$mv[i]+indexData$pos[i-1]*tmp$close*multiplier)
        indexData$cash[i] <-indexData$cash[i-1]-indexData$cost[i]+indexData$pos[i-1]*tmp$close*multiplier-indexData$mv[i]
        indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
        indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
        indexData$remark[i] <-'shift'
      }

      #position change
      if(indexData$benchPct[i]>para$bar){
        todayPos <- para$initPos-floor(indexData$benchPct[i]/para$bar)*para$posChg
      }else if(indexData$benchPct[i]<(-1*para$bar)){
        todayPos <- para$initPos+floor(abs(indexData$benchPct[i]/para$bar))*para$posChg
      }else{
        todayPos <- para$initPos
      }

      if(todayPos<indexData$pos[i-1] & indexData$pos[i-1]>0){
        posChg <- min(indexData$pos[i-1]-todayPos,indexData$pos[i-1])
        #subtract position
        if(is.na(indexData$remark[i])){
          indexData$pos[i] <-indexData$pos[i-1]-posChg
          indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
          indexData$cost[i] <-para$tradeCost*posChg*multiplier*indexData$close[i]
          indexData$cash[i] <-indexData$cash[i-1]-indexData$cost[i]+posChg*multiplier*indexData$close[i]
          indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
          indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
          indexData$remark[i] <-'subtract'
        }else{
          #shift position + subtract position
          indexData$pos[i] <-indexData$pos[i]-posChg
          indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
          indexData$cost[i] <-indexData$cost[i]+para$tradeCost*posChg*multiplier*indexData$close[i]
          indexData$cash[i] <-indexData$cash[i-1]-indexData$cost[i]+posChg*multiplier*indexData$close[i]
          indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
          indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
        }
      }else if(todayPos>indexData$pos[i-1] & indexData$cash[i-1]>=indexData$close[i]*multiplier){
        #add position
        posChg <- min(todayPos-indexData$pos[i-1],floor(indexData$cash[i-1]/indexData$close[i]*multiplier))
        if(is.na(indexData$remark[i])){
          indexData$pos[i] <-indexData$pos[i-1]+posChg
          indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
          indexData$cost[i] <-para$tradeCost*posChg*multiplier*indexData$close[i]
          indexData$cash[i] <-indexData$cash[i-1]-indexData$cost[i]-posChg*multiplier*indexData$close[i]
          indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
          indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
          indexData$remark[i] <-'add'
        }else{
          #shift position + add position
          indexData$pos[i] <-indexData$pos[i]+posChg
          indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
          indexData$cost[i] <-indexData$cost[i]+para$tradeCost*posChg*multiplier*indexData$close[i]
          indexData$cash[i] <-indexData$cash[i-1]-indexData$cost[i]-posChg*multiplier*indexData$close[i]
          indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
          indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
        }

      }else{
        #hold position
        if(is.na(indexData$remark[i])){
          indexData$pos[i] <-indexData$pos[i-1]
          indexData$mv[i] <-indexData$pos[i]*indexData$close[i]*multiplier
          indexData$cash[i] <-indexData$cash[i-1]
          indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
          indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
        }else next
      }
    }

    return(indexData)
  }

  allData <- getData(indexID,begT,endT)
  indexData <- allData$indexData
  shiftData <- allData$shiftData

  indexData <- calcData(indexData,shiftData,para)
  indexData <- transform(indexData,benchPct=round(benchPct,digits = 4),
                         rtn=round(rtn,digits = 4))
  indexData <- indexData[,c("date","stockID","close","benchClose","benchPct","pos","mv","rtn","totalasset","remark" )]
  return(indexData)
}




#' grid trading with index fund
#'
#'
#' @author Andrew Dow
#' @examples
#' indexID <- 'EI000905'
#' begT <- as.Date('2015-09-01')
#' endT <- Sys.Date()-1
#' para <- list(total=5e6,initmv=2e6,bar=0.1,mvChg=1e6,tradeCost=1/1000)
#' re <- gridTrade.index(indexID,begT,endT,para)
#' @export
gridTrade.index <- function(indexID,begT,endT=Sys.Date()-1,para){
  getData <- function(indexID,begT,endT){
    #get index quote
    indexData <- getIndexQuote(indexID,begT,endT,'close',datasrc="jy")
    indexData$benchClose <- indexData$close
    indexData$close <- indexData$close/indexData$close[1]
    indexData <- indexData[,c('date','stockID','close','benchClose')]
    return(indexData)
  }

  calcData <- function(indexData,para){
    indexData <- transform(indexData,benchPct=benchClose/indexData$benchClose[1]-1,
                           pos=c(0),mv=c(0),invest=c(0),cost=c(0),cash=c(0),rtn=c(0),totalasset=c(0),remark=NA)
    for(i in 1:nrow(indexData)){
      #initial
      if(i==1){
        indexData$invest[i] <- para$initmv
        indexData$pos[i] <- floor(para$initmv/(indexData$close[i]*100))*100
        indexData$mv[i] <-indexData$pos[i]*indexData$close[i]
        indexData$cost[i] <-indexData$mv[i]*para$tradeCost
        indexData$cash[i] <-para$total-indexData$mv[i]-indexData$cost[i]
        indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
        indexData$remark[i] <-'initial'
        indexData$rtn[i] <- indexData$totalasset[i]/para$total-1
        next
      }

      #position change
      if(indexData$benchPct[i]>para$bar){
        todayInvest <- para$initmv-floor(indexData$benchPct[i]/para$bar)*para$mvChg
      }else if(indexData$benchPct[i]<(-1*para$bar)){
        todayInvest <- para$initmv+floor(abs(indexData$benchPct[i]/para$bar))*para$mvChg
      }else{
        todayInvest <- para$initmv
      }

      if(todayInvest<indexData$invest[i-1] & indexData$mv[i-1]>0){
        #subtract position
        investChg <- min(indexData$invest[i-1]-todayInvest,indexData$mv[i-1])
        indexData$invest[i] <- max(todayInvest,0)
        chgPos <- floor(investChg/(indexData$close[i]*100))*100
        indexData$pos[i] <-indexData$pos[i-1]-chgPos
        indexData$mv[i] <-indexData$pos[i]*indexData$close[i]
        indexData$cost[i] <-chgPos*indexData$close[i]*para$tradeCost
        indexData$cash[i] <-indexData$cash[i-1]-indexData$cost[i]+chgPos*indexData$close[i]
        indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
        indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
        indexData$remark[i] <-'subtract'

      }else if(todayInvest>indexData$invest[i-1] & indexData$cash[i-1]>0){
        #add position
        investChg <- min(todayInvest-indexData$invest[i-1],indexData$cash[i-1])
        indexData$invest[i] <- min(todayInvest,para$total)
        chgPos <- floor(investChg/(indexData$close[i]*100))*100
        indexData$pos[i] <-indexData$pos[i-1]+chgPos
        indexData$mv[i] <-indexData$pos[i]*indexData$close[i]
        indexData$cost[i] <-chgPos*indexData$close[i]*para$tradeCost
        indexData$cash[i] <-indexData$cash[i-1]-chgPos*indexData$close[i]-indexData$cost[i]
        indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
        indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
        indexData$remark[i] <-'add'

      }else{
        #hold position
        indexData$invest[i] <- indexData$invest[i-1]
        indexData$pos[i] <-indexData$pos[i-1]
        indexData$mv[i] <-indexData$pos[i]*indexData$close[i]
        indexData$cash[i] <-indexData$cash[i-1]
        indexData$totalasset[i] <-indexData$mv[i]+indexData$cash[i]
        indexData$rtn[i] <- indexData$totalasset[i]/indexData$totalasset[i-1]-1
      }
    }
    return(indexData)
  }

  indexData <- getData(indexID,begT,endT)
  indexData <- calcData(indexData,para)
  indexData <- transform(indexData,benchPct=round(benchPct,digits = 4),
                         rtn=round(rtn,digits = 4))
  indexData <- indexData[,c("date","stockID","close","benchClose","benchPct","pos","mv","rtn","totalasset","remark")]
  return(indexData)
}




#' resumption stock arbitrage
#'
#'
#' @author Andrew Dow
#' @examples
#' begT <- Sys.Date()-1
#' endT <- Sys.Date()
#' re <- resumeArbitrage(begT,endT)
#' @export
resumeArbitrage <- function(begT,endT){
  get.resume.stock <- function(begT,endT,dayinterval=20,datasource=c('jy','tpan')){
    datasource <- match.arg(datasource)
    if(datasource=='jy'){
      qr <- paste("SELECT 'EQ'+ss.SecuCode 'stockID',ss.SecuAbbr 'stockName',
                  CONVERT(varchar(20),s.SuspendDate,112) 'suspendDate',
                  CONVERT(varchar(20),s.ResumptionDate,112) 'resumeDate'
                  from LC_SuspendResumption s,SecuMain ss
                  where s.ResumptionDate>=",QT(begT),
                  " and s.ResumptionDate<=",QT(endT),
                  " and s.InnerCode=ss.InnerCode and ss.SecuCategory=1")
      con <- db.jy()
      resume.stock <- sqlQuery(con,qr,stringsAsFactors=F)
      odbcClose(con)

      resume.stock$suspendDate <- intdate2r(resume.stock$suspendDate)
      resume.stock$resumeDate <- intdate2r(resume.stock$resumeDate)
      resume.stock$lastSuspendDay <- trday.nearby(resume.stock$resumeDate, by = -1)
      resume.stock <- resume.stock[(resume.stock$resumeDate-resume.stock$suspendDate)>dayinterval,]
    }else{
      tmp.begT <- trday.nearby(begT,by=0)
      dates <- trday.get(begT =tmp.begT, endT = endT)
      dates <- rdate2int(dates)
      txtname <- c(paste("T:/Input/ZS/index/csitfp4fund",dates,"001.txt",sep = ""),
                   paste("T:/Input/ZS/index/csitfp4fund",dates,"002.txt",sep = ""))
      suspendstock <- plyr::ldply(txtname,read.csv, header=FALSE, sep="|",skip = 1, stringsAsFactors=FALSE)
      suspendstock <- subset(suspendstock,V3 %in% c(T,"T"),select=c(V1,V2))
      suspendstock <- suspendstock[substr(suspendstock$V1, 1, 1) %in% c("6","0","3"),]
      colnames(suspendstock) <- c("stockID","suspendDate")
      suspendstock$stockID <- str_c('EQ',suspendstock$stockID)
      suspendstock <- plyr::arrange(suspendstock, suspendDate, stockID)
      result <- data.frame()
      for(i in length(dates):2){
        x <- suspendstock[suspendstock$suspendDate==dates[i],"stockID"]
        y <- suspendstock[suspendstock$suspendDate==dates[i-1],"stockID"]
        stock <- setdiff(y,x)
        if(length(stock)>0){
          tmp <- data.frame(resumeDate=rep(intdate2r(dates[i]),length(stock)),stockID=stock)
          result <- rbind(result,tmp)
        }else next
      }
      tmp <- str_c(str_sub(result$stockID,3,8),collapse = "','")
      tmp <- str_c("('",tmp,"')")

      qr <- paste("SELECT 'EQ'+ss.SecuCode 'stockID',ss.SecuAbbr 'stockName',
                  CONVERT(varchar(20),s.SuspendDate,112) 'suspendDate'
                  from LC_SuspendResumption s,SecuMain ss
                  where  s.InnerCode=ss.InnerCode and
                  (s.ResumptionDate>=",str_c("'",as.character(begT),"'"),
                  " or s.ResumptionDate='1900-01-01')
                  and ss.SecuCategory=1 and ss.SecuCode in",tmp)
      con <- db.jy()
      resume.stock <- sqlQuery(con,qr,stringsAsFactors=F)
      odbcClose(con)
      if(nrow(resume.stock)>0){
        resume.stock$suspendDate <- intdate2r(resume.stock$suspendDate)
        resume.stock <- merge(resume.stock,result,by="stockID")
        resume.stock$lastSuspendDay <- trday.nearby(resume.stock$resumeDate, by = -1)
        resume.stock <- resume.stock[(resume.stock$resumeDate-resume.stock$suspendDate)>dayinterval,]
      }

    }

    return(resume.stock)
  }

  get.fund.info <- function(){
    qr <- "select s.SecuCode 'fundCode',s.SecuAbbr 'fundName','EI'+s1.SecuCode 'indexCode',s1.SecuAbbr 'indexName'
    from MF_InvestTargetCriterion i
    inner join SecuMain s on s.InnerCode=i.InnerCode
    inner join SecuMain s1 on s1.InnerCode=i.TracedIndexCode
    where i.InvestTarget=90 and i.IfExecuted=1 and i.MinimumInvestRatio>=0.9
    and i.InnerCode in(
    select f.InnerCode
    from MF_FundArchives f,SecuMain s
    where f.Type=3 and f.InnerCode=s.InnerCode
    and f.ListedDate is not NULL and f.ExpireDate is NULL
    and f.FundTypeCode='1101' and f.InvestmentType=7 and s.SecuCode not like '%J'
    )"
    con <- db.jy()
    lof.info <- sqlQuery(con,qr)
    odbcClose(con)
    lof.info$type <- c("LOF")

    sf.info <- dbReadTable(db.local('main'), "SF_Info")

    fund.info <- sf.info[,c("MCode","MName","IndexCode","IndexName")]
    fund.info$MCode <- substr(fund.info$MCode,1,6)
    fund.info$IndexCode <- substr(fund.info$IndexCode,1,6)
    fund.info$IndexCode <- paste('EI',fund.info$IndexCode,sep="")
    fund.info$type <- c("SF")
    colnames(fund.info) <- colnames(lof.info)
    fund.info <- rbind(fund.info,lof.info)

    return(fund.info)
  }

  get.index.component <- function(stock,index,date){
    stock <- brkQT(substr(stock,3,8))
    index <- brkQT(substr(index,3,8))
    qr <- paste("select  'EI'+s1.SecuCode 'indexID',s1.SecuAbbr 'indexName',
                'EQ'+s2.SecuCode 'stockID',s2.SecuAbbr 'stockName',
                CONVERT(varchar(20),i.EndDate,112) 'enddate',
                i.Weight,CONVERT(varchar(20),i.UpdateTime,112) 'update'
                from LC_IndexComponentsWeight i
                left join SecuMain s1 on i.IndexCode=s1.InnerCode
                left join SecuMain s2 on i.InnerCode=s2.InnerCode
                where i.InnerCode in (select InnerCode from SecuMain where SecuCode in ",stock," and SecuCategory=1)
                and i.IndexCode in (SELECT InnerCode from SecuMain where SecuCode in ",index,"and SecuCategory=4)",
                " and i.EndDate>=",QT(date))
    con <- db.jy()
    index.component <- sqlQuery(con,qr)
    odbcClose(con)
    if(nrow(index.component)>0){
      index.component$enddate <- intdate2r(index.component$enddate)
      return(index.component)
    }else{
      print('No qualified stock in these index!')
    }
  }

  get.stock.industry <- function(stock){
    stock <- brkQT(substr(stock,3,8))
    qr <- paste("(select 'EQ'+b.SecuCode 'stockID',e.SecuCode 'sectorID',e.SecuAbbr 'sectorName'
                from LC_ExgIndustry as a
                inner join SecuMain as b on a.CompanyCode = b.CompanyCode
                inner join CT_SystemConst as c on a.SecondIndustryCode = c.CVALUE
                inner join LC_CorrIndexIndustry as d on c.DM = d.IndustryCode
                INNER join SecuMain as e on d.IndexCode = e.InnerCode
                where a.Standard = 23 and a.IfPerformed = 1 and b.SecuCode in ",stock,
                " and b.SecuCategory = 1 and c.LB = 1755 and d.IndustryStandard = 23)
                union
                (select 'EQ'+b.SecuCode 'stockID',e.SecuCode 'sectorID',e.SecuAbbr 'sectorName'
                from LC_ExgIndustry as a
                inner join SecuMain as b on a.CompanyCode = b.CompanyCode
                inner join CT_SystemConst as c on a.FirstIndustryCode = c.CVALUE
                inner join LC_CorrIndexIndustry as d on c.DM = d.IndustryCode
                INNER join SecuMain as e on d.IndexCode = e.InnerCode
                where a.Standard = 23 and a.IfPerformed = 1 and b.SecuCode in ",stock,
                " and b.SecuCategory = 1 and c.LB = 1755 and d.IndustryStandard = 23)")
    con <- db.jy()
    stock.industry <- sqlQuery(con,qr)
    odbcClose(con)
    return(stock.industry)
  }

  get.industry.quote <- function(industry,begday){
    industry <- brkQT(industry)
    qr <- paste("SELECT s.SecuCode 'sectorID',CONVERT(varchar(8),q.TradingDay,112) 'date',
                q.ClosePrice 'close'
                FROM QT_IndexQuote q,SecuMain s
                where q.InnerCode=s.InnerCode and q.TradingDay>=",QT(begday),
                " and s.SecuCategory=4 and s.SecuCode in ",industry,
                " order by s.SecuCode,q.TradingDay")
    con <- db.jy()
    index.quote <- sqlQuery(con,qr)
    odbcClose(con)
    index.quote$date <- intdate2r(index.quote$date)
    return(index.quote)
  }

  calc.match.industrypct <- function(resume.stock,index.quote){
    colnames(index.quote) <- c("sectorID","suspendDate","close1" )
    resume.stock <- merge(resume.stock,index.quote,by=c('sectorID','suspendDate'),all.x = T)
    colnames(index.quote) <- c("sectorID","lastSuspendDay","close2" )
    resume.stock <- merge(resume.stock,index.quote,by=c('sectorID','lastSuspendDay'),all.x = T)
    resume.stock$IndustryPct <- resume.stock$close2/resume.stock$close1-1
    resume.stock <- resume.stock[abs(resume.stock$IndustryPct)>=0.1,]

    if(nrow(resume.stock)>0){
      resume.stock <- resume.stock[,c("stockID","stockName","suspendDate", "resumeDate",
                                      "lastSuspendDay","sectorID","sectorName","IndustryPct")]
      return(resume.stock)
    }else{
      print('No valuation adjustment!')
    }


  }

  calc.match.indexcomponent <- function(resume.stock,index.component,bar=2){
    result <- data.frame()
    for(i in 1:nrow(resume.stock)){
      tmp.result <- resume.stock[i,]
      tmp.index.component <- index.component[index.component$stockID==resume.stock$stockID[i],]
      if(length(unique(tmp.index.component$indexID))>1){
        for(j in unique(tmp.index.component$indexID)){
          tmp <- tmp.index.component[tmp.index.component$indexID==j,]
          tmp <- arrange(tmp,enddate)
          ind <- findInterval(resume.stock[i,"suspendDate"],tmp$enddate)
          if(ind==0 || max(tmp$enddate)<resume.stock[i,"suspendDate"]) next
          tmp.result$inindex <- tmp$indexID[ind]
          tmp.result$inindexname <- tmp$indexName[ind]
          tmp.result$wgtinindex <- tmp$Weight[ind]
          result <- rbind(result,tmp.result)
        }
      }else{
        tmp <- tmp.index.component
        tmp <- arrange(tmp,enddate)
        ind <- findInterval(resume.stock[i,"suspendDate"],tmp$enddate)
        if(ind==0 || max(tmp$enddate)<resume.stock[i,"suspendDate"]) next
        tmp.result$inindex <- tmp$indexID[ind]
        tmp.result$inindexname <- tmp$indexName[ind]
        tmp.result$wgtinindex <- tmp$Weight[ind]
        result <- rbind(result,tmp.result)
      }
    }
    result <- result[result$wgtinindex>=bar,]
    if(nrow(result)>0) return(result)
    else print("No qualified index!")
  }

  calc.match.fundunit <- function(fund.result){
    tmp.sfcode <- unique(fund.result$fundCode[fund.result$type=='SF'])
    tmp.sfcode <- paste(tmp.sfcode,'.OF',sep='')
    tmp.lofcode <- unique(fund.result$fundCode[fund.result$type=='LOF'])
    tmp.begT <- min(fund.result$suspendDate)
    fund.size <- data.frame()
    if(length(tmp.sfcode)>0){
      tmp <- brkQT(tmp.sfcode)
      qr <- paste("select t.MCode,i.MName,t.Date,
                  (t.MUnit*t.MNav+ t.AUnit*t.ANav + t.BUnit*t.BNav) 'Unit'
                  from SF_TimeSeries t,SF_Info i
                  where t.MCode=i.MCode and t.MCode in",tmp,
                  "and t.Date>=",rdate2int(tmp.begT))
      con <- db.local('main')
      sf.size <- dbGetQuery(con,qr)
      dbDisconnect(con)
      colnames(sf.size) <- c("Code","Name","Date","Unit")
      sf.size$Code <- substr(sf.size$Code,1,6)
      fund.size <-rbind(fund.size,sf.size)
    }

    if(length(tmp.lofcode)>0){
      tmp <- brkQT(tmp.lofcode)
      qr <- paste("select s.SecuCode,s.SecuAbbr,CONVERT(varchar(8),m.EndDate,112) 'EndDate',m.FloatShares/100000000 'Unit'
                  from MF_SharesChange m,SecuMain s
                  where m.InnerCode=s.InnerCode and s.SecuCode in",tmp,
                  " and m.StatPeriod='996' and m.EndDate>=",
                  QT(tmp.begT),
                  " order by s.SecuCode,m.EndDate")
      con <- db.jy()
      lof.size <- sqlQuery(con,qr)
      odbcClose(con)
      colnames(lof.size) <- c("Code","Name","Date","Unit")
      fund.size <-rbind(fund.size,lof.size)
    }
    fund.size$Date <- intdate2r(fund.size$Date)

    fund.result$OldUnit <- c(0)
    fund.result$NewUnit <- c(0)
    for(i in 1:nrow(fund.result)){
      tmp <- fund.size[fund.size$Code==fund.result$fundCode[i] & !is.na(fund.size$Unit),]
      tmp <- arrange(tmp,Date)
      if(tmp$Date[1]>fund.result$suspendDate[i]) fund.result$OldUnit[i] <- tmp$Unit[1]
      else fund.result$OldUnit[i] <- tmp$Unit[tmp$Date==fund.result$suspendDate[i]]
      fund.result$NewUnit[i] <- tmp$Unit[nrow(tmp)]
    }

    fund.result$UnitPct <- as.numeric(fund.result$NewUnit)/as.numeric(fund.result$OldUnit)-1
    fund.result$newWeight <- fund.result$wgtinindex*fund.result$OldUnit/fund.result$NewUnit
    fund.result <- fund.result[fund.result$newWeight>=5 & fund.result$NewUnit>0.5,]
    if(nrow(fund.result)>0){
      fund.result <- fund.result[,c("fundCode","fundName","type",
                                    "stockName","wgtinindex","suspendDate","resumeDate",
                                    "sectorName","IndustryPct","OldUnit","NewUnit",'newWeight')]
      fund.result <- arrange(fund.result,desc(newWeight))
      return(fund.result)
    }else{
      print("No qualified stock!")
    }

  }


  resume.stock <- get.resume.stock(begT,endT) #get qualified resumption stock
  if(nrow(resume.stock)==0) return("None!")

  fund.info <- get.fund.info() #get all lof and structure fund basic info

  #get resumption stock in the traced index of these lof and sf
  tmp.index <- toupper(unique(fund.info$indexCode))
  tmp.date <- trday.offset(min(resume.stock$suspendDate), by = months(1))
  index.component <- get.index.component(resume.stock$stockID,tmp.index,tmp.date)
  if(is.character(index.component)) return("None!")

  #get stock's amac industy and the industry's corresponding index quote
  resume.stock <- resume.stock[resume.stock$stockID %in% index.component$stockID,]
  stock.industry <- get.stock.industry(resume.stock$stockID)
  resume.stock <- merge(resume.stock,stock.industry,by='stockID')
  index.quote <- get.industry.quote(industry = resume.stock$sectorID,begday = min(resume.stock$suspendDate))

  #calculate stock's industry change pct during suspend time
  resume.stock <- calc.match.industrypct(resume.stock,index.quote)
  if(is.character(resume.stock)) return("None!")
  #
  resume.stock <- calc.match.indexcomponent(resume.stock,index.component)
  if(is.character(resume.stock)) return("None!")


  # get the final result
  fund.info <- fund.info[fund.info$indexCode %in% resume.stock$inindex,]
  fund.result <- merge(fund.info,resume.stock,by.x='indexCode',by.y = 'inindex',all.x =T)
  fund.result <- arrange(fund.result,fundCode)
  fund.result <- fund.result[,c("fundCode","fundName","indexCode","indexName","type","stockID","stockName",
                                "wgtinindex","suspendDate","resumeDate","lastSuspendDay",
                                "sectorID","sectorName","IndustryPct")]
  fund.result <- calc.match.fundunit(fund.result)

  return(fund.result)

}







# ===================== xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ======================
# ===================== series of ultility functions  ===========================
# ===================== xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ======================


#' read from or write to clipboard
#'
#' @description \code{read.clipboard} read data from clipboard
#' @description \code{write.clipboard} write data to clipboard
#' @name read_write_clipboard
#' @rdname read_write_clipboard
#'
#' @export
#' @examples
#' re <- read.clipboard()
#' write.clipboard(re)
read.clipboard <- function(file = "clipboard", sep = "\t",header = TRUE,...) {
  read.table(file = file, sep = sep, header=header,...)
}

#' @rdname read_write_clipboard
#' @export
write.clipboard <- function(x,row.names=FALSE,col.names=TRUE,...) {
  write.table(x,"clipboard-16384",sep="\t",row.names=row.names,col.names=col.names,...)
}

#' xts2df
#'
#' turn xts to dataframe
#' @export
xts2df <- function(x) {
  df <- data.frame(date=zoo::index(x),zoo::coredata(x))
  return(df)
}


#' connect tinysoft database
#'
#'
#' @author Andrew Dow
#' @return a tinysoft conn.
#' @examples
#' qr <- "setsysparam(pn_stock(),'SZ000002');
#' setsysparam(pn_date(), today()); return nday(30,'date'
#' ,datetimetostr(sp_time()), 'open',open(), 'close',close());"
#' re <- sqlQuery(db.ts(), qr);
#' @export
db.ts <- function(){
  odbcConnect("tinysoftdb")
}



#' lcdb.update.CorpStockPool
#'
#' @param filenames a vector of filename with path.
#' @examples
#' filenames <- c('D:/sqlitedb/core.csv','D:/sqlitedb/preclose.csv')
#' lcdb.update.CorpStockPool(filenames)
#' @export
lcdb.update.CorpStockPool <- function(filenames){
  all <- data.frame()
  for(i in 1:length(filenames)){
    tmp <- read.csv(filenames[i])
    all <- rbind(all,tmp)
  }
  colnames(all) <- c('stockID','stockName',"MiscellaneousItem",'SecuMarket','FundBelong','CorpStockPool',
                     'InvestAdviceNum','DimensionID','DimensionName','Remark','Operator','AddDate','AddTime',
                     'CheckOperator','HavePosition','ValidBeginDate','ValidEndDate','SecurityCate')
  all$stockID <- stringr::str_pad(all$stockID,6,pad = '0')
  all$stockID <- stringr::str_c('EQ',all$stockID,sep = '')
  con <- db.local('main')
  dbWriteTable(con,'CT_CorpStockPool',all,overwrite=T,row.names=F)
  dbDisconnect(con)
}


#' combine rtn.periods and rtn.summary
#'
#' @param rtn an xts, vector, matrix, data frame, timeSeries or zoo object of asset returns
#' @param freq An interval specification, one of "day", "week", "month", "quarter" and "year", optionally preceded by an integer and a space, or followed by "s".See \code{\link{cut.Date}} for detail.
#' @param Rf risk free rate, in same period as your returns
#' @return a matrix, giving the summary infomation of the rtn series,including Annualized Return,Annualized Std Dev,Annualized Sharpe,HitRatio,Worst Drawdown
#' @seealso \code{\link[QUtility]{rtn.periods}}
#' @seealso \code{\link[QUtility]{rtn.summary}}
#' @examples
#' rtn <- rtndemo
#' rtn <- xts::xts(rtn[,-1],rtn[,1])
#' rtn.persum(rtn)
#' @export
rtn.persum <- function(rtn,freq="year",Rf=0,showPer=T){

  from <- unique(cut.Date2(zoo::index(rtn),freq,lab.side="begin"))
  to <- unique(cut.Date2(zoo::index(rtn),freq,lab.side="end"))

  rtn <- zoo::as.zoo(rtn)
  # ---- periods cumulative rtn
  table.periods <- timeSeries::fapply(timeSeries::as.timeSeries(rtn),from,to,FUN=PerformanceAnalytics::Return.cumulative)
  table.periods <- as.matrix(table.periods)
  rownames(table.periods) <- paste(from,to,sep=" ~ ")
  # ---- overall cumulative rtn and annnualized rtn
  table.overall <- PerformanceAnalytics::Return.cumulative(rtn)

  rtn <- xts::as.xts(rtn)
  annual <- as.matrix(Table.Annualized(rtn,Rf=Rf))

  maxDD <- PerformanceAnalytics::maxDrawdown(rtn)
  dim(maxDD) <- c(1, NCOL(rtn))
  colnames(maxDD) <- colnames(rtn)
  rownames(maxDD) <- "Worst Drawdown"
  result <- rbind(table.periods,table.overall,annual,maxDD)
  result <- as.data.frame(result)
  if(showPer==T){
    for(i in 1:ncol(result)){
      result[,i] <- paste(round(result[,i],3)*100,'%',sep='')
    }
  }

  return(result)

}


#' percent
#'
#' Percent formatter: multiply by one hundred and display percent sign.
#' @param x a numeric vector to format
#' @return a function with single parameter x, a numeric vector, that returns a character vector
#' @seealso \code{\link[scales]{percent}}
#' @examples
#' x <- c(-1, 0, 0.1, 0.555555, 1, 100)
#' percent(x)
#' @export
percent <- function(x, digits = 2, format = "f", ...) {
  paste0(formatC(100 * x, format = format, digits = digits, ...), "%")
}


#' getIndexBasicInfo
#'
#'
#' @param indexID is set of index ID.
#' @examples
#' index <- getIndexBasicInfo('EI000300')
#' index <- getIndexBasicInfo(c('EI000300','EI000905'))
#' @export
getIndexBasicInfo <- function(indexID) {
  tmp <- brkQT(substr(indexID,3,8))
  qr <- paste("SELECT 'EI'+s.SecuCode 'SecuCode'
              ,s.SecuAbbr
              ,ct1.MS 'IndexType'
              ,ct2.MS 'IndustryStandard'
              ,[PubOrgName]
              ,CONVERT(VARCHAR,PubDate,112) 'PubDate'
              ,CONVERT(VARCHAR,BaseDate,112) 'BaseDate'
              ,BasePoint
              ,ct3.MS 'WAMethod'
              ,ComponentSum
              ,ct3.MS 'ComponentAdPeriod'
              ,EndDate
              ,CONVERT(VARCHAR,l.XGRQ,112) 'XGRQ'
              FROM LC_IndexBasicInfo l
              left join SecuMain s on l.IndexCode=s.InnerCode
              left join CT_SystemConst ct1 on ct1.LB=1266 and l.IndexType=ct1.DM
              left join CT_SystemConst ct2 on ct2.LB=1081 and l.IndustryStandard=ct2.DM
              left join CT_SystemConst ct3 on ct3.LB=1265 and l.WAMethod=ct3.DM
              left join CT_SystemConst ct4 on ct4.LB=1264 and l.ComponentAdPeriod=ct4.DM
              where s.SecuCode in",tmp)
  re <- queryAndClose.odbc(db.jy(),qr)
  return(re)
}

# ===================== ~ convertible bond  ====================

#' lcdb.build.Bond_ConBDExchangeQuote
#'
#' @name cbondfuns
#' @export
#' @examples
#' lcdb.build.Bond_ConBDExchangeQuote()
#' lcdb.update.Bond_ConBDExchangeQuote()
lcdb.build.Bond_ConBDExchangeQuote <- function(){
  qr <- "select convert(varchar,cb.TradingDay,112) 'date',
  case c.SecuMarket
  when 83 then c.SecuCode+'.SH'
  when 90 then c.SecuCode+'.SZ'
  END 'bondID',c.SecuAbbr 'bondName',
  cb.BondNature,cb.Maturity,cb.YrMat,cb.ClosePrice,cb.ChangePCT,cb.TurnoverRate,cb.TurnoverValue
  ,cb.NewConvetPrice,cb.StockPrice,cb.ConvertPremiumRate
  from Bond_ConBDExchangeQuote cb
  INNER JOIN Bond_Code c on cb.InnerCode=c.InnerCode and c.BondNature in(10,29)
  where cb.TradingDay>='2005-01-01' and cb.YrMat is not NULL
  and cb.BondNature in(1,4)
  order by cb.TradingDay,c.SecuCode"
  cvbond <- queryAndClose.odbc(db.jy(),qr,stringsAsFactors =FALSE)

  require(WindR)
  w.start(showmenu = FALSE)

  #fix bugs to do
  cvbugs <- cvbond %>% filter(is.na(ConvertPremiumRate))
  if(nrow(cvbugs)>0){
    cvbugsbond <- cvbugs %>% group_by(bondID) %>%
      summarise(begT=intdate2r(min(date)),endT=intdate2r(max(date)))
    ConvetPrice <- data.frame(stringsAsFactors = FALSE)
    for(i in 1:nrow(cvbugsbond)){
      ConvetPrice_ <- w.wsd(cvbugsbond$bondID[i],'clause_conversion2_swapshareprice',cvbugsbond$begT[i],cvbugsbond$endT[i])[[2]]
      ConvetPrice_ <- ConvetPrice_ %>% mutate(bondID=as.character(cvbugsbond$bondID[i]),DATETIME=rdate2int(DATETIME)) %>%
        rename(date=DATETIME,NewConvetPrice=CLAUSE_CONVERSION2_SWAPSHAREPRICE) %>%
        select(date,bondID,NewConvetPrice)
      ConvetPrice <- rbind(ConvetPrice,ConvetPrice_)
    }
    cvbugs <- cvbugs %>% select(-NewConvetPrice) %>%
      left_join(ConvetPrice,by=c('date','bondID')) %>%
      mutate(ConvertPremiumRate=(ClosePrice/(StockPrice/NewConvetPrice*100)-1)*100)
    cvbugs <- cvbugs[,colnames(cvbond)]
    cvbond <- cvbond %>% filter(!is.na(ConvertPremiumRate)) %>%
      bind_rows(cvbugs) %>% arrange(date,bondID)

  }

  #add data
  cvstat <- cvbond %>% group_by(bondID) %>% summarise(begT=min(date),endT=max(date)) %>%
    ungroup() %>% mutate(begT=intdate2r(begT),endT=intdate2r(endT))
  strbvalue <- data.frame()

  for(i in 1:nrow(cvstat)){
    data <- w.wsd(cvstat$bondID[i],"strbvalue",cvstat$begT[i],cvstat$endT[i])[[2]]
    data <- rename(data,date=DATETIME,strbvalue=STRBVALUE)
    data <- cbind(data.frame(bondID=cvstat$bondID[i],row.names = NULL,stringsAsFactors = FALSE),data)
    strbvalue <- rbind(strbvalue,data)
  }
  strbvalue <- transform(strbvalue,date=rdate2int(date))
  cvbond <- left_join(cvbond,strbvalue,by=c('date','bondID'))
  cvbond <- transform(cvbond,strbPremiumRate=(ClosePrice/strbvalue-1)*100)
  con <- db.local('main')
  if(dbExistsTable(con,"Bond_ConBDExchangeQuote")){
    dbRemoveTable(con,"Bond_ConBDExchangeQuote")
  }
  dbWriteTable(con,'Bond_ConBDExchangeQuote',cvbond)
  dbDisconnect(con)
}


#' lcdb.update.Bond_ConBDExchangeQuote
#'
#' @rdname cbondfuns
#' @export
lcdb.update.Bond_ConBDExchangeQuote <- function(){
  con <- db.local('main')
  begT <- dbGetQuery(con,"select max(date) from Bond_ConBDExchangeQuote")[[1]]
  begT <- intdate2r(begT)
  endT <- trday.nearest(Sys.Date()-1)
  if(endT>begT){
    qr <- paste("select convert(varchar,cb.TradingDay,112) 'date',
                case c.SecuMarket
                when 83 then c.SecuCode+'.SH'
                when 90 then c.SecuCode+'.SZ'
                END 'bondID',c.SecuAbbr 'bondName',
                cb.BondNature,cb.Maturity,cb.YrMat,cb.ClosePrice,cb.ChangePCT,cb.TurnoverRate,cb.TurnoverValue
                ,cb.NewConvetPrice,cb.StockPrice,cb.ConvertPremiumRate
                from Bond_ConBDExchangeQuote cb
                INNER JOIN Bond_Code c on cb.InnerCode=c.InnerCode
                and c.BondNature in(10,29)
                where cb.TradingDay>",QT(begT)," and cb.TradingDay<=",QT(endT)," and cb.YrMat is not NULL
                order by cb.TradingDay,c.SecuCode")
    cvbond <- queryAndClose.odbc(db.jy(),qr)

    cvstat <- cvbond %>% filter(BondNature %in% c(1,4)) %>% mutate(date=intdate2r(date)) %>% select(date,bondID)
    dates <- unique(cvstat$date)
    strbvalue <- data.frame()
    require(WindR)
    w.start(showmenu = FALSE)
    for(i in 1:length(dates)){
      cvstat_ <- cvstat %>% filter(date==dates[i])
      data <- w.wss(cvstat_$bondID,'strbvalue',tradeDate=dates[i])[[2]]
      data <- rename(data,bondID=CODE,strbvalue=STRBVALUE)
      data <- cbind(data.frame(date=dates[i],row.names = NULL),data)
      strbvalue <- rbind(strbvalue,data)
    }
    strbvalue <- transform(strbvalue,date=rdate2int(date))
    cvbond <- left_join(cvbond,strbvalue,by=c('date','bondID'))
    cvbond <- transform(cvbond,strbPremiumRate=(ClosePrice/strbvalue-1)*100)
    dbWriteTable(con,'Bond_ConBDExchangeQuote',cvbond,overwrite=FALSE,append=TRUE)
    dbDisconnect(con)
  }
}





#' CBprice
#'
#' @rdname cbondfuns
#' @examples
#' CBcode <- c('128026.SZ','113015.SH','113001.SH')
#' @export
CBprice <- function(CBcode,begT,endT,vol=250){
  require(WindR)
  WindR::w.start(showmenu = FALSE)
  require(fOptions)

  cbinfo <- WindR::w.wss(CBcode,'underlyingcode,ipo_date,delist_date,term')[[2]]
  cbinfo <- cbinfo %>% mutate(IPO_DATE=w.asDateTime(IPO_DATE,asdate = TRUE),
                              DELIST_DATE=w.asDateTime(DELIST_DATE,asdate = TRUE))
  if(missing(begT)){
    cbinfo <- cbinfo %>% mutate(begT=IPO_DATE)
  }else{
    cbinfo <- cbinfo %>% mutate(begT=begT) %>%
      mutate(begT=ifelse(begT>=IPO_DATE,begT,IPO_DATE))
  }

  if(missing(endT)){
    cbinfo <- cbinfo %>% mutate(endT=DELIST_DATE)
  }else{
    cbinfo <- cbinfo %>% mutate(endT=endT) %>%
      mutate(endT=ifelse(endT<=DELIST_DATE,endT,DELIST_DATE))
  }
  cbinfo <- cbinfo %>% mutate(endT=ifelse(endT<=Sys.Date(),endT,Sys.Date())) %>%
    mutate(endT=as.Date(endT,origin='1970-01-01'))

  for(i in 1:nrow(cbinfo)){
    cbts_<-WindR::w.wsd(cbinfo$CODE[i],'close,strbvalue,convprice,convvalue,ptmyear,impliedvol',cbinfo$begT[i],cbinfo$endT[i],"rfIndex=1")[[2]]
    #stockts_ <- WindR::w.wsd(cbinfo$UNDERLYINGCODE[i],"close,annualstdevr_100w,annualstdevr_24m",cbinfo$begT[i],cbinfo$endT[i])[[2]]
    TS <- data.frame(date=cbts_$DATETIME,
                     stockID=stockID2stockID(cbinfo$UNDERLYINGCODE[i],'wind','local'),
                     stringsAsFactors = FALSE)


  }


  p <- GBSOption(TypeFlag = "c", S = 10.22, X = 11.74, Time = 5.7260, r = 0.015,
                 b = 0.015, sigma = 0.302862)
  GBSVolatility(price, TypeFlag, S, X, Time, r, b, tol, maxiter)
  p@price*100/11.74+84.12
}
QuantAndrew/quantbox documentation built on May 8, 2019, 3:50 a.m.