Quantstrat, How can I put a stop loss at a specific price?

Good day!

Friends I really need your help!

My question is: How can I put a stop loss at a specific price?

Quantstrat works like this (for a long position): Stop price = initial price - entry price threshold *.

For example, I am trying to run my code. But StopLossLONG doesn't work.

How do I write the code to stop?

library('TTR')
library('blotter')
library("quantmod")
require(quantstrat)

from <- "2016-04-01"
to <- "2016-07-01"

SPY <- getSymbols.yahoo('SPY',
                        env = .GlobalEnv,
                        return.class = 'xts',
                        index.class = 'Date',
                        from = from,
                        to = to,
                        periodicity = "daily",
                        auto.assign = FALSE)

SPY <- SPY[, c(1, 2, 3, 4, 5)]
names(SPY) <- c('Open','High','Low','Close','Volume')

level <- function(ts, level) {
    ts$level <- level
    res <- ts$level
    names(res) <- c("")
    return(res)
}

rm(list = ls(.blotter), envir = .blotter)
symbols = "SPY"
currency('USD')
initDate = from
from = from
to = to
initEq = 100000
strName = "test"

stock(symbols, currency = "USD", tick_size = 0.001, multiplier = 1)
getInstrument(symbols, type = "instrument")

strategy.st <- strName
portfolio.st <- strName
account.st <- strName
rm.strat(portfolio.st)
rm.strat(strategy.st)

initPortf(portfolio.st, symbols = symbols, initDate = initDate, currency = 'USD')
initAcct(account.st, portfolios = portfolio.st, initDate = initDate, currency = 'USD', initEq = initEq)
initOrders(portfolio.st, initDate = initDate)

strategy(strategy.st, store = TRUE)

addPosLimit(portfolio.st, symbols, timestamp = initDate, maxpos = 1, minpos = -1)

# indicators

add.indicator(strategy.st, name = "level",
              arguments = list(ts = quote((mktdata)), level = 208.0),
              label = "LEV208")

add.indicator(strategy.st, name = "level",
              arguments = list(ts = quote((mktdata)), level = 212.0),
              label = "LEV212")

add.indicator(strategy.st, name = "level",
              arguments = list(ts = quote((mktdata)), level = 207.0),
              label = "LEV207")

# signals

add.signal(strategy.st, name = "sigCrossover",
           arguments = list(columns = c("Close", "LEV208"),
                            relationship = "gt"),
           label = "OPEN")

add.signal(strategy.st, name = "sigCrossover",
           arguments = list(columns = c("Close", "LEV212"),
                            relationship = "gt"),
           label = "CLOSE")

# rules

add.rule(strategy.st, name = "ruleSignal",
         arguments = list(sigcol = "OPEN", sigval = TRUE,
                        orderside = "long",
                        ordertype = "market",
                        prefer = "Open",
                        orderqty = 1,
                        replace = FALSE,
                        osFUN = osMaxPos
         ),
         type = "enter",
         label = "LE"
)

add.rule(strategy.st, name = "ruleSignal",
         arguments = list(sigcol = "CLOSE", sigval = TRUE,
                        orderside = "long",
                        ordertype = "market",
                        prefer = "Open",
                        orderqty = "all",
                        replace = FALSE
         ),
         type = "exit",
         label = "LX"
)

add.rule(strategy.st,
         name = "ruleSignal",
         arguments = list(sigcol = "OPEN",
                          sigval = TRUE,
                          replace = FALSE,
                          orderside = "long",
                          ordertype = "stoplimit",
                          threshold = quote(0.005),
                          orderqty = "all",
                          orderset = "ocolong"),
         type = "chain",
         parent = "LE",
         label = "StopLossLONG",
         enabled = FALSE
)


applyStrategy(strategy.st, portfolio.st)
save.strategy(strategy.st)

orderbook <- getOrderBook(portfolio.st)
orderbook

      

Thank!

+3


source to share


1 answer


There are some odd settings in your code that I will point out if this is part of your problem:

1) You have set the enabled = FALSE

label to break rule StopLossLONG

, so this rule will not apply regardless.

2) It SPY

never seems to reach 208 during your data period, so you won't receive long input transactions.

You ask if you can set a stop at a specific price. After reading your question carefully, I think you mean that I can stop stopping at some absolute level like 0.005? Instead of some absolute level "initial price - some threshold value". Yes you can if you change ruleSignal

. This is why it name = 'ruleSignal

appears in the function add.rule

... so you can make your own settings for creating orders.

Here's an example where your entry is now at 202, which allows one trade in your example. It sets the stop level at 9.999 (you can set any absolute price level below your entry price). I have added comments to the function ruleSignalAbsoluteStopPrice

that will replace ruleSignal

. You can use any function you want, as long as you have the correct expected arguments (for example for ruleSignal) and you are calling addOrder

(or something like addOrder

if you want to use a modified version of that function ... but you need to understand the source of the quantumstratum before than to do it).

If you want to figure out how to change ruleSignal

in a way that is correct with respect to the rest of the existing quantumstrat code, try placing browser()

Signal inside the rule and step by line to see what you need to change in order for everything to work correctly.

See the comments I added where I changed parts of the existing code ruleSignal

.



library('TTR')
library('blotter')
library("quantmod")
require(quantstrat)

# Define new function to replace 'ruleSignal' for long stoplimit orders:

ruleSignalAbsoluteStopPrice <- function (mktdata = mktdata, timestamp, sigcol, sigval, orderqty = 0,
                                         ordertype, orderside = NULL, orderset = NULL, threshold = NULL,
                                         tmult = FALSE, replace = TRUE, delay = 1e-04, osFUN = "osNoOp",
                                         pricemethod = c("market", "opside", "active"), portfolio,
                                         symbol, ..., ruletype, TxnFees = 0, prefer = NULL, sethold = FALSE,
                                         label = "", order.price = NULL, chain.price = NULL, time.in.force = "",
                                         absoluteStopPrice = 9.999)
{

    if (!is.function(osFUN))
        osFUN <- match.fun(osFUN)
    if (hasArg(curIndex))
        curIndex <- eval(match.call(expand.dots = TRUE)$curIndex,
                         parent.frame())
    else curIndex <- mktdata[timestamp, which.i = TRUE]
    # Just for long orderside and stoplimit order types.
    if (curIndex > 0 && curIndex <= nrow(mktdata) && ordertype == "stoplimit" && orderside == "long" && (ruletype ==
                                                                                                         "chain" )) {
        pricemethod <- pricemethod[1]
        if (hasArg(prefer))
            prefer = match.call(expand.dots = TRUE)$prefer
        else prefer = NULL

        # chain.price is the transaction price of the long trade.
        # Handle the case where the price may be less than your absolute stop level (here we skip entering a long position):
        if (chain.price <= absoluteStopPrice)
            return()

        threshold <- chain.price - absoluteStopPrice
        # Ensure that tmult = FALSE when using this approach.

        if (is.null(orderside) & !isTRUE(orderqty == 0)) {
            curqty <- getPosQty(Portfolio = portfolio, Symbol = symbol,
                                Date = timestamp)
            if (curqty > 0) {
                orderside <- "long"
            }
            else if (curqty < 0) {
                orderside <- "short"
            }
            else {
                if (orderqty > 0)
                    orderside <- "long"
                else orderside <- "short"
            }
        }
        if (orderqty == "all") {
            if (orderside == "long") {
                tmpqty <- 1
            }
            else {
                tmpqty <- -1
            }
        }
        else {
            tmpqty <- orderqty
        }
        if (!is.null(order.price)) {
            orderprice <- order.price
        }
        else if (!is.null(chain.price)) {
            orderprice <- chain.price
        }
        else {

        }
        if (is.null(orderset))
            orderset = NA
        if (orderqty != "all") {
            orderqty <- osFUN(strategy = strategy, data = mktdata,
                              timestamp = timestamp, orderqty = orderqty, ordertype = ordertype,
                              orderside = orderside, portfolio = portfolio,
                              symbol = symbol, ... = ..., ruletype = ruletype,
                              orderprice = as.numeric(orderprice))
        }
        if (!is.null(orderqty) && orderqty != 0 && length(orderprice)) {

            # All the arguments passed to `addOrder` are reasonable, and similar to what ruleSignal expects
            addOrder(portfolio = portfolio, symbol = symbol,
                     timestamp = timestamp, qty = orderqty, price = as.numeric(orderprice),
                     ordertype = ordertype, side = orderside, orderset = orderset,
                     threshold = threshold, status = "open", replace = replace,
                     delay = delay, tmult = tmult, ... = ..., prefer = prefer,
                     TxnFees = TxnFees, label = label, time.in.force = time.in.force)
        }
    }
    if (sethold)
        hold <<- TRUE
}



from <- "2016-04-01"
to <- "2016-07-01"

SPY <- getSymbols.yahoo('SPY',
                        env = .GlobalEnv,
                        return.class = 'xts',
                        index.class = 'Date',
                        from = from,
                        to = to,
                        periodicity = "daily",
                        auto.assign = FALSE)

SPY <- SPY[, c(1, 2, 3, 4, 5)]
names(SPY) <- c('Open','High','Low','Close','Volume')

level <- function(ts, level) {
    ts$level <- level
    res <- ts$level
    names(res) <- c("")
    return(res)
}

rm(list = ls(.blotter), envir = .blotter)
symbols = "SPY"
currency('USD')
initDate = from
from = from
to = to
initEq = 100000
strName = "test"

stock(symbols, currency = "USD", tick_size = 0.001, multiplier = 1)
getInstrument(symbols, type = "instrument")

strategy.st <- strName
portfolio.st <- strName
account.st <- strName
rm.strat(portfolio.st)
rm.strat(strategy.st)

initPortf(portfolio.st, symbols = symbols, initDate = initDate, currency = 'USD')
initAcct(account.st, portfolios = portfolio.st, initDate = initDate, currency = 'USD', initEq = initEq)
initOrders(portfolio.st, initDate = initDate)

strategy(strategy.st, store = TRUE)

addPosLimit(portfolio.st, symbols, timestamp = initDate, maxpos = 1, minpos = -1)

# indicators

# Set the level to 202 to allow one entry trade at least:

add.indicator(strategy.st, name = "level",
              arguments = list(ts = quote((mktdata)), level = 202.0),
              label = "LEV202")

add.indicator(strategy.st, name = "level",
              arguments = list(ts = quote((mktdata)), level = 212.0),
              label = "LEV212")

add.indicator(strategy.st, name = "level",
              arguments = list(ts = quote((mktdata)), level = 207.0),
              label = "LEV207")

# signals

add.signal(strategy.st, name = "sigCrossover",
           arguments = list(columns = c("Close", "LEV202"),
                            relationship = "gt"),
           label = "OPEN")

add.signal(strategy.st, name = "sigCrossover",
           arguments = list(columns = c("Close", "LEV212"),
                            relationship = "gt"),
           label = "CLOSE")

# rules

add.rule(strategy.st, name = "ruleSignal",
         arguments = list(sigcol = "OPEN", sigval = TRUE,
                          orderside = "long",
                          ordertype = "market",
                          prefer = "Open",
                          orderqty = 1,
                          replace = FALSE,
                          osFUN = osMaxPos
         ),
         type = "enter",
         label = "LE"
)

add.rule(strategy.st, name = "ruleSignal",
         arguments = list(sigcol = "CLOSE", sigval = TRUE,
                          orderside = "long",
                          ordertype = "market",
                          prefer = "Open",
                          orderqty = "all",
                          replace = FALSE
         ),
         type = "exit",
         label = "LX"
)

add.rule(strategy.st,
         name = "ruleSignalAbsoluteStopPrice",
         arguments = list(sigcol = "OPEN",
                          sigval = TRUE,
                          replace = FALSE,
                          orderside = "long",
                          ordertype = "stoplimit",
                          #threshold = quote(0.005),  don't bother setting threshold argument as ruleSignalAbsoluteStopPrice won't used the passed in argument 'threshold'.
                          absoluteStopPrice = 9.999, # Demonstrat that we can use new arguments related to the `ruleSignalAbsoluteStopPrice`` function
                          tmult = FALSE, # tmult is potentially used in `addOrder`
                          orderqty = "all",
                          orderset = "ocolong"),
         type = "chain",
         parent = "LE",
         label = "StopLossLONG",
         enabled = TRUE # Enable this rule
)


applyStrategy(strategy.st, portfolio.st)
save.strategy(strategy.st)

orderbook <- getOrderBook(portfolio.st)
orderbook

      

Now check if you get what you expected (stoplimit at 9.999):

> orderbook
$test
$test$SPY
           Order.Qty Order.Price Order.Type  Order.Side Order.Threshold Order.Status Order.StatusTime      Prefer Order.Set Txn.Fees Rule           Time.In.Force
2016-04-13 "1"       "201.827"   "market"    "long"     NA              "closed"     "2016-04-14 00:00:00" "Open" NA        "0"      "LE"           ""           
2016-04-14 "all"     "9.999"     "stoplimit" "long"     "-192.812707"   "open"       NA                    ""     "ocolong" "0"      "StopLossLONG" ""  

      

And we can see that the trade is still open:

> getTxns(portfolio.st, "SPY")
                    Txn.Qty Txn.Price Txn.Fees Txn.Value Txn.Avg.Cost Net.Txn.Realized.PL
2016-04-01 00:00:00       0      0.00        0      0.00         0.00                   0
2016-04-13 20:00:00       1    202.87        0    202.87       202.87                   0

      

Hope it helps.

+2


source







All Articles