Linear Regression

Linear regression is widely used in financial engineering for modeling and forecasting financial data, such as stock prices, interest rates, and macroeconomic indicators. In machine learning, it is a fundamental technique for supervised learning tasks, such as regression and classification, and is often used as a baseline model or as a component in more complex models.

We provide three functions to perform linear regression.

  • LinearRegression1: Returns the bias and coefficient of y after performing linear regression on the data

  • LinearRegression2: Returns the bias and coefficients of y and y2 after performing linear regression on the data

  • LinearRegressionAny: Returns the bias and coefficient of each variable after performing linear regression on the data. Uses more gas than LinearRegression1 and LinearRegression2 functions above, when possible use the aforementioned functions.

  • LinearRegressionPredict: Given the coefficients and the variables predicts the value

The formal definition for linear regression is provided using the following equation. Where y is the response variable, x is the predictor variable, beta is the coefficients, and epsilon is the error term.

y=β0+β1x1+β2x2++βpxp+ϵy = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \ldots + \beta_p x_p + \epsilon

To implement the functions, see the method signatures below. Precision represents the number of decimal places and can be set between 0 and 18. It is applied to all inputs and outputs.

function LinearRegression1(int[] calldata x, int[] calldata y, uint8 precision) external returns (int, int);

function LinearRegression2(int[] calldata x, int[] calldata y, int[] calldata y2, uint8 precision) external returns (int, int, int);

function LinearRegressionAny(int[] calldata x, int[][] calldata vars, uint8 precision) external returns (int[] memory);

function LinearRegressionPredict(int[] calldata coefficients, int[] calldata data, uint8 precision) external returns (int memory);

Under the hood, the following functions are utilized directly in the Neural client.

func (con *NeuralMath) LinearRegression1(gas *big.Int, x []*big.Int, y []*big.Int, precision uint8) (*big.Int, *big.Int, error, *big.Int) {
	mul, err := validatePrecision(precision)
	if err != nil {
		return nil, nil, err, nil
	}

	if len(x) != len(y) {
		return nil, nil, errors.New("lengths of x and y have to be equal"), nil
	}
	r := new(regression.Regression)
	r.SetVar(0, "x")
	x_f, err := toFloats(x, mul)
	if err != nil {
		return nil, nil, err, nil
	}
	y_f, err := toFloats(y, mul)
	if err != nil {
		return nil, nil, err, nil
	}
	for i := range x {
		r.Train(regression.DataPoint(x_f[i], []float64{y_f[i]}))
	}
	r.Run()
	return toBig(r.Coeff(0), mul), toBig(r.Coeff(1), mul), nil, nil
}

func (con *NeuralMath) LinearRegression2(gas *big.Int, x []*big.Int, y []*big.Int, y2 []*big.Int, precision uint8) (*big.Int, *big.Int, *big.Int, error, *big.Int) {
	mul, err := validatePrecision(precision)
	if err != nil {
		return nil, nil, nil, err, nil
	}
	if len(x) != len(y) || len(x) != len(y2) {
		return nil, nil, nil, errors.New("lengths of x, y and y2 have to be equal"), nil
	}
	r := new(regression.Regression)
	r.SetVar(0, "x")
	x_f, err := toFloats(x, mul)
	if err != nil {
		return nil, nil, nil, err, nil
	}
	y_f, err := toFloats(y, mul)
	if err != nil {
		return nil, nil, nil, err, nil
	}
	for i := range x {
		r.Train(regression.DataPoint(x_f[i], []float64{y_f[i]}))
	}
	r.Run()
	return toBig(r.Coeff(2), mul), toBig(r.Coeff(1), mul), toBig(r.Coeff(0), mul), nil, nil
}

func (con *NeuralMath) LinearRegressionAny(gas *big.Int, x []*big.Int, vars [][]*big.Int, precision uint8) ([]*big.Int, error, *big.Int) {
	mul, err := validatePrecision(precision)
	if err != nil {
		return nil, err, nil
	}
	for _, v := range vars {
		if len(x) != len(v) {
			return nil, errors.New("lengths of x and each variable are not equal"), nil
		}
	}
	r := new(regression.Regression)
	r.SetVar(0, "x")
	x_f, err := toFloats(x, mul)
	if err != nil {
		return nil, err, nil
	}

	v_f := make([][]float64, len(vars), len(vars))
	for i, v := range vars {
		v_f[i], err = toFloats(v, mul)
		if err != nil {
			return nil, err, nil
		}
	}
	for i := range x {
		r.Train(regression.DataPoint(x_f[i], v_f[i]))
	}
	r.Run()

	coefficients := make([]*big.Int, len(vars)+1)
	for i := range coefficients {
		coefficients[i] = toBig(r.Coeff(i), mul)
	}

	return coefficients, nil, nil
}

func (con *NeuralMath) LinearRegressionPredict(gas *big.Int, coefficients []*big.Int, data []*big.Int, precision uint8) (*big.Int, error, *big.Int) {
	mul, err := validatePrecision(precision)
	if err != nil {
		return nil, err, nil
	}
	if len(coefficients) != len(data)+1 {
		return nil, fmt.Errorf("Missing coefficients"), nil
	}
	weights, err := toFloats(coefficients, mul)
	if err != nil {
		return nil, err, nil
	}
	vars, err := toFloats(data, mul)
	if err != nil {
		return nil, err, nil
	}
	out := weights[0]

	for i, d := range vars {
		out += d * weights[i+1]
	}
	return toBig(out, mul), nil, nil
}

Last updated