Eu fiz uma dessas coisas uma vez ...

 

Um dia de repente percebi uma coisa simples: a aproximação dos mínimos quadrados é essencialmente sobre a minimização de uma combinação linear de vetores. Ou seja, algum tipo de função aproximadora universal pode ser fabricada. É um negócio fechado, então aqui está o título da função:

//+------------------------------------------------------------------+
//  Аппроксимация методом наименьших квадратов                       |
//+------------------------------------------------------------------+
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] для размещения коэффициентов системы уравнений

Detalhe importante, todas as matrizes V e A são realmente unidimensionais, mas a matriz A está funcionando puramente, mas a matriz V precisa ser preenchida corretamente.

Também precisa de uma função para resolver um sistema de equações lineares. Quando eu estava inventando isto, conhecia apenas uma implementação em MQL, o método Gaussiano usado por ANG3110 para a regressão polinomial. Naturalmente, tomei o caminho de menor resistência e usei este algoritmo particular para a função. Em outras palavras, existem algoritmos mais eficientes, especialmente porque a matriz é simétrica, mas eu não os utilizei.

Como utilizá-lo:

Primeiro decidimos qual função vamos aproximar. Que seja uma regressão linear, por exemplo. Ou seja, teremos uma combinação linear de A*1 + B*X, apenas dois vetores, um vetor unitário e o próprio argumento.

Vamos criar arrays de trabalho e alocar memória para eles em algum lugar no init()

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

...

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

O que resta é preencher corretamente a matriz V e calcular os coeficientes. Isto pode ser feito da seguinte forma:

    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á feito, a regressão linear C[0] + C[1]*pos está pronta.

A primeira coisa que precisamos fazer é verificar o algoritmo. Para este fim, com base no indicador ang_PR (Din)-v1.mq4 ( ANG3110 ) escrevemos um indicador de regressão polinomial usando LSA e comparamos os resultados. Os resultados coincidiram visualmente, que foi o final do teste :). O indicador LSA_PR.mq4 está anexado.

Arquivos anexados:
pr_lsa.mq4  7 kb
 

Tudo isso foi há muito tempo, e recentemente eu me lembrei disso e decidi colocar em ação novamente a ferramenta que fiz.

Meu primeiro pensamento foi buscar a periodicidade no gráfico de cotação. A questão pode surgir por quê, pois existe uma transformada de Fourier discreta (DFT) para a busca de harmônicas. Mas o FFT só dará harmônicas com um período mais curto do que a duração da amostra. Agora podemos tentar encaixar os harmônicos com o período mais longo do que a duração da amostra na tabela de preços. Naturalmente, o ajuste bem sucedido não será um argumento "de ferro" em favor de sua existência real, a questão do grau de confiança em uma determinada aproximação deve ser decidida separadamente.

No indicador anexo LSA_SinLRR.mq4, a tendência linear é calculada antes de tentar a harmônica. É calculado utilizando o horizonte superior. Todos os comprimentos de amostra possíveis em um determinado intervalo são pesquisados e aquele que tem o erro RMS mínimo na saída da amostra (que é tomada como 1/4 do tamanho da amostra base) é selecionado.

O período harmônico está relacionado à duração da amostra, multiplicando-a por um determinado fator. Se for igual a 2, por exemplo, então a amostra conterá meio período da harmônica, e se for igual a 0,5, então dois períodos. O comprimento da amostra em si é determinado da mesma forma que para a regressão linear, somente ela é enumerada dentro do horizonte mais baixo.

Para reduzir a quantidade de cálculos, uma etapa de amostragem diferente é tomada para cada horizonte.

A matriz vetorial é preenchida da seguinte forma

  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++)

O resíduo é a diferença entre o preço e a tendência mais antiga.

Parâmetros indicadores:

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


Ugh, de alguma forma eu fiquei cansado de escrever :)

Resumidamente, a essência é a seguinte: Esta função não pretende ser ótima, ela simplesmente permite que você faça aproximações como panquecas e as experimente imediatamente, direto da panela :) . Assim, os indicadores são feitos de tal forma, ou seja, não fazem pretensões a nada, em termos de estilo e eficiência.

Este caso não funciona muito rapidamente, portanto, a história não é calculada. Isso significa que é melhor estudar no visualizador. Mas fica entediante rapidamente :). Mas não se pode descartar que alguém paciente possa encontrar uma maneira de se beneficiar disso :).


Em geral, estou ciente de que não poderia fazer uma descrição coerente, se alguém estiver interessado, provavelmente pode contar com explicações.


Basicamente, devemos falar de outro indicador, que se aproxima e extrapola de forma mais bonita do que os apresentados. Ou seja, estou tão impressionado com isso que, aparentemente, fiquei finalmente na posição de determinismo de preço por etapas. Mas isso não facilita nada, porque ainda não consegui determinar o comprimento dessas peças :) .

Mas eu não tenho mais energia para escrever, só posso dar algumas fotos :)

Exemplo de aproximação com extrapolação bem sucedida

Exemplo de aproximação com extrapolação "frustrada" por um impulso

Arquivos anexados:
lsa_sinlr.mq4  14 kb
 
Candid:

Você poderia acrescentar um pequeno pedaço de código, que HShift não está definido, mas é determinado pela posição real da primeira linha? mais precisamente se estiver definido <0 - então ambos os mecanismos funcionarão e será possível puxá-lo no gráfico para dentro da história e analisar como a previsão naquele ponto coincidiu com o que aconteceu depois. será interessante ;)

 
ForexTools:

Você poderia acrescentar um pequeno pedaço de código, que HShift não está definido, mas é determinado pela posição real da primeira linha? Mais precisamente, se estiver definido <0 - então ambos os mecanismos funcionarão e você pode arrastá-lo em um gráfico profundamente na história e analisar como a previsão naquele ponto coincidiu com o que aconteceu depois disso ;)

Sim, é bastante útil, vou lhe dar uma versão. Devo ressaltar que não estou particularmente interessado no controle gráfico, portanto, não há garantia de que tudo será tranquilo.


A propósito, acho que não disse explicitamente em nenhum lugar que os histogramas no canto inferior direito mostram o erro de aproximação na amostra base e o erro de extrapolação na amostra de fora da amostra. É razoável supor que esta informação seja relevante para avaliar a situação.


P.S. Sim, esqueci uma linha para acrescentar. Indicador substituído às 11:50

Arquivos anexados:
 

Mais algumas palavras. Por que exatamente uma tendência linear é tomada? De qualquer forma, as tendências reais parecem lineares. A suposição é que tal dissuasão pode ser feita inconscientemente, então há esperança de que também possa haver realidade por trás das harmônicas.

Em princípio, elevar o grau de polinômio não é um problema, na verdade, comecei com a opção da parábola. Isto é feito de forma elementar, em poucas linhas adicionadas e corrigidas, qualquer um pode tentar por conta própria, como um exercício.

 

Boa tarde.

Por favor, explique os desenhos. Estou interessado nas linhas verticais. eu entendi corretamente que é no intervalo entre as linhas azuis que estão os dados para a previsão? o que significa o vermelho? - o momento de divergência com a previsão ? por que as linhas de previsão vermelhas (azuis) têm lacunas ?

eu não olhei para o código porque seu nível de programação MQL é muito baixo para mim, é como um sonho aproximar-se desse nível ?

 

Prival:

por favor, explique os desenhos. Estou interessado nas linhas verticais. Entendi corretamente que é no intervalo entre as linhas azuis que estão os dados para a previsão? o que significa o vermelho? - por que as linhas de previsão vermelhas (azuis) têm lacunas?


Sim, na verdade, a aproximação é feita entre as linhas azuis. Entre o azul e o vermelho é calculado o RMS da extrapolação. Só está em nosso poder deslocá-lo com HShift (e agora apenas arrastando a linha ao longo do gráfico) e ver o que ele não vê.

As lacunas são "desperdício", a janela de trabalho do indicador se desloca com o tempo, os rabos são deixados para trás. Isto seria fácil de consertar com uma janela permanente, mas como se adapta, ainda não me ocorreu uma maneira barata de limpá-la.

Apresento-lhes a versão com as linhas repintadas.

Arquivos anexados:
 

seu novo código não funcionou como eu queria que funcionasse :(

Tomei a liberdade de derrubar minhas edições. funciona muito bem especialmente quando emparelhado com o ft.AutoRefresh

Arquivos anexados:
lsa_sinlr_1.mq4  16 kb
 

ForexTools:

Aqui eu me permiti derrubar minhas edições. funciona muito bem, especialmente quando emparelhado com o ft.AutoRefresh

Bem, eu acho que sua versão é mais à prova de interferência, mas você provavelmente precisará adicionar HShift- lá também, para que na ausência de ações do usuário a janela se mova com o tempo. Embora, hmm, talvez seja exatamente isso que você quisesse evitar?
 
É claro! Ao analisar a história, o gráfico não deve ir a lugar algum, mas "ficar" no lugar onde eu coloco a linha
 
ForexTools:
É claro! Ao analisar a história, o gráfico não deve ir a lugar algum, mas "ficar" no lugar onde eu coloco a linha

Bem, primeiro fiz uma variante estacionária e depois a substituí :). Eu estava interessado, antes de mais nada, na dinâmica do redesenho. Na verdade, é fácil adicionar um parâmetro como

if (ModeMoving) HShift--;
Mas bom demais também não é bom, deixe a variante ociosa.
Razão: