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

template<typename T, typename I = unsigned long>
struct ParabolicSARVisitor;

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

template<typename T, typename I = unsigned long>
using psar_v = ParabolicSARVisitor<T, I>;
        
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 Parabolic Stop And Reverse (PSAR) indicator. It requires 3 input columns in the order of low, high, close.
The result is a vector of boolean values with same number of items as the given columns. The first bar_periods items.

The parabolic SAR indicator, developed by J. Wells Wilder, is used by traders to determine trend direction and potential reversals in price. The indicator uses a trailing stop and reverse method called "SAR," or stop and reverse, to identify suitable exit and entry points. Traders also refer to the indicator as the parabolic stop and reverse, parabolic SAR, or PSAR.

This visitor has 4 result vectors:
get_result(): Returns a vector of Booleans where a transition from true <--> false signals a reversal from buy <--> sell
get_longs(): Returns a vector of prices for periods the buy signal is on, otherwise the value is a nan
get_shorts(): Returns a vector of prices for periods the sell signal is on, otherwise the value is a nan
get_acceleration_factors(): Returns the vector of acceleration factors in effect for each period

    explicit
    ParabolicSARVisitor(T acceleration_factor = 0.02,
                        T max_acceleration_factor = 0.2);
        
T: Column data type
I: Index type
static void test_ParabolicSARVisitor()  {

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

    typedef StdDataFrame<std::string> StrDataFrame;

    StrDataFrame    df;

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

        ParabolicSARVisitor<double, std::string> psar_v;

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

        assert(psar_v.get_result().size() == 1721);
        assert((! psar_v.get_result()[0]));
        assert((psar_v.get_result()[2]));
        assert((psar_v.get_result()[3]));
        assert((psar_v.get_result()[26]));
        assert((! psar_v.get_result()[1720]));
        assert((! psar_v.get_result()[1718]));
        assert((psar_v.get_result()[1709]));

        assert(psar_v.get_longs().size() == 1721);
        assert(std::isnan(psar_v.get_longs()[0]));
        assert(std::isnan(psar_v.get_longs()[2]));
        assert(std::abs(psar_v.get_longs()[5] - 185.401) < 0.001);
        assert(std::abs(psar_v.get_longs()[11] - 183.86) < 0.01);
        assert(std::isnan(psar_v.get_longs()[18]));
        assert(std::isnan(psar_v.get_longs()[1720]));
        assert(std::abs(psar_v.get_longs()[1708] - 124.46) < 0.01);

        assert(psar_v.get_shorts().size() == 1721);
        assert(std::isnan(psar_v.get_shorts()[0]));
        assert(std::abs(psar_v.get_shorts()[2] - 187.4) < 0.1);
        assert(std::isnan(psar_v.get_shorts()[6]));
        assert(std::abs(psar_v.get_shorts()[7] - 190.35) < 0.01);
        assert(std::abs(psar_v.get_shorts()[1720] - 120.7) < 0.1);
        assert(std::isnan(psar_v.get_shorts()[1708]));

        assert(psar_v.get_acceleration_factors().size() == 1721);
        assert(psar_v.get_acceleration_factors()[0] == 0.02);
        assert(psar_v.get_acceleration_factors()[2] == 0.02);
        assert(psar_v.get_acceleration_factors()[15] == 0.02);
        assert(psar_v.get_acceleration_factors()[16] == 0.04);
        assert(psar_v.get_acceleration_factors()[1720] == 0.14);
        assert(std::abs(psar_v.get_acceleration_factors()[1718] - 0.12) < 0.01);
    }
    catch (const DataFrameError &ex)  {
        std::cout << ex.what() << std::endl;
    }
}