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

template<typename T, typename I = unsigned long>
struct PSLVisitor;
        
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 rolling values of Psychological Line. It requires either one or two input column(s) in the order of close, open or only close.
The result is a vector of values with same number of items as the given column(s). The first roll_count items, in the result, will be NAN.
The Psychological Line (PSL) indicator is the ratio of the number of rising periods over the total number of periods. It reflects the buying power in relation to the selling power. If PSL is above 50%, it indicates that buyers are in control. Likewise, if it is below 50%, it indicates the sellers are in control. If the PSL moves along the 50% area, it indicates balance between the buyers and sellers and therefore there is no direction movement for the market.
There are two ways you can use PSLVisitor; with close and open time-series or only with the close time series. In the latter case, a one period diff of close will be the basis. In the former case the difference between close and open is the basis. Please see code sample below.
    explicit
    PSLVisitor(size_t roll_count = 14);
        
T: Column data type
I: Index type
static void test_PSLVisitor()  {

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

    typedef StdDataFrame<std::string> StrDataFrame;

    StrDataFrame    df;

    try  {
        df.read("IBM.csv", io_format::csv2);

        PSLVisitor<double, std::string> psl_v;

        df.single_act_visit<double, double>("IBM_Close", "IBM_Open", psl_v);
        assert(psl_v.get_result().size() == 5031);
        assert(std::isnan(psl_v.get_result()[0]));
        assert(std::isnan(psl_v.get_result()[12]));
        assert(std::abs(psl_v.get_result()[14] - 57.1429) < 0.0001);
        assert(std::abs(psl_v.get_result()[20] - 42.8571) < 0.0001);
        assert(std::abs(psl_v.get_result()[5030] - 42.8571) < 0.0001);
        assert(std::abs(psl_v.get_result()[5026] - 42.8571) < 0.0001);
        assert(std::abs(psl_v.get_result()[5021] - 57.1429) < 0.0001);

        df.single_act_visit<double>("IBM_Close", psl_v);
        assert(psl_v.get_result().size() == 5031);
        assert(std::isnan(psl_v.get_result()[0]));
        assert(std::isnan(psl_v.get_result()[12]));
        assert(std::abs(psl_v.get_result()[14] - 50) < 0.0001);
        assert(std::abs(psl_v.get_result()[20] - 42.8571) < 0.0001);
        assert(std::abs(psl_v.get_result()[5030] - 42.8571) < 0.0001);
        assert(std::abs(psl_v.get_result()[5026] - 42.8571) < 0.0001);
        assert(std::abs(psl_v.get_result()[5021] - 42.8571) < 0.0001);
    }
    catch (const DataFrameError &ex)  {
        std::cout << ex.what() << std::endl;
    }
}