1
$\begingroup$

Hi has anyone seen or know how to create an indicator for fractals in quantstrat?

fractals explained http://forex-indicators.net/bill-williams/fractals

example code (only interested in type 1 fractal) http://forexsb.com/forum/topic/68/fractals/

$\endgroup$
4
  • 2
    $\begingroup$ Would be great if your question were a bit more self-contained with less links ... then we don't have to click on them and we don't have to fear that they die someday .... ;) $\endgroup$ – Ric Jul 2 '15 at 12:09
  • 1
    $\begingroup$ Please don't cross-post. At minimum, tell people you're doing it so they don't possibly expend their valuable effort trying to answer a question that was answered on another forum they do not follow. $\endgroup$ – Joshua Ulrich Jul 3 '15 at 3:50
  • $\begingroup$ for reference and so you don't need to click, this is question and answer. $\endgroup$ – GeV 126 Jul 3 '15 at 4:08
  • $\begingroup$ Q) I'm not sure how the indicators work in quantstrat, in most backtesting software it loops through each day and calculates the indicator (for each day you then look back 5 days), does quanstrat do the same or do i need to write my own looping function in the indicator? A) You indicator and signal functions are presumed to be path-independent. They should return an xts time series object of the same length as the input data. My interpretation) The function processes once and should retrun a xts object $\endgroup$ – GeV 126 Jul 3 '15 at 4:11
2
$\begingroup$

Most technical indicators must be available in the TTR package. However, if they are not then you can write a custom indicator for use in quantstrat as follows.

fractalindicator.up <- function(x) {

  High <- Hi(x); Bars <- nrow(x)
  afFrUp <- rep(NA, Bars)

  for(iBar in seq(8,Bars-2))
  {
    if(High[iBar-1]<High[iBar-2] && High[iBar]<High[iBar-2])
    {
      #Fractal type 1
      if( High[iBar-4]<High[iBar-2] &&
          High[iBar-3]<High[iBar-2] )
          afFrUp[iBar+1]=High[iBar-2];
    }
  }

  names(afFrDn) <- "F.Up"
}

fractalindicator.dn <- function(x) {

  Low <- Lo(x); Bars <- nrow(x)
  afFrDn <- rep(NA, Bars)

  for(iBar in seq(8,Bars-2))
  {
    if(Low[iBar-1]>Low[iBar-2] && Low[iBar]>Low[iBar-2])
    {
      #Fractal type 1
      if( Low[iBar-4]>Low[iBar-2] && 
        Low[iBar-3]>Low[iBar-2] )
        afFrDn[iBar+1]=Low[iBar-2];
    }
  }

  names(afFrDn) <- "F.Down"
}

#Add indicators
add.indicator(strategy = "fractal", name = "fractalindicator.up",
          arguments = list(x = quote(mktdata)), label="fractalup")

#Add indicators
add.indicator(strategy = "fractal", name = "fractalindicator.dn",
          arguments = list(x = quote(mktdata)), label="fractaldn")

I have defined two here, fractalindicator.up and fractalindicator.dn. You can work with these just like you do in a regular quantstrat strategy. I may be wrong in constructing the indicator so check the logic. It is also possible to combine the two functions into one with an additional parameter.

Also, quantstrat related questions are best asked on r-sig-finance mailing list. The authors of quantstrat and many more R enthusiasts are very active on that mailing list.

$\endgroup$
1
  • $\begingroup$ yes Rohit thats it, thankyou! $\endgroup$ – GeV 126 Jul 3 '15 at 12:16
0
$\begingroup$

so i had to do a couple changes to get it fully working for me, but Rohit you pretty much got it close. Again this is what worked in my env

 fractalindicator.up <- function(x) {

  x$FUp  <- 0

  High <- Hi(x); Bars <- nrow(x)


  for(iBar in seq(8,Bars-2))
  {
    if(High[[iBar-1]]<High[[iBar-2]] && High[[iBar]]<High[[iBar-2]])
    {
      #Fractal type 1
      if( High[[iBar-4]]<High[[iBar-2]] &&
            High[[iBar-3]]<High[[iBar-2]] )
        #afFrUp[iBar+1]=High[iBar-2];
        x$FUp[iBar]= 1;
    }
  }

  return(x$FUp)
}

fractalindicator.dn <- function(x) {
  x$FDown  <- 0

  Low <- Lo(x); Bars <- nrow(x)

  for(iBar in seq(8,Bars-2))
  {
    if(Low[[iBar-1]]>Low[[iBar-2]] && Low[[iBar]]>Low[[iBar-2]])
    {
      #Fractal type 1
      if( Low[[iBar-4]]>Low[[iBar-2]] && 
            Low[[iBar-3]]>Low[[iBar-2]] )
        #afFrDn[iBar+1]=Low[iBar-2];
        x$FDown[iBar]=1;
        }
      }
      return(x$FDown)
}

I needed to return an xts object and include [[]] to access values in the dataframe

Pasted below is the full code (without analytics), I used the boilerplate code from Ilya Kipnis so full credit goes to him (please source the code from the link and not copy and paste from this) https://github.com/IlyaKipnis/DSTrading/blob/master/demo/TVI2.R

The strategy just buys as soon as it gets and up fractal and exits on a down fractal, obviously this is not a strategy anyone would trade, This is just an example of using fractals.

require(quantstrat)
require(IKTrading)
require(devtools)
require(DSTrading)
require(PerformanceAnalytics)
options("getSymbols.warning4.0"=FALSE)
rm(list=ls(.blotter), envir=.blotter)
currency('USD')
Sys.setenv(TZ="UTC")
symbols  <- "SPY"
suppressMessages(getSymbols(symbols, from="1998-01-01", to="2015-05-15"))
stock(symbols, currency="USD", multiplier=1)
initDate="1990-01-01"

tradeSize  <- 10000
initEq  <- tradeSize*length(symbols)

account.st  <- 0
strategy.st  <- portfolio.st <- account.st  <- "fractal"
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)


#new
fractalindicator.up <- function(x) {

  x$FUp  <- 0

  High <- Hi(x); Bars <- nrow(x)


  for(iBar in seq(8,Bars-2))
  {
    if(High[[iBar-1]]<High[[iBar-2]] && High[[iBar]]<High[[iBar-2]])
    {
      #Fractal type 1
      if( High[[iBar-4]]<High[[iBar-2]] &&
            High[[iBar-3]]<High[[iBar-2]] )
        #afFrUp[iBar+1]=High[iBar-2];
        x$FUp[iBar]= 1;
    }
  }

  return(x$FUp)
}

fractalindicator.dn <- function(x) {
  x$FDown  <- 0

  Low <- Lo(x); Bars <- nrow(x)

  for(iBar in seq(8,Bars-2))
  {
    if(Low[[iBar-1]]>Low[[iBar-2]] && Low[[iBar]]>Low[[iBar-2]])
    {
      #Fractal type 1
      if( Low[[iBar-4]]>Low[[iBar-2]] && 
            Low[[iBar-3]]>Low[[iBar-2]] )
        #afFrDn[iBar+1]=Low[iBar-2];
        x$FDown[iBar]=1;
        }
      }
      return(x$FDown)
}







#Add indicators
add.indicator(strategy = "fractal", name = "fractalindicator.up",
              arguments = list(x = quote(mktdata)), label="fractalup")

#Add indicators
add.indicator(strategy = "fractal", name = "fractalindicator.dn",
              arguments = list(x = quote(mktdata)), label="fractaldn")

applyIndicators(strategy=strategy.st, mktdata)


# 
# mktdata$FDown.FDownCompare <- 1
    # mktdata$FUp.FUpCompare <- 1

add.signal(strategy.st, name = "sigComparison", arguments = list(columns=c("fractalup", "fractaldn"),
                                                               relationship="gt"), label="upFractal")

add.signal(strategy.st, name = "sigComparison", arguments = list(columns=c("fractaldn", "fractalup"),
                                                        relationship="gt"), label="downFractal")

applySignals(strategy=strategy.st,mktdata)

#enter rule
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol="upFractal",
                                                            sigval=TRUE, 
                                                            ordertype="market",
                                                            orderside=NULL,
                                                            replace=FALSE,
                                                            prefer="close",
                                                            orderqty=1),
         type="enter",path.dep=TRUE,label="ruleUp")

#exit rule
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol="downFractal",
                                                            sigval=TRUE, 
                                                            orderqty="all",
                                                            orderqty=-1,
                                                            ordertype="market",
                                                            orderside=NULL,
                                                            replace=FALSE,
                                                            prefer="open"),
         type="enter",path.dep=TRUE,label="ruleDown")

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.