braverock / quantstrat

289 stars 114 forks source link

luxor - optimizing stop loss not working #152

Open drsramd opened 1 year ago

drsramd commented 1 year ago

Description

following script returns error in all results

View(results) print(results) <environment: 0x55bc1dd12560> print(results$error) [[1]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[2]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[3]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[4]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[5]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[6]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[7]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[8]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[9]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[10]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[11]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[12]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[13]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[14]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[15]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[16]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[17]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[18]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[19]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[20]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[21]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[22]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[23]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[24]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[25]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[26]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[27]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[28]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[29]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[30]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[31]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[32]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[33]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[34]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[35]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[36]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[37]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[38]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[39]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[40]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[41]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[42]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[43]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[44]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[45]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[46]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[47]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

[[48]] <simpleError in variable.name %in% c("timespan"): object 'variable.name' not found>

Expected behavior

non empty stats object, no errors

Minimal, reproducible example

[Insert sample data and code]

require(quantstrat) require(foreach)

if (!"doMC" %in% installed.packages()[,1]) { install.packages("doMC") }

require(doMC) registerDoMC(cores=2)

suppressWarnings(rm(list = c(paste("account", account.st, sep='.'), paste("portfolio", portfolio.st, sep='.')), pos=.blotter))

suppressWarnings(rm(list = c(strategy.st, paste("order_book", portfolio.st, sep='.')), pos=.strategy))

options(width = 240)

options(warn=1)

Sys.setenv(TZ="UTC")

startDate = '2002-10-21'

.from=startDate

.to='2008-07-04'

.to='2002-10-31'

strategy.st = 'luxor' portfolio.st = 'forex' account.st = 'IB'

.orderqty = 100000 .threshold = 0.0005 .txnfees = -6 # round-trip fee

Distributions for paramset analysis

.nsamples=100

.FastSMA = (1:20) .SlowSMA = (30:80)

.StopLoss = seq(0.05, 2.4, length.out=48)/100 .StopTrailing = seq(0.05, 2.4, length.out=48)/100 .TakeProfit = seq(0.1, 4.8, length.out=48)/100

.FastWFA = c(1, 3, 5, 7, 9) .SlowWFA = c(42, 44, 46)

generate 24x24h ISO8601 timespan vector

this includes non-ISO8601 elements (e.g. "T01:00/T00:59")

that are discarded at processing

.timespans.start<-paste(sprintf("T%02d",0:23),':00',sep='') .timespans.stop<-paste(sprintf("T%02d",0:23),':59',sep='')

.timespans<-outer(.timespans.start, .timespans.stop, FUN=paste, sep='/')

in order to run the full 24x24 hour scan above, comment out the following line:

.timespans<-c('T06:00/T10:00', 'T07:00/T11:00', 'T08:00/T12:00', 'T09:00/T13:00', 'T10:00/T14:00', 'T11:00/T15:00', 'T12:00/T16:00')

Actual arameters

.fast = 1 .slow = 30

.timespan = 'T09:00/T13:00'

.timespan = 'T00:00/T23:59'

.timespan = NULL

.stoploss <- 0.40/100 .stoptrailing <- 0.8/100 .takeprofit <- 2.0/100

FinancialInstrument

currency(c('GBP', 'USD'))

exchange_rate('GBPUSD', tick_size=0.0001)

quantmod

FinancialInstrument - method for loading data from split files

getSymbols.FI(Symbols='GBPUSD', dir=system.file('extdata',package='quantstrat'),

dir='~/R/OHLC',

          from=.from, to=.to
          , extension = 'rda'
          , use_identifier=NA

)

ALTERNATIVE WAY TO FETCH SYMBOL DATA

setSymbolLookup.FI(system.file('extdata',package='quantstrat'), 'GBPUSD')

getSymbols('GBPUSD', from=.from, to=.to, verbose=FALSE)

xts

GBPUSD = to.minutes30(GBPUSD) GBPUSD = align.time(GBPUSD, 1800)

define strategy

rm.strat(name = "luxor") rm.strat(name = "forex") rm.strat(name = "IB")

strategy(strategy.st, store=TRUE)

initPortf(portfolio.st, symbols='GBPUSD', currency='USD')

addPosLimit( portfolio=portfolio.st, symbol='GBPUSD', timestamp=startDate, maxpos=.orderqty)

initAcct(account.st, portfolios=portfolio.st, currency='USD')

initOrders(portfolio.st)

indicators

add.indicator(strategy.st, name = "SMA", arguments = list( x = quote(Cl(mktdata)[,1]), n = .fast ), label="nFast" )

add.indicator(strategy.st, name="SMA", arguments = list( x = quote(Cl(mktdata)[,1]), n = .slow ), label="nSlow" )

signals

add.signal(strategy.st, name='sigCrossover', arguments = list( columns=c("nFast","nSlow"), relationship="gte" ), label='long' )

add.signal(strategy.st, name='sigCrossover', arguments = list( columns=c("nFast","nSlow"), relationship="lt" ), label='short' )

rules

normal exit rules

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='long' , sigval=TRUE, replace=TRUE, orderside='short', ordertype='market', TxnFees=.txnfees, orderqty='all', orderset='ocoshort' ), type='exit', label='Exit2LONG' )

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='short', sigval=TRUE, replace=TRUE, orderside='long' , ordertype='market', TxnFees=.txnfees, orderqty='all', orderset='ocolong' ), type='exit', label='Exit2SHORT' )

normal entry rules

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='long' , sigval=TRUE, replace=FALSE, orderside='long' , ordertype='stoplimit', prefer='High', threshold=.threshold, TxnFees=0, orderqty=+.orderqty, osFUN=osMaxPos, orderset='ocolong' ), type='enter', label='EnterLONG' )

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='short', sigval=TRUE, replace=FALSE, orderside='short', ordertype='stoplimit', prefer='Low', threshold=-.threshold, TxnFees=0, orderqty=-.orderqty, osFUN=osMaxPos, orderset='ocoshort' ), type='enter', label='EnterSHORT' )

parameter sets

SMA

add.distribution(strategy.st, paramset.label = 'SMA', component.type = 'indicator', component.label = 'nFast', variable = list(n = .FastSMA), label = 'nFAST' )

add.distribution(strategy.st, paramset.label = 'SMA', component.type = 'indicator', component.label = 'nSlow', variable = list(n = .SlowSMA), label = 'nSLOW' )

add.distribution.constraint(strategy.st, paramset.label = 'SMA', distribution.label.1 = 'nFAST', distribution.label.2 = 'nSLOW', operator = '<', label = 'SMA' )

stop-loss

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='long' , sigval=TRUE, replace=FALSE, orderside='long', ordertype='stoplimit', tmult=TRUE, threshold=quote(.stoploss), TxnFees=.txnfees, orderqty='all', orderset='ocolong' ), type='chain', parent='EnterLONG', label='StopLossLONG', enabled=FALSE )

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='short' , sigval=TRUE, replace=FALSE, orderside='short', ordertype='stoplimit', tmult=TRUE, threshold=quote(.stoploss), TxnFees=.txnfees, orderqty='all', orderset='ocoshort' ), type='chain', parent='EnterSHORT', label='StopLossSHORT', enabled=FALSE )

add.distribution(strategy.st, paramset.label = 'StopLoss', component.type = 'chain', component.label = 'StopLossLONG', variable = list(threshold = .StopLoss), label = 'StopLossLONG' )

add.distribution(strategy.st, paramset.label = 'StopLoss', component.type = 'chain', component.label = 'StopLossSHORT', variable = list(threshold = .StopLoss), label = 'StopLossSHORT' )

add.distribution.constraint(strategy.st, paramset.label = 'StopLoss', distribution.label.1 = 'StopLossLONG', distribution.label.2 = 'StopLossSHORT', operator = '==', label = 'StopLoss' )

stop-trailing

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='long' , sigval=TRUE, replace=FALSE, orderside='long', ordertype='stoptrailing', tmult=TRUE, threshold=quote(.stoptrailing), TxnFees=.txnfees, orderqty='all', orderset='ocolong' ), type='chain', parent='EnterLONG', label='StopTrailingLONG', enabled=FALSE )

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='short' , sigval=TRUE, replace=FALSE, orderside='short', ordertype='stoptrailing', tmult=TRUE, threshold=quote(.stoptrailing), TxnFees=.txnfees, orderqty='all', orderset='ocoshort' ), type='chain', parent='EnterSHORT', label='StopTrailingSHORT', enabled=FALSE )

add.distribution(strategy.st, paramset.label = 'StopTrailing', component.type = 'chain', component.label = 'StopTrailingLONG', variable = list(threshold = .StopTrailing), label = 'StopTrailingLONG' )

add.distribution(strategy.st, paramset.label = 'StopTrailing', component.type = 'chain', component.label = 'StopTrailingSHORT', variable = list(threshold = .StopTrailing), label = 'StopTrailingSHORT' )

add.distribution.constraint(strategy.st, paramset.label = 'StopTrailing', distribution.label.1 = 'StopTrailingLONG', distribution.label.2 = 'StopTrailingSHORT', operator = '==', label = 'StopTrailing' )

take-profit

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='long' , sigval=TRUE, replace=FALSE, orderside='long', ordertype='limit', tmult=TRUE, threshold=quote(.takeprofit), TxnFees=.txnfees, orderqty='all', orderset='ocolong' ), type='chain', parent='EnterLONG', label='TakeProfitLONG', enabled=FALSE )

add.rule(strategy.st, name = 'ruleSignal', arguments=list(sigcol='short' , sigval=TRUE, replace=FALSE, orderside='short', ordertype='limit', tmult=TRUE, threshold=quote(.takeprofit), TxnFees=.txnfees, orderqty='all', orderset='ocoshort' ), type='chain', parent='EnterSHORT', label='TakeProfitSHORT', enabled=FALSE )

add.distribution(strategy.st, paramset.label = 'TakeProfit', component.type = 'chain', component.label = 'TakeProfitLONG', variable = list(threshold = .TakeProfit), label = 'TakeProfitLONG' )

add.distribution(strategy.st, paramset.label = 'TakeProfit', component.type = 'chain', component.label = 'TakeProfitSHORT', variable = list(threshold = .TakeProfit), label = 'TakeProfitSHORT' )

add.distribution.constraint(strategy.st, paramset.label = 'TakeProfit', distribution.label.1 = 'TakeProfitLONG', distribution.label.2 = 'TakeProfitSHORT', operator = '==', label = 'TakeProfit' )

Walk Forward Analysis

add.distribution(strategy.st, paramset.label = 'WFA', component.type = 'indicator', component.label = 'nFast', variable = list(n = .FastWFA), label = 'nFAST' )

add.distribution(strategy.st, paramset.label = 'WFA', component.type = 'indicator', component.label = 'nSlow', variable = list(n = .SlowWFA), label = 'nSLOW' )

add.distribution.constraint(strategy.st, paramset.label = 'WFA', distribution.label.1 = 'nFAST', distribution.label.2 = 'nSLOW', operator = '<', label = 'WFA' )

###############################################################################

save.strategy(strategy.st)

load.strategy(strategy.st)

BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules

enable.rule('luxor', 'chain', 'StopLoss')

enable.rule('luxor', 'chain', 'StopTrailing')

enable.rule('luxor', 'chain', 'TakeProfit')

END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules

############################

results <- apply.paramset(strategy.st, paramset.label='StopLoss', portfolio.st=portfolio.st, account.st=account.st, nsamples=.nsamples, verbose=TRUE)

results <- apply.paramset(strategy.st, paramset.label='SMA', portfolio.st=portfolio.st, account.st=account.st, nsamples=.nsamples, verbose=TRUE)

stats <- results$tradeStats

print(t(stats))

plot(100*stats$StopLossLONG, stats$Net.Trading.PL, type='b', xlab='Stoploss %', ylab='Net.Trading.PL', main='Luxor')

out <- applyStrategy(strategy=strategy.st,portfolios=portfolio.st) print(getOrderBook(portfolio.st)[[portfolio.st]]$GBPUSD)

###############################################################################

updatePortf(portfolio.st, Symbols='GBPUSD', Dates=paste('::',as.Date(Sys.time()),sep=''))

chart.Posn(portfolio.st, "GBPUSD")

###############################################################################

print(t(tradeStats(portfolio.st, 'GBPUSD')))

###############################################################################

Session Info

[Insert your sessionInfo() output]

sessionInfo() R version 4.2.3 (2023-03-15) Platform: x86_64-pc-linux-gnu (64-bit) Running under: Ubuntu 22.04.2 LTS Matrix products: default BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0 locale: [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C [9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C attached base packages: [1] parallel stats graphics grDevices utils datasets methods base other attached packages: [1] doMC_1.3.8 iterators_1.0.14 quantstrat_0.24 foreach_1.5.2 blotter_0.16.2 PerformanceAnalytics_2.0.4 FinancialInstrument_1.3.1 quantmod_0.4.24 [9] TTR_0.24.3 xts_0.13.1 zoo_1.8-12 loaded via a namespace (and not attached): [1] quadprog_1.5-8 lattice_0.20-45 codetools_0.2-19 MASS_7.3-58.3 grid_4.2.3 jsonlite_1.8.7 curl_5.0.1 boot_1.3-28 tools_4.2.3 compiler_4.2.3

 

| >