Skip to content

Commit

Permalink
Adding VCI
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaKipnis committed Aug 23, 2014
1 parent ba87158 commit 74f20e8
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 12 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ Collate:
'ERM.R'
'DVO.R'
'OHV.R'
'VCI.R'
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export(MSR)
export(ERM)
export(OHV)
export(DVO)
export(VCI)
export(agg.chart.ME)
41 changes: 41 additions & 0 deletions R/VCI.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#'ValueCharts Indicator
#'@description Computes a range-normalized difference between current price and a running moving average.
#'A value below -8 indicates oversold, while a value above 8 indicates overbought.
#'@param OHLC an OHLC time series
#'@param nLookback a moving average window, default 40
#'@param nRange a lookback window for the range computation. A number above
#'7 results in the following computation: take the difference between the nRange
#'max high and min low. Add up that value, that value lagged by nRange+1, nRange*2, nRange*3, and nRange*4,
#'and divide by 25.
#'If nRange is 7 or less, the daily range is instead computed as the 5-day SMA of the following quantity:
#'for each day, take the maximum of the difference between the high and low, or the absolute difference between current and previous close.
#'Multiply that final quantity by .16.
#'@return an OHLC-like 4-column output computing the values given OHLC prices, or a percent rank of the close variant.
#'The column names will be VO, VH, VL, and VC, respectively.
#'@references \url{http://www.tradesignalonline.com/en/lexicon/view.aspx?id=Value+Charts+Indicator}
#'@export
"VCI" <- function(OHLC, nLookback=40, nRange=8, pctRank=FALSE) {
if(nLookback > 7) {
varA <- runMax(Hi(OHLC), nRange) - runMin(Lo(OHLC), nRange)
varB <- lag(varA, nRange+1)
varC <- lag(varA, nRange*2)
varD <- lag(varA, nRange*3)
varE <- lag(varA, nRange*4)
LRange <- (varA+varB+varC+varD+varE)/25
}
if(nLookback <=7) {
absDiff <- abs(diff(Cl(OHLC)))
dailyRange <- Hi(OHLC) - Lo(OHLC)
tmp <- cbind(absDiff, dailyRange)
maxTmp <- pmax(tmp)
LRange <- SMA(maxTmp, 5)*.16
}
hilo <- (Hi(OHLC)+Lo(OHLC))/2
VO <- (Op(OHLC)-SMA(hilo, nLookback))/LRange
VH <- (Hi(OHLC)-SMA(hilo, nLookback))/LRange
VL <- (Lo(OHLC)-SMA(hilo, nLookback))/LRange
VC <- (Cl(OHLC)-SMA(hilo, nLookback))/LRange
out <- cbind(VO=VO, VH=VH, VL=VL, VC=VC)
colnames(out) <- c("VO", "VH", "VL", "VC")
return(out)
}
13 changes: 12 additions & 1 deletion demo/DV2_OHV.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ initDate="1990-01-01"
from="2003-01-01"
to=as.character(Sys.Date())
options(width=70)
verose=TRUE

source("demoData.R")

Expand Down Expand Up @@ -179,3 +178,15 @@ colnames(dailyRetComparison) <- c("strategy", "SPY")
round(apply.yearly(dailyRetComparison, Return.cumulative),3)
round(apply.yearly(dailyRetComparison, SharpeRatio.annualized),3)
round(apply.yearly(dailyRetComparison, maxDrawdown),3)

chart.Posn(portfolio.st, "XLB")
tmp <- DVO(HLC=HLC(XLB), nAvg=nAvg, pctLookback=pctLookback, maType=maType, deTrend=deTrend, nDT=nDT)
add_TA(tmp, col="purple")
tmp <- tmp - tmp + entryThresh
add_TA(tmp, on=5, col="blue", lwd=1.5)
tmp <- tmp - tmp + exitThresh
add_TA(tmp, on=5, col="red", lwd=1.5)
tmp <- OHV(x=Cl(XLB), n1=n1, n2=n2)
add_TA(tmp, col="purple")
tmp <- tmp-tmp+volThresh
add_TA(tmp, on=6, col="blue", lwd=1.5)
24 changes: 14 additions & 10 deletions demo/MSR_I.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ initDate="1990-01-01"
from="2003-01-01"
to=as.character(Sys.Date())
options(width=70)
verose=TRUE

source("demoData.R")

Expand Down Expand Up @@ -80,20 +79,20 @@ updateEndEq(account.st)
#trade statistics
tStats <- tradeStats(Portfolios = portfolio.st, use="trades", inclZeroDays=FALSE)
tStats[,4:ncol(tStats)] <- round(tStats[,4:ncol(tStats)], 2)
print(data.frame(t(tStats[,-c(1,2)])))
#print(data.frame(t(tStats[,-c(1,2)])))
(aggPF <- sum(tStats$Gross.Profits)/-sum(tStats$Gross.Losses))
(aggCorrect <- mean(tStats$Percent.Positive))
(numTrades <- sum(tStats$Num.Trades))
(meanAvgWLR <- mean(tStats$Avg.WinLoss.Ratio[tStats$Avg.WinLoss.Ratio < Inf], na.rm=TRUE))

#daily and duration statistics
dStats <- dailyStats(Portfolios = portfolio.st, use="Equity")
rownames(dStats) <- gsub(".DailyEndEq","", rownames(dStats))
print(data.frame(t(dStats)))
#dStats <- dailyStats(Portfolios = portfolio.st, use="Equity")
#rownames(dStats) <- gsub(".DailyEndEq","", rownames(dStats))
#print(data.frame(t(dStats)))
durStats <- durationStatistics(Portfolio=portfolio.st, Symbols=sort(symbols))
indivDurStats <- durationStatistics(Portfolio=portfolio.st, Symbols=sort(symbols), aggregate=FALSE)
#indivDurStats <- durationStatistics(Portfolio=portfolio.st, Symbols=sort(symbols), aggregate=FALSE)
print(t(durStats))
print(t(indivDurStats))
#print(t(indivDurStats))

#market exposure
tmp <- list()
Expand All @@ -105,15 +104,15 @@ for(i in 1:nrow(dStats)) {
}
mktExposure <- data.frame(do.call(rbind, tmp))
colnames(mktExposure) <- c("Symbol","MktExposure")
print(mktExposure)
#print(mktExposure)
print(mean(as.numeric(as.character(mktExposure$MktExposure))))

#portfolio cash PL
portString <- paste0("portfolio.", portfolio.st)
portPL <- .blotter[[portString]]$summary$Net.Trading.PL

#Cash Sharpe
(SharpeRatio.annualized(portPL, geometric=FALSE))
#(SharpeRatio.annualized(portPL, geometric=FALSE))

#Portfolio comparisons to SPY
instRets <- PortfReturns(account.st)
Expand Down Expand Up @@ -147,4 +146,9 @@ dailyRetComparison <- cbind(portfRets, SPYrets)
colnames(dailyRetComparison) <- c("strategy", "SPY")
round(apply.yearly(dailyRetComparison, Return.cumulative),3)
round(apply.yearly(dailyRetComparison, SharpeRatio.annualized),3)
round(apply.yearly(dailyRetComparison, maxDrawdown),3)
round(apply.yearly(dailyRetComparison, maxDrawdown),3)

chart.Posn(portfolio.st, "XLB")
add_TA(MSR(HLC=HLC(XLB), nMed=nMed, nMax=nMax))
add_TA(xts(rep(.5, nrow(XLB)), order.by=index(XLB)), on=5, col="green")
add_TA(lagATR(HLC=HLC(XLB), n=period), col="purple")
1 change: 0 additions & 1 deletion demo/SIROC_I.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ initDate="1990-01-01"
from="2003-01-01"
to=as.character(Sys.Date())
options(width=70)
verose=TRUE

source("demoData.R")

Expand Down
181 changes: 181 additions & 0 deletions demo/VCI.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
require(IKTrading)
require(quantstrat)
require(PerformanceAnalytics)

initDate="1990-01-01"
from="2003-01-01"
to=as.character(Sys.Date())
options(width=70)

source("demoData.R")

#trade sizing and initial equity settings
tradeSize <- 100000
initEq <- tradeSize*length(symbols)

strategy.st <- portfolio.st <- account.st <- "VCI_test"
rm.strat(portfolio.st)
rm.strat(strategy.st)
initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD')
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD',initEq=initEq)
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)

#parameters
pctATR=.02
period=10

nRange=2
nLookback=10
pctRank=FALSE

buyThresh=-2
sellThresh=2

nSMA=200

#indicators
add.indicator(strategy.st, name="lagATR",
arguments=list(HLC=quote(HLC(mktdata)), n=period),
label="atrX")

add.indicator(strategy.st, name="VCI",
arguments=list(OHLC=quote(OHLC(mktdata)), nLookback=nLookback,
nRange=nRange, pctRank=pctRank),
label="vci")

add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=nSMA),
label="sma")

#signals
add.signal(strategy.st, name="sigComparison",
arguments=list(columns=c("Close", "SMA.sma"), relationship="gt"),
label="filter")

add.signal(strategy.st, name="sigThreshold",
arguments=list(column="VC.vci", threshold=buyThresh,
relationship="lt", cross=FALSE),
label="VCIltThresh")

add.signal(strategy.st, name="sigAND",
arguments=list(columns=c("filter", "VCIltThresh"), cross=TRUE),
label="longEntry")

add.signal(strategy.st, name="sigThreshold",
arguments=list(column="VC.vci", threshold=sellThresh,
relationship="gt", cross=TRUE),
label="longExit")

add.signal(strategy.st, name="sigCrossover",
arguments=list(columns=c("Close", "SMA.sma"), relationship="lt"),
label="filterExit")

#rules
add.rule(strategy.st, name="ruleSignal",
arguments=list(sigcol="longEntry", sigval=TRUE, ordertype="market",
orderside="long", replace=FALSE, prefer="Open", osFUN=osDollarATR,
tradeSize=tradeSize, pctATR=pctATR, atrMod="X"),
type="enter", path.dep=TRUE)

add.rule(strategy.st, name="ruleSignal",
arguments=list(sigcol="longExit", sigval=TRUE, orderqty="all", ordertype="market",
orderside="long", replace=FALSE, prefer="Open"),
type="exit", path.dep=TRUE)

add.rule(strategy.st, name="ruleSignal",
arguments=list(sigcol="filterExit", sigval=TRUE, orderqty="all", ordertype="market",
orderside="long", replace=FALSE, prefer="Open"),
type="exit", path.dep=TRUE)

#apply strategy
t1 <- Sys.time()
out <- applyStrategy(strategy=strategy.st,portfolios=portfolio.st)
t2 <- Sys.time()
print(t2-t1)

#set up analytics
updatePortf(portfolio.st)
dateRange <- time(getPortfolio(portfolio.st)$summary)[-1]
updateAcct(portfolio.st,dateRange)
updateEndEq(account.st)


#trade statistics
tStats <- tradeStats(Portfolios = portfolio.st, use="trades", inclZeroDays=FALSE)
tStats[,4:ncol(tStats)] <- round(tStats[,4:ncol(tStats)], 2)
print(data.frame(t(tStats[,-c(1,2)])))
(aggPF <- sum(tStats$Gross.Profits)/-sum(tStats$Gross.Losses))
(aggCorrect <- mean(tStats$Percent.Positive))
(numTrades <- sum(tStats$Num.Trades))
(meanAvgWLR <- mean(tStats$Avg.WinLoss.Ratio[tStats$Avg.WinLoss.Ratio < Inf], na.rm=TRUE))

#daily and duration statistics
dStats <- dailyStats(Portfolios = portfolio.st, use="Equity")
rownames(dStats) <- gsub(".DailyEndEq","", rownames(dStats))
print(data.frame(t(dStats)))
durStats <- durationStatistics(Portfolio=portfolio.st, Symbols=sort(symbols))
indivDurStats <- durationStatistics(Portfolio=portfolio.st, Symbols=sort(symbols), aggregate=FALSE)
print(t(durStats))
print(t(indivDurStats))

#market exposure
tmp <- list()
length(tmp) <- length(symbols)
for(i in 1:nrow(dStats)) {
totalDays <- nrow(get(rownames(dStats)[i]))
mktExposure <- dStats$Total.Days[i]/totalDays
tmp[[i]] <- c(rownames(dStats)[i], round(mktExposure, 3))
}
mktExposure <- data.frame(do.call(rbind, tmp))
colnames(mktExposure) <- c("Symbol","MktExposure")
print(mktExposure)
print(mean(as.numeric(as.character(mktExposure$MktExposure))))

#portfolio cash PL
portString <- paste0("portfolio.", portfolio.st)
portPL <- .blotter[[portString]]$summary$Net.Trading.PL

#Cash Sharpe
(SharpeRatio.annualized(portPL, geometric=FALSE))

#Portfolio comparisons to SPY
instRets <- PortfReturns(account.st)

#Correlations
instCors <- cor(instRets)
diag(instRets) <- NA
corMeans <- rowMeans(instCors, na.rm=TRUE)
names(corMeans) <- gsub(".DailyEndEq", "", names(corMeans))
print(round(corMeans,3))
mean(corMeans)

portfRets <- xts(rowMeans(instRets)*ncol(instRets), order.by=index(instRets))
portfRets <- portfRets[!is.na(portfRets)]
cumPortfRets <- cumprod(1+portfRets)
firstNonZeroDay <- as.character(index(portfRets)[min(which(portfRets!=0))])
getSymbols("SPY", from=firstNonZeroDay, to=to)
SPYrets <- diff(log(Cl(SPY)))[-1]
cumSPYrets <- cumprod(1+SPYrets)
comparison <- cbind(cumPortfRets, cumSPYrets)
colnames(comparison) <- c("strategy", "SPY")
chart.TimeSeries(comparison, legend.loc = "topleft",
colors=c("green","red"))
chart.RelativePerformance(portfRets,SPYrets)

SharpeRatio.annualized(portfRets)
Return.annualized(portfRets)
maxDrawdown(portfRets)

dailyRetComparison <- cbind(portfRets, SPYrets)
colnames(dailyRetComparison) <- c("strategy", "SPY")
round(apply.yearly(dailyRetComparison, Return.cumulative),3)
round(apply.yearly(dailyRetComparison, SharpeRatio.annualized),3)
round(apply.yearly(dailyRetComparison, maxDrawdown),3)

chart.Posn(portfolio.st, "XLB")
add_TA(SMA(Cl(XLB), n=nSMA), on=1, col="blue", lwd=2)
vci <- VCI(OHLC(XLB), nRange=nRange, nLookback=nLookback, pctRank=pctRank)
add_TA(vci$VC)
add_TA(vci$VC - vci$VC + buyThresh, on=5, col="green")
add_TA(vci$VC - vci$VC + sellThresh, on=5, col="red")
37 changes: 37 additions & 0 deletions man/VCI.Rd
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
\name{VCI}
\alias{VCI}
\title{ValueCharts Indicator}
\usage{
VCI(OHLC, nLookback = 40, nRange = 8, pctRank = FALSE)
}
\arguments{
\item{OHLC}{an OHLC time series}

\item{nLookback}{a moving average window, default 40}

\item{nRange}{a lookback window for the range
computation. A number above 7 results in the following
computation: take the difference between the nRange max
high and min low. Add up that value, that value lagged by
nRange+1, nRange*2, nRange*3, and nRange*4, and divide by
25. If nRange is 7 or less, the daily range is instead
computed as the 5-day SMA of the following quantity: for
each day, take the maximum of the difference between the
high and low, or the absolute difference between current
and previous close. Multiply that final quantity by .16.}
}
\value{
an OHLC-like 4-column output computing the values given
OHLC prices, or a percent rank of the close variant. The
column names will be VO, VH, VL, and VC, respectively.
}
\description{
Computes a range-normalized difference between current
price and a running moving average. A value below -8
indicates oversold, while a value above 8 indicates
overbought.
}
\references{
\url{http://www.tradesignalonline.com/en/lexicon/view.aspx?id=Value+Charts+Indicator}
}

0 comments on commit 74f20e8

Please sign in to comment.