Site icon Trading Analytics and Machine Learning

Introduction to Some Metrics of Algorithmic Trading

Price Cross Strategy

Introduction

In the previous simple moving average price cross analysis, the SMA with the highest returns was computed by checking all price cross possibilities from 2 to 250 period simple moving averages. The result was that an uncommon length for a simple moving average was discovered to have the best overall returns over the period of 2016 to 2022; however, depending on the overall conditions of the market it may under perform other moving averages.

In addition, as mentioned in the previous price cross analysis, there are other metrics that are important to analyze in regards to determining if a strategy is the right one to use (this will depend on the trader, as each trader has varied levels of risk tolerance). These values will be used to truly compare different strategies as there can be a significant amount of variation between them. For instance, if a strategy has a certain point estimate for its accuracy or the mean return it must be compared against other strategies. This will provide statistical evidence for the performance estimates of trading algorithms. So, we will explore a little of the differences between returns can capitalize on the differences if there are any.

Understand the Returns of Bitcoin

BTC_ret <- BTC %>% 
  mutate(sma_38 = sma(Close, 38),
         signal = replace_na(ifelse(Close > sma_38, 1, -1), 0),
         ret = c(NA, diff(log(Close))),
         pc_ret = ret * lag(signal)) %>%
  select(date, ret, pc_ret) %>%
  pivot_longer(c(ret, pc_ret), names_to = "strat")

strat_mean <- BTC_ret %>%
  filter(strat == "pc_ret") %>%
  summarize(mean(value, na.rm = TRUE)* 100) %>%
  pull() %>%
  round(3)

hold_mean <- BTC_ret %>%
  filter(strat == "ret") %>%
  summarize(mean(value, na.rm = TRUE)* 100) %>%
  pull() %>%
  round(3)
  
ggplot(BTC_ret, aes(value * 100, fill = strat)) +
  geom_histogram(bins = 100, position = "jitter", alpha = .5) +
  geom_vline(xintercept = strat_mean, linetype = "twodash", color = "orange") +
  annotate("text", label = paste0("Mean Return (Cross):\n", strat_mean, "%"),
    x = strat_mean + 20, y = 300, size = 4, colour = "orange"
  ) +
  geom_vline(xintercept = hold_mean, linetype = "twodash", color = "lightblue") +
  annotate("text", label = paste0("Mean Return (BTC):\n", hold_mean, "%"),
    x = hold_mean + 20, y = 100, size = 4, colour = "lightblue"
  ) + theme_dark()
## Warning: Removed 2 rows containing non-finite values (stat_bin).

An important factor to understanding a strategy is understanding the returns of the strategy and its following distribution and how it compares against the asset itself corresponding assets.And based on the histogram presented above of both the returns generated from the price cross strategy of the 38 period simple moving average and the returns of bitcoin, the strategy was able to maintain a higher average return than bitcoin (nearly double that of bitcoin). Thus, it seems as though it was able to negate some of the downside losses, this can be further analyzed using a quantile value at risk and through statistical testing.

Understanding the Returns the Price Cross Strategy (Entry and Exity Only)

BTC_pc <- BTC %>% 
  mutate(sma_38 = sma(Close, 38),
         signal = replace_na(ifelse(Close > sma_38, 1, -1), 0),
         Ent_Ext = ifelse(signal == lag(signal), 0, 1)) %>%
   filter(Ent_Ext == 1) %>%
   mutate(ret = c(NA, diff(log(Close))),
          pc_ret =  ret*lag(signal))
  
BTC_pc %>%
  ggplot(aes(pc_ret*100)) +
  geom_histogram(bins = 100, fill = "lightblue") +
  geom_vline(xintercept = mean(BTC_pc$pc_ret, na.rm  = TRUE)* 100, linetype = "twodash", color = "orange") +
  annotate("text", label = paste0("Mean Return:\n", round(mean(BTC_pc$pc_ret, na.rm  = TRUE), 3)*100, "%"),
    x = mean(BTC_pc$pc_ret, na.rm  = TRUE)*100 + 12, y = 35, size = 4, colour = "orange"
  ) +
  geom_vline(xintercept = round(quantile(BTC_pc$pc_ret, probs = 0.05, na.rm  = TRUE), 3)*100, linetype = "twodash", color = "gold") +
  annotate("text", label = paste0("Lower 5% Return:\n", round(quantile(BTC_pc$pc_ret, probs = 0.05, na.rm  = TRUE), 3)*100, "%"),
    x =  round(quantile(BTC_pc$pc_ret, probs = 0.05, na.rm  = TRUE), 3)*100, y = 30, size = 4, colour = "gold"
  ) +
  labs(x = "Returns (%)",y = "Count", title = "Histogram of Returns for 38-period SMA Price Crossover") +
  theme_dark()
## Warning: Removed 1 rows containing non-finite values (stat_bin).

The histogram presented above is representation of the returns considering only the entry and exit of the positions without considering what happens in between them. Thus, there is drawdown and missed opportunities that is omitted from the trades. This current version of the dataset is what we will be using to develop some of the statistics for the trading algorithm also known as an alpha.

Information to gather

Using the returns of the entry and exit positions the algorithm will be treated similarly to a classification model and the information that will be collected are the following:

  • Accuracy (Interval and Point Estimate)
  • Sensitivity
  • Specificity
  • Value At Risk (VaR)
  • Average Number of a time period in a Trade
  • Number of trades for the Trading Period
  • Max Loss

Conclusion

There are significant amount of important information that can be collected which is overwhelming for one post so this will be split into a series of posts to cover and explain the statistics to be collected. In addition, statistical testing will be used to compare the results of the trading algorithm (alpha) to determine whether there truly is a difference between one another.

Exit mobile version