[R] Producing a SMA signal when closing price is above the moving average for 3 days

William Dunlap wdunlap at tibco.com
Wed Sep 5 06:10:50 CEST 2012


You could think of your problem as one of combining a signal
that tells when the state of the system should change to (or
remain at) "on" and a signal that tells when it should change to
"off" to come up with a series giving the state at each time point.
E.g.,

OnOrOff <- function(toOn, toOff, wasOn){
   # toOn and toOff are logical vectors (indexed implicitly by time).
   # toOn[t] is TRUE means that the state should change to (or continue to
   # be) "on" (1) from time t until a later toOff value turns it off.
   # If both toOn[t] and toOff[t] are FALSE, then state[t] is copied from
   # state[t-1].
   # wasOn=TRUE means that the state was "on" at time 0.
   stopifnot(length(toOn)==length(toOff), !any(toOn & toOff))
   tmp <- integer(length(toOn))
   tmp[1] <- if (wasOn) 1 else -1
   tmp[toOn] <- 1
   tmp[toOff] <- -1
   s <- tmp != 0
   zeroDups <- function(x) { x[-1][x[-1]==x[-length(x)]] <- 0 ; x }
   tmp[s] <- zeroDups(tmp[s])
   cumsum(tmp) + (tmp[1] == -1)
}

In your example you have a series of 1s and 0s saying whether
the price is currently above or below the 50-day runing average.   E.g.,
   x <- c(1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1)
(TRUE and FALSE instead of 1 and 0 would be more convenient, but I'll
follow your lead.)

You can use filter to to find where there were 3 aboves (TRUEs) or 3 belows
(FALSEs) in a row and pass those into OnOrOff.  The following does this
but assumes the previous state was "off" (an exercise for the reader):
  SwitchAtThree  <- function (x, init = c(0, 0)) 
  {
      count <- function(x) filter(c(init, x), rep(1, 3), side = 1)[-seq_along(init)]
      OnOrOff(count3(x == 1) == 3, count3(x == 0) == 3, FALSE)
  }
With the above x we get:
  > data.frame(x, fx=SwitchAtThree(x))
     x fx
  1  1  0
  2  1  0
  3  0  0
  4  1  0
  5  1  0
  6  1  1
  7  0  1
  8  1  1
  9  0  1
  10 0  1
  11 0  0
  12 1  0

An advantage of this technique is that you can fiddle with the filter
coefficients and the '==3' to change the start-on/start-off conditions from 3 in
a row to 3 out of the last 4 or the last two plus at least one of the two prior to
them or make the on/off signals assymetric (e.g., 3 in a row TRUE to turn on, 2 in
a row FALSE to turn off).

It is pretty quick for long series.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com


> -----Original Message-----
> From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf
> Of Douglas Karabasz
> Sent: Monday, September 03, 2012 8:24 PM
> To: r-help at r-project.org
> Subject: [R] Producing a SMA signal when closing price is above the moving average for 3
> days
> 
> I have loaded price data for GE and then calculated a 50 day simple moving
> average.  Then I have a created a ifelse statement that produce a 1 when
> GE's closing price is above the simple moving average and a 0 when GE
> Closing price is below the 50 day simple moving average.
> 
> However, what I really want to do is to produce a 1 for when the price is
> above the simple moving average for 3 days and I want it to keep the 1 until
> the price moves back below the 50 day simple moving average for 3 days then
> I want to return a 0 until the Price closes above the SMA for 3 days.
> 
> Thank you,
> Douglas
> 
> 
> library(quantmod)
> 
> getSymbols("GE")  # Get Price Data
> 
> GEsma  <- SMA(GE$GE.Close, n=50) # Simple Moving Average of the closing
> price
> 
> GEsma[is.na(GEsma)] <- 50  # Make NA's to 50 so ifelse statement works
> correctly
> 
> aboveSMA  <- ifelse(GE$GE.Close > GEsma, 1, 0)  # 1 when price is above 50
> day moving average
> # 0 When below moving average
> 
> chartSeries(GE)  # Shows Price chart
> addSMA(n=50)  #  adds 50 day moving average to chart
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.




More information about the R-help mailing list