Hilfe beim Schreiben einer linearen Regression - Seite 5

 
Rosh писал (а) >>

Und so sieht es in Excel 2007 aus



Es könnte also notwendig sein, Matcad zu überprüfen.

Wenn ich es richtig verstehe, liefert Excel das dritte Ergebnis, das sich von den ersten beiden unterscheidet). Wo liegt die Wahrheit? B ist dasselbe wie Matcad, aber der Koeffizient A ist anders.

 
Prival писал (а) >>

Wenn ich es richtig verstehe, hat Excel das dritte Ergebnis geliefert, das sich von den ersten beiden unterscheidet). Wo liegt die Wahrheit? B ist derselbe wie in Matcad, aber der Koeffizient A ist anders.

Bei so vielen signifikanten Ziffern und einer solchen Bandbreite von Berechnungen wird im Allgemeinen irgendwo auf der Rückseite der Mantisse gerechnet. Das heißt, dass sogar Elemente des Zufalls in die Antwort einfließen können. Ich denke, Korrektheit kann nur für einen speziellen Algorithmus mit hoher Genauigkeit erwartet werden. In diesem Fall sollten Sie den Koordinatenursprung näher an den X-Bereich verschieben .



P.S. Besonders wenn die Summe von X*X berechnet wird, geht die Information direkt ins Klo :)

 
lna01 писал (а) >>

Bei so vielen signifikanten Ziffern und einem solchen Bereich werden die Berechnungen in der Regel im hinteren Teil der Mantisse durchgeführt. Das heißt, dass sogar Elemente des Zufalls in die Antwort einfließen können. Ich denke, dass man sich nur bei einem speziellen Algorithmus mit erhöhter Genauigkeit auf die Korrektheit verlassen kann. Aber in diesem Fall ist es besser , den Koordinatenursprung näher an den X-Bereich zu verschieben.

Es geht darum, dass ich mit den Vorbereitungen für die Meisterschaft begonnen habe. Ich begann, meine Entwicklungen in Matkadec in MQL zu übersetzen. Wenn Sie sich erinnern, haben wir die ACF (Autokorrelationsfunktion) erstellt, und ich habe damit begonnen und beschlossen, direkte Formeln zu verwenden, da ich die CPU durch Fourier-Transformationen zu stark belastet habe.

Deshalb habe ich mich auf die Suche nach der Quelle der Harke gemacht (

Ich werde versuchen, X (Zeit) auf 0 zu setzen. Aber ich werde alles noch einmal überprüfen müssen. Ich muss bereits etwa 50 % meiner Ideen aufgeben.

 
Prival писал (а) >>

Die Sache ist die, dass ich begonnen habe, mich auf die Meisterschaft vorzubereiten. Und ich begann, meine Entwicklungen in Matcadet auf MQL zu übertragen. Wenn Sie sich erinnern, haben wir die ACF (Autokorrelationsfunktion) erstellt. Ich habe damit begonnen und beschlossen, sie mit direkten Formeln zu berechnen, da Fourier-Transformationen den Prozessor stark belasten.

Deshalb habe ich angefangen zu analysieren, wo das Problem zu wachsen begann.

Ich werde versuchen, X (Zeit) auf 0 zu setzen. Aber ich werde alles noch einmal überprüfen müssen. Schon jetzt muss ich 50 % meiner Ideen aufgeben.

MT behält 15 Ziffern in der Mantisse. Wenn wir die Wurzel ziehen, erhalten wir 10^7. Das heißt, man muss Zahlen, die größer als 10000000 sind, quadrieren und aufsummieren, siehe Nachtrag zum vorherigen Beitrag :). Glücklicherweise entspricht diese Grenze der Anzahl der Minutenbalken in der realen Historie, so dass es trotzdem funktionieren sollte, wenn dies der Fall ist. Aber wenn es die Zeit ist, dann ist eine Verschiebung des Koordinatenursprungs einfach unvermeidlich.


P.S. Übrigens, wenn Sie Ihre Funktion in der Meisterschaft verwenden wollen, fügen Sie einen Schutz gegen Division durch Null hinzu. Andernfalls besteht die Gefahr, dass Ihr Indikator in der Mitte der Meisterschaft steht. Oder am Anfang. Denken Sie daran, dass es so etwas auch bei Fourier gab.

 

Derselbe Algorithmus in Java

import java.util.ArrayList;

public class Prival {
public static void main(String arg[]){
int N = 6;
double Y[];
double X[];
ArrayList<Double> Parameters = new ArrayList<Double>();
Parameters.add(0.0);
Parameters.add(0.0);
X = new double[6];
Y = new double[6];
for ( int i = 0; i < N; i ++ )
{
// массивы Y и X для проверки работоспособности
// intercept = -3.33333333 slope = 5.00000000

X[i]=i;
Y[i]=i*i;
}

LinearRegr(X, Y, N,Parameters);
System.out.println("intercept = "+Parameters.get(0)+" slope = "+ Parameters.get(1));

// вторая проверка
X[0]=1216640160;
X[1]=1216640100;
X[2]=1216640040;
X[3]=1216639980;
X[4]=1216639920;
X[5]=1216639860;

Y[0]=1.9971;
Y[1]=1.9970;
Y[2]=1.9967;
Y[3]=1.9969;
Y[4]=1.9968;
Y[5]=1.9968;


LinearRegr(X, Y, N, Parameters);
System.out.println("intercept = "+Parameters.get(0)+" slope = "+ Parameters.get(1));

}
public static void LinearRegr(double X[], double Y[], int N, ArrayList<Double> Parameters){
double sumY = 0.0, sumX = 0.0, sumXY = 0.0, sumX2 = 0.0;
double A=0,B=0;
for ( int i = 0; i < N; i ++ ){
sumY +=Y[i];
sumXY +=X[i]*Y[i];
sumX +=X[i];
sumX2 +=X[i]*X[i];
}
B=(sumXY*N-sumX*sumY)/(sumX2*N-sumX*sumX);
A=(sumY-sumX*B)/N;
Parameters.set(0, A);
Parameters.set(1, B);
}
}


Ergebnis:


Achsenabschnitt = -3,3333333333333335 Steigung = 5,0
Achsenabschnitt = -1102,169141076954 Steigung = 9,075536028198574E-7

Prozess mit Exit-Code 0 beendet

 

Rosch

Ich stimme zu, dass diese Formeln das gleiche Ergebnis liefern, hier ist Matcad

Ich sehe, dass die Ergebnisse mit MQL und Java übereinstimmen, aber Matcad hat mich noch nie im Stich gelassen, daher habe ich Zweifel. Ich habe es überprüft und die Ergebnisse sortiert.

Ich habe es überprüft und nach X sortiert und die Koeffizienten erneut berechnet.

ERGEBNIS hat sich geändert!!!, das sollte nicht der Fall sein. Höchstwahrscheinlich ist der Fehler auf eine Fehlerakkumulation aufgrund der Quadrierung großer Zahlen zurückzuführen(Candid hat Recht). Ich habe in der Literatur nachgeforscht und eine einfachere Formel gefunden, die ohne Quadratur auskommt und scheinbar weniger Berechnungen erfordert.

Das Ergebnis ist dasselbe wie in Matcad, und es hängt nicht von der Sortierung ab.

Ich empfehle die Verwendung dieser Formel zur Berechnung der linearen Regressionskoeffizienten.

//+------------------------------------------------------------------+
//|                                                       LinReg.mq4 |
//|                                                    Привалов С.В. |
//|                                             Skype -> privalov-sv |
//+------------------------------------------------------------------+
#property copyright "Привалов С.В."
#property link      "Skype -> privalov-sv"

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
   int      N=6;                 // Размер массива
   double   Y[],X[],A=0.0, B=0.0;
   
  ArrayResize(X,N);
  ArrayResize(Y,N);
      
// проверка 
    X[0]=1216640160;
    X[1]=1216640100;
    X[2]=1216640040;
    X[3]=1216639980;
    X[4]=1216639920;
    X[5]=1216639860;
    
    Y[0]=1.9971;
    Y[1]=1.9970;    
    Y[2]=1.9967;
    Y[3]=1.9969;    
    Y[4]=1.9968;    
    Y[5]=1.9968;
    
    
  LinearRegr(X, Y, N, A, B);
  
  Print("A = ", DoubleToStr(A,8)," B = ",DoubleToStr(B,8));
           
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Рассчет коэффициентов A и B в уравнении                          |
//| y(x)=A*x+B                                                       |
//| используються формулы https://forum.mql4.com/ru/10780/page5       |
//+------------------------------------------------------------------+

void LinearRegr(double X[], double Y[], int N, double& A, double& B)
{
      double mo_X = 0.0, mo_Y = 0.0, var_0 = 0.0, var_1 = 0.0;
      
    for ( int i = 0; i < N; i ++ )
      {
        mo_X +=X[i];
        mo_Y +=Y[i];
      }
    mo_X /=N;
    mo_Y /=N;
        
    for ( i = 0; i < N; i ++ )
      {
        var_0 +=(X[i]-mo_X)*(Y[i]-mo_Y);
        var_1 +=(X[i]-mo_X)*(X[i]-mo_X);
      }
        A = var_0 / var_1;
        B = mo_Y - A * mo_X;
}

Ich hänge das Skript an, wenn jemand LinearRegr bereinigt (um Fehler bei der Arbeit mit echten Daten zu vermeiden und die Leistung zu erhöhen), wäre das gut. Ich habe A und B vertauscht, weil

Die Notation y(x)=a*x+b ist mir (aus Büchern) geläufiger.

Dateien:
linreg_1.mq4  2 kb
 

Ich verstehe nicht, wie das Ergebnis von der Sortierung abhängen kann. Die Sortierung wird in den Formeln nirgends explizit verwendet.


Außerdem verwendet der letztgenannte Algorithmus Erwartungswerte von X und Y und kann daher möglicherweise auch einen Fehler in die Berechnungen einbringen. Und noch etwas: Die Verwendung von zwei Schleifen anstelle einer Schleife wird die Leistung wahrscheinlich nicht verbessern.


Wenn wir umfangreiche lineare Regressionsberechnungen für eine Reihe von Preissequenzen durchführen müssen, ist es besser, separate Puffer in einem Indikator auszuwählen und die Berechnung mit der kumulativen Gesamtmethode durchzuführen. Damit lassen sich die Berechnungen um Größenordnungen beschleunigen. Beispiel - Kaufman AMA optimiert : Perry Kaufman AMA optimiert

 
Rosh писал (а) >>

Ich verstehe nicht, wie das Ergebnis von der Sortierung abhängen kann. Die Sortierung wird in den Formeln nirgends explizit verwendet.


Außerdem verwendet der letzte Algorithmus die Erwartung der X- und Y-Werte, was zu Fehlern in den Berechnungen führen kann. Und noch etwas: Die Verwendung von zwei Schleifen statt einer würde die Leistung kaum verbessern.

Wenn wir die Massenberechnungen der linearen Regression für eine Reihe von Preissequenzen durchführen müssen, ist es besser, separate Puffer in einem Indikator zu wählen und die kumulative Totalisierungsmethode zu verwenden. Damit lassen sich die Berechnungen um Größenordnungen beschleunigen. Beispiel - Kaufman AMA optimiert : Perry Kaufman AMA optimiert

1. Der Punkt ist, dass das Ergebnis nicht von der Sortierung abhängen sollte, während der Algorithmus dies tut. Sehen Sie sich das an.

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
   int      N=6;                 // Размер массива
   double   Y[],X[],Y1[],X1[],A=0.0, B=0.0;
   
  ArrayResize(X,N);
  ArrayResize(Y,N);
  ArrayResize(X1,N);
  ArrayResize(Y1,N);
      
// проверка 
    X[0]=1216640160;
    X[1]=1216640100;
    X[2]=1216640040;
    X[3]=1216639980;
    X[4]=1216639920;
    X[5]=1216639860;
    
    Y[0]=1.9971;
    Y[1]=1.9970;    
    Y[2]=1.9967;
    Y[3]=1.9969;    
    Y[4]=1.9968;    
    Y[5]=1.9968;
    

// отсортируем массив по возрастанию X (исходный массив был по убыванию)
  for (int i = 0; i < N; i++)
   {
   X1[i]=X[N-i-1];
   Y1[i]=Y[N-i-1];
//   Print(X[i], " ", X1[i], " ", Y[i], " ", Y1[i]);
   }            
//----
// 
  LinearRegr(X, Y, N, A, B);
  Print("A = ", DoubleToStr(A,8)," B = ",DoubleToStr(B,8));
  LinearRegr(X1, Y1, N, A, B);
  Print(" A = ", DoubleToStr(A,8)," B = ",DoubleToStr(B,8));

  LinearRegr1(X, Y, N, A, B);
  Print("A = ", DoubleToStr(A,8)," B = ",DoubleToStr(B,8));
  LinearRegr1(X1, Y1, N, A, B);
  Print(" A = ", DoubleToStr(A,8)," B = ",DoubleToStr(B,8));

   return(0);
  }

//-------------------------------------------------------------------------------
// использование этой формулы приводит к ошибкам если X=Time
// формула предложена вот тут https://forum.mql4.com/ru/10780/page4
//| y(x)=A+B*x  

void LinearRegr(double X[], double Y[], int N, double& A, double& B)
{
      double sumY = 0.0, sumX = 0.0, sumXY = 0.0, sumX2 = 0.0;
      
    for ( int i = 0; i < N; i ++ )
    {
        sumY   +=Y[i];
        sumXY  +=X[i]*Y[i];
        sumX   +=X[i];
        sumX2  +=X[i]*X[i];
    }
   B=(sumXY*N-sumX*sumY)/(sumX2*N-sumX*sumX);
   A=(sumY-sumX*B)/N;
}

//+------------------------------------------------------------------+
//| Формула предлагаемая мной                                        |
//| Рассчет коэффициентов A и B в уравнении                          |
//| y(x)=A*x+B                                                       |
//| используються формулы https://forum.mql4.com/ru/10780/page5       |
//+------------------------------------------------------------------+

void LinearRegr1(double X[], double Y[], int N, double& A, double& B)
{
      double mo_X = 0.0, mo_Y = 0.0, var_0 = 0.0, var_1 = 0.0;
      
    for ( int i = 0; i < N; i ++ )
      {
        mo_X +=X[i];
        mo_Y +=Y[i];
      }
    mo_X /=N;
    mo_Y /=N;
        
    for ( i = 0; i < N; i ++ )
      {
        var_0 +=(X[i]-mo_X)*(Y[i]-mo_Y);
        var_1 +=(X[i]-mo_X)*(X[i]-mo_X);
      }
        A = var_0 / var_1;
        B = mo_Y - A * mo_X;
}

Das Ergebnis ist

2008.07.30 13:51:08 LinReg EURUSD,M1: A = 0.00000090 B = -1098.77264952

2008.07.30 13:51:08 LinReg EURUSD,M1: A = 0.00000090 B = -1098.77264952

2008.07.30 13:51:08 LinReg EURUSD,M1: A = -1078.77267965 B = 0.00000089

2008.07.30 13:51:08 LinReg EURUSD,M1: A = -1102.16914108 B = 0.00000091

Dies sollte nicht der Fall sein.

Ich kann sehen, dass zwei Schleifen erscheinen, deshalb habe ich um eine schnellere Leistung gebeten. Der Algorithmus "Regression: Was ist das?" mag schneller sein, aber wir sollten auch ihn optimieren (ich glaube, Vinin hat das bereits getan).

3. Danke für Kaufmann, das ist ein guter Indikator. Falls Sie es noch nicht vergessen haben: Vor der zweiten Meisterschaft habe ich darin Ungenauigkeiten entdeckt. Danke, dass Sie sie korrigiert haben.

Z.U. frage ich, werdie Mathematik hat. Geben Sie diese Arrays ein und berechnen Sie die eingebauten Formeln (soweit ich mich erinnere, gibt es welche), und posten Sie das Ergebnis hier. Um zu einem Konsens zu kommen. Ich danke Ihnen. Hilfe )). Rosh ist ziemlich schwer zu überzeugen, aber ich habe auch eine militärische Stirn )))

 
Prival писал (а) >>

2. ich kann sehen, dass zwei Schleifen auftreten, deshalb habe ich um eine Beschleunigung gebeten. Der Algorithmus "Regression: Was ist das?" ist vielleicht schneller, aber wir sollten ihn auch optimieren (ich glaube, Vinin hat das bereits getan).

LWMA ist in der Tat sicherer als X*X, so dass Ihre Arbeit mit Mathemat eine neue Bedeutung erhält :). Ich halte jedoch meine erste Empfehlung (Verschiebung des Koordinatenursprungs) nach wie vor für die beste Option. Ist die formale Ersetzung von Time[pos] durch Time[pos]-Time[Bars-1] überall ein solches Fehlerrisiko?

 
Prival писал (а) >>

1. Das ist das Problem: Das Ergebnis sollte nicht von der Sortierung abhängen, aber in diesem Algorithmus ist es das. Sehen Sie sich das an.

Ergebnis

2008.07.30 13:51:08 LinReg EURUSD,M1: A = 0.00000090 B = -1098.77264952

2008.07.30 13:51:08 LinReg EURUSD,M1: A = 0.00000090 B = -1098.77264952

2008.07.30 13:51:08 LinReg EURUSD,M1: A = -1078.77267965 B = 0.00000089

2008.07.30 13:51:08 LinReg EURUSD,M1: A = -1102.16914108 B = 0.00000091

Dies sollte nicht der Fall sein.



Fügen Sie die ristrintokwa in Ihrem Code:

//-------------------------------------------------------------------------------
// использование этой формулы приводит к ошибкам если X=Time
// формула предложена вот тут https://forum.mql4.com/ru/10780/page4
//| y(x)=A+B*x  
 
void LinearRegr(double X[], double Y[], int N, double& A, double& B)
{
      double sumY = 0.0, sumX = 0.0, sumXY = 0.0, sumX2 = 0.0;
      
    for ( int i = 0; i < N; i ++ )
    {
        sumY   +=Y[i];
        sumXY  +=X[i]*Y[i];
        sumX   +=X[i];
        sumX2  +=X[i]*X[i];
    }
   Print("sumY = ",DoubleToStr(sumY,8)," sumX = ",DoubleToStr(sumX,8)," sumXY = ",DoubleToStr(sumXY,8)," sumX2 = ",DoubleToStr(sumX2,8));
   Print("sumXY*dN-sumX*sumY = ",DoubleToStr(sumXY*dN-sumX*sumY,8));    
   Print("sumX2*dN-sumX*sumX = ",DoubleToStr(sumX2*dN-sumX*sumX,8));    
 
   B=(sumXY*N-sumX*sumY)/(sumX2*N-sumX*sumX);
   A=(sumY-sumX*B)/N;
}

Holen Sie sich so etwas wie das hier:

erster Aufruf
sumY = 11.98130000 sumX = 7299840060.00000000 sumXY = 14576928951.87000100 sumX2 = 8881277483596863500.00000000
sumXY*dN-sumX*sumY = 0,34199524
sumX2*dN-sumX*sumX = 376832.00000000
A = -1102,16914108 B = 0,00000091
Zweitanruf
sumY = 11.98130000 sumX = 7299840060.00000000 sumXY = 14576928951.87000300 sumX2 = 8881277483596864500.00000000
sumXY*dN-sumX*sumY = 0,34202576
sumX2*dN-sumX*sumX = 385024.00000000
A = -1078,77267965 B = 0,00000089

Dies ist ein weiterer Fallstrick bei Computerberechnungen und Rundungen. Einerseits habe ich selbst nicht mit einer solchen Abweichung gerechnet, andererseits ist eine solche Differenz verständlich, wenn zwei Wertreihen (X und Y) zu große Unterschiede in der Reihenfolge der Werte aufweisen.