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

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]:

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

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 = 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.

Written by