Trading strategies are composed of multiple conditions. Technical trading strategies are the same but use conditions from technical indicators. This article presents an example of a strategy that can use technical rules.

I have released a new book after the success of my previous one “*Trend Following Strategies in Python*”. It features advanced contrarian indicators and strategies with a **GitHub **page dedicated to the continuously updated code. If you feel that this interests you, feel free to visit the below Amazon link (which contains a sample), or if you prefer to buy the PDF version, you could check the link at the end of the article.

**Contrarian Trading Strategies in Python***Amazon.com: Contrarian Trading Strategies in Python: 9798434008075: Kaabar, Sofien: Books*www.amazon.com

### The Basic Ingredients of the Strategy

The strategy is composed of three known technical indicators:

**A 2-period relative strength index (RSI).****A 14-period stochastic oscillator.****A MACD oscillator.**

As a refresher, the RSI and the stochastic oscillator are normalization technique that trap the price action between 0 and 100 while the MACD is the difference between two moving averages that gives out trend following signals.

To code the indicators in Python while you have a numpy array, you can use the following:

```
def add_column(data, times):
for i in range(1, times + 1):
new = np.zeros((len(data), 1), dtype = float)
data = np.append(data, new, axis = 1)
```

` return data`

```
def delete_column(data, index, times):
for i in range(1, times + 1):
data = np.delete(data, index, axis = 1)
```

` return data`

```
def delete_row(data, number):
data = data[number:, ]
return data
```

```
def ma(data, lookback, close, position):
data = add_column(data, 1)
for i in range(len(data)):
try:
data[i, position] = (data[i - lookback + 1:i + 1, close].mean())
except IndexError:
pass
data = delete_row(data, lookback)
return data
```

```
def ema(data, alpha, lookback, close, position):
alpha = alpha / (lookback + 1.0)
beta = 1 - alpha
data = ma(data, lookback, close, position)
```

` data[lookback + 1, position] = (data[lookback + 1, close] * alpha) + (data[lookback, position] * beta)`

```
for i in range(lookback + 2, len(data)):
try:
data[i, position] = (data[i, close] * alpha) + (data[i - 1, position] * beta)
except IndexError:
pass
return data
```

```
def rsi(data, lookback, close, position):
data = add_column(data, 5)
for i in range(len(data)):
data[i, position] = data[i, close] - data[i - 1, close]
for i in range(len(data)):
if data[i, position] > 0:
data[i, position + 1] = data[i, position]
elif data[i, position] < 0:
data[i, position + 2] = abs(data[i, position])
data = smoothed_ma(data, 2, lookback, position + 1, position + 3)
data = smoothed_ma(data, 2, lookback, position + 2, position + 4)
```

```
data[:, position + 5] = data[:, position + 3] / data[:, position + 4]
data[:, position + 6] = (100 - (100 / (1 + data[:, position + 5])))
```

```
data = delete_column(data, position, 6)
data = delete_row(data, lookback)
```

```
return data
def stochastic_oscillator(data,
lookback,
high,
low,
close,
position,
slowing = False,
smoothing = False,
slowing_period = 1,
smoothing_period = 1):
data = add_column(data, 1)
for i in range(len(data)):
try:
data[i, position] = (data[i, close] - min(data[i - lookback + 1:i + 1, low])) / (max(data[i - lookback + 1:i + 1, high]) - min(data[i - lookback + 1:i + 1, low]))
except ValueError:
pass
data[:, position] = data[:, position] * 100
if slowing == True and smoothing == False:
data = ma(data, slowing_period, position, position + 1)
if smoothing == True and slowing == False:
data = ma(data, smoothing_period, position, position + 1)
if smoothing == True and slowing == True:
data = ma(data, slowing_period, position, position + 1)
data = ma(data, smoothing_period, position + 1, position + 2)
data = delete_row(data, lookback)
```

` return data`

```
def macd(data, close, long_ema, short_ema, signal_ema, position):
data = add_column(data, 1)
data = ema(data, 2, long_ema, close, position)
data = ema(data, 2, short_ema, close, position + 1)
data[:, position + 2] = data[:, position + 1] - data[:, position]
```

```
data = delete_row(data, long_ema)
data = ema(data, 2, signal_ema, position + 2, position + 3)
data = delete_column(data, position, 2)
data = delete_row(data, signal_ema)
return data
```

Make sure to focus on the concepts and not the code. You can find the codes of most of my strategies in my books. The most important thing is to comprehend the techniques and strategies.

If you are also interested by trend following strategies and indicators, then my previous book might also interest you:

**Trend Following Strategies in Python: How to Use Indicators to Follow the Trend.***Amazon.com: Trend Following Strategies in Python: How to Use Indicators to Follow the Trend.: 9798756939620: Kaabar…*www.amazon.com

### Creating the Rules of the Strategy

The trading conditions of the strategy are as follows:

**A long (buy) signal is generated whenever the 2-period RSI is below 20 while the stochastic oscillator is below 20 and the MACD is above 0.****A short (sell) signal is generated whenever the 2-period RSI is above 80 while the stochastic oscillator is above 80 and the MACD is below 0.**

`def signal(data, rsi_column, stochastic_column, macd_column, buy, sell):`

```
data = add_column(data, 10)
for i in range(len(data)):
```

```
try:
if data[i, rsi_column] < lower_barrier and \
data[i - 1, rsi_column] > lower_barrier and \
data[i, stochastic_column] < lower_barrier and \
data[i, macd_column] > 0:
data[i + 1, buy] = 1
elif data[i, rsi_column] > upper_barrier and \
data[i - 1, rsi_column] < upper_barrier and \
data[i, stochastic_column] > upper_barrier and \
data[i, macd_column] < 0:
data[i + 1, sell] = -1
```

```
except IndexError:
pass
return data
```

### Summary

To summarize up, what I am trying to do is to simply contribute to the world of objective technical analysis which is promoting more transparent techniques and strategies that need to be back-tested before being implemented. This way, technical analysis will get rid of the bad reputation of being a subjective and scientifically unfounded.

I recommend you always follow the the below steps whenever you come across a trading technique or strategy:

Have a critical mindset and get rid of any emotions.

Back-test it using real life simulation and conditions.

If you find potential, try optimizing it and running a forward test.

Always include transaction costs and any slippage simulation in your tests.

Always include risk management and position sizing in your tests.

Finally, even after making sure of the above, stay careful and monitor the strategy because market dynamics may shift and make the strategy unprofitable.

For the PDF alternative, the price of the book is **9.99 EUR**. Please include your email in the note before paying so that you receive it on the right address. Also, once you receive it, make sure to download it through google drive.

**Pay Kaabar using PayPal.Me***If you accept cookies, we’ll use them to improve and customize your experience and enable our partners to show you…*www.paypal.com