R: Quantstrat, как совершить сделку для полного капитала в портфеле?

Я все еще играю с примером Кванта Гая Йоллинса. В этом примере он покупает 1000 акций SPY, когда он пересекает свою 10-дневную MA. Поскольку мы определяем первоначальный капитал, можно ли всегда покупать на весь объем портфеля, а не только на 900 акций? "все" не работает для входа, только выход..

if (!exists('.blotter')) .blotter <- new.env()
if (!exists('.strategy')) .strategy <- new.env()
if (!exists('.instrument')) .instrument <- new.env()
currency("USD")
stock("SPY",currency="USD",multiplier=1)
ls(envir=FinancialInstrument:::.instrument)


initDate <- '1997-12-31'
startDate <- '1998-01-01'
endDate <- '2013-07-31'
initEq <- 1e6
Sys.setenv(TZ="UTC")
getSymbols('SPY', from=startDate, to=endDate, adjust=T)
SPY=to.monthly(SPY, indexAt='endof')
SPY$SMA10m <- SMA(Cl(SPY), 10)

# inz portfolio, account
qs.strategy <- "qsFaber"
rm.strat(qs.strategy) # remove strategy etc. if this is a re-run
initPortf(qs.strategy,'SPY', initDate=initDate)
initAcct(qs.strategy,portfolios=qs.strategy, initDate=initDate, initEq=initEq)


initOrders(portfolio=qs.strategy,initDate=initDate)
# instantiate a new strategy object
strategy(qs.strategy,store=TRUE)
add.indicator(strategy = qs.strategy, name = "SMA",
              arguments = list(x = quote(Cl(mktdata)), n=10), label="SMA10")
add.signal(qs.strategy,name="sigCrossover",
           arguments = list(columns=c("Close","SMA10"),relationship="gt"),
           label="Cl.gt.SMA")
add.signal(qs.strategy,name="sigCrossover",
           arguments = list(columns=c("Close","SMA10"),relationship="lt"),
           label="Cl.lt.SMA")

add.rule(qs.strategy, name='ruleSignal',
         arguments = list(sigcol="Cl.gt.SMA", sigval=TRUE, orderqty=900,
                          ordertype='market', orderside='long', pricemethod='market'),
         type='enter', path.dep=TRUE)
add.rule(qs.strategy, name='ruleSignal',
         arguments = list(sigcol="Cl.lt.SMA", sigval=TRUE, orderqty='all',
                          ordertype='market', orderside='long', pricemethod='market'),
         type='exit', path.dep=TRUE)


out <- applyStrategy(strategy=qs.strategy , portfolios=qs.strategy)
updatePortf(qs.strategy)
updateAcct(qs.strategy)
updateEndEq(qs.strategy)

myTheme<-chart_theme()
myTheme$col$dn.col<-'lightblue'
myTheme$col$dn.border <- 'lightgray'
myTheme$col$up.border <- 'lightgray'
# plot performance
chart.Posn(qs.strategy, Symbol = 'SPY', Dates = '1998::',theme=myTheme)
plot(add_SMA(n=10,col=4, on=1, lwd=2))

2 ответа

Вы не можете использовать orderqty="all" на записи, потому что "all" относится к текущему размеру позиции (т. е. когда вы хотите выйти из всей позиции).

Можно приобрести сумму, равную общему доступному капиталу портфеля, но вы должны определить функцию определения размера заказа. И эта функция обязательно должна пометить книгу (используя updatePortf) для определения суммы доступного капитала.

Вот игрушечный пример, который достигает того, что вы хотите.

Вам необходимо ввести функцию определения размера заказа.

Взгляните на аргументы функции ruleSignal (например formals(ruleSignal) а также ?ruleSignal).

Вы увидите, что есть аргумент osFUN, где вы можете написать свою пользовательскую функцию, которая будет определять, как вы заказываете размер.

Вы изменяете соответствующие параметры в add.rule ввести размер ордера (на входных торгах).

osFUN_all_eq <- function (data, timestamp, orderqty, ordertype, orderside, equity, portfolio, symbol, ruletype, ..., initEq) {
    datePos <- format(timestamp,"%Y-%m-%d")

    updatePortf(Portfolio = portfolio, Symbol = symbol, Dates = paste0(start(data), "/", datePos))

    trading_pl <- sum(.getPortfolio(portfolio)$summary$Net.Trading.PL)
    # The total equity in the strategy for this symbol (and this symbol only in isolation always, as this is how quantstrat by default works with applyStrategy)
    equity <- initEq + trading_pl
    ClosePrice <- getPrice(data, prefer = "Close")[datePos]
    UnitSize <- as.numeric(trunc(equity / ClosePrice))
    UnitSize <- osMaxPos(data, timestamp, UnitSize, ordertype, orderside, portfolio, symbol, ruletype, digits=0)
    UnitSize
}





library(quantstrat)

currency("USD")
stock("SPY",currency="USD",multiplier=1)


initDate <- '1997-12-31'
startDate <- '1998-01-01'
endDate <- '2013-07-31'
initEq <- 1e6
Sys.setenv(TZ="UTC")
getSymbols('SPY', from=startDate, to=endDate, adjust=T)
SPY=to.monthly(SPY, indexAt='endof')
SPY$SMA10m <- SMA(Cl(SPY), 10)


qs.strategy <- "qsFaber"
rm.strat(qs.strategy) # remove strategy etc. if this is a re-run
initPortf(qs.strategy,'SPY', initDate=initDate)
initAcct(qs.strategy,portfolios=qs.strategy, initDate=initDate, initEq=initEq)


initOrders(portfolio=qs.strategy,initDate=initDate)
# instantiate a new strategy object
strategy(qs.strategy,store=TRUE)


# Specify the max quantity you could hold in the SPY instrument.  Here we simply assume 1e5 units. You could reduce this number to limit the exposure
max_qty_traded <- 1e5
addPosLimit(qs.strategy, "SPY", timestamp = startDate, maxpos = max_qty_traded)

add.indicator(strategy = qs.strategy, name = "SMA",
              arguments = list(x = quote(Cl(mktdata)), n=10), label="SMA10")
add.signal(qs.strategy,name="sigCrossover",
           arguments = list(columns=c("Close","SMA10"),relationship="gt"),
           label="Cl.gt.SMA")
add.signal(qs.strategy,name="sigCrossover",
           arguments = list(columns=c("Close","SMA10"),relationship="lt"),
           label="Cl.lt.SMA")

add.rule(qs.strategy, name='ruleSignal',
         arguments = list(sigcol="Cl.gt.SMA",
                          sigval=TRUE,
                          orderqty = 1, # the acutal orderqty size becomes redundant when supplying a function to the argument `osFUN`
                          osFUN = osFUN_all_eq,
                          ordertype='market', orderside='long', pricemethod='market'),
         type='enter', path.dep=TRUE)


add.rule(qs.strategy, name='ruleSignal',
         arguments = list(sigcol="Cl.lt.SMA",
                          sigval=TRUE,
                          orderqty='all', # flatten all open long positions
                          ordertype='market',
                          orderside='long',
                          pricemethod='market'),
                          type='exit',
         path.dep=TRUE)


# supply initEq parameter and its value, which pass through to `osFUN`
out <- applyStrategy(strategy=qs.strategy , portfolios=qs.strategy, initEq=initEq)
updatePortf(qs.strategy)
updateAcct(qs.strategy)
updateEndEq(qs.strategy)

myTheme<-chart_theme()
myTheme$col$dn.col<-'lightblue'
myTheme$col$dn.border <- 'lightgray'
myTheme$col$up.border <- 'lightgray'
# plot performance
chart.Posn(qs.strategy, Symbol = 'SPY', Dates = '1998::',theme=myTheme)
plot(add_SMA(n=10,col=4, on=1, lwd=2))

Есть несколько вещей, которые вы должны рассмотреть в функции определения размера заказа:

1) Если у вас уже есть открытая позиция, хотите ли вы разрешить "укладку" / пирамиду позиций на определенной стороне? Например, если вы хотите иметь только одну позицию, на которую вы больше не вносите свой вклад, вы можете включить getPosQty(qs.strategy, "SPY", timestamp) в вашем osFUN и верните 0, если текущая позиция не равна 0.

2) Хотите максимальный размер сделки? Это может быть обработано с помощью addPosLimit() как было сделано в этом примере выше.

Я знаю, что этот вопрос был опубликован давно, но посмотрите пакет "IKTrading" и функцию определения размера заказа "osMaxDollar". Вот сообщение в блоге на эту тему; Когда вы используете эту функцию определения размера ордера, вы можете установить стоимость каждой сделки в долларах и общую позицию.

https://quantstrattrader.wordpress.com/2014/08/29/comparing-atr-order-sizing-to-max-dollar-order-sizing/

Другие вопросы по тегам