TingTing

Martingale Trading Strategy - Guide and Example

Trading Strategy


Background

Martingale strategy is a betting system that originated in 18th century France and was popularized in the 19th century. The system was named after a casino owner in London named John Henry Martindale, who encouraged players to use the strategy to win at his casino.

It is based on the idea of doubling your bet after each loss in order to recoup previous losses and make a profit.



Casino Example

Here's an example of how the Martingale strategy works in roulette:

  • The player places a $1 bet on red. If the ball lands on black, they lose the bet.
  • The player doubles their bet to $2 and places it on red again. If the ball lands on black again, they lose $2.
  • The player doubles their bet to $4 and places it on red again. If the ball lands on black again, they lose $4.
  • The player doubles their bet to $8 and places it on red again. If the ball lands on red this time, they win $8 and have recouped their previous losses and made a $1 profit.

Here's a table that shows the player's bets and outcomes:

BetOutcomeTotal Profit/Loss
$1Loss-$1
$2Loss-$3
$4Loss-$7
$8Win+$1

The mathematics behind martigale strategy

A martingale strategy operates in a way that a player doubles their bet after every loss, with the goal of eventually winning back all of their losses and making a profit. Assume the initial bet size is $1, the betting sequence will be {1, 2, 4, 8, 16, ..., 2^n}. Each term is double the previous term, which represents the doubling of the bet after each loss.

Mathematically, the martingale strategy works under the assumption of a fair game with no house edge. In a fair game, the probability of winning and losing is equal, and the expected value of each bet is zero. Therefore, if a player bets $1 and loses, they will bet $2 on the next round. If they lose again, they will bet $4, and so on. Eventually, they will win a round and recoup all of their previous losses, plus a profit of $1.

In other words, suppose a player loses for n consecutive rounds and win at n+1 round,

  • Sum of all previous loss = 1 + 2 + 4 + ... + 2^(n-1) = 2^n - 1
  • Win at (n+1) th round = 2^n
  • So the total profit/loss will be +1

The probability of losing n consecutive rounds is 0.5^n. Therefore, the probability of losing 10 consecutive rounds is only 1/1024, which means that the martingale strategy is highly likely to succeed in the short term. However, in the long run, the strategy is not sustainable as it requires an infinite bankroll and the possibility of hitting a losing streak that exceeds the player's bankroll.


How martingale strategy works in financial market?

An important assumption for martingale is that each round is independent. In financial market, there are literactures already showed that the price movement is somehow random. Thus, the idea is simply that by doubling the position size after a loss, a trader will eventually win and make up for the previous losses, assuming that the market will eventually turn in the trader's favor.


Working with ALGOGENE trading API

In this example, we apply martingale strategy for day trading on S&P500.

At initialization, we set the base bet size to be 0.01 lot and cap the take profit and stop loss each round to be 10 index points (i.e. bet_amt).

1
2
3
4
5
6
7
8
9
from AlgoAPI import AlgoAPIUtil, AlgoAPI_Backtest

class AlgoEvent:
    def __init__(self):
        self.bet_amt = 10
        self.bet_size_base = 0.01
        self.bet_size = self.bet_size_base
        self.entry_price = None
        

Now, under 'on_marketdatafeed()', when there feed in new day market data, we will open a buy order if we have no outstanding position.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    def on_marketdatafeed(self, md, ab):
        # open new trade if no position
        pos, _, _ = self.evt.getSystemOrders()
        if pos[md.instrument]["netVolume"]==0:
            order = AlgoAPIUtil.OrderObject(
                instrument = md.instrument,
                openclose = 'open', 
                buysell = 1,                   # buy
                ordertype = 0,                 # market order
                volume = self.bet_size, 
                takeProfitLevel = md.askPrice + self.bet_amt,
                stopLossLevel = md.askPrice - self.bet_amt
            )
            self.evt.sendOrder(order)

Once there is order status change, we will update the order entry price if it succesfully open an order. If the order is closed, we will check whether it is a win (take profit) or loss (stoploss) trade, and update the bet size accordingly.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    def on_orderfeed(self, of):
        if of.status=="success":
            if of.openclose=="open":
                self.entry_price = of.fill_price
            elif of.openclose=="close":
                # reset to base size if win
                if of.fill_price > self.entry_price:
                    self.bet_size = self.bet_size_base
                # double bet size if lose
                else:
                    self.bet_size*=2
            

Here the full script I use for backtesting.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from AlgoAPI import AlgoAPIUtil, AlgoAPI_Backtest

class AlgoEvent:
    def __init__(self):
        self.bet_amt = 10
        self.bet_size_base = 0.01
        self.bet_size = self.bet_size_base
        self.entry_price = None
        
    def start(self, mEvt):
        self.evt = AlgoAPI_Backtest.AlgoEvtHandler(self, mEvt)
        self.evt.start()
        
    def on_marketdatafeed(self, md, ab):
        # open new trade if no position
        pos, _, _ = self.evt.getSystemOrders()
        if pos[md.instrument]["netVolume"]==0:
            order = AlgoAPIUtil.OrderObject(
                instrument = md.instrument,
                openclose = 'open', 
                buysell = 1,                   # buy
                ordertype = 0,                 # market order
                volume = self.bet_size, 
                takeProfitLevel = md.askPrice + self.bet_amt,
                stopLossLevel = md.askPrice - self.bet_amt
            )
            self.evt.sendOrder(order)

    def on_orderfeed(self, of):
        if of.status=="success":
            if of.openclose=="open":
                self.entry_price = of.fill_price
            elif of.openclose=="close":
                # reset to base size if win
                if of.fill_price > self.entry_price:
                    self.bet_size = self.bet_size_base
                # double bet size if lose
                else:
                    self.bet_size*=2
            

Backtest Setup

  • Period: 2022-01 to 2022-12
  • Initial Capital: US$100,000
  • Data Interval: 1-day
  • Leverage: 1x
  • Instrument: SPXUSD

Backtest Result

We can effectively earn some profits.


Conclusion

Martingale stategy is a relatively simple trading strategy that does not require prediction on market movement. However, there is no 100% sure win strategy in the world. When applying the martingale strategy, we should pay attention to the following.

  • the strategy doesn't guarantee a win if the player experiences a long losing streak and runs out of money to continue doubling the bets
  • the strategy is based on assumptions
    • only 2 possible outcomes (i.e. win or lose)
    • probability of win and lose are equal
    • each round's outcome is independent

The strategy script presented above is simply to demonstrate how to use ALGOGENE API. It is not the only way to formula the problem.



Like and follow me

If you find my articles inspiring, like this post and follow me here to receive my latest updates.

Enter my promote code "fMpr6tZJACaF" for any purchase on ALGOGENE, you will automatically get 5% discount.


 
Darius
Personally, I think Martingale strategy won't work in long run, but it is a good coding example to learn.
Thanks for sharing.  
 
Terminator
Followed! 
 
Jeremy
The Martingale strategy no longer work in casino nowsday. 
Casino will introduce certain senario such that the expected value for players will actually be negative.