0
$\begingroup$

I'm working on a script to calculate and plot the Hurst Exponent and Smoothed Hurst Exponent for a stock's historical price data using Python. When I run the script, I face two major issues:

The Smoothed Hurst Exponent and the Hurst Exponent values are the same. I expect the Smoothed Hurst Exponent to be different from the Hurst Exponent, as it should be a moving average of the Hurst Exponent.

The plotting doesn't seem to be done correctly. I'm trying to plot the Hurst Exponent, the Smoothed Hurst Exponent, and the confidence intervals, but the resulting plot doesn't display the data as expected.

I'm looking for help in identifying the issues in my code that are causing these problems and suggestions on how to fix them.

Any assistance would be greatly appreciatedExample Output

My code is as follows:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
from scipy.stats import linregress

# (a) - inputs
def inputs(barsize=100, slen=18, Min=8, Max=2):
    return barsize, slen, Min, Max

# (b) - Declaration
Min = 8
Max = 2
fluc = np.full(10, np.nan)
scale = np.full(10, np.nan)
slope = np.nan

# (c) - SS function
def ss(series, period):
    PI = 2.0 * np.arcsin(1.0)
    SQRT2 = np.sqrt(2.0)
    _lambda = PI * SQRT2 / period
    a1 = np.exp(-_lambda)
    coeff2 = 2.0 * a1 * np.cos(_lambda)
    coeff3 = - np.power(a1, 2.0)
    coeff1 = 1.0 - coeff2 - coeff3
    filt1 = np.zeros_like(series)
    
    for i in range(2, len(series)):
        filt1[i] = coeff1 * (series[i] + (series[i - 1] if i - 1 >= 0 else 0)) * 0.5 + coeff2 * filt1[i - 1] + coeff3 * filt1[i - 2]

    return filt1

# (d) - Calculations
def RMS(N1, N, csum):
    seq = np.arange(1, N + 1)
    y = csum[N1 : N1 + N]
    sdx = np.std(seq) * np.sqrt(N / (N - 1))
    sdy = np.std(y) * np.sqrt(N / (N - 1))
    cov = np.cov(seq, y, bias=True)[0, 1] * (N / (N - 1))
    r2 = np.power(cov / (sdx * sdy), 2)
    rms = np.sqrt(1 - r2) * sdy
    return rms

def Arms(bar, csum, barsize):
    num = np.floor(barsize / bar).astype(int)
    sumr = sum(RMS(i * bar, bar, csum) for i in range(num))
    avg = np.log10(sumr / num)
    return avg

def fs(x, barsize, Min, Max):
    return np.round(Min * np.power(np.power(barsize / (Max * Min), 0.1111111111), x)).astype(int)

def hurst_exponent(close, barsize=100, slen=18, Min=8, Max=2):
    # Calculate Log Return
    r = np.log(close / np.roll(close, 1))
    # Mean of Log Return
    mean = np.convolve(r, np.ones(barsize) / barsize, mode="valid")
    mean = np.pad(mean, (barsize - 1, 0), 'constant', constant_values=0)

    # Calculate Cumulative Sum
    csum = np.cumsum(r - mean)

    # Set Ten Points of Root Mean Square Average along the Y log axis
    fluc = np.array([Arms(fs(i, barsize, Min, Max), csum, barsize) for i in range(10)])

    # Set Ten Points of data scale along the X log axis
    scale = np.array([np.log10(fs(i, barsize, Min, Max)) for i in range(10)])

        # Calculate Slope Measured From RMS and Scale on Log log plot using linear regression
    slopes = np.array([np.cov(scale, fluc, bias=True)[0, 1] / np.var(scale, ddof=0) for i in range(len(close) - barsize + 1)])

    # Calculate Moving Average Smoothed Hurst Exponent
    smooth = ss(slopes, slen)

    # Calculate Critical Value based on Confidence Interval (95% Confidence)
    ci = 1.645 * (0.3912 / np.power(barsize, 0.3))
    # Calculate Expected Value plus Critical Value
    cu = 0.5 + ci
    cd = 0.5 - ci

    return slopes, smooth, cu, cd

# (e) - Plots
def plot_hurst_exponent(close, barsize=100, slen=18, Min=8, Max=2):
    slopes, smooth, cu, cd = hurst_exponent(close, barsize, slen, Min, Max)

    # Color of HE
    c = "green" if slopes[-1] > cu else "blue" if slopes[-1] >= 0.5 else "red" if slopes[-1] < cd else "orange" if slopes[-1] < 0.5 else "black"

    # Text of Table
    text = "Significant Trend" if slopes[-1] > cu else "Trend" if slopes[-1] >= 0.5 else "Significant Mean Reversion" if slopes[-1] < cd else "Mean Reversion" if slopes[-1] < 0.5 else "N/A"

    # Plotting
    fig, ax = plt.subplots()

    # Hurst Exponent
    ax.plot(slope, label="Hurst Exponent", color=c, linewidth=2)

    # Confidence Interval
    ax.axhline(cu, label="Confidence Interval", color="purple", linestyle="--")
    ax.axhline(cd, label="Confidence Interval", color="purple", linestyle="--")

    # Moving Average
    ax.plot(smooth, label="MA", color="gray", linewidth=1)

    # 0.5 Mid Level
    ax.axhline(0.5, color="black", linestyle="dashed")

    # Display legend and text
    ax.legend()
    plt.title(f"Hurst Exponent: {slopes[-1]:.3f} ({text})") 
    
    print(f"Hurst Exponent: {slopes[-1]:.3f}")
    print(f"Smoothed Hurst Exponent: {smooth[-1]:.3f}")
    
    plt.show()

# Example usage
import yfinance as yf

# Fetch historical stock data for Apple Inc. (AAPL)
ticker = "AAPL"
data = yf.download(ticker, start="2020-01-01", end="2021-01-01")

# Use the 'Close' column for Hurst Exponent calculation
close_prices = data['Close'].values

plot_hurst_exponent(close_prices)
$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.