Signature Description

enum class return_policy : unsigned char  {
    log = 1,         // log(Xt / Xt-1)
    percentage = 2,  // (Xt - Xt-1) / Xt-1
    monetary = 3,    // Xt - Xt-1
    trinary = 4,     // 1 if Xt - Xt-1 > 0, -1 if Xt - Xt-1 < 0, else 0
};
        
This policy specifies the type of return to be calculated

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

template<typename T, typename I = unsigned long,
         std::size_t A = 0>
struct ReturnVisitor;
        
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 class calculates the return of a given column, according to the above return policy. The result is a vector of returns.
    explicit
    ReturnVisitor (return_policy rp);
        
T: Column data type.
I: Index type.
A: Memory alignment boundary for vectors. Default is system default alignment
static void test_return()  {

    std::cout << "\nTesting Return ..." << std::endl;

    std::vector<unsigned long>  idx =
        { 123450, 123451, 123452, 123453, 123454, 123455, 123456, 123457, 123458, 123459, 123460, 123461, 123462, 123466,
          123467, 123468, 123469, 123470, 123471, 123472, 123473 };
    std::vector<double>         d1 =
        { 15, 16, 15, 18, 19, 16, 21, 0.34, 1.56, 0.34, 2.3, 0.34, 19.0, 0.387, 0.123, 1.06, 0.65, 2.03, 0.4, 1.0, 0.59 };
    std::vector<double>         d2 =
        { 1.23, 1.22, 1.21, 1.20, 1.19, 1.185, 1.181, 1.19, 1.195, 1.189, 1.185, 1.18, 1.181, 1.186,
          1.189, 1.19, 1.194, 1.198, 1.199, 1.197, 1.193 };
    std::vector<int>            i1 = { 22, 23, 24, 25, 99 };
    MyDataFrame                 df;

    df.load_data(std::move(idx),
                 std::make_pair("col_1", d1),
                 std::make_pair("col_2", d2),
                 std::make_pair("col_3", i1));

    ReturnVisitor<double>   return_visit(return_policy::monetary);
    const auto              &result = df.single_act_visit<double>("col_1", return_visit).get_result();

    assert(result.size() == 21);
    assert(std::isnan(result[0]));
    assert(result[1] == 1.0);
    assert(result[2] == -1.0);
    assert(result[17] == 1.38);
    assert(result[7] == -20.66);
    assert(fabs(result[11] - -1.96) < 0.00001);

    ReturnVisitor<double>   return_visit2(return_policy::percentage);
    const auto              &result2 = df.single_act_visit<double>("col_1", return_visit2).get_result();

    assert(result2.size() == 21);
    assert(std::isnan(result2[0]));
    assert(fabs(result2[1] - 0.0666667) < 0.00001);
    assert(fabs(result2[2] - -0.0625) < 0.00001);
    assert(fabs(result2[17] - 2.12308) < 0.00001);
    assert(fabs(result2[7] - -0.98381) < 0.00001);
    assert(fabs(result2[11] - -0.852174) < 0.00001);

    ReturnVisitor<double>   return_visit3(return_policy::log);
    const auto              &result3 = df.single_act_visit<double>("col_1", return_visit3).get_result();

    assert(result3.size() == 21);
    assert(std::isnan(result3[0]));
    assert(fabs(result3[1] - 0.0645385) < 0.00001);
    assert(fabs(result3[2] - -0.0645385) < 0.00001);
    assert(fabs(result3[17] - 1.13882) < 0.00001);
    assert(fabs(result3[7] - -4.12333) < 0.00001);
    assert(fabs(result3[11] - -1.91172) < 0.00001);

    ReturnVisitor<double>   return_visit4(return_policy::trinary);
    const auto              &result4 = df.single_act_visit<double>("col_1", return_visit4).get_result();

    assert(result4.size() == 21);
    assert(std::isnan(result4[0]));
    assert(result4[1] == 1);
    assert(result4[2] == -1);
    assert(result4[17] == 1);
    assert(result4[7] == -1);
    assert(result4[11] == -1);
}

C++ DataFrame