Signature Description Parameters
#include <DataFrame/DataFrameFinancialVisitors.h>

template<typename T, typename I = unsigned long,
         std::size_t A = 0>
struct HurstExponentVisitor;

// -------------------------------------

template<typename T, typename I = unsigned long,
         std::size_t A = 0>
using hexpo_v = HurstExponentVisitor<T, I, A>;
        
This is a “single action visitor”, meaning it is passed the whole data vector in one call and you must use the single_act_visit() interface.

This functor calculates the Hurst exponent for the given column.
We can use the Hurst exponent (H) as a measure for long-term memory of a time series, that is, to measure the amount by which that series deviates from a random walk. The scalar represents the relative tendency of a time series either to regress strongly to the mean (mean-reverting pattern) or to cluster in a certain direction (trending pattern).
The values of the Hurst exponent range between 0 and 1. Based on the value of H, we can classify any time series into one of the three categories:
  • H < 0.5 — a mean-reverting (anti-persistent) series. The closer the value is to 0, the stronger the mean-reversion process is. In practice, it means that a high value is followed by a low value and vice-versa.
  • H = 0.5 — a geometric random walk.
  • H > 0.5 — a trending (persistent) series. The closer the value is to 1, the stronger the trend. In practice, it means that a high value is followed by a higher one.
    using RangeVec =
        std::vector<size_type, typename allocator_declare<size_type, A>::type>;

    explicit
    HurstExponentVisitor(RangeVec<size_t> &&ranges);

    ranges: A vector of column length divisors.
            For example, {1, 2, 4 } means calculate Hurst exponent in 3 steps.
            It divides the time-series column to 1 chunk, 2 chunks and 4 chunks.
        
T: Column data type.
I: Index type.
A: Memory alignment boundary for vectors. Default is system default alignment
static void test_HurstExponentVisitor()  {

    std::cout << "\nTesting HurstExponentVisitor{ } ..." << std::endl;

    RandGenParams<double>   p;

    p.seed = 123;
    p.min_value = 0;
    p.max_value = 30;

    std::vector<double> d1 = gen_uniform_real_dist<double>(1024, p);
    std::vector<double> d2 = { 0.04, 0.02, 0.05, 0.08, 0.02, -0.17, 0.05, 0.0 };
    std::vector<double> d3 = { 0.04, 0.05, 0.055, 0.06, 0.061, 0.072, 0.073, 0.8 };

    MyDataFrame df;

    df.load_index(std::move(MyDataFrame::gen_sequence_index(0, 1024, 1)));
    df.load_column("d1_col", std::move(d1), nan_policy::dont_pad_with_nans);
    df.load_column("d2_col", std::move(d2), nan_policy::dont_pad_with_nans);
    df.load_column("d3_col", std::move(d3), nan_policy::dont_pad_with_nans);

    HurstExponentVisitor<double>    he_v1 ({ 1, 2, 4 });
    auto                            result1 = df.single_act_visit<double>("d2_col", he_v1).get_result();

    assert(result1 - 0.865926 < 0.00001);

    HurstExponentVisitor<double>    he_v2 ({ 1, 2, 4, 5, 6, 7 });
    auto                            result2 = df.single_act_visit<double>("d1_col", he_v2).get_result();

    assert(result2 - 0.487977 < 0.00001);

    HurstExponentVisitor<double>    he_v3 ({ 1, 2, 4 });
    auto                            result3 = df.single_act_visit<double>("d3_col", he_v3).get_result();

    assert(result3 - 0.903057 < 0.00001);
}
C++ DataFrame