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

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

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

template<typename T, typename I = unsigned long,
         std::size_t A = 0>
using eri_v = ElderRayIndexVisitor<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 visitor calculates the Elder Ray Index indicator. It requires 3 input columns in the order of close, high, low.
The Elder-Ray Index is a technical indicator developed by Dr. Alexander Elder that measures the amount of buying and selling pressure in a market. This indicator consists of two indicators known as "bull power" and "bear power," which are derived from a 13-period exponential moving average (EMA). These, along with the EMA, help traders determine the trend direction and isolate spots to enter and exit trades. Technical traders will use the values of bull and bear power, along with divergence, to make trading decisions. Long positions are taken when the bear power has a value below zero but is increasing, and the bull power's latest peak is higher than it was previously (rising). A short position is taken when the bull power value is positive but falling, and the bear power's recent low is lower than it was previously (falling).
get_result() returns the vector of Bulls. get_bears() returns the vector of Bears
    explicit
    ElderRayIndexVisitor(size_t roll_period = 13);

    rolling_period: Applied to the final EWMA calculations
        
T: Column data type
I: Index type
A: Memory alignment boundary for vectors. Default is system default alignment
static void test_ElderRayIndexVisitor()  {

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

    StrDataFrame    df;

    try  {
        df.read("data/SHORT_IBM.csv", io_format::csv2);

        eri_v<double, std::string>  eri;

        df.single_act_visit<double, double, double>("IBM_Close", "IBM_High", "IBM_Low", eri);

        assert(eri.get_result().size() == 1721);
        assert(std::abs(eri.get_result()[0] - 1.87) < 0.0001);
        assert(std::abs(eri.get_result()[12] - 2.627) < 0.0001);
        assert(std::abs(eri.get_result()[20] - -2.7599) < 0.0001);
        assert(std::abs(eri.get_result()[25] - 0.1827) < 0.0001);
        assert(std::abs(eri.get_result()[30] - 5.0969) < 0.0001);
        assert(std::abs(eri.get_result()[1720] - -3.1783) < 0.0001);
        assert(std::abs(eri.get_result()[1712] - -3.7028) < 0.0001);
        assert(std::abs(eri.get_result()[1707] - 2.7576) < 0.0001);

        assert(eri.get_bears().size() == 1721);
        assert(std::abs(eri.get_bears()[0] - -0.33) < 0.0001);
        assert(std::abs(eri.get_bears()[12] - -0.973) < 0.0001);
        assert(std::abs(eri.get_bears()[20] - -5.2599) < 0.0001);
        assert(std::abs(eri.get_bears()[25] - -2.3073) < 0.0001);
        assert(std::abs(eri.get_bears()[30] - 1.6569) < 0.0001);
        assert(std::abs(eri.get_bears()[1720] - -7.2283) < 0.0001);
        assert(std::abs(eri.get_bears()[1712] - -7.0128) < 0.0001);
        assert(std::abs(eri.get_bears()[1707] - 0.0676) < 0.0001);
    }
    catch (const DataFrameError &ex)  {
        std::cout << ex.what() << std::endl;
    }
}
C++ DataFrame