# Chapter 5 Basic Strategy

Let’s kick things off with a variation of the Luxor trading strategy. This strategy uses two SMA indicators: SMA(10) and SMA(30).

If the SMA(10) indicator is greater than or equal to the SMA(30) indicator we will submit a stoplimit long order to open and close any short positions that may be open. If the SMA(10) is less than the SMA(30) we will submit a stoplimit short order to open and close any open long positions.

If SMA(10) >= SMA(30):

BTC short, BTO long

Else if SMA(10) < SMA(30):

STC long, STO short

Note: Remember we have already set some variables earlier in the book. If you copy and paste the code below by itself you will get errors. There will be complete tutorials listed later in the book.

## 5.1 Strategy Setup

We load our symbols into symbols.

symbols <- basic_symbols()
getSymbols(Symbols = symbols,
src = "yahoo",
index.class = "POSIXct",
from = start_date,
to = end_date,
adjust = adjustment)
## [1] "IWM" "QQQ" "SPY"

After we’ve loaded our symbols we use FinancialInstrument::stock() to define the meta-data for our symbols. In this case we’re defining the currency in USD (US Dollars) with a multiplier of 1. Multiplier is applied to price. This will vary depending on the financial instrument you are working on but for stocks it should always be 1.

stock(symbols,
currency = "USD",
multiplier = 1)
## [1] "IWM" "QQQ" "SPY"

Next we’ll assign proper names for our portfolio, account and strategy objects. These can be any name you want and should be based on how you intend to log the data later on.

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

We remove any residuals from previous runs by clearing out the portfolio and account values. At this point for what we have done so far this is unnecessary. However, it’s a good habit to include this with all of your scripts as data stored in memory can affect results or generate errors.

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

Now we initialize our portfolio, account and orders. We will also store our strategy to save for later.

initPortf(name = portfolio.st,
symbols = symbols,
initDate = init_date)
## [1] "Port.Luxor"
initAcct(name = account.st,
portfolios = portfolio.st,
initDate = init_date,
initEq = init_equity)
## [1] "Acct.Luxor"
initOrders(portfolio = portfolio.st,
symbols = symbols,
initDate = init_date)
strategy(strategy.st, store = TRUE)

Indicators are functions used to measure a variable. A SMA is just an average of the previous n prices; typically closing price. So SMA(10) is just an average of the last 10 closing prices.

This is where the TTR library comes in; short for Technical Trading Rules. SMA() is a function of TTR as are many other indicators. If you want MACD, RSI, Bollinger Bands, etc., you will use the TTR library.

add.indicator(strategy = strategy.st,
name = "SMA",
arguments = list(x = quote(Cl(mktdata)),
n = 10),
label = "nFast")
## [1] "Strat.Luxor"
add.indicator(strategy = strategy.st,
name = "SMA",
arguments = list(x = quote(Cl(mktdata)),
n = 30),
label = "nSlow")
## [1] "Strat.Luxor"

add.indicator is a function of quantstrat and adds our indicators to our strategy object. For now we’ll use the following parameters:

• strategy: As we stored our strategy name in the strategy.st variable all we need to do is pass that variable. Otherwise we would provide a string. Use variables when this will become redundant as we move along.

• name: Indicator function; for this example SMA. We only pass the name of the function as a character string. Parameters for the function are passed into the arguments parameter…

• arguments: If we look at ?SMA we see required parameters are x and n with the default n being 10. x is the price object. In our example we are using closing prices.

• label: Label of the variable that will be added to our dataset. This must be unique for each indicator we add.

## 5.5 Apply Strategy

Now we get to the fun part! Do or die. Here we’ll find out if we built our strategy correctly or if we have any errors in our code. Cross your fingers. Let’s go!

cwd <- getwd()
setwd("./_data/")
results_file <- paste("results", strategy.st, "RData", sep = ".")
if( file.exists(results_file) ) {
} else {
results <- applyStrategy(strategy.st, portfolios = portfolio.st)
updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)
if(checkBlotterUpdate(portfolio.st, account.st, verbose = TRUE)) {
save(list = "results", file = results_file)
save.strategy(strategy.st)
}
}
setwd(cwd)

Awesome! We know that at least our code is good.

applyStrategy() is the function we will run when we have a straight strategy. What I mean by that is a strategy that doesn’t test different parameters. We’ll get to that type of testing later.

You can see it’s a pretty simple call; we just pass our strategy.st variable as the first parameter and our portfolio as the second parameter. There is no need to get into additional parameters at the moment.

We won’t show the results of any more applyStrategy runs to save space. Just know that if you get trade output you should be good.

Next we update our portfolio and account objects. We do this with the updatePortf(), updateAcct() and updateEndEq() functions. updatePortf calculates the P&L for each symbol in symbols. updateAcct calculcates the equity from the portfolio data. And updateEndEq updates the ending equity for the account. They must be called in order.

We also use the checkBlotterUpdate() mentioned in 3.3. We’re looking for a TRUE value to be returned. Anything FALSE will need to be researched. (If you forgot to clear our your portfolio or strategy with the rm.strat() call mentioned earlier this can result in a FALSE value).

If checkBlotterUpdate returns true we save the results and our strategy (save.strategy) as a RData file into our _data directory. We’ll use them for analysis later.