Skip to content

Instantly share code, notes, and snippets.

@quantra-go-algo
Last active May 5, 2024 19:08
Show Gist options
  • Save quantra-go-algo/dbc9af7442eee07adb06234636cc9710 to your computer and use it in GitHub Desktop.
Save quantra-go-algo/dbc9af7442eee07adb06234636cc9710 to your computer and use it in GitHub Desktop.
# Function to create the DC indicators provided by Chen and Tsang (2021)
def directional_change_events(data, theta=0.2):
# Copy the dataframe
data = data.copy()
# Create the necessary columns and variables
data["Event"] = 0.0
# Set the initial event variable value
event = "upward" # initial event
# Set the initial value for low and high prices
ph = data['Close'].iloc[0] # highest price
pl = data['Close'].iloc[0] # lowest price
# Create loop to run through each date
for t in range(0, len(data.index)):
# Check if we're on a downward trend
if event == "downward":
# Check if the close price is higher than the low price by the theta threshold
if data["Close"].iloc[t] >= pl * (1 + theta):
# Set the event variable to upward
event = "upward"
# Set the high price as the current close price
ph = data["Close"].iloc[t]
# If the close price is lower than the low price by the theta threshold
else:
# Check if the close price is less than the low price
if data["Close"].iloc[t] < pl:
# Set the low price as the current close price
pl = data["Close"].iloc[t]
# Set the Event to upward for the current period
data["Event"].iloc[t] = 1
# Check if we're on a upward trend
elif event == "upward":
# Check if the close price is less than the high price by the theta threshold
if data["Close"].iloc[t] <= ph * (1 - theta):
# Set the event variable to downward
event = "downward"
# Set the low price as the current close price
pl = data["Close"].iloc[t]
# If the close price is higher than the high price by the theta threshold
else:
# Check if the close price is higher than the high price
if data["Close"].iloc[t] > ph:
# Set the high price as the current close price
ph = data["Close"].iloc[t]
# Set the Event to downward for the current period
data["Event"].iloc[t] = -1
# Set the peak and trough prices and forward-fill the column
data['peak_trough_prices'] = np.where(data['Event']!=0, data['Close'],0)
data['peak_trough_prices'].replace(to_replace=0, method='ffill', inplace=True)
# Count the number of periods between a peak and a trough
data['count'] = 0
for i in range(1,len(data.index)):
if data['Event'].iloc[(i-1)]!=0:
data['count'].iloc[i] = 1+data['count'].iloc[(i-1)]
else:
data['count'].iloc[i] = 1
# Compute the TMV indicator
data['TMV'] = np.where(data['Event']!=0, abs(data['peak_trough_prices']-data['peak_trough_prices'].shift())/\
(data['peak_trough_prices'].shift()*theta),0)
# Compute the time-completion-for-a-trend indicator
data['T'] = np.where(data['Event']!=0, data['count'],0)
# Compute the time-adjusted-return indicator and forward-fill it
data['R'] = np.where(data['Event']!=0, np.log(data['TMV']/data['T']*theta),0)
data['R'] = data['R'].replace(to_replace=0, method='ffill')
# Drop NaN or inifinite values
data.replace([np.inf, -np.inf], np.nan, inplace=True)
return data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment