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;
}