Hey, thanks! I generally put the relevant parts because the full code is connected to other custom functions and databases so putting all of the code will not be useful to readers. But here’s most of it (that can be run on OHLC data anyway):

lower_barrier = 40

upper_barrier = 60

lookback = 14

atr_lookback = 50

def atr(Data, atr_lookback, high, low, close, whereTR, whereATR):

# TR

for i in range(len(Data)):

Data[i, whereTR] = max(Data[i, high] — Data[i, low],

abs(Data[i, high] — Data[i — 1, close]),

abs(Data[i, low] — Data[i — 1, close]))

Data[0, whereATR] = Data[0, high] — Data[0, low]

Data[atr_lookback — 1, whereATR] = Data[0:atr_lookback — 1, whereTR].mean()

first_atr = Data[0, whereATR]

for i in range(len(Data)):

Data[0, whereATR] = first_atr

Data[i, whereATR] = (((Data[i — 1, whereATR] * (atr_lookback — 1)) + Data[i, whereTR]) / atr_lookback)

return Data

# Harami example

def complex_strategy_2(Data, indicator, buy, sell):

for i in range(len(Data)):

if Data[i, indicator] < lower and \

Data[i — 1, 3] < Data[i — 1, 0] and \

Data[i, 3] > Data[i, 0] and \

Data[i — 1, 3] < Data[i, 2] and \

Data[i — 1, 0] > Data[i, 1]:

Data[i, buy] = 1

if Data[i, indicator] > upper and \

Data[i — 1, 3] > Data[i — 1, 0] and \

Data[i, 3] < Data[i, 0] and \

Data[i — 1, 3] > Data[i, 1] and \

Data[i — 1, 0] < Data[i, 2]:

Data[i, sell] = -1

def adder(Data, times):

for i in range(1, times + 1):

z = np.zeros((len(Data), 1), dtype = float)

Data = np.append(Data, z, axis = 1)

return Data

def ema(Data, alpha, window, what, whereSMA, whereEMA):

# alpha is the smoothing factor

# window is the lookback period

# what is the column that needs to have its average calculated

# where is where to put the exponential moving average

alpha = alpha / (window + 1.0)

beta = 1 — alpha

# First value is a simple SMA

Data[window — 1, whereSMA] = np.mean(Data[:window — 1, what])

# Calculating first EMA

Data[window, whereEMA] = (Data[window, what] * alpha) + (Data[window — 1, whereSMA] * beta)

# Calculating the rest of EMA

for i in range(window + 1, len(Data)):

try:

Data[i, whereEMA] = (Data[i, what] * alpha) + (Data[i — 1, whereEMA] * beta)

except IndexError:

pass

return Data

def rsi(Data, rsi_lookback, what1, what2):

rsi_lookback = (rsi_lookback * 2) — 1 # From exponential to smoothed

# Get the difference in price from previous step

delta = []

for i in range(len(Data)):

try:

diff = Data[i, what1] — Data[i — 1, what1]

delta = np.append(delta, diff)

except IndexError:

pass

delta = np.insert(delta, 0, 0, axis = 0)

delta = delta[1:]

# Make the positive gains (up) and negative gains (down) Series

up, down = delta.copy(), delta.copy()

up[up < 0] = 0

down[down > 0] = 0

up = np.array(up)

down = np.array(down)

roll_up = up

roll_down = down

roll_up = np.reshape(roll_up, (-1, 1))

roll_down = np.reshape(roll_down, (-1, 1))

roll_up = adder(roll_up, 3)

roll_down = adder(roll_down, 3)

roll_up = ema(roll_up, 2, rsi_lookback, what2, 1, 2)

roll_down = ema(abs(roll_down), 2, rsi_lookback, what2, 1, 2)

# Calculate the SMA

roll_up = roll_up[rsi_lookback:, 2:3]

roll_down = roll_down[rsi_lookback:, 2:3]

Data = Data[rsi_lookback + 1:,]

# Calculate the RSI based on SMA

RS = roll_up / roll_down

RSI = (100.0 — (100.0 / (1.0 + RS)))

RSI = np.array(RSI)

RSI = np.reshape(RSI, (-1, 1))

RSI = RSI[1:,]

Data = np.concatenate((Data, RSI), axis = 1)

return Data

Asset1 = rsi(Asset1, lookback, 3, 0)

Sorry for the mess.