Skip to content

luxor - optimizing stop loss not working #152

@drsramd

Description

@drsramd

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

 

| >

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions