# Mastering Martingale Strategies: How to Test Mean Reversion Trading Systems in the Stock Market Using Python

### Learn to develop, test, and enhance your Martingale strategies (mean revertsion systems with pyramiding) with practical Python code.

Simplicity often triumphs over complexity. One of the strategies that have shown promise involves leveraging periods of consecutive down days in the SPY ETF, with a straightforward approach to pyramiding positions and setting profit targets. The following chart displays the equity curve of the strategy we are about to present giving confirmation to the eye that the edge is present.

**The Strategy Overview**

This strategy is designed to capitalize on the market's tendency to revert after periods of consecutive declines. Here’s a breakdown of the core principles:

**Entry Signal:**The strategy enters a position when SPY experiences three consecutive down days. On each of these signals, the system commits $10,000.**Pyramiding:**The system allows for up to seven positions to be added, each of $10,000, provided the SPY continues to close lower. This pyramiding continues until either the maximum of seven positions is reached or a profit target or time stop is hit.**Profit Target:**Each position has a predefined profit target of 4%. If the price reaches this target, the position is exited.**Time Stop:**If the profit target isn’t hit, the position is automatically exited after four trading days.

**Implementation in Python Using NumPy**

To implement this strategy, we leverage Python and the NumPy library for efficient data processing. The core of the strategy is relatively simple but requires careful handling of multiple positions and individual exits.

#### Great! Let’s break down the code segment by segment, providing a detailed explanation of each part before presenting the full code at the end.

### 1. Importing Libraries

```
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
```

**Explanation:**

`numpy`

is imported as`np`

for numerical operations, especially useful for handling arrays and performing vectorized operations.`yfinance`

is imported as`yf`

to download historical stock data. It's a popular library to fetch financial data directly from Yahoo Finance.`matplotlib.pyplot`

is imported as`plt`

for plotting purposes, allowing us to visualize the equity curve of our trading strategy.

### 2. Downloading Historical Data

`data = yf.download('SPY', start='2000-01-01', end='2024-08-13') close = data['Close'].to_numpy()`

**Explanation:**

The

`yf.download()`

function is used to download historical data for the SPY ETF (which tracks the S&P 500 index) from January 1, 2000, to August 13, 2024.`data['Close']`

extracts the closing prices from the downloaded data.The closing prices are then converted to a NumPy array using

`.to_numpy()`

for efficient numerical operations.

### 3. Defining Strategy Parameters

```
initial_investment = 10000
profit_target = 0.04 # 4% profit target
max_days = 4 # Maximum holding period
max_positions = 7 # Maximum number of pyramiding positions
```

**Explanation:**

`initial_investment`

is set to $10,000, which will be the size of each position when a trade is initiated.`profit_target`

is set to 4%, meaning that any position will be closed once it reaches a 4% gain.`max_days`

is the maximum holding period for any position. If the position is not closed by the profit target within 4 days, it will be closed regardless of its performance.`max_positions`

is the maximum number of positions that can be open simultaneously, allowing up to 7 pyramiding positions.

### 4. Initializing Variables

`equity = 100000 # Starting equity positions = [] # List to store active positions position_size = initial_investment`

**Explanation:**

`equity`

is set to $100,000, representing the initial capital available for trading.`positions`

is an empty list that will store the details of active positions, including entry price, entry day, and position size.`position_size`

is initially set to the`initial_investment`

value, which will be used when opening new positions.

### 5. Tracking Equity Over Time

`equity_curve = []`

**Explanation:**

`equity_curve`

is initialized as an empty list to store the value of the equity after each trading day. This list will be used later to plot the equity curve.

### 6. Running the Trading Strategy

```
for i in range(3, len(close)):
# Check for three consecutive down closes
if close[i] < close[i-1] < close[i-2] < close[i-3] and len(positions) < max_positions:
# Open a new position
positions.append({'entry_price': close[i], 'entry_day': i, 'size': position_size})
```

**Explanation:**

The loop iterates over the closing prices, starting from the fourth price (

`i=3`

) since we need to check the previous three days.The condition

`if close[i] < close[i-1] < close[i-2] < close[i-3]`

checks if there are three consecutive days of lower closing prices.If this condition is met and the number of active positions is less than

`max_positions`

, a new position is opened with the current closing price, and the details are stored in the`positions`

list.

### 7. Managing Open Positions

```
# Update positions
for position in positions[:]:
entry_price = position['entry_price']
entry_day = position['entry_day']
size = position['size']
# Calculate the return
return_ = (close[i] - entry_price) / entry_price
# Check if profit target is reached or holding period is exceeded
if return_ >= profit_target or (i - entry_day + 1) >= max_days:
# Close the position
profit = return_ * size
equity += profit
positions.remove(position)
```

**Explanation:**

This block iterates over each active position and checks whether the profit target has been reached or the maximum holding period has been exceeded.

`return_`

calculates the percentage return of the position.If the return meets or exceeds the

`profit_target`

, or if the position has been held for the`max_days`

, the position is closed, the profit or loss is added to the`equity`

, and the position is removed from the`positions`

list.

### 8. Tracking the Equity Curve

```
# Track equity
equity_curve.append(equity)
```

**Explanation:**

After updating the positions, the current

`equity`

is appended to the`equity_curve`

list, tracking the performance of the strategy over time.

### 9. Final Equity and Plotting the Equity Curve

```
# Final equity
print(f"Final equity: {equity}")
# Plotting the equity curve
plt.figure(figsize=(12, 6))
plt.plot(equity_curve, label='Equity Curve')
plt.title('Equity Curve of the Trading Strategy')
plt.xlabel('Days')
plt.ylabel('Equity ($)')
plt.legend()
plt.show()
```

**Explanation:**

The final equity is printed to show the result of the strategy after processing all the data.

The equity curve is plotted using

`matplotlib`

, displaying how the equity evolved over time. The X-axis represents the number of trading days, and the Y-axis represents the equity in dollars.

### Full Code

Now that we've dissected each segment, here’s the full code:

```
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
# Download SPY data
data = yf.download('SPY', start='2000-01-01', end='2024-08-13')
close = data['Close'].to_numpy()
# Parameters
initial_investment = 10000
profit_target = 0.04 # 4% profit target
max_days = 4 # Maximum holding period
max_positions = 7 # Maximum number of pyramiding positions
# Variables
equity = 100000 # Starting equity
positions = [] # List to store active positions
position_size = initial_investment
# Track equity over time
equity_curve = []
for i in range(3, len(close)):
# Check for three consecutive down closes
if close[i] < close[i-1] < close[i-2] < close[i-3] and len(positions) < max_positions:
# Open a new position
positions.append({'entry_price': close[i], 'entry_day': i, 'size': position_size})
# Update positions
for position in positions[:]:
entry_price = position['entry_price']
entry_day = position['entry_day']
size = position['size']
# Calculate the return
return_ = (close[i] - entry_price) / entry_price
# Check if profit target is reached or holding period is exceeded
if return_ >= profit_target or (i - entry_day + 1) >= max_days:
# Close the position
profit = return_ * size
equity += profit
positions.remove(position)
# Track equity
equity_curve.append(equity)
# Final equity
print(f"Final equity: {equity}")
# Plotting the equity curve
plt.figure(figsize=(12, 6))
plt.plot(equity_curve, label='Equity Curve')
plt.title('Equity Curve of the Trading Strategy')
plt.xlabel('Days')
plt.ylabel('Equity ($)')
plt.legend()
plt.show()
```

**Strategy Performance**

The results of this strategy, as plotted in the equity curve, show how the portfolio evolves over time. By systematically entering positions during periods of market weakness and exiting on either a profit or a time stop, this strategy effectively harnesses market momentum.

**Key Takeaways**

**Simplicity in Execution:**The beauty of this strategy lies in its simplicity. By focusing on consecutive down days, it targets periods where the market is more likely to experience a rebound.**Risk Management:**The use of a fixed number of positions (maximum of seven) and the predefined profit target and time stop ensures that risk is managed effectively.**Customizability:**While the strategy is simple, it can be easily adjusted. For example, altering the number of consecutive down days, adjusting the profit target, or modifying the time stop can lead to different performance characteristics.

In conclusion, this strategy offers a straightforward approach to trading SPY, with clear entry and exit rules that can be implemented and adjusted as needed. The strategy showcases how a disciplined approach can lead to consistent performance in trading.

**Become a Professional Funded Trader for Less Than $150/Month with These 4 Essential Tools**

Ready to take your trading to the next level? Here’s how you can start building your trading career with minimal investment:

**Subscribe to Momentum Alpha**

Unlock expert trading insights for as low as $9/month (even less with an annual plan).**Gain access to actionable trading setups**that can help you make smarter decisions in the market.

**Get Funded**

Start trading with a remote stock prop firm that gives you $20,000 in buying power or more for just a one-time payment of $97.**Trade The Pool**is the best option to scale your trading.

**Trade with the Best Charting Platform**

Take your analysis to the next level with**TradingView**, the most powerful charting software available. Whether you’re a beginner or a pro, TradingView has the tools you need to succeed.

**Analyze Your Trades and Improve Daily**

Get better every day by reviewing your trades with the**TraderSync Trading Journal**. Learn from your wins and losses with detailed analytics. Check out the article I’ve written to see how TraderSync can elevate your trading performance.

**With over 8 years of market experience, $20k spent on books and courses, and managing multiple six-figure portfolios, these are the tools I would use if I were starting my trading journey today.**

**Stop waiting** and start your journey to becoming a professional funded trader now!

Disclaimer