Get Rich Quick Trading Strategies (and why they don’t work)

Every aspiring millionaire who comes to the markets armed with some programming ability has implemented a systematic Get Rich Quick (GRQ) trading strategy.

Of course, they don’t work.

Deep down even the greenest of newbies knows this. Yet, still, we are compelled to give them a try, just once, just for fun (or so we tell ourselves).

In this series, we’ll explore three of the Get Rich Quick trading strategies that tempted me back in the early years of my market adventures. In particular, we’ll have a look at why they don’t work…and what we might do instead.

The Martingale

Martingale refers not to a trading strategy, but to a betting scheme whereby the bettor doubles the stake following each losing bet until a winner occurs.

As is frequently the case in GRQ strategies, naïve traders mistake such a betting scheme for an edge.

If you have an edge, you have a positive expectancy because the odds are tilted in your favour. Casinos have edges simply by the design of their games, such as the roulette wheel paying out 35:1 on a correct guess that has a probability of only 1 in 36.

Betting strategies don’t fundamentally change these odds – how could they?

I think this is probably the most misunderstood point that tricks people into thinking Martingale is a good idea: a losing streak does not increase the odds of the next bet being a winner.

The Martingale as a Get Rich Quick (from now on, “GRQ”) trading strategy also has a fundamental constraint: no one can go on increasing their bankroll infinitely. Eventually, you come up against the hard limit imposed by your bank account or your broker’s willingness to extend you margin.

That means that with Martingale betting, you’re guaranteed to lose because the winning and losing streaks of a trading strategy – like a game of chance in a casino – are random.

Said differently… even if you do have an edge, you’re eventually going to have a losing streak that puts you out of business if you use Martingale sizing.

Let’s Do Some Simulation

Here’s some Zorro Lite-C code for simulating a random trading strategy with Martingale position sizing and an account that started with $10,000:

function run()
{
    setf(PlotMode, PL_FINE);
    StartDate = 2010;
    Capital = 10000;
    BarPeriod = 1440;
    
    if(Equity - MarginVal < Capital)         
        Lots = 0;
    
    // random trading strategy 
    Stop = TakeProfit = ATR(100);
    Lots = pow(2, LossStreakTotal);  // Martingale position sizing
    
    if(NumOpenTotal == 0) {
        if(random() < 0)
            enterShort();
        else 
            enterLong();
    }
    set(PLOTNOW);
}

When it holds no position, it enters long or short randomly using the minimum position size possible, sticks in a stop and take profit limit, and then doubles down on the next trade if the previous one was a loser.

If I run this a few times over any financial market, I get equity curves that look like this:

And this…

Occasionally, I get one that looks like this:

That last one is an example of where the sequence of winning and losing trades didn’t blow up our trading account over the simulation period.

How often does that happen?

We can get some empirical insight by simulating our strategy a few thousand times and plotting a histogram of the results. Zorro makes that quite easy. This code runs that same simulation 5,000 times and spits out a histogram of account ending balances:

void plotHistogram(string Name,var Val,var Step,var Weight,int Color)
{
    var Bucket = floor(Val/Step);
    plotBar(Name, Bucket, Step*Bucket, Weight, SUM+BARS+LBL2, Color);   
}

function run()
{
    setf(PlotMode, PL_FINE);
    StartDate = 2010;
    Capital = 10000;
    BarPeriod = 1440;
    NumTotalCycles = 5000;
    
    if(Equity - MarginVal < Capital)         
        Lots = 0;
    
    // random trading strategy 
    Stop = TakeProfit = ATR(100);
    Lots = pow(2, LossStreakTotal);  // Martingale position sizing
    
    if(NumOpenTotal == 0) {
        if(random() < 0)
            enterShort();
        else 
            enterLong();
    }
    set(PLOTNOW);
    if(is(EXITRUN)) 
    {
        var finalValue = max(0, Equity);
        plotHistogram("Account Equity", finalValue, 500, 1, RED);   
    }
}

Here’s the result.

This is a histogram of our terminal account equity at the end of the simulation.

We lost our shirts in about 80% of the simulations… Complete Capital Destruction.

In  20% of the simulations, we ended up with (slightly) more money than we started with if we Martingale this strategy for ten years (ignoring real-world constraints and frictions, like transaction costs).

Of course, that 20% of favourable simulations doesn’t mean the strategy has an edge. It simply means that the sequence of winning and losing trades that played out just happened to be favourable a few times. Given a long enough time horizon, that 20% of simulations that made money will go to 0%.

Effect of Increasing Trading Frequency

Although we don’t have an unlimited amount of data over which to demonstrate this, we can do something analogous by increasing the frequency of our trades. Whatever edge we have will be more closely born out in the simulation if we can get more trades. We can do that by simply decreasing the bar period to say 60 minutes, so now the strategy gets the opportunity to trade every hour.

Give it a try – you’ll find that almost certainly, all the simulations will go bust.

 

Effect of Increasing Starting Capital

Finally, a well-capitalised trader might be tempted to simply increase their bankroll – that is, give themselves more room for tolerating longer losing streaks and bigger positions.

Let’s see how a starting capital of $100,000 plays out over 5,000 simulations of our original daily-frequency strategy:

Indeed, as expected we see fewer blow-ups over this ten year period. But no sensible trader would mistake that for an edge – we know that over a long enough time horizon those finishing balances are all going to zero.

 

Probability of Going Bust with Martingale position sizing

Let’s think about this in terms of probability.

No matter your initial position size, if you continue to double it with every loss, there’s some loss streak, \( N \), that sends you bust. That loss streak depends only on the size of your initial stake. For simplicity, let’s measure that initial stake as a percentage of account equity.

Switching over to R, here’s a function for calculating that loss streak:

blow_up_loss_streak <- function(initial_size = 0.01) {
  # loss streak required to lose starting capital
  
  loss_pct <- cumsum(initial_size*2^(c(0:50)))
  return(which(loss_pct > 1)[1])
}

If we start by betting 1% of our bankroll and commence a losing streak, our cumulative losses after each trade are 1%, 3%, 7%, 15%, 31%, 63%, 127% – so by the 7th trade we’ve blown up.

The probability of this loss streak occurring is a function of the strategy’s win rate:   \( P(streak) = (1 - w)^N \) where \( P(streak) \) is the probability of having a losing streak of sufficient length to blow up the account, \( w \) is the strategy’s win rate, and \( N \) is the length of the losing streak.

The probability of that not happening in \( n \) trades is \( (1 - P(streak))^n \), from which we can find \( n_{50} \), the number of trades we’d need to take to have a 50% of chance of blowing up: \( n_{50} = \frac{log(0.5)}{log(1 - P(streak))} \).

Here’s some R code for determining \( n_{50} \) given an initial bet size and a strategy win rate:

n_50 <- function(win_rate, initial_size) {
  
  # loss streak to blow up
  streak <- blow_up_loss_streak(initial_size)
  
  # probability of streak of losses given win rate
  P_blow_up <- (1 - win_rate)^streak
  
  # number of trades for whcih probability of blowing up exceeds 50%
  n <- log(0.5)/log(1 - P_blow_up)   
  
  return(n)
}

And here’s some code for plotting the relationship between initial stake, win rate and \( n_{50} \):

library(tidyverse)

win_rates <- seq(0.5, 0.65, by = 0.02)
initial_sizes <- c(0.0025, 0.005, 0.01)

df <- data.frame(
  win_rate = rep(win_rates, length(initial_sizes)), 
  initial_size = (
    map(initial_sizes, ~rep(., length(win_rates))) %>% 
    unlist()
  )
) 
df <- df%>%
  mutate(n_50 = map2_dbl(df$win_rate, df$initial_size, .f = n_50)) 

df %>%
  ggplot(aes(x = win_rate, y = n_50, colour = as.factor(initial_size))) +
    geom_line() +
    labs(
      x = "Win Rate",
      y = "n 50",
      title = "Martingale Position Sizing",
      subtitle = "Number of trades for 50% probability of blowing up",
      colour = "Initial size"
    ) +
  theme_bw()

Here’s the resulting plot:

Conclusion

Martingale is not a trading strategy – it’s a bet sizing technique that relies on infinite capital, which of course no one possesses. In the real world, it’s mathematically guaranteed to blow up your trading account.

If you had a real edge, you’d be foolish to trade it using the Martingale approach, since you’re essentially removing your edge and guaranteeing eventual failure. You will run out of bankroll eventually, even if you do have an edge.

So what’s the solution?

To state the obvious, have an edge and trade it at a sensible size! Or at least give yourself the best chance of trading with an edge. At a high level, that looks like this:

  • Trade the risk premia
  • Trade the carry
  • Look for inefficiencies that you can exploit with your trading costs and setup
  • Size sensibly, and embrace the fact that not all your positions will be winners

We’ll walk you through the practicalities of this in our upcoming Bootcamp:

Want all the Code?

Get it from our github repository here.

1 thought on “Get Rich Quick Trading Strategies (and why they don’t work)”

Leave a Comment