R: Quantstrat how to make a transaction for complete equity in portfolio?
Asked Answered
J

3

5

I'm still playing around with Guy Yollins quantstrat example. In this example he buys 1000 shares of the SPY when it crosses its 10 day MA. Since we define an initial equity, is it possible to always buy for the whole portfolio amount and not just 900 shares? 'all' didn't work for the enter, just the exit..

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))
Jaborandi answered 21/10, 2013 at 12:13 Comment(0)
T
4

You cannot use orderqty="all" on entries because "all" refers to the current position size (i.e., when you want to exit the entire position).

It's possible to purchase an amount equal to the total available portfolio equity, but you have to define a custom order sizing function. And that function would necessarily have to mark the book (using updatePortf) in order to determine the amount of available equity.

Tamworth answered 21/10, 2013 at 12:23 Comment(5)
Thx for your answer. Do you have a link to an example how to do that?Jaborandi
@MichiZH: No, I don't.Tamworth
But any hint how I get the current equity which I can use in these rules? I mean such a custom order sizing function would need to access the current equity...Jaborandi
@MichiZH: I already told you that. Use updatePorf to mark the book.Tamworth
Sorry I'm still new to R and especially quantstrat, quantmod etc. and the learning curve is quite steep. Sorry that I didn't understand the first time and still don't know how to implement it.Jaborandi
M
3

Here is a toy example that achieves what you want.

You need to introduce an order sizing function.

Take a look at the arguments to the function ruleSignal (e.g. formals(ruleSignal) and ?ruleSignal).

You'll see there is an argument osFUN, which is where you can write your custom function that will determine how you order size.

You modify the appropriate parameters in add.rule to introduce ordersizing (on entry trades).

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))

There are a few things you should consider in an order sizing function:

1) If you already have a position open, do you want to permit "stacking"/pyramidying of positions on a particular side? For example, if you want to just have one position on, which you don't contribute further to, you could include getPosQty(qs.strategy, "SPY", timestamp) in your osFUN and return 0 if the current position held is not 0.

2) Do you want a max trade size? This can be handled using addPosLimit() as was done in this example above.

Misdoubt answered 20/4, 2019 at 7:4 Comment(0)
H
1

I know this question was posted long ago, but check out package "IKTrading," and the order sizing function "osMaxDollar." Here's a blog post on the topic; when you use this order sizing function you can set the dollar value of each trade and the total position.

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

Hoad answered 30/7, 2015 at 19:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.