Calculate Pearson's R for Linear Regression PineScript - linear-regression

I have a pinescript strategy below in which I am trying to calculate the Pearsons R correlation value. I got the code from here and modified it a bit (https://www.tradingview.com/script/CD7yUWRV-Linear-Regression-Trend-Channel/).
His code does not include the Pearson's R correlation which is very important to the trading strategy I'm trying to use since it indicates the strength of the trend and it's direction (up or down). To see a working examle of the Pearson's R, add the default indicator linear regression and it will be the number to the bottom left. I'll attach a screenshot for an example.
How do I calculate the Pearson's R Value from the code I have so far?
I have looked for sample pine scripts that have the Pearson's R calculation for linear regression in pinescript and could not find anything.
strategy(title="Linear Regression Trend Channel Strategy", overlay=true,initial_capital=1000,commission_type=strategy.commission.percent,commission_value=0.26,default_qty_type=strategy.percent_of_equity,default_qty_value=100)
period = input( 240, "Period" , input.integer, minval=3)//288
deviations = input( 2.0, "Deviation(s)" , input.float , minval=0.1, step=0.1)
extendType = input("Right", "Extend Method", input.string , options=["Right","None"])=="Right" ? extend.right : extend.none
periodMinusOne = period-1
Ex = 0.0, Ey = 0.0, Ex2 = 0.0, Exy = 0.0, for i=0 to periodMinusOne
closeI = nz(close[i]), Ex := Ex + i, Ey := Ey + closeI, Ex2 := Ex2 + (i * i), Exy := Exy + (closeI * i)
ExEx = Ex * Ex, slope = Ex2==ExEx ? 0.0 : (period * Exy - Ex * Ey) / (period * Ex2 - ExEx)
linearRegression = (Ey - slope * Ex) / period
intercept = linearRegression + bar_index * slope
deviation = 0.0, for i=0 to periodMinusOne
deviation := deviation + pow(nz(close[i]) - (intercept - slope * (bar_index[i])), 2.0)
deviation := deviations * sqrt(deviation / periodMinusOne)
startingPointY = linearRegression + slope * periodMinusOne
var line upperChannelLine = na , var line medianChannelLine = na , var line lowerChannelLine = na
line.delete(upperChannelLine[1]), line.delete(medianChannelLine[1]), line.delete(lowerChannelLine[1])
upperChannelLine := line.new(bar_index - period + 1, startingPointY + deviation, bar_index, linearRegression + deviation, xloc.bar_index, extendType, color.new(#FF0000, 0), line.style_solid , 2)
medianChannelLine := line.new(bar_index - period + 1, startingPointY , bar_index, linearRegression , xloc.bar_index, extendType, color.new(#C0C000, 0), line.style_solid , 1)
lowerChannelLine := line.new(bar_index - period + 1, startingPointY - deviation, bar_index, linearRegression - deviation, xloc.bar_index, extendType, color.new(#00FF00, 0), line.style_solid , 2)
if(crossunder(close,line.get_y2(lowerChannelLine)))
strategy.entry("Long", strategy.long)
if(crossover(close,line.get_y2(upperChannelLine)))
strategy.entry("Short", strategy.short)

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © x11joe
// Credit given to #midtownsk8rguy for original source code. I simply modified to add Pearson's R
//#version=4
study("Linear Regression Trend Channel With Pearson's R", "LRTCWPR", true, format.inherit)
period = input( 20, "Period" , input.integer, minval=3)
deviations = input( 2.0, "Deviation(s)" , input.float , minval=0.1, step=0.1)
extendType = input("Right", "Extend Method", input.string , options=["Right","None"])=="Right" ? extend.right : extend.none
periodMinusOne = period-1
Ex = 0.0, Ey = 0.0, Ex2 = 0.0,Ey2 =0.0, Exy = 0.0, for i=0 to periodMinusOne
closeI = nz(close[i]), Ex := Ex + i, Ey := Ey + closeI, Ex2 := Ex2 + (i * i),Ey2 := Ey2 + (closeI * closeI), Exy := Exy + (closeI * i)
ExT2 = pow(Ex,2.0) //Sum of X THEN Squared
EyT2 = pow(Ey,2.0) //Sym of Y THEN Squared
PearsonsR = (Exy - ((Ex*Ey)/period))/(sqrt(Ex2-(ExT2/period))*sqrt(Ey2-(EyT2/period)))
ExEx = Ex * Ex, slope = Ex2==ExEx ? 0.0 : (period * Exy - Ex * Ey) / (period * Ex2 - ExEx)
linearRegression = (Ey - slope * Ex) / period
intercept = linearRegression + bar_index * slope
deviation = 0.0, for i=0 to periodMinusOne
deviation := deviation + pow(nz(close[i]) - (intercept - slope * (bar_index[i])), 2.0)
deviation := deviations * sqrt(deviation / periodMinusOne)
startingPointY = linearRegression + slope * periodMinusOne
var label pearsonsRLabel = na
label.delete(pearsonsRLabel[1])
pearsonsRLabel := label.new(bar_index,startingPointY - deviation*2,text=tostring(PearsonsR), color=color.black,style=label.style_labeldown,textcolor=color.white,size=size.large)
var line upperChannelLine = na , var line medianChannelLine = na , var line lowerChannelLine = na
line.delete(upperChannelLine[1]), line.delete(medianChannelLine[1]), line.delete(lowerChannelLine[1])
upperChannelLine := line.new(bar_index - period + 1, startingPointY + deviation, bar_index, linearRegression + deviation, xloc.bar_index, extendType, color.new(#FF0000, 0), line.style_solid , 2)
medianChannelLine := line.new(bar_index - period + 1, startingPointY , bar_index, linearRegression , xloc.bar_index, extendType, color.new(#C0C000, 0), line.style_solid , 1)
lowerChannelLine := line.new(bar_index - period + 1, startingPointY - deviation, bar_index, linearRegression - deviation, xloc.bar_index, extendType, color.new(#00FF00, 0), line.style_solid , 2)
Okay so I posted my solution below. I got the idea thanks to a youtube video here, https://www.youtube.com/watch?v=2B_UW-RweSE
This really helped me figure out the formula. Hope this helps someone else on tradingView that needed this!

i think this
PearsonsR = (Exy - ((Ex*Ey)/period))/(sqrt(Ex2-(ExT2/period))*sqrt(Ey2-(EyT2/period)))
should be
PearsonsR = (((Ex*Ey)/period)-Exy)/(sqrt(Ex2-(ExT2/period))*sqrt(Ey2-(EyT2/period)))
according with:https://it.wikipedia.org/wiki/Indice_di_correlazione_di_Pearson#/media/File:Correlation_coefficient.png

Related

Using desolve The number of derivatives returned by func must equal the length of the initial conditions vector

I get this error The number of derivatives returned by func() (1) must equal the length of the initial conditions vector (3)
Can some kindly suggest how resolve ?
Thanks
# Define the ODE system
diffeq <- function(t, y, params) {
with(as.list(c(y, params)), {
dCc <- -k12 * c_central + k21 * c_peripheral - k10 * c_central
dCp <- k12 * c_central - k21 * c_peripheral
dy <- -alpha * exp(-beta * y) * y + (c_central - gamma) * (c_central - gamma)
dw <- g * (t - delay) - kw * w
dg <- ks * kw * w0 * (w/W0)^(-param) * exp(-u * y) - (ks + v * y) * g
return(list(dCc, dCp,dy, dw, dg))
})
}
# Set the initial conditions and parameter values
y0 <- 0
g0 <- 0
w0 <- 100
c_central0 <- 500/5
c_peripheral0 <- 0
params <- c(alpha = 1, beta = 2, gamma = 3, kw = 0.1, k12 = 1.2,
k21 = 1.5, k10 = 0.04,ks = 0.01, delay = 0.5,
W0 = 100, param = 2, u = 1, v = 2,c_central = c_central0, c_peripheral = c_peripheral0)
# Solve the differential equations using an ODE solver
result <- ode(y = c(y = y0, w = w0, g = g0), times = seq(0, 40, by = 0.1), func = diffeq, parms = params)
# Plot the solution
plot(result[, "time"], result[, "y"], type = "l", xlab = "Time (t)", ylab = "y(t)")
lines(result[, "time"], result[, "w"], col = "red")
lines(result[, "time"], result[, "g"], col = "blue")```

How to compute the derivatives automatically within for-loop in Matlab?

For the purpose of generalization, I hope Matlab can automatically compute the 1st & 2nd derivatives of the associated function f(x). (in case I change f(x) = sin(6x) to f(x) = sin(8x))
I know there exists built-in commands called diff() and syms, but I cannot figure out how to deal with them with the index i in the for-loop. This is the key problem I am struggling with.
How do I make changes to the following set of codes? I am using MATLAB R2019b.
n = 10;
h = (2.0 * pi) / (n - 1);
for i = 1 : n
x(i) = 0.0 + (i - 1) * h;
f(i) = sin(6 * x(i));
dfe(i) = 6 * cos(6 * x(i)); % first derivative
ddfe(i) = -36 * sin(6 * x(i)); % second derivative
end
You can simply use subs and double to do that. For your case:
% x is given here
n = 10;
h = (2.0 * pi) / (n - 1);
syms 'y';
g = sin(6 * y);
for i = 1 : n
x(i) = 0.0 + (i - 1) * h;
f(i) = double(subs(g,y,x(i)));
dfe(i) = double(subs(diff(g),y,x(i))); % first derivative
ddfe(i) = double(subs(diff(g,2),y,x(i))); % second derivative
end
By #Daivd comment, you can vectorize the loop as well:
% x is given here
n = 10;
h = (2.0 * pi) / (n - 1);
syms 'y';
g = sin(6 * y);
x = 0.0 + ((1:n) - 1) * h;
f = double(subs(g,y,x));
dfe = double(subs(diff(g),y,x)); % first derivative
ddfe = double(subs(diff(g,2),y,x)); % second derivative

Applying 2D Gabor Wavelet on Image

EDIT: This is the code I am using that generates an edge detected looking image:
cookiesImage = rgb2gray(imread('Cookies.png'));
width = 45;
height = 45;
KMAX = pi / 2;
f = sqrt(2);
delta = pi / 3;
output = zeros(size(cookiesImage, 1), size(cookiesImage, 2), 8);
for i = 0 : 7
wavelets = GaborWavelet(width, height, KMAX, f, i, 2, delta);
figure(1);
subplot(1, 8, i + 1), imshow(real(wavelets), []);
output(:, :, i + 1) = imfilter(cookiesImage, wavelets, 'symmetric');
end
display = sum(abs(output).^2, 3).^0.5;
display = display./max(display(:));
figure(2); imshow(display);
function GWKernel = GaborWavelet (width, height, KMAX, f, u , v, delta)
delta2 = delta * delta;
kv = KMAX / (f^v);
thetaU = (u * pi) / 8;
kuv = kv * exp (1i * thetaU);
kuv2 = abs(kuv)^2;
GWKernel = zeros (height, width);
for y = -height/ 2 + 1 : height / 2
for x = -width / 2 + 1 : width / 2
GWKernel(y + height / 2, x + width / 2) = (kuv2 / delta2) * exp(-0.5 * kuv2 * (x * x + y * y) / delta2) * (exp(1i * (real(kuv) * y + imag (kuv) * x )) - exp (-0.5 * delta2));
end
end
This is the function that I am using for the Wavelets and this is how I am trying to apply them but all I am getting is an edge detected looking image, rather than one as in this link.
Running your code, I see the following wavelets being generated:
These look a lot like rotated second derivatives. This is only the real (even) component of the Gabor filter kernels. The imaginary (odd) counterparts look like first derivatives.
This is why you feel like your result is like an edge-detected image. It sort of is.
Try increasing the size of the filter (not the footprint widthxheight, but the delta that determines the size of the envelope). This will make it so that you see a larger portion of the sinusoid waves that form the Gabor kernel.
Next, the result image you show is the sum of the square magnitude of the individual Gabor filters. Try displaying the real or imaginary components of one of the filter results, you'll see it looks more like you'd expect:
imshow(real(output(:,:,3)),[])
I'm not familiar with this parametrization of the Gabor kernel, but note that it has a Gaussian envelope. Therefore, the footprint (width, height) of the kernel can be adjusted to the size of this Gaussian (which seems to use delta as the sigma). I typically recommend using a kernel footprint of 2*ceil(3*sigma)+1 for the Gaussian kernel. The same applies here:
width = 2*ceil(3*delta)+1;
height = width;
This will speed up computations, as you see in the image above your kernels have lots of near-zero values in them, it is possible to crop them to a smaller size without affecting the output.
The GaborWavelet function can also be simplified a lot using vectorization:
function GWKernel = GaborWavelet (width, height, KMAX, f, u , v, delta)
delta2 = delta * delta;
kv = KMAX / (f^v);
thetaU = (u * pi) / 8;
kuv = kv * exp (1i * thetaU);
kuv2 = abs(kuv)^2;
x = -width/2 + 1 : width/2;
[x,y] = meshgrid(x,x);
GWKernel = (kuv2 / delta2) * exp(-0.5 * kuv2 * (x .* x + y .* y) / delta2) ...
.* (exp(1i * (real(kuv) * y + imag (kuv) * x )) - exp (-0.5 * delta2));

For loop in MATLAB for vectors

I run the following code and expect to get a vector IB, I do get a vector but all of whose elements are same I don't know what the problem is with this code?
function IB = ibtest(VCC)
RL = [1000, 10000, 200000, 400000, 600000, 800000, 1000000];
RB = 22000;
RP = 50;
R = 470;
B = 300;
i = 0;
for t = 1:length(RL)
i = i+1;
IB(i) = ((VCC - 2.1)*(RL(i) + RP)) / ( (RL(i) * RP) + (RB*(RL(i) + RP)) + (301 * 470 * (RL(i) + RP)) );
end
IB
end
There's nothing wrong with your code. You should get equal numbers as you increase numerator and denominator by the same fraction every iteration. Try running this code:
function IB = ibtest(VCC)
RL = [1000, 10000, 200000, 400000, 600000, 800000, 1000000];
RB = 22000;
RP = 50;
R = 470;
B = 300;
for t = 1:length(RL)
num = ((VCC - 2.1)*(RL(t) + RP))
denom = ( (RL(t) * RP) + (RB*(RL(t) + RP)) + (301 * 470 * (RL(t) + RP)) )
IB(t) = num / denom
end
end
I also don't know what you want to compute so if you don't get what you expect there must be something wrong with the formula.

MATLAB orbit of earth and moon about the sun

We are trying to plot the orbit of the moon around the earth, which in turn is orbiting the sun. We are employing the Euler-Cromer method. This code works for a simulation of the planets. And it should work given the right initial conditions, for a more complicated set up such as what we are trying now with three bodies. Our code is this:
function [xe, ye, xm, ym] = earth_moon(me, mm)
% Constants
ms = 2e30;
ntsteps = 12;
dt = 0.001;
% Variables: Earth
xe = 1 : dt : ntsteps;
xe(1) = 1; % Initial x pos (AU)
ye = 1 : dt : ntsteps;
ye(1) = 0; % Initial y pos (AU)
vex = 0;
vey = 6.27; % AU/yr
% Variables: Moon
xm = 1 : dt : ntsteps;
xm(1) = 1.0027; % Initial x pos (AU)
ym = 1 : dt : ntsteps;
ym(1) = 0; % Initial y pos (AU)
vmx = 0;
vmy = 0.215 + vey; % AU/yr
% Calculations
for i = 1 : ntsteps / dt
rm = sqrt(xm(i)^2 + ym(i)^2);
re = sqrt(xe(i)^2 + ye(i)^2);
rme = sqrt((xm(i) - xe(i))^2 + (ym(i) - ye(i))^2);
vex = vex - 4 * pi^2 * xe(i) / re^3 * dt - 4 * pi^2 * (mm / ms) * (xe(i) - xm(i))/rme^3 * dt;
vey = vey - 4 * pi^2 * ye(i) / re^3 * dt - 4 * pi^2 * (mm / ms) * (ye(i) - xm(i))/rme^3 * dt;
vmx = vmx - 4 * pi^2 * xm(i) / rm^3 * dt - 4 * pi^2 * (me / ms) * (xm(i) - xe(i))/rme^3 * dt;
vmy = vmy - 4 * pi^2 * ym(i) / rm^3 * dt - 4 * pi^2 * (me / ms) * (ym(i) - ye(i))/rme^3 * dt;
xm(i + 1) = xm(i) + vmx * dt;
ym(i + 1) = ym(i) + vmy * dt;
xe(i + 1) = xe(i) + vex * dt;
ye(i + 1) = ye(i) + vey * dt;
end
end
And the script is as follows:
clear
clc
me = 5.97237e24;
mm = 7.3477e22;
[xe, ye, xm, ym] = earth_moon(me, mm);
hold on;
plot(xm, ym, 'r');
plot(xe, ye, 'b');
plot(0, 0, 'r.', 'Markersize', 50);
plot(0, 0, 'y.', 'Markersize', 40);
grid on;
axis square;
xlabel('X position (AU)');
ylabel('Y position (AU)');
ylim([-2, 2])
xlim([-2, 2])
title('Three-body orbit: Sun, Earth, Moon');
text(2, 5.5, strcat('Earth: ', num2str(me), ' kg'));
text(3.5, 4.5, strcat('Moon: ', num2str(mm), ' kg'));
legend('Moon', 'Earth', 'Location', 'eastoutside');
But we just cant get the moon to cooperate. Any suggestions?
Thanks!