GT::Indicators::LinearRegression

This function will calculate an L-Period linear regression line. Note that the term "linear regression" is the same as a "least squares" or "best fit" line.

The linear regression value is "a * i + b". i is the day number. a and b are also provided by the indicator if you want to calculate the value of the linear regression for other days.

Parameters

Takes 2 or 3 parameters. The first is the period over which the regression is calculated. The following parameters indicate the series that are being compared. If there is only a second parameter, this parameter forms the dependent variables, while the numerical sequence is the independent parameter. If there are both a second and a third parameter, the former is the independent and the latter the dependent parameter.


=cut

sub initialize { my ($self) = @_;

    # No default value for the first arg on purpose
    # It means use all the values for the regression and not only the XX
    # latest
    if (defined $self->{'args'}[0]) {
        $self->add_prices_dependency($self->{'args'}->get_arg_constant(1));
    }
}

sub calculate { my ($self, $calc, $i) = @_; my $linear_regression_line_name = $self->get_name(0); my $linear_regression_coefficient_a_name = $self->get_name(1); my $linear_regression_coefficient_b_name = $self->get_name(2); my $period = $self->{'args'}->get_arg_values($calc, $i, 1); my ($sum_x, $sum_y, $sum_xy) = 0; my ($variance_x, $variance_y) = 0;


    return if ($calc->indicators->is_available($linear_regression_line_name, $i) &&
               $calc->indicators->is_available($linear_regression_coefficient_a_name, $i) &&
               $calc->indicators->is_available($linear_regression_coefficient_b_name, $i));
    $self->remove_volatile_dependencies();
    $self->add_volatile_arg_dependency(2, $period);
    $self->add_volatile_arg_dependency(3, $period);
    return if (! $self->check_dependencies($calc, $i));
    # Initialize $period to $i if nothing was previously defined
    if (!defined $period) {
        $period = $i;
    }
    
    # Calculate the average of (x), (y) and (xy)
    for(my $n = $i - $period + 1; $n <= $i; $n++) {
        my $x = $self->{'args'}->get_arg_values($calc, $n, 2);
        my $y;
        if ( defined( $self->{'args'}->get_arg_object(3) ) ) {
          my $y = $self->{'args'}->get_arg_values($calc, $n, 3);
        } else {
          $y = $x;
          $x = $n;
        }
        $sum_x += $x;
        $sum_y += $y;
        $sum_xy += ($x * $y);
    }
    
    my $average_x = $sum_x / $period;
    my $average_y = $sum_y / $period;
    my $average_xy = $sum_xy / $period;
    # Calculate the variance of (x) and (y)
    for(my $n = $i - $period + 1; $n <= $i; $n++) {
        my $x = $self->{'args'}->get_arg_values($calc, $n, 2);
        my $y;
        if ( defined( $self->{'args'}->get_arg_object(3) ) ) {
          my $y = $self->{'args'}->get_arg_values($calc, $n, 3);
        } else {
          $y = $x;
          $x = $n;
        }
        $variance_x += (($x - $average_x) ** 2);
        $variance_y += (($y - $average_y) ** 2);
    }
    $variance_x /= $period;
    $variance_y /= $period;
    # Calculate the covariance(x,y)
    my $covariance = $average_xy - $average_x * $average_y;
    
    # Calculate the linear regression coefficients
    my $a = $covariance / $variance_x;
    my $b = $average_y - $a * $average_x;
    # Calculate the linear regression line value
    my $linear_regression_line_value = $a * $i + $b;
    
    # Return the results
    $calc->indicators->set($linear_regression_line_name, $i, $linear_regression_line_value);
    $calc->indicators->set($linear_regression_coefficient_a_name, $i, $a);
    $calc->indicators->set($linear_regression_coefficient_b_name, $i, $b);
}

1;