I am looking for examples of Parameter optimization codes in Quantstrat when using custom indicators. Most of the examples I can find online use SMA, MACD and other classic indicators. It doesn't help me much as I'd like mostly to optmize trading systems with custom indicators.
Does anyone have relevant links or material ?
To be more specific, I am trying for the first time the indicator optimization option. The indicator I am using is the momentum of the MACD forest . I'm trying to assess the effectiveness of this indicator vs. the usual MACD crossing signal line. But I don't want to focus too much on this specific indicator as the goal for me is to have a viable optimization code for future custom indicators I'll be using.
Here is the code, the data is intraday EURUSD quotes (5 mins candles) :
library(quantstrat)
Sys.setenv(TZ = "UTC")
currency(c('EUR', 'USD'))
exchange_rate(c('EURUSD'), tick_size=0.0001)
init_date <- "2018-01-07"
start_date <- "2018-01-08"
end_date <- "2018-01-08"
init_equity <- 1e8 # $100,000,000
adjustment <- FALSE
basic_symbols <- function() {
symbols <- c(
"EUR"
)
}
symbols <- basic_symbols()
portfolio.st <- "Port.Luxor.Opt"
account.st <- "Acct.Luxor.Opt"
strategy.st <- "Strat.Luxor.Opt"
rm.strat(portfolio.st)
rm.strat(account.st)
initPortf(name = portfolio.st,
symbols = symbols,
initDate = init_date)
initAcct(name = account.st,
portfolios = portfolio.st,
initDate = init_date,
initEq = init_equity)
initOrders(portfolio = portfolio.st,
symbols = symbols,
initDate = init_date)
strategy(strategy.st, store = TRUE)
fastMA_custom = 12
fastMA_custom2 = 12
slowMA_custom = 26
slowMA_custom2 = 26
signalMA_custom = 9
signalMA_custom2 = 9
maType="EMA"
MAforest = 3
forest <- function(x){
step1 <- EMA(x,fastMA_custom)
step2 <- EMA(x,slowMA_custom)
step3 <- step1-step2
step4 <- EMA(step3,signalMA_custom)
step5 <- step3-step4
return(step5)
}
smaforest <- function(x){
step1 <- EMA(x,fastMA_custom2)
step2 <- EMA(x,slowMA_custom2)
step3 <- step1-step2
step4 <- EMA(step3,signalMA_custom2)
step5 <- step3-step4
step6 <- EMA(step5,MAforest)
return(step6)
}
add.indicator(strategy = strategy.st,
name ="forest",
arguments = list(x=quote(Cl(mktdata))),
label="forest")
add.indicator(strategy=strategy.st,
name ="smaforest",
arguments = list(x=quote(Cl(mktdata))),
label="smaforest")
add.distribution(strategy.st,
paramset.label = "forestopt",
component.type = "indicator",
component.label = "forest",
variable = list(fastMA_custom= 8:14),
label = "fastMA_custom")
add.signal(strategy = strategy.st,
name="sigCrossover",
arguments = list(columns = c("forest", "smaforest"),
relationship = "gte"),
label = "long")
add.signal(strategy = strategy.st,
name="sigCrossover",
arguments = list(columns = c("forest", "smaforest"),
relationship = "lte"),
label = "short")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "long",
sigval = TRUE,
orderqty = 100000,
ordertype = "market",
orderside = "long",
TxnFees = -1,
replace = FALSE),
type = "enter",
label = "EnterLONG")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "short",
sigval = TRUE,
orderqty = -100000,
ordertype = "market",
orderside = "short",
replace = FALSE,
TxnFees = -1
),
type = "enter",
label = "EnterSHORT")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "short",
sigval = TRUE,
orderside = "long",
ordertype = "market",
orderqty = "all",
TxnFees = -1,
replace = TRUE),
type = "exit",
label = "Exit2SHORT")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "long",
sigval = TRUE,
orderside = "short",
ordertype = "market",
orderqty = "all",
TxnFees = -1,
replace = TRUE),
type = "exit",
label = "Exit2LONG")
addPosLimit(portfolio.st, 'EUR', timestamp=initDate, maxpos=500, minpos=0)
resultsopt <- apply.paramset(strategy.st,
paramset.label = "forestopt",
portfolio.st = portfolio.st,
account.st = account.st,
nsamples = 0)
The backtesting without the optimization part works perfectly. It's really the optimization bit that causes the error.
Here is the error I get :
error calling combine function: "simpleError in fun(result.1, result.2, result.3, result.4, result.5, result.6, result.7): attempt to select less than one element"
答案 0 :(得分:2)
请在下次提供可重复的数据集。
以下是与您的示例代码非常相似的示例代码,可用于优化自定义指标。希望你应该清楚如何调整你的代码。你做错了几件事。特别是,您必须提供forest
的形式参数,或者您希望在quantstrat中优化的任何其他自定义函数。通常,默认情况下全局定义所有“n”变量是个坏主意。将它们直接提供给add.indicator
调用中的参数。就像下面针对forest
函数所做的那样。
library(quantstrat)
Sys.setenv(TZ = "UTC")
currency(c('USD'))
symbols <- "AAPL"
getSymbols(symbols)
stock(symbols, currency = "USD")
AAPL <- AAPL["2016/"]
init_date <- "2017-01-07"
start_date <- "2018-01-31"
end_date <- "2018-01-31"
init_equity <- 1e8 # $100,000,000
adjustment <- FALSE
portfolio.st <- "Luxor.Opt"
account.st <- "Luxor.Opt"
strategy.st <- "Luxor.Opt"
rm.strat(name = portfolio.st)
initPortf(name = portfolio.st,
symbols = symbols)
initAcct(name = account.st,
portfolios = portfolio.st,
initEq = init_equity)
initOrders(portfolio = portfolio.st,
symbols = symbols)
strategy(strategy.st, store = TRUE)
fastMA_custom2 = 12
slowMA_custom2 = 26
signalMA_custom2 = 9
maType="EMA"
MAforest = 3
forest <- function(x, fastMA_custom, slowMA_custom, signalMA_custom){
step1 <- EMA(x,fastMA_custom)
step2 <- EMA(x,slowMA_custom)
step3 <- step1-step2
step4 <- EMA(step3,signalMA_custom)
step5 <- step3-step4
return(step5)
}
smaforest <- function(x){
step1 <- EMA(x,fastMA_custom2)
step2 <- EMA(x,slowMA_custom2)
step3 <- step1-step2
step4 <- EMA(step3,signalMA_custom2)
step5 <- step3-step4
step6 <- EMA(step5,MAforest)
return(step6)
}
add.indicator(strategy = strategy.st,
name ="forest",
arguments = list(x=quote(Cl(mktdata)),
fastMA_custom = 12,
slowMA_custom = 26,
signalMA_custom = 9
),
label="forest")
add.indicator(strategy=strategy.st,
name ="smaforest",
arguments = list(x=quote(Cl(mktdata))),
label="smaforest")
add.signal(strategy = strategy.st,
name="sigCrossover",
arguments = list(columns = c("forest", "smaforest"),
relationship = "gte"),
label = "long")
add.signal(strategy = strategy.st,
name="sigCrossover",
arguments = list(columns = c("forest", "smaforest"),
relationship = "lte"),
label = "short")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "long",
sigval = TRUE,
orderqty = 100000,
ordertype = "market",
orderside = "long",
TxnFees = -1,
replace = FALSE),
type = "enter",
label = "EnterLONG")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "short",
sigval = TRUE,
orderqty = -100000,
ordertype = "market",
orderside = "short",
replace = FALSE,
TxnFees = -1
),
type = "enter",
label = "EnterSHORT")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "short",
sigval = TRUE,
orderside = "long",
ordertype = "market",
orderqty = "all",
TxnFees = -1,
replace = TRUE),
type = "exit",
label = "Exit2SHORT")
add.rule(strategy.st,
name = "ruleSignal",
arguments = list(sigcol = "long",
sigval = TRUE,
orderside = "short",
ordertype = "market",
orderqty = "all",
TxnFees = -1,
replace = TRUE),
type = "exit",
label = "Exit2LONG")
addPosLimit(portfolio.st, symbols[], timestamp=init_date, maxpos=500, minpos=0)
# applyStrategy(strategy.st, portfolio.st)
#
# updatePortf(portfolio.st)
# tradeStats(portfolio.st, symbols)
# Portfolio Symbol Num.Txns Num.Trades Net.Trading.PL Avg.Trade.PL Med.Trade.PL Largest.Winner Largest.Loser Gross.Profits Gross.Losses Std.Dev.Trade.PL Std.Err.Trade.PL Percent.Positive Percent.Negative Profit.Factor
# AAPL Luxor.Opt AAPL 127 63 -45123.5 -28493.01 -46000.1 1328999 -1047001 10371975 -12167035 474783 59817.04 42.85714 57.14286 0.8524653
# Avg.Win.Trade Med.Win.Trade Avg.Losing.Trade Med.Losing.Trade Avg.Daily.PL Med.Daily.PL Std.Dev.Daily.PL Std.Err.Daily.PL Ann.Sharpe Max.Drawdown Profit.To.Max.Draw Avg.WinLoss.Ratio Med.WinLoss.Ratio Max.Equity Min.Equity
# AAPL 384147.2 305999.5 -337973.2 -298000.6 -28493.01 -46000.1 474783 59817.04 -0.952672 -3182097 -0.01418043 1.13662 1.026842 985976.4 -2196121
# End.Equity
# AAPL -45123.5
add.distribution(strategy.st,
paramset.label = "forestopt", #The label we will use when we want to run this optimisation in paramset
component.type = "indicator", # The custom function is of indicator type (not other alternatives including signal or rule)
component.label = "forest", #this is the name of your custom function
variable = list(fastMA_custom = seq(8, 12, by = 2)),
label = "myForestOptLabel") #choose whatever you want
resultsopt <- apply.paramset(strategy.st,
paramset.label = "forestopt",
portfolio.st = portfolio.st,
account.st = account.st,
nsamples = 0)
# Check, results are equal in the case where fastMA_custom = 12 compared to when running `applyStrategy`:
resultsopt$tradeStats
# myForestOptLabel Portfolio Symbol Num.Txns Num.Trades Net.Trading.PL Avg.Trade.PL Med.Trade.PL Largest.Winner Largest.Loser Gross.Profits Gross.Losses Std.Dev.Trade.PL Std.Err.Trade.PL Percent.Positive Percent.Negative
# 1 8 Luxor.Opt.1 AAPL 97 48 2609902.7 23790.64 -34500.75 1405999 -1055001 9615975 -8474024 492362.4 71066.39 43.75000 56.25000
# 2 10 Luxor.Opt.2 AAPL 105 52 -340106.5 -34770.27 -52500.75 1405999 -1047001 8538977 -10347031 480790.5 66673.64 40.38462 59.61538
# 3 12 Luxor.Opt.3 AAPL 127 63 -45123.5 -28493.01 -46000.10 1328999 -1047001 10371975 -12167035 474783.0 59817.04 42.85714 57.14286
# Profit.Factor Avg.Win.Trade Med.Win.Trade Avg.Losing.Trade Med.Losing.Trade Avg.Daily.PL Med.Daily.PL Std.Dev.Daily.PL Std.Err.Daily.PL Ann.Sharpe Max.Drawdown Profit.To.Max.Draw Avg.WinLoss.Ratio Med.WinLoss.Ratio Max.Equity
# 1 1.1347590 457903.6 386998.5 -313852.8 -237000.5 23790.64 -34500.75 492362.4 71066.39 0.7670464 -2444032 1.06786773 1.458976 1.632902 3585933.7
# 2 0.8252586 406617.9 334998.1 -333775.2 -245002.2 -34770.27 -52500.75 480790.5 66673.64 -1.1480282 -3152090 -0.10789872 1.218239 1.367327 1343982.9
# 3 0.8524653 384147.2 305999.5 -337973.2 -298000.6 -28493.01 -46000.10 474783.0 59817.04 -0.9526720 -3182097 -0.01418043 1.136620 1.026842 985976.4
# Min.Equity End.Equity
# 1 -1122012 2609902.7
# 2 -1808107 -340106.5
# 3 -2196121 -45123.5
# Results for fastMA_custom = 12 are identical.
上面我还展示了如何快速检查apply.paramsets
输出,通过apply.Strategy
将其与n = 12的个案进行比较。这样做是个好主意。检查。