rtradingalgorithmic-tradingquantstrat

Why doesn't it close the position? quantstrat package


I have a simple signal strategy

0 = close all positions

1 = open buy (close sell if available)

-1= open a sell (close a buy if there is one)

Only one position can be opened during trading

Here is the code for generating fake data and calculating signals

require(quantstrat)

set.seed(1)
fake_data <- rnorm(100) |> cumsum() |> xts(order.by=as.POSIXct(x=60*1:100, origin='2021-07-01'))
colnames(fake_data) <-'Close'

make_seq <- function() sample(c(-1,0,1),size=1) |> rep(sample(3:20,1))
fake_data$signal <- lapply(1:50,\(x) make_seq())  |> unlist() |> tail(n = length(fake_data))

# signal 
chart_Series(fake_data)
abline(h=0)



fake_data$buy_open <- 0
fake_data$buy_close <- 0
fake_data$sell_open <- 0
fake_data$sell_close <- 0

S <- fake_data$signal |> coredata() |> as.vector()
for(i in 2:nrow(fake_data)){
  if(S[i-1]!=  1 & S[i]==  1) fake_data$buy_open[i]   <- 1
  if(S[i-1]==  1 & S[i]!=  1) fake_data$buy_close[i]  <- 1
  if(S[i-1]!= -1 & S[i]== -1) fake_data$sell_open[i]  <- 1
  if(S[i-1]== -1 & S[i]!= -1) fake_data$sell_close[i] <- 1
}

Next I create rules for trading

rm.strat(strat.st)

strat.st <- "FAKESTRAT"
currency("USD")
stock("fake_data",currency = "USD")
initPortf(strat.st, symbols="fake_data")
initEq<-1000
initAcct(strat.st, portfolios=strat.st, initEq=initEq)
initOrders(portfolio=strat.st)
strategy(name=strat.st,store=TRUE)

addPosLimit("FAKESTRAT", "fake_data", maxpos = 1, timestamp = start(fake_data)-1)


# enterLong  exitLong

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="buy_open",
                        sigval=TRUE,
                        orderqty=1,
                        ordertype='market', 
                        orderside='long',
                        osFUN = osMaxPos),
         type="enter",
         label="enterLong"
)

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="buy_close",
                        sigval=TRUE,
                        orderqty="all",
                        ordertype='market', 
                        orderside='long'),
         type="exit",
         label="exitLong"
)

# enterShort  exitShort

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="sell_open",
                        sigval=TRUE,
                        orderqty=-1,
                        ordertype='market', 
                        orderside='short',
                        osFUN = osMaxPos),
         type="enter",
         label="enterShort"
)

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="sell_close",
                        sigval=TRUE,
                        orderqty="all",
                        ordertype='market', 
                        orderside='short'),
         type="exit",
         label="exitShort"
)




out<-applyStrategy(strat.st , portfolios=strat.st, verbose=T)
updatePortf(strat.st)
book <- getOrderBook(portfolio=strat.st)

....

print(book)


book
$FAKESTRAT
$FAKESTRAT$fake_data
                    Order.Qty      Order.Price Order.Type Order.Side Order.Threshold
2021-07-01 03:24:00        -1 3.59680448297358     market      short            <NA>
2021-07-01 03:40:00       all 3.68104715087989     market      short            <NA>
2021-07-01 03:40:00         1 3.68104715087989     market       long            <NA>
2021-07-01 03:54:00        -1 4.02025008047271     market      short            <NA>
2021-07-01 04:12:00       all 10.7346453103169     market      short            <NA>
2021-07-01 04:35:00        -1 13.8781211399328     market      short            <NA>
                    Order.Status    Order.StatusTime Prefer Order.Set Txn.Fees       Rule
2021-07-01 03:24:00       closed 2021-07-01 03:25:00             <NA>        0 enterShort
2021-07-01 03:40:00     replaced 2021-07-01 03:40:00             <NA>        0  exitShort
2021-07-01 03:40:00       closed 2021-07-01 03:41:00             <NA>        0  enterLong
2021-07-01 03:54:00       closed 2021-07-01 03:55:00             <NA>        0 enterShort
2021-07-01 04:12:00       closed 2021-07-01 04:13:00             <NA>        0  exitShort
2021-07-01 04:35:00       closed 2021-07-01 04:36:00             <NA>        0 enterShort
                    Time.In.Force
2021-07-01 03:24:00              
2021-07-01 03:40:00              
2021-07-01 03:40:00              
2021-07-01 03:54:00              
2021-07-01 04:12:00              
2021-07-01 04:35:00     

And I don't understand why the open position is long

2021-07-01 03:40:00         1 3.68104715087989     market       long

was not closed when the sell signal arrived

 2021-07-01 03:54:00        -1 4.02025008047271     market      short

Solution

  • I don't understand how this works but the answer lies in the replace variable.

    All you need to do is include it in the rule for opening and closing a position

    replace=TRUE for close position

    replace=FALSE for open position

    # enterLong  exitLong
    
    add.rule(strat.st,"ruleSignal", 
             arguments=list(sigcol="buy_open",
                            sigval=TRUE,
                            replace=FALSE,
                            orderqty=1,
                            ordertype='market', 
                            orderside='long',
                            osFUN = osMaxPos),
             type="enter",
             label="enterLong"
    )
    
    add.rule(strat.st,"ruleSignal", 
             arguments=list(sigcol="buy_close",
                            sigval=TRUE,
                            replace=TRUE,
                            orderqty="all",
                            ordertype='market', 
                            orderside='long'),
             type="exit",
             label="exitLong"
    )
    

    The same needs to be done for sales rules

    book$FAKESTRAT$fake_data[,c(1,4,11)]
                        Order.Qty Order.Side       Rule
    2021-07-01 03:24:00        -1      short enterShort
    2021-07-01 03:40:00       all      short  exitShort
    2021-07-01 03:40:00         1       long  enterLong
    2021-07-01 03:54:00       all       long   exitLong
    2021-07-01 03:54:00        -1      short enterShort
    2021-07-01 04:12:00       all      short  exitShort
    2021-07-01 04:35:00        -1      short enterShort