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.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store