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+ϵ
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
}