Mustafa Kutay Yabas - EC581 - 26.11.2016

Assignment #4

Oversold Strategy

Design a long-only trading strategy for BIST100 index that bets on reversals after the indes becomes oversold

Buy Signal

  • $Low \le BBands_{Low}(n,s)$ and $RSI(m) \le c$ here $n, s, m$ are parameters and $c$ is a fixed threshold
  • Example $Low \le BBands_{Low}(65,2)$ and $RSI(14) \le 30$
  • Whenever this rule turns on, send a market order and assume that the order is executed at the opening price of the next dat. i.e. prefer="Open" in quantstrat
  • Add one lot each time we have a new buy signal

Sell Signal

  • Close the position whenever $Close \ge BBands_{Low}(n,s_{2})$ where $s_{2}$ is another parameter
  • Parameter constraint: $s_{2} \lt s$ must hold
  • Whenever this tule turns on, send a market order to sell all and assume that the order is executed at the opening price of next day, i.e. prefer="Open" in quantstrat

Optimization Perform a walk forward (WFA) analysis with the following parameters;

  • Use rolling windows
  • Paramset:
    • $s \ \epsilon \ 1,\ 1.5,\ 2,\ 2.5,\ 3 $
    • $s_{2} \ \epsilon \ 1,\ 1.5,\ 2,\ 2.5,\ 3 $
    • $s_{2} \ \lt s$ must hold
    • $c \ \epsilon \ 10,\ 20,\ 30,\ 40$
  • Use $n_{samples} = 10$
  • In sample period length $=$ 36 months
  • Out of sample period length $=$ 12 months
  • Objective function: Profit to max drawdown

*Present your results using graphs and tables

Load Libraries


In [2]:
library(zoo)
library(TTR)
library(xts)
library(xtsExtra) 
library(quantmod)
library(quantstrat)
library(doParallel)

Import Data


In [3]:
currency("USD")
stock("BIST",currency="USD",multiplier=1)

load("../../database/database.RData")
.from="2000-01-03"
.to="2016-09-30"

BIST<-as.xts(na.omit(merge(Open[,"XU100"], High[,"XU100"], Low[,"XU100"], Close[,"XU100"])))
BIST<-window(BIST,start = .from,end=.to)
colnames(BIST)<-c("Open","High","Low","Close")

BIST<-xts(coredata(BIST), as.POSIXct(time(BIST)))#Must be POSIXct
index(BIST)<-as.POSIXct(round(index(BIST),"day"))


'USD'
'BIST'

Setup Quantstrat & Strategy


In [54]:
strategy.st = 'OverSold'
portfolio.st = 'MeanReversion'
account.st = 'Investiphi'

#Defined as a function to apply strategies with different rules easily
setup_strat <- function(.open_period = 21, .std_open = 2, .std_close = 2, .rsi_t = 30, .close_period=21, .rsi_period=21) {
rm.strat(strategy.st)
rm.strat(portfolio.st)
rm.strat(account.st)
if (!exists('.blotter')) .blotter <- new.env()
if (!exists('.strategy')) .strategy <- new.env()
    
initDate<-as.character(as.Date(.from)-1) # One day before data starts
initEq<-30000

initPortf(portfolio.st, symbols='BIST', 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)
    
#.period = 21
#.std_open = 2.5
#.std_close = 1

add.indicator(strategy.st, 
              name = "BBands",
              arguments = list(
                HLC = quote(Cl(mktdata)[,1]),
                n = .open_period,
                sd = .std_open
              ),
              label="bband_open"
)

add.indicator(strategy.st, 
              name = "BBands",
              arguments = list(
                HLC = quote(Cl(mktdata)[,1]),
                n = .close_period,
                sd = .std_close
              ),
              label="bband_close"
)
    
add.signal(strategy.st, name='sigCrossover',
           arguments = list(
             columns=c("Close","dn.bband_open"),
             relationship="lt"
           ),
           label='bblong'
)
    
## Close Signal
add.signal(strategy.st, name='sigCrossover',
           arguments = list(
             columns=c("Close","dn.bband_close"),
             relationship="gte"
           ),
           label='short'
)
    
add.indicator(strategy.st, 
              name = "RSI",
              arguments = list(
                price = quote(Cl(mktdata)[,1]),
                n = .rsi_period
              ),
              label="rsi"
)
    
#.rsi_t = 40 # rsi threshold
add.signal(strategy.st, name='sigThreshold',
           arguments = list(
             column= "EMA.rsi",
             relationship = "lt",
             threshold = .rsi_t
           ),
           label='rsilong'
)

add.signal(strategy.st, name='sigFormula',
           arguments = list(
             columns=c("bblong","rsilong"),
             formula= "(bblong == TRUE) & (rsilong == 1)"
           ),
           label='long'
)
    
.orderqty = 1
.txnfees = 0 # round-trip fee

add.rule(strategy.st, 
         name='ruleSignal',
         arguments=list(sigcol='long' , 
                        sigval=TRUE,
                        orderside='long' ,
                        ordertype='market', 
                        prefer='Open', 
                        tmult=TRUE,
                        orderqty=+.orderqty,
                        replace=FALSE
         ),
         type='enter',
         label='EnterLONG'
)
    
add.rule(strategy.st, name='ruleSignal',
         arguments=list(sigcol='short', 
                        sigval=TRUE,
                        orderside='long' ,
                        ordertype='market',
                        orderqty='all',
                        prefer='Open',
                        TxnFees=.txnfees, #Only on exits
                        replace=TRUE #Replace any pending open orders
         ),
         type='exit',
         label='Exit2SHORT'
)
    
}

Apply the Strategy!


In [26]:
setup_strat()
applyStrategy(strategy.st, portfolio.st)
# Update portfolio & account
updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)
# Analyze performance
chart.Posn(portfolio.st, "BIST")
getEndEq(account.st,.to)


'OverSold'
[1] "2000-09-19 00:00:00 BIST 1 @ 10378"
[1] "2000-09-21 00:00:00 BIST -1 @ 11320.79"
[1] "2000-11-29 00:00:00 BIST 1 @ 9512.51"
[1] "2000-11-30 00:00:00 BIST -1 @ 8747.68"
[1] "2000-12-01 00:00:00 BIST 1 @ 7977.83"
[1] "2000-12-06 00:00:00 BIST -1 @ 10387.38"
[1] "2006-06-14 00:00:00 BIST 1 @ 32384.42"
[1] "2006-06-15 00:00:00 BIST -1 @ 32899.74"
[1] "2008-01-22 00:00:00 BIST 1 @ 43916.65"
[1] "2008-01-25 00:00:00 BIST -1 @ 45852.98"
[1] "2008-10-13 00:00:00 BIST 1 @ 29993.2"
[1] "2008-10-14 00:00:00 BIST -1 @ 30875.6"
[1] "2008-10-20 00:00:00 BIST 1 @ 26408.48"
[1] "2008-10-21 00:00:00 BIST -1 @ 27027.98"
'MeanReversion'
'Investiphi'
'Investiphi'
36541.06

The Strategy Works. Now We can Optimize it


In [36]:
param_s = c(1, 1.5, 2, 2.5, 3)
param_s2 = c(1, 1.5, 2, 2.5, 3)
param_c = c(10,20,30,40)

In [37]:
add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'bband_open',
                 variable = list(sd = param_s),
                 label = 'bband_open_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'bband_close',
                 variable = list(sd = param_s2),
                 label = 'bband_close_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'signal',
                 component.label = 'rsilong',
                 variable = list(threshold = param_c),
                 label = 'rsilong_dist'
)


'OverSold'
'OverSold'
'OverSold'

In [38]:
add.distribution.constraint(strategy.st,
                            paramset.label = 'Paramset',
                            distribution.label.1 = 'bband_open_dist',
                            distribution.label.2 = 'bband_close_dist',
                            operator = '>=',
                            label = 'bband_constraint'
)


'OverSold'

In [30]:
summary(get("OverSold",envir = .strategy))


            Length Class  Mode     
name        1      -none- character
assets      0      -none- NULL     
indicators  3      -none- list     
signals     4      -none- list     
rules       3      -none- list     
constraints 0      -none- NULL     
init        0      -none- list     
wrapup      0      -none- list     
call        3      -none- call     
paramsets   1      -none- list     

Regular Optimization


In [31]:
detectCores()


8

In [32]:
registerDoParallel(cores=8) # Parallel computing

# Use nsamples if you want random samples from the parameter space
results <- apply.paramset(strategy.st, 
                          paramset.label='Paramset', 
                          portfolio.st=portfolio.st, 
                          account.st=account.st, 
                          verbose=FALSE)

In [33]:
stats <- results$tradeStats
stats[order(stats[,"Profit.To.Max.Draw"],decreasing = T),
      c("bband_open_dist","bband_close_dist","rsilong_dist","Profit.To.Max.Draw","Ann.Sharpe","End.Equity")]


bband_open_distbband_close_distrsilong_distProfit.To.Max.DrawAnn.SharpeEnd.Equity
432.5 2.5 30 6.5323374316.36590785 3703.77
492.5 1.0 40 5.6858553811.2049103133550.47
402.0 2.0 30 3.1842061714.42495081 6541.06
443.0 2.5 30 3.17455318 NA 1763.75
453.0 3.0 30 3.17455318 NA 1763.75
482.0 1.0 40 2.27126101 5.1479743730609.83
532.5 1.5 40 2.05724439 5.6660795717066.92
372.0 1.5 30 2.0166082711.78416881 5709.26
522.0 1.5 40 1.94390304 4.1096869020722.92
582.5 2.5 40 1.79913571 5.0340295813035.26
471.5 1.0 40 1.29074363 3.7542915224142.34
503.0 1.0 40 1.28514157 7.17235596 7504.43
562.5 2.0 40 1.07506335 2.71280130 8395.89
342.5 1.0 30 0.9062826120.93256083 5158.76
603.0 3.0 40 0.80874047 2.70214857 3032.89
511.5 1.5 40 0.79639340 1.64195756 8251.44
412.5 2.0 30 0.6332113114.06593678 3063.47
552.0 2.0 40 0.60080204 1.12769305 6241.45
382.5 1.5 30 0.35007256 4.63388656 1992.69
332.0 1.0 30 0.33730170 4.36122283 2897.85
593.0 2.5 40 0.20232178 1.11438007 1465.88
543.0 1.5 40 0.11212210 0.66734600 807.87
353.0 1.0 30 0.03201739 NA 182.25
573.0 2.0 40 0.00556909 0.03504617 46.84
423.0 2.0 30 -0.01680863 NA -81.32
461.0 1.0 40 -0.08557587-0.33952307-1182.65
393.0 1.5 30 -0.30657459 NA-1745.09
321.5 1.0 30 NA NA 774.92
361.5 1.5 30 NA NA 463.42

Best Values for Regular Optimization

bband_open = 2.5

bband_close = 1

rsi_threshold = 40

Lets apply the strategy with these new variables


In [34]:
setup_strat(21, 2.5, 1, 40)
applyStrategy(strategy.st, portfolio.st)
# Update portfolio & account
updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)
# Analyze performance
chart.Posn(portfolio.st, "BIST")
getEndEq(account.st,.to) # We have nearly doubled the equity


'OverSold'
[1] "2000-06-19 00:00:00 BIST 1 @ 14544"
[1] "2000-06-26 00:00:00 BIST -1 @ 14544"
[1] "2000-07-14 00:00:00 BIST 1 @ 13522"
[1] "2000-07-18 00:00:00 BIST 1 @ 12737"
[1] "2000-07-24 00:00:00 BIST -2 @ 13720"
[1] "2000-09-08 00:00:00 BIST 1 @ 12172"
[1] "2000-09-26 00:00:00 BIST -1 @ 11360"
[1] "2000-11-21 00:00:00 BIST 1 @ 11313.97"
[1] "2000-12-07 00:00:00 BIST -1 @ 9364.17"
[1] "2001-02-22 00:00:00 BIST 1 @ 7890.4"
[1] "2001-02-27 00:00:00 BIST -1 @ 8665.88"
[1] "2001-03-30 00:00:00 BIST 1 @ 8022.72"
[1] "2001-04-02 00:00:00 BIST -1 @ 7855.67"
[1] "2001-07-11 00:00:00 BIST 1 @ 9445.38"
[1] "2001-07-20 00:00:00 BIST -1 @ 9618.77"
[1] "2001-09-14 00:00:00 BIST 1 @ 8089.46"
[1] "2001-10-01 00:00:00 BIST -1 @ 7735.1"
[1] "2002-02-11 00:00:00 BIST 1 @ 11541.85"
[1] "2002-03-04 00:00:00 BIST -1 @ 11693.4"
[1] "2002-05-20 00:00:00 BIST 1 @ 10609.89"
[1] "2002-05-28 00:00:00 BIST -1 @ 11199.04"
[1] "2003-03-18 00:00:00 BIST 1 @ 9482.92"
[1] "2003-03-19 00:00:00 BIST -1 @ 10581.5"
[1] "2005-03-17 00:00:00 BIST 1 @ 25331.7"
[1] "2005-03-28 00:00:00 BIST -1 @ 25502.6"
[1] "2005-04-19 00:00:00 BIST 1 @ 23285.94"
[1] "2005-04-22 00:00:00 BIST -1 @ 24419.37"
[1] "2006-05-16 00:00:00 BIST 1 @ 40268.68"
[1] "2006-05-23 00:00:00 BIST 1 @ 36351.06"
[1] "2006-05-30 00:00:00 BIST -2 @ 38908.6"
[1] "2007-08-17 00:00:00 BIST 1 @ 43503.82"
[1] "2007-08-24 00:00:00 BIST -1 @ 47080.96"
[1] "2008-01-22 00:00:00 BIST 1 @ 43916.65"
[1] "2008-02-04 00:00:00 BIST -1 @ 45233.47"
[1] "2008-07-02 00:00:00 BIST 1 @ 33308.06"
[1] "2008-07-08 00:00:00 BIST -1 @ 34410.21"
[1] "2008-09-16 00:00:00 BIST 1 @ 34475.45"
[1] "2008-09-22 00:00:00 BIST -1 @ 36446.54"
[1] "2010-11-30 00:00:00 BIST 1 @ 64072.16"
[1] "2010-12-03 00:00:00 BIST -1 @ 66939.08"
[1] "2011-02-25 00:00:00 BIST 1 @ 61389.89"
[1] "2011-03-02 00:00:00 BIST 1 @ 58204.85"
[1] "2011-03-07 00:00:00 BIST -2 @ 60561.07"
[1] "2011-07-25 00:00:00 BIST 1 @ 59227.3"
[1] "2011-07-29 00:00:00 BIST -1 @ 62338.64"
[1] "2011-08-08 00:00:00 BIST 1 @ 55111.78"
[1] "2011-08-17 00:00:00 BIST -1 @ 53812.76"
[1] "2011-11-22 00:00:00 BIST 1 @ 53333.21"
[1] "2011-12-01 00:00:00 BIST -1 @ 54412.8"
[1] "2013-06-04 00:00:00 BIST 1 @ 78413.91"
[1] "2013-06-17 00:00:00 BIST -1 @ 78596.16"
[1] "2013-08-22 00:00:00 BIST 1 @ 68839.44"
[1] "2013-08-28 00:00:00 BIST 1 @ 64523.88"
[1] "2013-09-03 00:00:00 BIST -2 @ 68828.63"
[1] "2013-12-20 00:00:00 BIST 1 @ 69444.28"
[1] "2013-12-31 00:00:00 BIST -1 @ 68210.33"
[1] "2014-01-30 00:00:00 BIST 1 @ 62210.46"
[1] "2014-02-07 00:00:00 BIST -1 @ 64616.2"
[1] "2015-03-06 00:00:00 BIST 1 @ 80927"
[1] "2015-03-11 00:00:00 BIST 1 @ 78257.95"
[1] "2015-03-18 00:00:00 BIST -2 @ 79972.74"
[1] "2015-06-09 00:00:00 BIST 1 @ 78410.98"
[1] "2015-06-12 00:00:00 BIST -1 @ 80848.27"
[1] "2015-07-24 00:00:00 BIST 1 @ 78151.53"
[1] "2015-07-28 00:00:00 BIST 1 @ 77687.15"
[1] "2015-08-03 00:00:00 BIST -2 @ 79879.67"
[1] "2015-08-24 00:00:00 BIST 1 @ 72638.68"
[1] "2015-08-28 00:00:00 BIST -1 @ 74981.53"
'MeanReversion'
'Investiphi'
'Investiphi'
63550.47

Great! We have nearly doubled the equity with Regular Optimization.

Now lets try Walk Forward Optimization

Walk Forward Optimization


In [39]:
wfa_results <-walk.forward(
  strategy.st=strategy.st, 
  portfolio.st=portfolio.st, 
  account.st=account.st,
  paramset.label='Paramset', # Use this paramset
  period='months', 
  k.training=36, # Optimize over last 36 months
  k.testing=12, # Trade with optimized params during next 12 months
  #nsamples=10, # Only search for 10 param combos
  #obj.func=function(x){which(x == max(x,na.rm=T))}, 
  #obj.args=list(x=quote(tradeStats.list$Profit.To.Max.Draw)), #Obj fnc
  #audit.prefix='wfa', # Will be used in creating RData filenames
  anchored=FALSE) # Rolling WFA, not anchored


[1] "=== training Paramset on 2000-01-03/2002-12-31"
[1] "=== testing param.combo 37 on 2003-01-02/2003-12-31"
   bband_open_dist bband_close_dist rsilong_dist
37               2              1.5           30
[1] "=== training Paramset on 2001-01-02/2003-12-31"
[1] "=== testing param.combo 47 on 2004-01-02/2004-12-29"
   bband_open_dist bband_close_dist rsilong_dist
47             1.5                1           40
[1] "2004-05-07 00:00:00 BIST 1 @ 17624.05"
[1] "2004-05-14 00:00:00 BIST 1 @ 16645.92"
[1] "2004-05-24 00:00:00 BIST -2 @ 16628.77"
[1] "=== training Paramset on 2002-01-02/2004-12-29"
[1] "=== testing param.combo 48 on 2005-01-03/2005-12-30"
   bband_open_dist bband_close_dist rsilong_dist
48               2                1           40
[1] "2005-03-17 00:00:00 BIST 1 @ 25331.7"
[1] "2005-03-22 00:00:00 BIST 1 @ 24636.68"
[1] "2005-04-18 00:00:00 BIST 1 @ 23853.34"
[1] "=== training Paramset on 2003-01-02/2005-12-30"
[1] "=== testing param.combo 48 on 2006-01-02/2006-12-29"
   bband_open_dist bband_close_dist rsilong_dist
48               2                1           40
[1] "2006-06-14 00:00:00 BIST 1 @ 32384.42"
[1] "2006-06-20 00:00:00 BIST -1 @ 34807.73"
[1] "=== training Paramset on 2004-01-02/2006-12-29"
[1] "=== testing param.combo 48 on 2007-01-04/2007-12-31"
   bband_open_dist bband_close_dist rsilong_dist
48               2                1           40
[1] "=== training Paramset on 2005-01-03/2007-12-31"
[1] "=== testing param.combo 49 on 2008-01-02/2008-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "2008-07-02 00:00:00 BIST 1 @ 33308.06"
[1] "2008-09-16 00:00:00 BIST 1 @ 34475.45"
[1] "=== training Paramset on 2006-01-02/2008-12-31"
[1] "=== testing param.combo 49 on 2009-01-02/2009-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "=== training Paramset on 2007-01-04/2009-12-31"
[1] "=== testing param.combo 49 on 2010-01-04/2010-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "2010-11-30 00:00:00 BIST 1 @ 64072.16"
[1] "=== training Paramset on 2008-01-02/2010-12-31"
[1] "=== testing param.combo 49 on 2011-01-03/2011-12-30"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "2011-02-25 00:00:00 BIST 1 @ 61389.89"
[1] "2011-03-02 00:00:00 BIST 1 @ 58204.85"
[1] "2011-07-25 00:00:00 BIST 1 @ 59227.3"
[1] "2011-08-08 00:00:00 BIST 1 @ 55111.78"
[1] "2011-11-22 00:00:00 BIST 1 @ 53333.21"
[1] "=== training Paramset on 2009-01-02/2011-12-30"
[1] "=== testing param.combo 49 on 2012-01-02/2012-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "=== training Paramset on 2010-01-04/2012-12-31"
[1] "=== testing param.combo 49 on 2013-01-02/2013-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "2013-06-04 00:00:00 BIST 1 @ 78413.91"
[1] "2013-08-22 00:00:00 BIST 1 @ 68839.44"
[1] "2013-08-28 00:00:00 BIST 1 @ 64523.88"
[1] "2013-12-20 00:00:00 BIST 1 @ 69444.28"
[1] "=== training Paramset on 2011-01-03/2013-12-31"
[1] "=== testing param.combo 49 on 2014-01-02/2014-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "=== training Paramset on 2012-01-02/2014-12-31"
[1] "=== testing param.combo 49 on 2015-01-02/2015-12-31"
   bband_open_dist bband_close_dist rsilong_dist
49             2.5                1           40
[1] "2015-03-06 00:00:00 BIST 1 @ 80927"
[1] "2015-03-11 00:00:00 BIST 1 @ 78257.95"
[1] "2015-06-09 00:00:00 BIST 1 @ 78410.98"
[1] "2015-07-24 00:00:00 BIST 1 @ 78151.53"
[1] "2015-07-28 00:00:00 BIST 1 @ 77687.15"
[1] "2015-08-24 00:00:00 BIST 1 @ 72638.68"

In [40]:
wfa_stats = wfa_results[[1]]$apply.paramset$tradeStats
wfa_stats[order(wfa_stats[,"Profit.To.Max.Draw"],decreasing = T),
      c("bband_open_dist","bband_close_dist","rsilong_dist","Profit.To.Max.Draw","Ann.Sharpe","End.Equity")]


bband_open_distbband_close_distrsilong_distProfit.To.Max.DrawAnn.SharpeEnd.Equity
402.0 2.0 30 1.83115247 8.6181850 2587.51
593.0 2.5 40 1.49990932 9.0604110 578.92
372.0 1.5 30 1.4931228620.2637968 4227.21
603.0 3.0 40 1.29920726 5.2021874 421.19
471.5 1.0 40 1.29905729 9.2297228 3418.82
332.0 1.0 30 0.7434396597.3415555 2220.00
573.0 2.0 40 0.73096355 3.0965299 282.13
503.0 1.0 40 0.53108477 5.0542982 739.27
522.0 1.5 40 0.37220127 5.1538522 2779.64
543.0 1.5 40 0.28701149 2.4456900 399.52
511.5 1.5 40 0.25676821 1.4980198 657.36
482.0 1.0 40 0.15932603 3.3067361 1159.97
461.0 1.0 40 -0.07333568-0.6217412 -178.81
492.5 1.0 40 -0.08603191-0.7430826 -412.64
532.5 1.5 40 -0.17288119-2.5579758 -945.24
552.0 2.0 40 -0.48086997-1.9371260 -1932.40
582.5 2.5 40 -0.53556779-2.4847283 -633.25
562.5 2.0 40 -0.82936486-8.1832093 -3175.58
321.5 1.0 30 NA NA 774.92
361.5 1.5 30 NA NA 463.42

Apply the Best Results from WFA

bband_open = 2.0

bband_close = 1.5

rsi_threshold = 30


In [46]:
setup_strat(21, 2, 1.5, 30)
applyStrategy(strategy.st, portfolio.st)
# Update portfolio & account
updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)
# Analyze performance
chart.Posn(portfolio.st, "BIST")
getEndEq(account.st,.to)


'OverSold'
[1] "2000-09-19 00:00:00 BIST 1 @ 10378"
[1] "2000-09-21 00:00:00 BIST -1 @ 11320.79"
[1] "2000-11-29 00:00:00 BIST 1 @ 9512.51"
[1] "2000-12-01 00:00:00 BIST 1 @ 7977.83"
[1] "2000-12-06 00:00:00 BIST -2 @ 10387.38"
[1] "2006-06-14 00:00:00 BIST 1 @ 32384.42"
[1] "2006-06-16 00:00:00 BIST -1 @ 33627.4"
[1] "2008-01-22 00:00:00 BIST 1 @ 43916.65"
[1] "2008-01-28 00:00:00 BIST -1 @ 44145.46"
[1] "2008-10-13 00:00:00 BIST 1 @ 29993.2"
[1] "2008-10-15 00:00:00 BIST -1 @ 30430.97"
[1] "2008-10-20 00:00:00 BIST 1 @ 26408.48"
[1] "2008-10-22 00:00:00 BIST -1 @ 25980.97"
'MeanReversion'
'Investiphi'
'Investiphi'
35709.26

WFA Results are Worse Than Regular Optimization!

  • WFA may work better in the future, or the high earnings may be a statistical fluctuation in the regular optimization.
  • OverSold strategy may be a long term strategy and testing it in a short time-span yields false variables.

Lets continue with regular optimization and add Indicator Periods to the Paramset


In [48]:
setup_strat() #Reset

param_s = c(1, 1.5, 2, 2.5, 3)
param_s2 = c(1, 1.5, 2, 2.5, 3)
param_c = c(10,20,30,40)
param_period = c(7,21,65)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'bband_open',
                 variable = list(sd = param_s),
                 label = 'bband_open_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'bband_open',
                 variable = list(n = param_period),
                 label = 'bband_open_period_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'bband_close',
                 variable = list(sd = param_s2),
                 label = 'bband_close_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'bband_close',
                 variable = list(n = param_period),
                 label = 'bband_close_period_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'indicator',
                 component.label = 'rsi',
                 variable = list(n = param_period),
                 label = 'rsi_period_dist'
)

add.distribution(strategy.st,
                 paramset.label = 'Paramset',
                 component.type = 'signal',
                 component.label = 'rsilong',
                 variable = list(threshold = param_c),
                 label = 'rsilong_dist'
)

add.distribution.constraint(strategy.st,
                            paramset.label = 'Paramset',
                            distribution.label.1 = 'bband_open_dist',
                            distribution.label.2 = 'bband_close_dist',
                            operator = '>=',
                            label = 'bband_constraint'
)


'OverSold'
'OverSold'
'OverSold'
'OverSold'
'OverSold'
'OverSold'
'OverSold'
'OverSold'

In [49]:
results <- apply.paramset(strategy.st, 
                          paramset.label='Paramset', 
                          portfolio.st=portfolio.st, 
                          account.st=account.st, 
                          verbose=FALSE)

In [53]:
stats <- results$tradeStats
stats[order(stats[,"End.Equity"],decreasing = T),
      c("bband_open_period_dist","bband_open_dist","bband_close_period_dist","bband_close_dist","rsi_period_dist","rsilong_dist","Profit.To.Max.Draw","Ann.Sharpe","End.Equity")]


bband_open_period_distbband_open_distbband_close_period_distbband_close_distrsi_period_distrsilong_distProfit.To.Max.DrawAnn.SharpeEnd.Equity
1321 7 1.5 65 1.5 7 40 1.654348 2.213442211278.54
132521 1.5 65 1.5 7 40 1.830889 2.714258174904.16
132621 2.0 65 1.5 7 40 2.377659 3.671522121778.72
1322 7 2.0 65 1.5 7 40 1.876920 3.426618105664.15
92121 2.0 65 1.5 7 30 1.691420 3.376468 95951.82
124621 2.0 7 2.0 7 40 1.481368 2.899248 95534.39
1442 7 1.5 65 1.0 21 40 4.450777 13.041076 87385.71
92021 1.5 65 1.5 7 30 1.418699 3.331879 84624.85
138121 2.0 7 2.0 21 40 2.015798 3.734305 81295.61
89665 2.5 21 2.5 7 30 1.480403 3.624730 79841.73
130165 2.5 21 2.5 7 40 1.480403 3.624730 79841.73
143665 2.5 21 2.5 21 40 1.480403 3.624730 79841.73
146021 1.5 65 1.5 21 40 3.028613 4.516705 78468.70
1441 7 1.0 65 1.0 21 40 2.256762 12.340534 73972.62
132721 2.5 65 1.5 7 40 3.306927 5.728083 68359.14
84121 2.0 7 2.0 7 30 1.048948 2.329578 66982.03
144721 1.5 65 1.0 21 40 2.349962 11.096255 63180.14
144821 2.0 65 1.0 21 40 3.589917 10.454282 62606.40
124965 2.0 7 2.0 7 40 2.035574 3.209725 62244.44
1456 7 1.5 65 1.5 21 40 4.018407 7.120164 62199.68
92221 2.5 65 1.5 7 30 2.977442 5.871901 61548.19
901 7 1.0 65 1.0 7 30 1.111213 4.550969 61302.97
138465 2.0 7 2.0 21 40 1.979270 3.162774 60522.77
94421 3.0 65 3.0 7 30 1.299309 6.816475 59180.51
134921 3.0 65 3.0 7 40 1.299309 6.816475 59180.51
1411 7 1.5 21 1.5 21 40 4.519966 3.767816 51883.20
84465 2.0 7 2.0 7 30 1.661121 3.166137 51281.76
138221 2.5 7 2.0 21 40 2.404867 4.425947 50641.09
146121 2.0 65 1.5 21 40 3.021196 6.549534 48443.97
145265 1.5 65 1.0 21 40 2.135448 8.904420 47769.24
63621 1.5 21 1.5 7 40 -0.3354202 -0.5390083 -9179.11
637 7 2.0 65 1.0 7 40 -0.1162791 -0.6192770 -9199.01
63821 2.5 65 2.0 7 30 -0.1602711 -0.7554908 -9248.13
63965 2.0 7 1.5 7 30 -0.4522993 -1.8012068 -9615.35
64065 2.5 7 2.0 65 40 -0.5621172 -8.2805132 -9821.79
64165 2.0 7 1.5 21 40 -0.4403201 -1.1825431 -9849.81
64221 3.0 65 3.0 7 10 -0.6056245 NA-10203.58
64321 3.0 65 3.0 21 30 -0.6056245 NA-10203.58
644 7 2.0 65 1.0 7 30 -0.2190029 -1.1902568-10229.28
64521 1.0 21 1.0 7 30 -0.5981217 -1.8374383-11348.05
64665 3.0 21 3.0 21 30 -0.3303170 -16.2731867-11802.91
64765 1.5 7 1.5 7 30 -0.6313806 -2.3297703-11876.49
64821 1.5 7 1.0 7 40 -0.4753768 -0.7302933-12187.61
64921 2.5 65 2.5 21 40 -0.3572970 -1.7202234-12190.79
650 7 2.0 65 2.0 7 30 -0.3219858 -1.0988315-12393.55
65121 2.0 65 2.0 7 40 -0.1152573 -0.4183563-12773.52
652 7 2.0 7 2.0 7 40 -0.8435263 -1.8744196-12777.93
65321 2.0 65 2.0 7 20 -0.6959571 -4.0198371-13350.33
65465 3.0 21 3.0 7 20 -0.3380485 -15.8369747-14284.16
655 7 2.0 7 1.5 7 40 -0.7274049 -2.2952103-17579.26
65621 2.0 65 2.0 21 40 -0.3477424 -1.4209946-18175.12
65721 1.0 7 1.0 7 30 -0.8290259 -3.2617566-18881.57
658 7 1.5 7 1.5 7 40 -0.7523376 -1.2576798-20484.46
659 7 1.0 7 1.0 7 40 -0.7860602 -1.2394990-23497.40
66065 1.5 7 1.5 7 40 -0.7472343 -2.2600476-27943.29
66121 2.5 65 2.5 7 40 -0.3406475 -2.3854629-30396.41
662 7 2.0 7 1.0 7 40 -0.8355191 -2.8902465-31020.91
663 7 1.5 7 1.0 7 40 -0.7460978 -1.5562719-33244.21
66421 2.5 65 2.5 7 30 -0.3674353 -2.7180349-34053.57
66521 2.0 65 2.0 7 30 -0.3176081 -1.4115692-38921.29

A reasonable variable list selected by Profit.to.Max.Draw and Ann.Sharpe

bband_open_period = 7

bband_open_std = 1.5

bband_close_period = 65

bband_close_std = 1.0

rsi_period = 21

rsi_threshold = 40

Profit.To.Max.Draw 4.450777

Ann.Sharpee. = 13.041076

End.Eq = +87385.71


In [56]:
setup_strat(7,1.5,1,40,65,21)
applyStrategy(strategy.st, portfolio.st)
# Update portfolio & account
updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)
# Analyze performance
chart.Posn(portfolio.st, "BIST")
getEndEq(account.st,.to)


'OverSold'
[1] "2000-07-05 00:00:00 BIST 1 @ 14638"
[1] "2000-07-13 00:00:00 BIST 1 @ 13394"
[1] "2000-07-18 00:00:00 BIST 1 @ 12737"
[1] "2000-07-31 00:00:00 BIST -3 @ 13870"
[1] "2000-09-08 00:00:00 BIST 1 @ 12172"
[1] "2000-09-19 00:00:00 BIST 1 @ 10378"
[1] "2000-10-09 00:00:00 BIST -2 @ 12071"
[1] "2000-11-29 00:00:00 BIST 1 @ 9512.51"
[1] "2001-01-05 00:00:00 BIST -1 @ 10007.3"
[1] "2001-02-13 00:00:00 BIST 1 @ 9385.06"
[1] "2001-02-14 00:00:00 BIST -1 @ 9971.69"
[1] "2001-02-20 00:00:00 BIST 1 @ 8768.52"
[1] "2001-02-22 00:00:00 BIST 1 @ 7890.4"
[1] "2001-03-02 00:00:00 BIST -2 @ 9513.77"
[1] "2001-09-24 00:00:00 BIST 1 @ 7503.71"
[1] "2001-10-09 00:00:00 BIST 1 @ 7496.28"
[1] "2001-10-12 00:00:00 BIST -2 @ 8305.34"
[1] "2002-02-21 00:00:00 BIST 1 @ 11091.91"
[1] "2002-03-05 00:00:00 BIST -1 @ 11672.52"
[1] "2002-06-03 00:00:00 BIST 1 @ 10413.7"
[1] "2002-06-10 00:00:00 BIST 1 @ 10151.02"
[1] "2002-06-18 00:00:00 BIST 1 @ 9230.7"
[1] "2002-06-25 00:00:00 BIST 1 @ 8984.58"
[1] "2002-06-27 00:00:00 BIST 1 @ 8627.42"
[1] "2002-07-15 00:00:00 BIST -5 @ 9499.41"
[1] "2002-09-11 00:00:00 BIST 1 @ 9008.26"
[1] "2002-09-12 00:00:00 BIST -1 @ 9268.47"
[1] "2003-01-08 00:00:00 BIST 1 @ 9752.86"
[1] "2003-01-09 00:00:00 BIST -1 @ 10161.21"
[1] "2003-03-18 00:00:00 BIST 1 @ 9482.92"
[1] "2003-03-19 00:00:00 BIST -1 @ 10581.5"
[1] "2003-03-25 00:00:00 BIST 1 @ 8892.65"
[1] "2003-04-04 00:00:00 BIST -1 @ 10153.15"
[1] "2004-04-30 00:00:00 BIST 1 @ 17737.88"
[1] "2004-05-05 00:00:00 BIST -1 @ 18244.74"
[1] "2004-05-10 00:00:00 BIST 1 @ 17001.97"
[1] "2004-05-18 00:00:00 BIST 1 @ 15922.44"
[1] "2004-06-07 00:00:00 BIST -2 @ 17708.15"
[1] "2005-04-29 00:00:00 BIST 1 @ 23519.63"
[1] "2005-05-05 00:00:00 BIST -1 @ 24560.22"
[1] "2006-05-23 00:00:00 BIST 1 @ 36351.06"
[1] "2006-06-08 00:00:00 BIST 1 @ 36709.55"
[1] "2006-06-14 00:00:00 BIST 1 @ 32384.42"
[1] "2006-06-26 00:00:00 BIST 1 @ 33132.3"
[1] "2006-07-03 00:00:00 BIST -4 @ 35453.31"
[1] "2008-01-22 00:00:00 BIST 1 @ 43916.65"
[1] "2008-02-08 00:00:00 BIST 1 @ 42446.85"
[1] "2008-02-19 00:00:00 BIST -2 @ 45654.11"
[1] "2008-03-18 00:00:00 BIST 1 @ 40022.14"
[1] "2008-04-01 00:00:00 BIST 1 @ 38530.05"
[1] "2008-04-03 00:00:00 BIST -2 @ 41482.96"
[1] "2008-05-26 00:00:00 BIST 1 @ 39709.72"
[1] "2008-06-04 00:00:00 BIST -1 @ 40187.79"
[1] "2008-06-24 00:00:00 BIST 1 @ 37644.35"
[1] "2008-06-27 00:00:00 BIST 1 @ 36294.78"
[1] "2008-07-18 00:00:00 BIST -2 @ 37553.59"
[1] "2008-10-17 00:00:00 BIST 1 @ 28120.29"
[1] "2008-10-27 00:00:00 BIST 1 @ 23630.26"
[1] "2008-11-18 00:00:00 BIST 1 @ 23768.63"
[1] "2008-11-28 00:00:00 BIST -3 @ 25476.97"
[1] "2009-03-06 00:00:00 BIST 1 @ 22837.78"
[1] "2009-03-20 00:00:00 BIST -1 @ 23824.24"
[1] "2010-05-26 00:00:00 BIST 1 @ 52257.07"
[1] "2010-05-27 00:00:00 BIST -1 @ 54103.5"
[1] "2010-11-30 00:00:00 BIST 1 @ 64072.16"
[1] "2010-12-23 00:00:00 BIST -1 @ 65440.22"
[1] "2011-01-31 00:00:00 BIST 1 @ 62589.06"
[1] "2011-02-03 00:00:00 BIST -1 @ 65432.43"
[1] "2011-03-02 00:00:00 BIST 1 @ 58204.85"
[1] "2011-03-11 00:00:00 BIST -1 @ 62710.45"
[1] "2011-05-20 00:00:00 BIST 1 @ 63801.11"
[1] "2011-05-30 00:00:00 BIST 1 @ 62113.12"
[1] "2011-06-01 00:00:00 BIST -2 @ 62929.05"
[1] "2011-07-22 00:00:00 BIST 1 @ 60990.46"
[1] "2011-07-29 00:00:00 BIST -1 @ 62338.64"
[1] "2011-08-05 00:00:00 BIST 1 @ 57585.71"
[1] "2011-09-08 00:00:00 BIST -1 @ 55225.05"
[1] "2012-05-10 00:00:00 BIST 1 @ 58432.73"
[1] "2012-05-15 00:00:00 BIST 1 @ 58012.3"
[1] "2012-05-24 00:00:00 BIST 1 @ 55959.78"
[1] "2012-06-11 00:00:00 BIST -3 @ 58243.09"
[1] "2013-06-21 00:00:00 BIST 1 @ 74268.98"
[1] "2013-07-16 00:00:00 BIST -1 @ 76180.34"
[1] "2013-08-22 00:00:00 BIST 1 @ 68839.44"
[1] "2013-08-28 00:00:00 BIST 1 @ 64523.88"
[1] "2013-09-11 00:00:00 BIST -2 @ 71552.65"
[1] "2013-12-20 00:00:00 BIST 1 @ 69444.28"
[1] "2013-12-26 00:00:00 BIST 1 @ 66381.72"
[1] "2014-01-27 00:00:00 BIST 1 @ 64360.15"
[1] "2014-01-29 00:00:00 BIST 1 @ 64777.12"
[1] "2014-02-17 00:00:00 BIST -4 @ 65437.15"
[1] "2014-09-25 00:00:00 BIST 1 @ 75246.1"
[1] "2014-10-03 00:00:00 BIST 1 @ 74207.74"
[1] "2014-10-09 00:00:00 BIST 1 @ 73928.93"
[1] "2014-10-21 00:00:00 BIST -3 @ 76300.95"
[1] "2015-03-05 00:00:00 BIST 1 @ 80969.69"
[1] "2015-03-11 00:00:00 BIST 1 @ 78257.95"
[1] "2015-03-16 00:00:00 BIST 1 @ 77676.66"
[1] "2015-03-20 00:00:00 BIST -3 @ 82247.73"
[1] "2015-06-02 00:00:00 BIST 1 @ 80745.27"
[1] "2015-06-03 00:00:00 BIST -1 @ 81576.74"
[1] "2015-06-09 00:00:00 BIST 1 @ 78410.98"
[1] "2015-06-12 00:00:00 BIST -1 @ 80848.27"
[1] "2015-07-24 00:00:00 BIST 1 @ 78151.53"
[1] "2015-07-28 00:00:00 BIST 1 @ 77687.15"
[1] "2015-08-03 00:00:00 BIST -2 @ 79879.67"
[1] "2015-08-21 00:00:00 BIST 1 @ 74392.08"
[1] "2015-09-07 00:00:00 BIST 1 @ 72435.48"
[1] "2015-09-18 00:00:00 BIST -2 @ 74880.25"
[1] "2015-11-27 00:00:00 BIST 1 @ 74824"
[1] "2015-12-07 00:00:00 BIST 1 @ 74265.3"
[1] "2015-12-10 00:00:00 BIST -2 @ 74583.74"
[1] "2015-12-11 00:00:00 BIST 1 @ 72354.16"
[1] "2015-12-24 00:00:00 BIST -1 @ 74044.89"
[1] "2016-01-21 00:00:00 BIST 1 @ 69603.95"
[1] "2016-01-27 00:00:00 BIST -1 @ 71808.91"
[1] "2016-05-16 00:00:00 BIST 1 @ 77959.97"
[1] "2016-05-25 00:00:00 BIST -1 @ 79472.58"
[1] "2016-06-17 00:00:00 BIST 1 @ 75347.49"
[1] "2016-06-21 00:00:00 BIST -1 @ 77559.36"
[1] "2016-07-22 00:00:00 BIST 1 @ 72728.07"
[1] "2016-07-29 00:00:00 BIST -1 @ 75306.5"
'MeanReversion'
'Investiphi'
'Investiphi'
117385.71

Comparios of the Results

Comparison is made by the best End.Equities of all optimization processes with maximum Profit.To.Max.Draw and Ann.Sharpe.

Profit.to.Max.Draw Ann.Sharpe End.Eq
Regular Opt. 5.7 11.2 63550
WFA Opt. 1.5 20.3 35709
Regular Opt. w/ Periods 4.4 13.0 117385

117385/30000 = 3.91, 391% return in 16 years.