3

I have a matrix (named ichimoku) with 516 rows and 2 columns ,each one of them containing values to be plotted, the goal is to recreate the clouds for the Ichimoku strategy. Using matpot, I am able to plot these two curves but what I want is to shade the area between the two curves. I have two problems :

  • I tried using polygon to shade the area but it does not work. I suspect it is because the two series (senkouA and senkouB) cross several times on the plot instead of having one always greater than the other

  • I would like the area to be shaded in green if senkouA>senkouB and in red if senkouB>senkouA but from what I read the polygon can only be of one color.

Is there an other function that polygon which might help me achieve what I am looking for, that is a shade area in green between senkouA and senkouB when senkouA>senkouB and a shade area in red when senkouB>senkouA ?

The ichimoku matrix looks like this (the first column is senkouA, the other senkouB)

        [,1]      [,2]
[1,] 23323.62   23320.53
[2,] 23334.67   23328.71
[3,] 23334.11   23323.06
[4,] 23332.94   23323.06
...

here is my matplot function (which works):

matplot(ichimoku,lty=1,lwd=1,pch=20,type="l",col=c("red","blue"))

and my polygon function (which doesn't):

polygon(c(1:516,516:1),c(senkouA,senkouB),col='green')
Hack-R
  • 22,422
  • 14
  • 75
  • 131
etienne
  • 3,648
  • 4
  • 23
  • 37
  • Did you have a look at `quantmod` package? –  Aug 19 '15 at 10:15
  • @Pascal Unfortunately I don't think that `quantmod` contains Ichimoku charting. But [this](http://www.r-bloggers.com/ichimoku-clouds-r-code-trading/) blog could be interesting. – RHertel Aug 19 '15 at 10:17
  • There is also a [github post](https://github.com/IlyaKipnis/IKTrading/issues/3) on the Ichimoku indicator – RHertel Aug 19 '15 at 10:19
  • @RHertel Right, I mixed up with what it seems to be Bollinger bands. Sorry for the confusion. –  Aug 19 '15 at 10:20
  • I have to reprogram the Ichimoku strategy so using an already existing interface is not possible. However, thanks for the github links, that will help. – etienne Aug 19 '15 at 10:35
  • See http://stackoverflow.com/questions/33318391/fill-area-between-two-lines-with-high-low-and-dates I recently asked a similar question, in the context of the ``ggplot2`` package and ``geom_ribbon()`` function. I hadn't seen etienne's question at the time, so I'd like to link here to make it easier for the next person to navigate between our questions (while the questions are partly "duplicate", the answers are not) – PatrickT Oct 25 '15 at 09:55

2 Answers2

4

If you find the intersections between the curves, then you can draw the polygons between the intersections. Here is a modification of a previous post where they find intersections between curves, and a function to draw the polygons.

## Some sample data
set.seed(0)
dat <- data.frame(x1=3*sin(3*(x=seq(0,10,len=100)))+rnorm(100),
                  x2=2*cos(x)+rnorm(100))

## https://stackoverflow.com/questions/20519431/finding-point-of-intersection-in-r
intersects <- function(x1, x2) {
    seg1 <- which(!!diff(x1 > x2))                            # location of first point in crossing segments
    above <- x2[seg1] > x1[seg1]                              # which curve is above prior to crossing
    slope1 <- x1[seg1+1] - x1[seg1]
    slope2 <- x2[seg1+1] - x2[seg1]
    x <- seg1 + ((x2[seg1] - x1[seg1]) / (slope1 - slope2))
    y <- x1[seg1] + slope1*(x - seg1)
    data.frame(x=x, y=y, pindex=seg1, pabove=(1:2)[above+1L])  # pabove is greater curve prior to crossing
}

ichimoku <- function(data, addLines=TRUE) {
    ## Find points of intersections
    ints <- intersects(data[,1], data[,2])
    intervals <- findInterval(1:nrow(data), c(0, ints$x))

    ## Make plot
    matplot(data, type="n", col=2:3, lty=1, lwd=4)
    legend("topright", c("A", "B"), col=3:2, lty=1, lwd=2)

    ## Draw the polygons
    for (i in seq_along(table(intervals))) {
        xstart <- ifelse(i == 1, 0, ints$x[i-1])
        ystart <- ifelse(i == 1, dat[1,ints$pindex[1]], ints$y[i-1])
        xend <- ints$x[i]
        yend <- ints$y[i]
        x <- seq(nrow(data))[intervals == i]
        polygon(c(xstart, x, xend, rev(x)), c(ystart, data[x,1], yend, rev(data[x,2])),
                col=ints$pabove[i]%%2+2)
    }

    ## Add lines for curves
    if (addLines)
        invisible(lapply(1:2, function(x) lines(seq(nrow(data)), data[,x], col=x%%2+2, lwd=2)))
}

## Plot the data
ichimoku(dat)

enter image description here

Community
  • 1
  • 1
Rorschach
  • 31,301
  • 5
  • 78
  • 129
  • I works great except for a few problems : my first pindex in the ints df equals 63 (then 98 and 105), so the first ystart doesn't work because there are only two columns in dat, not 63. I replaced the ints$pindex[1] with 2 and it polts the polygons except the last one. Thanks for your post ! – etienne Aug 20 '15 at 07:04
1

Here is some code that works for a simple version of your problem, in which the lines only cross once. I haven't tested it for repeated crossings, however.

# Make toy data
ichimoku <- data.frame(senkouA = rep(10, 10), senkouB = c(3, 5, 4, 7, 10, 11, 15, 12, 13, 14))

# Make indices for the conditions that define the fill colors. They need to intersect for the polygons to connect.
index.green = with(ichimoku, as.logical(senkouA >= senkouB))
index.red = with(ichimoku, as.logical(senkouA <= senkouB))

# Make the line plot
matplot(ichimoku, lty=1, lwd=1, pch=20, type="l", col=c("red","blue"))

# Now add polygons with fill color based on those conditions by subsetting the task using the indices.
with(ichimoku, polygon(x = c(seq(length(senkouA))[index.green], rev(seq(length(senkouA))[index.green])),
    y = c(senkouB[index.green], senkouA[index.green]), col = "green"))
with(ichimoku, polygon(x = c(seq(length(senkouA))[index.red], rev(seq(length(senkouA))[index.red])),
    y = c(senkouB[index.red], senkouA[index.red]), col = "red"))

Here's my result:

enter image description here

ulfelder
  • 5,305
  • 1
  • 22
  • 40