braverock / quantstrat

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

problems in buying stocks below high/ open using ordertype="limit"

kvekka opened this issue · comments

Was trying to buy stocks at a certain price offset to the open price in a long position. A simple moving average rule - buy at price lower than the price at open when nFast is gte nSlow; sell when nSlow is gt nFast, taking cues from https://r.789695.n4.nabble.com/Quantstrat-Entering-a-limit-order-below-the-open-price-td4717350.html

Problem that is occurring is as follows:
Order.Status on "2018-02-16" is "closed" but it should not be because, the Order.Price = "265.24377134782" which is not within the OHLC for the day after it.
It is executed 2 days after, on 21st.
SPY data
SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted
2018-02-16 267.2438 270.1878 267.1947 268.0190 160420100 264.3314
2018-02-20 266.9592 268.5686 265.4577 266.3409 86369700 262.6763
2018-02-21 266.8316 269.5990 264.9081 265.0161 98883700 261.3698

mktdata is as follows:
mktdata["2018-02-16::2018-02-21"]
SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted SMA.nFast SMA.nSlow long short

2018-02-16 267.2438 270.1878 267.1947 268.0190 160420100 264.3314 264.3919 262.6681 1 NA
2018-02-20 266.9592 268.5686 265.4577 266.3409 86369700 262.6763 265.5813 262.8714 NA NA
2018-02-21 266.8316 269.5990 264.9081 265.0161 98883700 261.3698 266.3762 263.0450 NA NA

rules used to buy includes - ordertype ="limit", with threshold = 2

Code used is detailed below:
library(dplyr)
library(quantstrat)

init_date <- "2017-01-01"
start_date <- "2017-01-01"
end_date <- "2018-12-31"
init_equity <- 1e6 # $10,000
.orderqty <- 100
Sys.setenv(TZ = "UTC")
fast <- 5
slow <- 73
currency("USD")
symbols <- symbol <- "SPY"
stock(symbols,
currency = "USD",
multiplier = 1)
for(symbol in symbols){getSymbols(Symbols = symbol, src = "yahoo",auto.assign=T,index.class = "POSIXct",from = start_date,to = end_date,adjust = T)}
symbols %>% get() %>% chart_Series()

portfolio.st <- "Port.Luxor"
account.st <- "Acct.Luxor"
strategy.st <- "Strat.Luxor"

rm.strat(strategy.st)
rm.strat(portfolio.st)
rm.strat(account.st)

initPortf(name = portfolio.st, symbols = symbols, initDate = init_date)

initAcct(name = account.st, portfolios = portfolio.st, initDate = init_date, initEq = init_equity)

initOrders(portfolio = portfolio.st, symbols = symbols, initDate = init_date)

strategy(strategy.st, store = TRUE)

add.indicator(strategy = strategy.st, name = "SMA", arguments = list(x = quote(Cl(mktdata)), n = fast), label = "nFast")

add.indicator(strategy = strategy.st, name = "SMA", arguments = list(x = quote(Cl(mktdata)), n = slow), label = "nSlow")

add.signal(strategy = strategy.st, name="sigCrossover", arguments = list(columns = c("nFast", "nSlow"), relationship = "gte"), label = "long")

add.signal(strategy = strategy.st, name="sigCrossover", arguments = list(columns = c("nFast", "nSlow"), relationship = "lt"), label = "short")

add.rule(strategy.st, name = "ruleSignal",
arguments = list(sigcol = "short",
sigval = TRUE,
orderside = "long",
ordertype = "market",
prefer = "Open",
orderqty = "all",
TxnFees = -10,
replace = T),
type = "exit",
label = "Exit2SHORT")

add.rule(strategy = strategy.st, name = "ruleSignal",
arguments = list(sigcol = "long",
sigval = TRUE,
orderqty = .orderqty,
ordertype = "limit",
orderside = "long",
threshold = 2,
prefer = "Open",
# threshold = 0.01, #used to buy at 1% below open
# tmult = T, #used to buy at % below open
TxnFees = -10,
replace = F),
type = "enter",
label = "EnterLONG")

applyStrategy(strategy = strategy.st, portfolios = portfolio.st)
updatePortf(portfolio.st)
daterange <- time(getPortfolio(portfolio.st)$summary)[-1]
updateAcct(account.st, daterange)
updateEndEq(account.st)
tstats <- tradeStats(Portfolios = portfolio.st)
tstats %>% t()
chart.Posn(Portfolio = portfolio.st, Symbol = symbols, TA= c("add_SMA(n=fast, col='blue')", "add_SMA(n=slow, col='red')"))
getOrderBook(portfolio.st)$Port.Luxor$SPY
SPY[getOrderBook(portfolio.st)$Port.Luxor$SPY %>% index() %>% as.character()]

Hi @kvekka looks fine to me. Singal fires on 2018-02-16 and the order price (265.2438, or Open on 2018-02-16 minus order threshold of 2) is inside the OHLC on the day of the entry transaction, 2018-02-21.

image

The order status is "retrospectively" updated to "closed" on 2018-02-16, when the order is filled on 2018-02-21.

Hi @kvekka can we close this issue?

Yes, sure, the issue can be closed.
I was thinking that the limit order is either implemented on the next day (when the condition are satisfied) or cancelled (if the conditions are not satisfied).
It seems that the order is carried over even further till the conditions are met or is replaced.
Again, thank you for your valuable time.

No problem, thanks for confirming

Limit orders are GTC (good till canceled), not GTD (good today). You need to cancel an order if you don't want it in the market.

Good point thanks @braverock. FYI @kvekka the time in force (TIF) is documented in the help file for ?addOrder. You may find the other documentation rather insightful.

Thank you @braverock and @jaymon0703
Your suggestions and guidances are really helpful.