What is a trading algorithm?

Quantitative trading algorithms are pervasive in the current market. Big banks pay mathmeticians and computer scientists hundreds of thousands of dollars to design the next best algorithm that can outperform the market as well as other banks. So what is a trading algorithm exactly?

A trading algorithm is a program that automates the trading of stocks, options, bonds, etc., to allow the creator to play the market based off variables like time, volume, and price that a human trader could not consistently monitor and trade on. When you hear about things like high-frequency-trading, arbitrage (exploting the price differences of a stock on two exchanges), latency, or machine learning for finance, trading algorithms are the vehicle used to execute those strategies.

Building an algorithm

The general structure of a basic trading algorithm is:

if(x){
  buy
}
else if(y){
  sell
}
else{no change}

Using this structure, let’s build a trading algorithm that buys a stock based off the percent increase between the previous and current day, and sells the stock when that percent occurs happens again.

We’ll begin by filling in some arguments in the code shown above.

First_Strategy <- function(Input){
  if(PercentIncrease > Input & Position < 1){ #Don't buy if you're already in a bought position
   buy
  }
  else if(abs(PercentIncrease) > Input & Position == 1 ){
    #You can only sell if you are in a bought position (have stocks to sell)
   sell
  }
  else{no change}
}

This code means that if the percent increase between days is greater than a user defined number, then buy the stock only if we have not already in a bought position. Or, if we are in a bought position, then sell when the percent increase is greater than the user defined paramter. Using the absolute value function here means that we will sell if the percent increase is greater than 3% or less than -3%. This makes sure we don’t hold on to stocks as they are falling rapidly in price.

Backtesting

The next step in creating our algorithm is to backtest it.

To do this, we will use a for loop and pricing data from google (yahoo is not working currently).

First lets get our data:

getSymbols("SPY", src = "google")

SPY             <- as.data.frame(SPY) #Transform timeseries to data frame
SPY$Date        <- row.names(SPY) #Create Date column
SPY <- SPY %>%
  filter(Date > "2012-01-01") #Filter for data after 2012

colnames(SPY) <- c("Open", "High", "Low", "Close", "Volume", "Date") #Rename columns
SPY <- SPY[,c(6,1,2,3,4,5)] #Reorder columns

SPY$PercentIncrease <- 100*(as.numeric(Delt(SPY$Close)))


We will be running our strategy on an index of the S&P500 (SPY) after 2012.

The for loop should go row by row through the data and execute the hypothetical buys and sells. We’ll need to define some new variables to help us with this.

First_Strategy <- function(Data, Input){
  Data$Signal  <- ""  #Signal will visually show whether the stock was bought, sold, or no change
  nrows     <- nrow(Data)  #Easier way of referencing the number of rows in the data
  Position  <- 0 #Indicates whether we are in a bought, sold, or null position (begin in null position)
  
  for(i in 2:nrows){
   if(Data$PercentIncrease[i] > Input & Position < 1){ #Buy when price increases
     Data$Signal[i]     <- "buy" 
     Position           <- 1  #We are now in a bought position
    }
    else if(abs(Data$PercentIncrease[i]) > Input & Position == 1 ){ 
      #Sell when price increases or decreases
     Data$Signal[i]     <- "sell"
     Position           <- -1 #We are now in a sold position
    }
    else{Data$Signal[i] <- "no change"}
  }
  return(Data) #Return the data frame
}



This strategy works fine so far, but we want to know if we are making or losing money on these trades, and what our final profit is.

First_Strategy <- function(Data, Input){
  Data$Signal <- "" #Signal will visually show whether the stock was bought, sold, or no change
  Data$`Buy or Sell Price`  <- 0  #How much did we buy or sell the stock for?
  Data$`Possible Transaction Profit` <- 0  #Profit if you had sold on that day
  Data$`Real Cumulative Profit`      <- 0  #Running total of Buy or Sell Price

  nrows <- nrow(Data) #Easier way of referencing the number of rows in the data
  Position <- 0  #Indicates whether we are in a bought, sold, or null position
  
  for(i in 2:nrows){
   if(Data$PercentIncrease[i] > Input & Position < 1){ #Buy when price increases
     Data$Signal[i]              <- "buy" 
     Data$`Buy or Sell Price`[i] <- -Data$Close[i] 
     MostRecentBuy               <- Data$Close[i] #Store this buy price for later
     Position                    <- 1  #We are now in a bought position
    }
   else if(abs(Data$PercentIncrease[i]) > Input & Position == 1 ){ 
     #Sell when price increases or decreases
     Data$Signal[i]               <- "sell"
     Data$`Buy or Sell Price`[i]  <- Data$Close[i]
     Position                     <- -1 #We are now in a sold position
    }
   else{Data$Signal[i] <- "no change"} #end of buy/sell ifs
    
        #Calculate transaction profit
    if(Position != 0){Data$`Possible Transaction Profit`[i] <- Data$Close[i]-MostRecentBuy }
    
    Data$`Real Cumulative Profit`[i] <- ifelse(Position == 1, sum(Data$`Buy or Sell Price`[1:i]) + Data$Close[i],                                                                  sum(Data$`Buy or Sell Price`[1:i])) #Calculate real profit

    
   if(Position > 0 & i == nrows){ 
     Data$`Real Cumulative Profit`[i]   <- sum(Data$`Buy or Sell Price`[1:i]) + Data$Close[nrows] 
     } #If we end in a bought position, calculate profit as if we had sold on the last day

  }#End for loop
  return(Data) #Return the data frame
}



With our finished trading algorithm above, let’s test it out on the SPY data.
Here we tell the program to use SPY as the ‘Data’ argument and 0.5 as the ‘Input’.

Test <- First_Strategy(SPY, 0.5)

If we wanted to visualizes the results of this, you can view Test in R, or we could graph it.