Note: Make sure you have C++11 or later support for nan("") usage and adjust the plotting mechanism according to your environment.
Also, the code will create a simple command-line output for the plot as TradingView does not support C++:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// Constants
const int MAX_LINES = 500; // Maximum number of lines
// Settings
int length = 50; // Length of the data series
int extrapolate = 10; // Number of points to extrapolate
int degree = 3; // Degree of the polynomial
vector<float> src(length, 0.0); // Source data (close prices)
bool lock = false; // Lock forecast flag
// Style
int up_css = 0x0cb51a26; // Color for upward lines
int dn_css = 0xff110026; // Color for downward lines
int ex_css = 0x00dfd0; // Color for extrapolated lines
int width = 1; // Line width
// Creating the line structure
struct Line {
float x1, y1, x2, y2; // Coordinates of the line
int color; // Color of the line
};
// Creating a new array of lines
vector<Line> array_new_line() {
return vector<Line>(MAX_LINES);
}
// Adding a line to the lines array
void array_push(vector<Line>& lines, float x1, float y1, float x2, float y2, int color, int idx) {
lines[idx].x1 = x1;
lines[idx].y1 = y1;
lines[idx].x2 = x2;
lines[idx].y2 = y2;
lines[idx].color = color;
}
// Creating a new matrix with given dimensions
vector<vector<float>> matrix_new(int rows, int cols) {
return vector<vector<float>>(rows, vector<float>(cols, 0.0));
}
// Adding a column to the matrix
void matrix_add_col(vector<vector<float>>& matrix, const vector<float>& column) {
for (int i = 0; i < matrix.size(); ++i) {
matrix[i].push_back(column[i]);
}
}
// Transposing the matrix
vector<vector<float>> matrix_transpose(const vector<vector<float>>& matrix) {
vector<vector<float>> result(matrix[0].size(), vector<float>(matrix.size()));
for (int i = 0; i < matrix.size(); ++i) {
for (int j = 0; j < matrix[i].size(); ++j) {
result[j][i] = matrix[i][j];
}
}
return result;
}
// Multiplying two matrices
vector<vector<float>> matrix_mult(const vector<vector<float>>& A, const vector<vector<float>>& B) {
vector<vector<float>> result(A.size(), vector<float>(B[0].size(), 0.0));
for (int i = 0; i < A.size(); ++i) {
for (int j = 0; j < B[0].size(); ++j) {
for (int k = 0; k < B.size(); ++k) {
result[i][j] += A[i][k] * B[k][j];
}
}
}
return result;
}
// Inversing the matrix (placeholder implementation, assuming diagonal matrix for simplicity)
vector<vector<float>> matrix_inv(const vector<vector<float>>& matrix) {
vector<vector<float>> result(matrix.size(), vector<float>(matrix[0].size(), 0.0));
for (int i = 0; i < matrix.size(); ++i) {
result[i][i] = 1.0 / matrix[i][i];
}
return result;
}
// Calculating power of a number
float math_pow(float base, int exponent) {
return pow(base, exponent);
}
// Getting the element from the matrix
float matrix_get(const vector<vector<float>>& matrix, int i, int j) {
return matrix[i][j];
}
// The main function
int main() {
int current_bar = 0; // Current bar index
vector<Line> lines = array_new_line(); // Array of lines
vector<vector<float>> design = matrix_new(degree + 1, length); // Design matrix
vector<vector<float>> response = matrix_new(length, 1); // Response matrix
vector<vector<float>> a; // Intermediate matrix a
vector<vector<float>> b; // Intermediate matrix b
vector<vector<float>> coefficients; // Coefficients matrix
int pass = 1; // Pass flag
float x = -extrapolate; // Initial x value for extrapolation
float forecast = 0.0; // Forecast value
// Fill lines array
if (current_bar == 0) {
for (int i = -extrapolate; i < length; ++i) {
array_push(lines, nan(""), nan(""), nan(""), nan(""), 0, i + extrapolate);
}
}
// Get design matrix & partially solve system
if (current_bar == 0) {
for (int i = 0; i <= degree; ++i) {
vector<float> column;
for (int j = 0; j < length; ++j) {
column.push_back(math_pow(j, i));
}
matrix_add_col(design, column);
}
a = matrix_inv(matrix_mult(matrix_transpose(design), design));
b = matrix_mult(a, matrix_transpose(design));
}
// Get response matrix and compute rolling polynomial regression
if (current_bar == 0) {
if (pass) {
vector<float> prices;
for (int i = 0; i < length; ++i) {
prices.push_back(src[i]);
}
matrix_add_col(response, prices);
coefficients = matrix_mult(b, response);
float y1 = nan("");
int idx = 0;
for (int i = -extrapolate; i < length; ++i) {
float y2 = 0.0;
for (int j = 0; j <= degree; ++j) {
y2 += math_pow(i, j) * matrix_get(coefficients, j, 0);
}
if (idx == 0) {
forecast = y2;
}
int css = y2 < y1 ? up_css : dn_css;
array_push(lines, current_bar - i + 1, y1, current_bar - i, y2, i <= 0 ? ex_css : css, idx + extrapolate);
y1 = y2;
++idx;
}
if (lock) {
pass = 0;
}
} else {
float y2 = 0.0;
x -= 1;
for (int j = 0; j <= degree; ++j) {
y2 += math_pow(x, j) * matrix_get(coefficients, j, 0);
}
forecast = y2;
}
}
// Plotting the curve
if (pass == 0) {
cout << "Extrapolation: " << forecast << endl;
} else {
cout << "Not ready for extrapolation yet." << endl;
}
return 0;
}
Now, let’s check out how well it back tests!