선형 회귀 작성 도움말 - 페이지 5

 
Rosh писал (а) >> 를 썼습니다.

다음은 Excel 2007에서 생성한 것입니다.



따라서 Matkad를 확인해야 할 수도 있습니다.

내가 올바르게 이해했다면 Excel은 처음 두 개와 다른 세 번째 결과를 제공했습니다. 그리고 진실은 어디에 있습니까? B는 matkad와 일치하지만 계수 A는 다릅니다.

 
Prival писал (а) >> 를 작성했습니다.

내가 올바르게 이해하면 Excel은 처음 두 개와 다른 세 번째 결과를 제공했습니다. 그리고 진실은 어디에 있습니까? B는 matkad와 일치하지만 계수 A는 다릅니다.

일반적으로 유효 자릿수와 범위가 너무 많기 때문에 계산은 가수의 뒤쪽 어딘가에 있습니다. 즉, 임의성의 요소도 답변에 도입될 수 있습니다. 정확성은 증가된 정확도의 일부 특수 알고리즘에 대해서만 기대할 수 있다고 생각합니다. 하지만 이 경우에는 더 좋습니다. 원점을 X 범위에 더 가깝게 이동합니다.



추신 특히 X*X의 양을 계산하면 정보가 바로 변기에 쏙쏙 :)

 
lna01 писал (а) >>

일반적으로 유효 자릿수와 범위가 너무 많기 때문에 계산은 가수의 뒤쪽 어딘가에 있습니다. 즉, 임의성의 요소도 답변에 도입될 수 있습니다. 정확성은 증가된 정확도의 일부 특수 알고리즘에 대해서만 기대할 수 있다고 생각합니다. 하지만 이 경우에는 더 좋습니다. 원점을 X 범위에 더 가깝게 이동합니다.

사실 그는 우승을 준비하기 시작했다. 그리고 그는 matcad에서 개발한 내용을 MQL 로 번역하기 시작했습니다. 기억하신다면, 우리는 ACF(자기상관 함수)를 만들었습니다. 저는 그것으로 시작했고 직접 공식을 사용하여 계산하기로 결정했습니다. 왜냐하면 푸리에 변환을 통해 프로세서에 과부하가 걸립니다.

첫 번째 시도와 즉시 matcad의 ACF 레이크가 MQL 의 ACF와 일치하지 않으므로 레이크가 어디에서 자라는지 알아내기 시작했습니다(

X(시간)를 0점으로 이동하려고 합니다. 하지만 다시 모든 것을 다시 확인해야 합니다. 그래서 이미 아이디어의 50%는 포기해야 합니다.

 
Prival писал (а) >> 를 썼습니다.

사실 그는 우승을 준비하기 시작했다. 그리고 그는 matcad에서 개발한 내용을 MQL 로 번역하기 시작했습니다. 기억하신다면, 우리는 ACF(자기상관 함수)를 만들었습니다. 저는 그것으로 시작했고 직접 공식을 사용하여 계산하기로 결정했습니다. 왜냐하면 푸리에 변환을 통해 프로세서에 과부하가 걸립니다.

첫 번째 시도와 즉시 matcad의 ACF 레이크가 MQL 의 ACF와 일치하지 않으므로 레이크가 어디에서 자라는지 파악하기 시작했습니다(

X(시간)를 0점으로 이동하려고 합니다. 하지만 다시 모든 것을 다시 확인해야 합니다. 그래서 이미 아이디어의 50%는 포기해야 합니다.

MT는 가수에서 15자리를 보유합니다. 루트를 추출하면 10 ^ 7이 됩니다. 즉, 제곱하고 그 후에도 10000000보다 큰 숫자를 합산하려면 이전 게시물의 포스트 스크립트를 참조하세요. 다행히도 이 제한은 실제 기록의 분 막대 수에 해당하므로 이에 대해 이야기하면 여전히 작동해야 합니다. 그리고 이것이 시간이라면 원점의 이동은 단순히 그 자체를 암시합니다.


PS 그건 그렇고, 챔피언십에서 기능을 사용하려면 0으로 나누기 보호를 추가하십시오. 그렇지 않으면 지표가 단순히 챔피언십 중간에 서게 될 위험이 있습니다. 또는 처음에. Fourier에는 그러한 트릭이 있음을 기억하십시오.

 

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);
}
}


결과:


절편 = -3.3333333333333335 기울기 = 5.0
절편 = -1102.169141076954 기울기 = 9.075536028198574E-7

종료 코드 0으로 프로세스 완료

 

로쉬

나는 이 공식이 matkad에서 같은 결과를 줄 것이라는 데 동의합니다.

결과가 MQL과 Java와 일치하는 것을 볼 수 있지만 matcad는 나를 실망시킨 적이 없으므로 의심됩니다. 게다가 이것은 심각한 매트입니다. 반복적으로 테스트된 패키지.

확인하고 X 로 정렬했습니다. 그리고 다시 계수를 계산했습니다.

결과가 변경되었습니다!!!, 하지만 이것은 변경되어서는 안됩니다. 오류는 큰 수를 제곱하여 발생하는 오류의 누적으로 인한 것일 가능성이 큽니다( Candid 오른쪽). 나는 문헌을 파헤치고 더 간단한 공식을 찾았습니다. 제곱도 없고 계산도 적습니다.

결과는 matkad와 일치하며 정렬에 의존하지 않습니다.

이 공식을 사용하여 선형 회귀 계수를 계산하는 것이 좋습니다.

 //+------------------------------------------------------------------+
//|                                                       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 ;
}

누군가 LinearRegr을 정리하면(실생활에서 작업할 때 오류가 발생하고 성능이 향상되는 경우) 스크립트를 첨부하면 일반적으로 좋습니다. AB 를 교환했기 때문에

항목 y ( x )= a * x + b 더 친숙합니다(저에게는 책에서).

파일:
linreg_1.mq4  2 kb
 

결과가 정렬에 어떻게 의존하는지 알 수 없습니다. 정렬은 수식의 어느 곳에서도 명시적으로 사용되지 않습니다.


또한 후자의 알고리즘은 X와 Y의 예상 값을 사용하며 잠재적으로 계산에 약간의 오류가 발생할 수도 있습니다. 그리고 한 가지 더: 하나에 대해 두 개의 루프를 사용하면 성능이 향상되지 않을 것입니다.


여러 가격 시퀀스에 대한 선형 회귀의 대량 계산이 필요한 경우 지표에 별도의 버퍼를 할당하고 합계를 누적하는 방법으로 계산하는 것이 좋습니다. 이를 통해 계산 속도를 몇 배나 높일 수 있습니다. 예 - Kaufman의 최적화된 AMA : Perry Kaufman 의 최적화된 AMA

 
Rosh писал (а) >> 를 썼습니다.

결과가 정렬에 어떻게 의존하는지 알 수 없습니다. 정렬은 수식의 어느 곳에서도 명시적으로 사용되지 않습니다.


또한 후자의 알고리즘은 X와 Y의 예상 값을 사용하며 잠재적으로 계산에 약간의 오류가 발생할 수도 있습니다. 그리고 한 가지 더: 하나에 대해 두 개의 루프를 사용하면 성능이 향상되지 않을 것입니다.

여러 가격 시퀀스에 대한 선형 회귀의 대량 계산이 필요한 경우 지표에 별도의 버퍼를 할당하고 합계를 누적하는 방법으로 계산하는 것이 좋습니다. 이를 통해 계산 속도를 몇 배나 높일 수 있습니다. 예 - Kaufman의 최적화된 AMA : Perry Kaufman 의 최적화된 AMA

1. 결과가 정렬에 의존하지 않아야 하고 그 알고리즘이 의존해야 한다는 점입니다. 여기 확인합니다.

 //+------------------------------------------------------------------+
//| 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 ;
}

결과

2008.07.30 13:51:08 린레그 EURUSD , M 1: A = 0.00000090 B =-1098.77264952

2008.07.30 13:51:08 린레그 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

그리고 이것은 안됩니다.

2. 두 개의 사이클이 있는 것을 보니 어떻게든 속도를 높여달라고 요청했습니다. 이 알고리즘은 아마도 더 빠를 것입니다 . '회귀: 무엇입니까?' , 하지만 최적화도 필요합니다( Vinin 이 이미 이 작업을 수행했다고 생각합니다)

3. 좋은 지표인 Kaufman에 감사드립니다. 잊지 않았다면 두 번째 우승 전에 작업의 부정확성을 포착했습니다. 수정해주셔서 감사합니다.

Z.Y. 누가 Ma tlab 을 가지고 있는지 부탁드립니다 . 이 배열을 입력하고 기본 제공 공식(내가 기억하는 한 있음)으로 계산하고 결과를 여기에 게시하십시오. 합의에 도달하기 위해. 고맙습니다. 돕다)). Rosh는 설득하기가 상당히 어렵지만 군대 이마도 있습니다))

 
Prival писал (а) >> 를 썼습니다.

2. 두 개의 사이클이 있는 것을 보니 어떻게든 속도를 높여달라고 요청했습니다. 이 알고리즘은 아마도 더 빠를 것입니다 . '회귀: 무엇입니까?' , 하지만 최적화도 필요합니다( Vinin 이 이미 이 작업을 수행했다고 생각합니다)

LWMA는 실제로 X*X보다 안전하므로 Mathemat 를 사용한 작업은 새로운 의미를 갖게 됩니다. :) 하지만 첫 번째 추천(원점 이동)은 계속해서 최선의 선택을 고려합니다. 모든 곳에서 Time[pos]를 Time[pos]-Time[Bars-1]으로 공식적으로 대체하면 오류가 발생할 위험이 있습니까?

 
Prival писал (а) >> 를 썼습니다.

1. 결과가 정렬에 의존하지 않아야 하고 그 알고리즘이 의존해야 한다는 점입니다. 여기 확인합니다.

결과

2008.07.30 13:51:08 린레그 EURUSD , M 1: A = 0.00000090 B =-1098.77264952

2008.07.30 13:51:08 린레그 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

그리고 이것은 안됩니다.



출력물을 코드에 붙여넣습니다.

 //-------------------------------------------------------------------------------
// использование этой формулы приводит к ошибкам если 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 ;
}

다음과 같은 것을 얻으십시오.

첫 전화
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
두 번째 전화
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

이것은 컴퓨터 계산 및 반올림의 또 다른 함정입니다. 한편으로는 나 자신도 그런 갈퀴를 예상하지 못했는데, 한편으로는 두 계열의 값(X, Y)이 값의 순서에 너무 큰 차이가 있을 때 그러한 차이를 충분히 이해할 수 있다.