Una vez hice una de estas cosas...

 

Un día me di cuenta de una cosa muy sencilla: la aproximación por mínimos cuadrados consiste esencialmente en minimizar una combinación lineal de vectores. Es decir, se puede fabricar algún tipo de función aproximadora universal. Es un hecho, así que aquí está el título de la función:

//+------------------------------------------------------------------+
//  Аппроксимация методом наименьших квадратов                       |
//+------------------------------------------------------------------+
bool LSA(double& V[], int M, int N, double& A[], double& C[]) {
// Имеется N векторов размером M
// и вектор их линейной комбинации Y размером естестственно тоже M.
// На вход функции они подаются в виде матрицы V[0..M-1][0..N],
// где Y размещён в столбце N 
// На выходе мы должны получить вектор коэффициентов C размером M.
// Нам нужна также матрица A[N][N+1] для размещения коэффициентов системы уравнений

Detalle importante, todas las matrices V y A son realmente unidimensionales, la matriz A es puramente de trabajo, pero la matriz V necesita ser llenada correctamente.

También necesita una función para resolver un sistema de ecuaciones lineales. Cuando estaba haciendo esto, sólo conocía una implementación en MQL, el método gaussiano utilizado por ANG3110 para la regresión polinómica. Naturalmente, tomé el camino de menor resistencia y utilicé este algoritmo particular para la función. En otras palabras, hay algoritmos más eficientes, especialmente porque la matriz es simétrica, pero no los he utilizado.

Cómo utilizarlo:

Primero decidimos qué función vamos a aproximar. Sea una regresión lineal, por ejemplo. Es decir, tendremos una combinación lineal de A*1 + B*X, sólo dos vectores, un vector unitario y el propio argumento.

Vamos a crear matrices de trabajo y a asignarles memoria en alguna parte de init()

double V[];
double A[],С[];

...

  ArrayResize(A,6);  // размер N*(N+1)
  ArrayResize(C,2);  // размер N
  ArrayResize(V,M*3);  // M*(N+1), M - не что иное как размер выборки

Sólo queda rellenar correctamente la matriz V y calcular los coeficientes. Esto puede hacerse de la siguiente manera:

    ind = 0;
    Stop = Start + M;
// Заполняем векторы
    for(pos = Start; i < Stop; i++) {
     V[ind] = 1.0;
     ind++;
     V[ind] = pos;
     ind++;
     V[ind] = Close[pos];   
     ind++;
    }
// Считаем коэффициенты
   LSA(V, M, N, A, C);

Está hecho, la regresión lineal C[0] + C[1]*pos está lista.

Lo primero que tenemos que hacer es comprobar el algoritmo. Para ello, basándonos en el indicador ang_PR (Din)-v1.mq4 ( ANG3110 ) escribimos un indicador de regresión polinómica utilizando LSA y comparamos los resultados. Los resultados coincidieron visualmente, ese fue el final de la prueba :). Se adjunta el indicador LSA_PR.mq4.

Archivos adjuntos:
pr_lsa.mq4  7 kb
 

Todo esto fue hace bastante tiempo, y hace poco me acordé de ello y decidí volver a poner en marcha la herramienta que hice.

Lo primero que pensé fue en buscar la periodicidad en el gráfico de citas. Puede surgir la pregunta de por qué, porque existe una transformada discreta de Fourier (DFT) para buscar armónicos. Pero la FFT sólo dará armónicos con un período más corto que la longitud de la muestra. Ahora podemos intentar ajustar los armónicos con el período más largo que la longitud de la muestra al gráfico de precios. Por supuesto, el éxito del ajuste no será un argumento "irrefutable" a favor de su existencia real, la cuestión del grado de confianza en una aproximación concreta debe decidirse por separado.

En el indicador adjunto LSA_SinLRR.mq4 se calcula la tendencia lineal antes de probar con la armónica. Se calcula utilizando el horizonte superior. Se buscan todas las longitudes de muestra posibles dentro de un determinado rango y se selecciona la que tiene el mínimo error RMS en la muestra fuera de la muestra (que se toma como 1/4 del tamaño de la muestra base).

El periodo armónico se relaciona con la longitud de la muestra, multiplicándola por un factor determinado. Si es igual a 2, por ejemplo, la muestra contendrá medio período del armónico, y si es igual a 0,5, dos períodos. La longitud de la muestra se determina de la misma manera que para la regresión lineal, pero la búsqueda se realiza dentro del horizonte más bajo.

Para reducir la cantidad de cálculos, se realiza un paso de muestreo diferente para cada horizonte.

La matriz vectorial se rellena de la siguiente manera

  for(i = IntShift; i < Frame; i++) {
    pos = HShift+i*Step;
    VT[ind] = MathSin(AFreq*pos);
    ind ++;
    VT[ind] = MathCos(AFreq*pos);
    ind ++;
    VT[ind] = Resid[i];   
    ind ++;
  }  //  for(i = IntShift; i < Frame; i++)

El residuo es la diferencia entre el precio y la tendencia más antigua.

Parámetros del indicador:

extern double kPer = 4.0;   // Коэффициент для определения периода
extern int LRRank = 1;      // Номер старшего горизонта, больше 3-х не ставить
extern int FShift = 120;    // Расстояние в барах, на которое производится экстраполяция в будущее
extern int HShift = 1;      // Сдвиг текущего времени индикатора в прошлое в барах, бары правее него тоже будут проэктраполированы
extern double PointFactor = 0.1;  // Масштабирование гистограммы ошибок аппроксимации, 0.1 подойдёт для минуток на пятизнаке 
extern bool PriceClose = true; // Если false, то будет считаться по HL/2


Uf, de alguna manera me he cansado de escribir :)

Brevemente, la esencia es la siguiente: Esta función no pretende ser óptima, simplemente permite hacer aproximaciones como tortitas y probarlas de inmediato, nada más sacarlas de la sartén :) . En consecuencia, los indicadores están hechos de tal manera, es decir, no pretenden nada, en términos de estilo y eficacia.

Este caso no funciona muy rápidamente, por lo que el historial no se calcula. Esto significa que es mejor estudiar en el visualizador. Pero se aburre rápidamente :). Pero no se puede descartar que algún paciente pueda encontrar la manera de beneficiarse de ello :).


En general, soy consciente de que no podría hacer una descripción coherente, si alguien está interesado, probablemente pueda contar con explicaciones.


Básicamente, se trata de otro indicador, que se aproxima y extrapola mejor que los presentados. Es decir, me impresiona tanto, que parece que por fin me he convertido en un determinista de los precios a destajo. Pero eso no lo hace más fácil, porque todavía no he conseguido determinar la longitud de esas piezas :) .

Pero no tengo energía para escribir más, sólo puedo dar un par de fotos :)

Ejemplo de aproximación con extrapolación exitosa

Ejemplo de aproximación con extrapolación "frustrada" por un impulso

Archivos adjuntos:
lsa_sinlr.mq4  14 kb
 
Candid:

¿Podría añadir un pequeño trozo de código, que HShift no se establece, pero se determina por la posición real de la primera línea? más precisamente si se establece <0 - a continuación, ambos mecanismos funcionará y será posible tirar de él en el gráfico de profundidad en la historia y analizar cómo la previsión en ese punto coincidió con lo que sucedió después. será interesante ;)

 
ForexTools:

¿Podría añadir un pequeño trozo de código, que HShift no se establece, sino que se determina por la posición real de la primera línea? Más precisamente, si se establece <0 - entonces ambos mecanismos funcionarán y se puede arrastrar en un gráfico de profundidad en la historia y analizar cómo la previsión en ese punto coincidió con lo que sucedió después. será interesante ;)

Sí, es bastante práctico, te daré una versión. Debo señalar que no soy especialmente aficionado al control gráfico, así que no hay garantía de que todo vaya a funcionar bien.


Por cierto, creo que no he dicho explícitamente en ningún sitio que los histogramas de la esquina inferior derecha muestren el error de aproximación sobre la muestra base y el error de extrapolación sobre la muestra fuera. Es razonable suponer que esta información es relevante para evaluar la situación.


P.D. Sí, se me olvidó añadir una línea. Indicador reemplazado a las 11:50

Archivos adjuntos:
 

Unas pocas palabras más. ¿Por qué se toma exactamente una tendencia lineal? De todos modos, las tendencias reales parecen lineales. La suposición es que tal detrending se puede hacer inconscientemente, entonces hay esperanza de que puede haber realidad detrás de los armónicos también.

En principio, elevar el grado de un polinomio no es un problema, de hecho yo empecé con la opción de la parábola. Esto se hace de forma elemental, en unas pocas líneas añadidas y corregidas, cualquiera puede probarlo por sí mismo, como ejercicio.

 

Buenas tardes.

Por favor, explique los dibujos. Me interesan las líneas verticales. ¿he entendido bien que en el intervalo entre las líneas azules están los datos para la previsión? ¿qué significa la roja? - el momento de divergencia con la previsión ? ¿por qué las líneas de previsión rojas (azules) tienen huecos ?

No he mirado el código porque su nivel de programación MQL es demasiado bajo para mí, es como un sueño acercarse a ese nivel ?

 

Prival:

por favor, explique los dibujos. Me interesan las líneas verticales. ¿He entendido bien que en el intervalo entre las líneas azules están los datos para la previsión? ¿Qué significa la roja? - ¿por qué las líneas de previsión rojas (azules) tienen huecos?


Sí, en realidad la aproximación se hace entre las líneas azules. Entre el azul y el rojo se calcula la RMS de la extrapolación. Sólo está en nuestra mano desplazarlo con HShift (y ahora sólo arrastrando la línea a lo largo del gráfico) y ver lo que no ve.

Los huecos son "residuos", la ventana de trabajo del indicador se desplaza en el tiempo, se dejan colas. Esto sería fácil de arreglar con una ventana permanente, pero como se adapta, todavía no se me ha ocurrido una forma barata de limpiarlo.

Te doy la versión con las líneas repintadas.

Archivos adjuntos:
 

su nuevo código no funcionó como yo quería :(

Me tomé la libertad de desmontar mis ediciones. funciona muy bien, especialmente cuando se combina con ft.AutoRefresh

Archivos adjuntos:
lsa_sinlr_1.mq4  16 kb
 

ForexTools:

Aquí me permití desmontar mis ediciones. funciona muy bien especialmente cuando se combina con ft.AutoRefresh

Bueno, creo que tu versión es más resistente a las interferencias, pero probablemente necesites añadir HShift-- ahí también, para que en ausencia de acciones del usuario la ventana se mueva en el tiempo. Aunque, hmm, ¿tal vez eso es exactamente lo que querías evitar?
 
Por supuesto, al analizar la historia, el gráfico no debe ir a ninguna parte, sino "pararse" en el lugar en el que coloco la línea
 
ForexTools:
Por supuesto, al analizar la historia, el gráfico no debe ir a ninguna parte, sino "pararse" en el lugar en el que coloco la línea

Bueno, primero hice una variante estacionaria y luego la sustituí :). Me interesaba, en primer lugar, la dinámica del rediseño. En realidad, es fácil añadir un parámetro como

if (ModeMoving) HShift--;
Pero demasiado bueno tampoco es bueno, que la variante quede ociosa.