【问题标题】:quantstrat, How could I put a stop-loss at a specific price?quantstrat,我怎样才能在特定价格设置止损?
【发布时间】:2017-06-24 13:58:28
【问题描述】:

美好的一天!

朋友们,我真的需要你的帮助!

我的问题是: 如何在特定价格设置止损?

Quantstrat 的工作方式如下(对于多头头寸): 止损价 = 入场价 - 入场价 * 门槛。

例如,我尝试运行我的代码。但是 StopLossLONG 不起作用。

如何编写停止代码?

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

谢谢!

【问题讨论】:

    标签: r quantstrat


    【解决方案1】:

    你的代码有一些奇怪的设置,我会指出,以防它是你问题的一部分:

    1) 您已经为带有标签StopLossLONG 的停止规则设置了enabled = FALSE,因此无论如何都不会应用此规则。

    2) SPY 在您的数据周期内似乎从未达到 208,因此您不会获得任何多头交易。

    您询问是否可以在特定价格设置止损。仔细阅读您的问题后,我认为您的意思是我可以将止损设置在某个绝对水平,例如此​​处的 0.005?而不是某个绝对水平的“入场价 - 某个门槛金额”。是的,你可以,如果你修改ruleSignal。这就是 name = 'ruleSignaladd.rule 函数中公开的原因......因此您可以对订单的生成方式进行自己的调整。

    这是一个示例,您的输入现在是 202,在您的示例中允许进行一次交易。它将止损位设置为 9.999(您可以将任何绝对价格水平设置为低于您的入场价)。我已将 cmets 添加到函数 ruleSignalAbsoluteStopPrice,它将替换 ruleSignal。你可以使用任何你想要的函数,只要你有正确的预期参数(比如那些用于 ruleSignal 的参数),并且你调用addOrder(或者类似addOrder,如果你也想使用这个函数的修改版本......但在执行此操作之前您需要了解 quantstrat 源)。

    如果您想了解如何以相对于现有 quantstrat 代码的其余部分正确的方式修改 ruleSignal,请尝试将 browser() 放入 ruleSignal 并逐行查看您需要更改的内容使事情正常工作。

    查看我添加的 cmets,其中我调整了现有 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
    

    现在检查您是否得到了预期的结果(止损价为 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" ""  
    

    我们看到交易仍然开放:

    > 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
    

    希望这会有所帮助。

    【讨论】:

    • 这是否意味着在您的代码中,如果最低价跌破 9.999 并且我们有一个未平仓多头头寸,那么 StopLossLONG 成为市价单并且 LX(退出单)被取消?
    • 顺便说一句...我认为您甚至不需要 getTxns(portfolio.st, "SPY") 来查看交易是否仍然开放...在订单簿中,我们有一个显示订单的“Order.Status”列仍处于“打开状态”。
    • LX 的规则将在信号值为 TRUE 时触发订单,与止损订单无关。检查交易取决于您对需要的定义。对我来说,展示交易的目的是在策略中的状态一致性方面充当双重角色,我总是会这样做,尤其是在策略变得复杂的情况下。对于任何新策略的实施,我总是需要对至少几笔交易的订单行为进行抽查。如果您发现您的规则逻辑并不完全符合您的预期,从长远来看,它可以为您节省大量时间。
    • 如果你想引入订单之间的依赖关系,所以当另一个被触发时取消(在止损和退出市场订单之间),你需要创建订单集。 OP没有这样做,所以我没有添加它。您会考虑在退出市场订单规则中添加类似 `parent = "LE" 的内容
    • 非常感谢。我现在有了更好的理解。我将尝试使用 add.rule 和 ruleSignalAbsoluteStopPrice 完全理解您的代码部分,以查看它何时被准确触发。还有一个非常明智的评论,用 getTxns 进行双重检查。
    猜你喜欢
    • 2014-06-05
    • 2015-05-14
    • 1970-01-01
    • 2018-04-05
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2018-11-25
    相关资源
    最近更新 更多