Last active
May 5, 2024 19:08
-
-
Save quantra-go-algo/dbc9af7442eee07adb06234636cc9710 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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