More DSL Functions


 

Regression


This function performs regression analysis and outputs various calculated values as a tuple. This is the pure DSL implementation. The actual library implementation is based on a functor. The library also has a regression against time which differs slightly.

 

     series_tuple<double> REGRESSION(sref<double> x, sref<double> y, size_t period)

     {

                    verify_non_zero(period);

                    auto sum_xy  = SUM_XY(x, y, period);

                    auto sum_x   = SUM(x, period);

                    auto sum_y   = SUM(y, period);

                    auto sum_x2  = SUM(POW(x, 2), period);

                    auto sum_y2  = SUM(POW(y, 2), period);

 

                    auto dividend    = sum_xy - ((sum_x * sum_y) / period);

                    auto divisor     = sum_x2 - (POW(sum_x, 2) / period);

                    auto slope       = SAFE_DIVIDE(dividend, divisor);

                    auto y_intercept = ((sum_y - (slope * sum_x)) / period);

 

                    auto SST      = sum_y2 - (POW(sum_y, 2) / period);

                    auto SSR      = slope * (sum_xy - ((sum_x * sum_y) / period));

                    auto r_square = SAFE_DIVIDE(SSR, SST);

 

                    auto last_line_pt = y_intercept + (slope * (period - 1));

 

                    series_tuple<double> t;

                    t.add(slope.name("slope").plot_as("REGR-SLOPE", period));

                    t.add(r_square.name("r_square").plot_as("REGR-RSQR", period));

                    t.add(last_line_pt.name("line").plot_as("REGR-LINE", period));

                    t.add(y_intercept.name("y_intercept").plot_as("REGR-Y-INTERC", period));

 

                    return t;

          }

 

 

Dominant Cycle Period  (Hilbert)


This is the Dominant Cycle Period function as popularised by John F. Ehlers

 

          sref<double> DOMINANTCYCLEPERIOD_HILBERT(sref<double> price)

          {

                    // Smooth and detrend

                    self_ref_series<double> period(10);

                    auto smoother = (4.0 * price + 3.0 * price(1) + 2 * price(2) + price(3)) / 10.0;

                    auto detrender = (0.25*smoother + 0.75*smoother(2) - 0.75*smoother(4)

                              - 0.25*smoother(6)) * (0.046*period + 0.332);

 

                    // Compute InPhase and Quadrature components

                    auto Q1 = (0.25*detrender + 0.75*detrender(2) - 0.75*detrender(4)

                              - 0.25*detrender(6))*(0.046*period + 0.332);

 

                    auto I1 = detrender(3);

 

                    // Advance the phase of I1 and Q1 by 90 degrees

                    auto jI = 0.25*I1 + 0.75*I1(2) - 0.75*I1(4) - 0.25*I1(6);

                    auto jQ = 0.25*Q1 + 0.75*Q1(2) - 0.75*Q1(4) - 0.25*Q1(6);

 

                    // Phasor addition to equalize amplitude due to quadrature calculations (and 3 bar averaging)

                    // Smooth the I and Q components before applying the discriminator

                    auto _I2 = I1 - jQ;

                    auto _Q2 = Q1 + jI;

 

                    self_ref_series<double> I2(0), Q2(0);

                    I2 = 0.15*_I2 + 0.85*I2;

                    Q2 = 0.15*_Q2 + 0.85*Q2;

                    ASSERT(I2 == 0.15*_I2 + 0.85*I2(1));

                    ASSERT(Q2 == 0.15*_Q2 + 0.85*Q2(1));

 

                    // Homodyne Discriminator, Complex Conjugate Multiply

                    auto X1 = I2 * I2(1);

                    auto X2 = I2 * Q2(1);

                    auto Y1 = Q2 * Q2(1);

                    auto Y2 = Q2 * I2(1);

                    auto _Re = X1 + Y1;

                    auto _Im = X2 - Y2;

 

                    //// Smooth to remove undesired cross products

                    self_ref_series<double> Re(0), Im(0);

                    Re = 0.2*_Re + 0.8*Re;

                    Im = 0.2*_Im + 0.8*Im;

                    ASSERT(Re == 0.2*_Re + 0.8*Re(1));

                    ASSERT(Im == 0.2*_Im + 0.8*Im(1));

 

                    auto Re0 = IF(Re == 0, 0.000001, Re);

                    auto Im0 = IF(Im == 0, 0.000001, Im);

 

                    //// Compute Cycle Period

                    auto new_period = CONST(360.0) / (ATAN(SAFE_DIVIDE(Im0, Re0)) * (180.0 / const_pi()));

                    new_period = CAP(new_period, 1.5  * period);

                    new_period = FLOOR(new_period, 0.67 * period);

                    new_period = CAP(new_period, 50.0);

                    new_period = FLOOR(new_period, 6.0);

 

                    period = 0.2*new_period + 0.8* period;

 

                    period.plot_as("Dominant Cycle Period (Hilbert)", 0.0, plot_type::line, color::cadet_blue, 2);

                    return period;

          }

Fisher Transform


 

          sref<double> FISHERTRANSFORM(sref<double> data, sref<size_t> period, size_t max_period)

          {

                    auto per = VERIFY_PERIOD(period, max_period);

                    self_ref_series<double> esto(0.0);

                    auto hh = MAX(data, per, max_period);

                    auto ll = MIN(data, per, max_period);

                    auto sto = 2 * SAFE_DIVIDE(data - ll, hh - ll) - 1.0;

                    esto = 0.33*sto + 0.67*esto(1);

                    auto isto = IF(esto > 0.999, 0.999, IF(esto < -0.999, -0.999, esto));

                    auto dsto = SAFE_DIVIDE(1.0 + esto, 1.0 - esto);

                    auto fsto = LN(dsto);

 

                    fsto.plot_as("Fisher Transform", 0, plot_type::line, color::cadet_blue, 2);

                    fsto.pane_h_line(color::white, 0.0, 2);

                    return fsto;

          }