简体   繁体   English

如何将热图添加到quantmod :: chart_Series?

[英]How to add heatmap to quantmod::chart_Series?

I would like to plot heatmap(s) below quantmod::chart_Series(). 我想在quantmod :: chart_Series()下面绘制热图。 How to add the below heatmap to chart_Series (or xts::plot.xts): 如何将以下热图添加到chart_Series(或xts :: plot.xts):

library(quantmod)

# Get data fro symbol from Google Finance
symbol <- "SPY"
src <- "google"
from <- "2017-01-01"
symbolData <- getSymbols(symbol, src=src, from=from, auto.assign=FALSE)

# Calculate simple returns
symbolData.ret <- ROC(Cl(symbolData), type="discrete")

# Calculate lagged autocorrelations (Pearson correlation for each value of lag)
nLags <- 100
averageLength <- 3
symbolData.laggedAutocorr <- matrix(0, nLags, NROW(symbolData.ret))
for (lag in 2: nLags) {
    # Set the average length as M
    if (averageLength == 0) M <- lag
    else M <- averageLength
    symbolData.laggedAutocorr[lag, ] <- runCor(symbolData.ret, lag(symbolData.ret, lag), M)
}
symbolData.laggedAutocorr[is.na(symbolData.laggedAutocorr)] <- 0
symbolData.laggedAutocorr.xts <- reclass(t(symbolData.laggedAutocorr), symbolData)ž
subset <- "2017"
chart_Series(symbolData, name=symbol, subset=subset)

# Use transposed symbolData.laggedAutocorr for plot so you have data aligned to symbolData
# How to add the below heatmap to chart_Series?
heatmap(symbolData.laggedAutocorr.xts, Rowv = NA, Colv = NA, na.rm = TRUE, labCol = "")

add_Heatmap <- function(heatmapdata, ...) {
    lenv <- new.env()
    lenv$plot_ta <- function(x, heatmapdata, ...) {
        # fill in body of low level plot calls here
        # use a switch based on type of TA to draw: bands, bars, lines, dots...
        xsubset <- x$Env$xsubset
        #heatmapdata <- heatmapdata[subset] # TODO: Something is wrong if I have a subset here
        heatmap(heatmapdata, Rowv=NA, Colv=NA, na.rm=TRUE, labCol="")
        #image(1:NROW(heatmapdata), 1:NCOL(heatmapdata), coredata(heatmapdata), axes=FALSE)
    }
    mapply(function(name, value) {assign(name,value,envir=lenv)},
            names(list(heatmapdata=heatmapdata,...)),
            list(heatmapdata=heatmapdata,...))
    exp <- parse(text=gsub("list","plot_ta",
                    as.expression(substitute(list(x=current.chob(),
                                            heatmapdata=heatmapdata,
                                            ...)))), srcfile=NULL)
    chob <- current.chob()
    chob$add_frame(ylim=c(0, 0.3), asp=0.3)  # need to have a value set for ylim
    chob$next_frame()
    chob$replot(exp,env=c(lenv, chob$Env),expr=TRUE)

    chob
}

chart_Series(symbolData)
add_Heatmap(symbolData.laggedAutocorr.xts)

The above almost works... The issue is that the heatmap or image is plotted over the main part of chart_Series instead below of it. 上面几乎可以工作......问题是热图或图像是在chart_Series的主要部分上绘制的,而不是在它下面。 What to do in order for it to plot correctly? 怎么做才能正确绘图?

I hope this is useful for other people since I managed to get this working (to a certain level). 我希望这对其他人有用,因为我设法让这个工作(到一定程度)。 There are still issues. 还有一些问题。 Please see comments at the end of code below and comment what to do in order to remove those issues. 请参阅下面代码末尾的注释,并评论如何删除这些问题。

在此输入图像描述

add_Heatmap <- function(heatmapcol, ..., yvalues=1:NCOL(heatmapcol)) {
    lenv <- new.env()

    lenv$plot_ta <- function(x, heatmapcol, ...) {
        xdata <- x$Env$xdata        # internal main series
        xsubset <- x$Env$xsubset
        heatmapcol <- heatmapcol[xsubset]

        x.pos <- 1:NROW(heatmapcol)
        segments(axTicksByTime(xdata[xsubset], ticks.on=x$Env$ticks.on),
                0, 
                axTicksByTime(xdata[xsubset], ticks.on=x$Env$ticks.on),
                NCOL(heatmapcol), col=x$Env$theme$grid)

        # TODO: What is faster polgon or rect (https://stackoverflow.com/questions/15627674/efficiency-of-drawing-rectangles-on-image-matrix-in-r)
        # TODO: What is faster for or lapply?
#       for (i in 1:NCOL(heatmapcol)) {
#           rect(x.pos - 1/2, i - 1/2, x.pos + 1/2, i + 1/2 + 1, col=heatmapcol[x.pos, i], border=NA, ...)  # base graphics call
#       }

        lapply(1:NCOL(heatmapcol), function(i) rect(x.pos - 1/2, i - 1/2, x.pos + 1/2, i + 1/2 + 1, col=heatmapcol[x.pos, i], border=NA, ...))
    }

    mapply(function(name, value) {assign(name,value,envir=lenv)},
            names(list(heatmapcol=heatmapcol, ...)),
            list(heatmapcol=heatmapcol, ...))
    exp <- parse(text=gsub("list", "plot_ta",
                    as.expression(substitute(list(x=current.chob(),
                                            heatmapcol=heatmapcol,
                                            ...)))), srcfile=NULL)
    chob <- current.chob()
#   chob$add_frame(ylim=c(0, 1),asp=0.15)   # add the header frame
#   chob$next_frame()                      # move to header frame

    chob$add_frame(ylim=c(1, NCOL(heatmapcol)), asp=1)  # need to have a value set for ylim
    chob$next_frame()

    if (length(yvalues) != NCOL(heatmapcol)) {
        # We have a case when min and max is specified
        yvalues <- (range(yvalues)[1]):(range(yvalues)[2])
    }

    # add grid lines
    lenv$grid_lines_val <- function(xdata, x) { 
        ret <- pretty(yvalues)

        if (ret[1] != min(yvalues)) {
            if (ret[1] <= min(yvalues)) {
                ret[1] <- min(yvalues)
            } else {
                ret <- c(min(yvalues), ret)
            }
        }

        if (ret[length(ret)] != max(yvalues)) {
            if (ret[length(ret)] >= max(yvalues)) {
                ret[length(ret)] <- max(yvalues)
            } else {
                ret <- c(ret, max(yvalues))
            }
        }

        return(ret)
    }

    lenv$grid_lines_pos <- function(xdata, x) { 
        ret <- lenv$grid_lines_val(xdata, x)

        ret <- ret - min(yvalues)

        return(ret)
    }

    exp <- c(exp, 
            # Add axis labels/boxes
           expression(text(1- 1/3 - max(strwidth(grid_lines_val(xdata, xsubset))), grid_lines_pos(xdata, xsubset),
                      noquote(format(grid_lines_val(xdata, xsubset), justify="right")),
                      col=theme$labels, offset=0, pos=4, cex=0.9)),
           expression(text(NROW(xdata[xsubset]) + 1/3, grid_lines_pos(xdata, xsubset),
                      noquote(format(grid_lines_val(xdata, xsubset), justify="right")),
                      col=theme$labels, offset=0, pos=4, cex=0.9)))

    chob$replot(exp, env=c(lenv, chob$Env), expr=TRUE)

    chob
}

colorsForHeatmap<-function(heatmapdata) {
    heatmapdata <- 0.5*(heatmapdata + 1)

    r <- coredata((heatmapdata > 0.5)*round(255*(2 - 2*heatmapdata)) + (heatmapdata <= 0.5)*255)
    g <- coredata((heatmapdata > 0.5)*255 + (heatmapdata <= 0.5)*round(255*2*heatmapdata))
    b <- coredata(heatmapdata*0.0) # Set to 0 for all

    col <- rgb(r, g, b, maxColorValue=255)
    dim(col) <- dim(r)

    col <- reclass(col, heatmapdata)

    return(col)
}

library(quantmod)

# Get data for symbol from Google Finance
symbol <- "SPY"
src <- "google"
from <- "1990-01-01"
symbolData <- getSymbols(symbol, src=src, from=from, auto.assign=FALSE)

# Calculate simple returns
symbolData.ret <- ROC(Cl(symbolData), type="discrete")

# Calculate lagged autocorrelations (Pearson correlation for each value of lag)
nLags <- 48
averageLength <- 3
symbolData.laggedAutocorr <- matrix(0, NROW(symbolData.ret), nLags)
for (lag in 2:nLags) {
    # Set the average length as M
    if (averageLength == 0) M <- lag
    else M <- averageLength
    symbolData.laggedAutocorr[, lag] <- runCor(symbolData.ret, lag(symbolData.ret, lag), M)
}
symbolData.laggedAutocorr[is.na(symbolData.laggedAutocorr)] <- 0

symbolData.laggedAutocorr.xts <- xts(symbolData.laggedAutocorr, index(symbolData))

heatmapColData <- colorsForHeatmap(symbolData.laggedAutocorr.xts)

symbolData.rsi2 <- RSI(Cl(symbolData), n=2)

subset <- "2011/"
chart_Series(symbolData, name=symbol, subset=subset)
add_Heatmap(heatmapColData, yvalues=2:nLags)

# TODO: There are still issues:
#   - add a horizontal line
five <- symbolData[, 1]
five[, 1] <- 5
add_TA(five, col="violet", on=3)
#> add_TA(five, col="violet", on=3)
#Error in ranges[[frame]] : subscript out of bounds
#   - add RSI for example and heatmap disappears
add_RSI()
#   - or add TA
add_TA(symbolData.rsi2)
# What to do so it works like intended: I can add lines on top of heatmaps? I can add other TAs in new panes?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM