Ho fatto una di queste cose una volta ...

 

Un giorno mi sono improvvisamente reso conto di una cosa semplice: l'approssimazione dei minimi quadrati consiste essenzialmente nel minimizzare una combinazione lineare di vettori. Cioè, si può fabbricare una specie di funzione approssimatrice universale. È un affare fatto, quindi ecco il titolo della funzione:

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

Dettaglio importante, tutti gli array V e A sono davvero unidimensionali, l'array A è puramente funzionante, ma l'array V deve essere riempito correttamente.

Ha anche bisogno di una funzione per risolvere un sistema di equazioni lineari. Quando stavo facendo questo, conoscevo solo un'implementazione in MQL, il metodo Gaussiano usato da ANG3110 per la regressione polinomiale. Naturalmente, ho preso la via di minor resistenza e ho usato questo particolare algoritmo per la funzione. In altre parole, ci sono algoritmi più efficienti, soprattutto perché la matrice è simmetrica, ma non li ho usati.

Come usarlo:

Per prima cosa decidiamo quale funzione vogliamo approssimare. Sia una regressione lineare, per esempio. Cioè, avremo una combinazione lineare di A*1 + B*X, solo due vettori, un vettore unitario e l'argomento stesso.

Creiamo degli array funzionanti e allarghiamo la memoria per loro da qualche parte init()

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

...

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

Resta solo da riempire correttamente la matrice V e calcolare i coefficienti. Questo può essere fatto come segue:

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

È fatto, la regressione lineare C[0] + C[1]*pos è pronta.

La prima cosa da fare è controllare l'algoritmo. A questo scopo, basandoci sull'indicatore ang_PR (Din)-v1.mq4 ( ANG3110 ) abbiamo scritto un indicatore di regressione polinomiale usando LSA e abbiamo confrontato i risultati. I risultati coincidevano visivamente, questa era la fine del test :). L'indicatore LSA_PR.mq4 è allegato.

File:
pr_lsa.mq4  7 kb
 

Tutto questo è successo molto tempo fa, e recentemente mi sono ricordato e ho deciso di mettere di nuovo in azione lo strumento che avevo fatto.

Il mio primo pensiero è stato quello di cercare la periodicità nel grafico delle citazioni. Ci si può chiedere perché, visto che esiste una trasformata discreta di Fourier (DFT) per cercare le armoniche. Ma la FFT darà solo le armoniche con un periodo più breve della lunghezza del campione. Possiamo ora cercare di adattare le armoniche con il periodo più lungo della lunghezza del campione al grafico del prezzo. Naturalmente, l'adattamento riuscito non sarà un argomento "ferreo" a favore della sua reale esistenza, la questione del grado di fiducia in una particolare approssimazione dovrebbe essere decisa separatamente.

Nell'indicatore allegato LSA_SinLRR.mq4 la tendenza lineare è calcolata prima di provare sull'armonica. Si calcola utilizzando l'orizzonte superiore. Si provano tutte le possibili lunghezze del campione in un certo intervallo e si seleziona quella che ha il minimo errore RMS sul fuori campione (che è preso come 1/4 della dimensione del campione di base).

Il periodo armonico è legato alla lunghezza del campione, moltiplicandolo per un determinato fattore. Se è uguale a 2, per esempio, allora il campione conterrà mezzo periodo dell'armonica, e se è uguale a 0,5, allora due periodi. La lunghezza del campione stesso è determinata nello stesso modo come per la regressione lineare, solo che è enumerato all'interno dell'orizzonte più basso.

Per ridurre la quantità di calcoli, un passo di campionamento diverso è preso per ogni orizzonte.

La matrice vettoriale è compilata come segue

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

Il residuo è la differenza tra il prezzo e la vecchia tendenza.

Parametri dell'indicatore:

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, in qualche modo mi sono stancato di scrivere :)

In breve, il succo è il seguente: Questa funzione non pretende di essere ottimale, semplicemente ti permette di fare approssimazioni come frittelle e di provarle immediatamente, direttamente dalla padella :) . Di conseguenza, gli indicatori sono fatti in modo tale, cioè, non hanno pretese di nulla, in termini di stile ed efficienza.

Questo caso non funziona molto rapidamente, quindi la storia non viene calcolata. Significa che è meglio studiare in Visualizer. Ma diventa noioso velocemente :). Ma non si può escludere che qualcuno paziente possa trovare un modo per trarne beneficio :).


In generale, sono consapevole che non potrei fare una descrizione coerente, se qualcuno è interessato, probabilmente può contare su spiegazioni.


Fondamentalmente, dovremmo parlare di un altro indicatore, che approssima ed estrapola più meravigliosamente di quelli presentati. Cioè, sono così impressionato da questo, che apparentemente sono diventato finalmente nella posizione del determinismo dei prezzi. Ma questo non rende le cose più facili, perché non sono ancora riuscito a determinare la lunghezza di quei pezzi :) .

Ma non ho più energia per scrivere, posso solo dare un paio di foto :)

Esempio di approssimazione con estrapolazione riuscita

Esempio di approssimazione con estrapolazione "contrastata" da un impulso

File:
lsa_sinlr.mq4  14 kb
 
Candid:

Potresti aggiungere un piccolo pezzo di codice, che HShift non è impostato, ma è determinato dalla posizione attuale della prima linea? più precisamente se è impostato <0 - allora entrambi i meccanismi funzioneranno e sarà possibile tirarlo sul grafico in profondità nella storia e analizzare come la previsione in quel punto ha coinciso con ciò che è successo dopo. sarà interessante ;)

 
ForexTools:

Potresti aggiungere un piccolo pezzo di codice, che HShift non è impostato, ma è determinato dalla posizione attuale della prima linea? Più precisamente, se è impostato <0 - allora entrambi i meccanismi funzioneranno e puoi trascinarlo su un grafico in profondità nella storia e analizzare come la previsione in quel punto ha coinciso con ciò che è successo dopo. sarà interessante ;)

Sì, è abbastanza pratico, vi darò una versione. Devo precisare che non sono particolarmente appassionato di controllo grafico, quindi non c'è garanzia che tutto sia fluido.


A proposito, non credo di aver detto esplicitamente da nessuna parte che gli istogrammi in basso a destra mostrano l'errore di approssimazione sul campione base e l'errore di estrapolazione sul fuori campione. È ragionevole supporre che queste informazioni siano rilevanti per valutare la situazione.


P.S. Sì, ho dimenticato una riga da aggiungere. Indicatore sostituito alle 11:50

File:
 

Qualche parola in più. Perché proprio una tendenza lineare? Comunque, le vere tendenze sono lineari. L'ipotesi è che tale detrending possa essere fatto inconsciamente, allora c'è la speranza che ci possa essere realtà anche dietro le armoniche.

In linea di principio, aumentare il grado di un polinomio non è un problema, infatti ho iniziato con l'opzione parabola. Questo è fatto in modo elementare, in poche righe aggiunte e corrette, chiunque può provarlo da solo, come esercizio.

 

Buon pomeriggio.

Si prega di spiegare i disegni. Sono interessato alle linee verticali. Ho capito bene che sono nell'intervallo tra le linee blu i dati per la previsione? Cosa significa quella rossa? - il momento di divergenza con la previsione? perché le linee di previsione rosse (blu) hanno delle lacune?

Non ho guardato il codice perché il tuo livello di programmazione MQL è troppo basso per me, è come un sogno avvicinarsi a quel livello?

 

Prival:

si prega di spiegare i disegni. Sono interessato alle linee verticali. Ho capito bene che sono nell'intervallo tra le linee blu i dati per la previsione? Cosa significa quella rossa? - perché le linee di previsione rosse (blu) hanno dei vuoti?


Sì, infatti l'approssimazione è fatta tra le linee blu. Tra il blu e il rosso si calcola l'RMS dell'estrapolazione. È solo in nostro potere spostarla con HShift (e ora solo trascinando la linea lungo il grafico) e vedere ciò che non vede.

I vuoti sono "scarti", la finestra di lavoro dell'indicatore si sposta nel tempo, le code vengono lasciate indietro. Questo sarebbe facile da sistemare con una finestra permanente, ma dato che si adatta, non mi è ancora venuto in mente un modo economico per pulirlo.

Vi do la versione con le linee ridipinte.

File:
 

il tuo nuovo codice non ha funzionato come volevo :(

Mi sono preso la libertà di eliminare le mie modifiche. funziona alla grande soprattutto se abbinato a ft.AutoRefresh

File:
lsa_sinlr_1.mq4  16 kb
 

ForexTools:

Qui mi sono permesso di abbattere le mie modifiche. funziona alla grande soprattutto se accoppiato con ft.AutoRefresh

Beh, penso che la tua versione sia più a prova di interferenze, ma probabilmente hai bisogno di aggiungere HShift anche lì, in modo che in assenza di azioni dell'utente la finestra si muova nel tempo. Anche se, hmm, forse è proprio quello che volevi evitare?
 
Certo, quando si analizza la storia, il grafico non deve andare da nessuna parte, ma "stare" nel posto dove ho messo la linea
 
ForexTools:
Certo, quando si analizza la storia, il grafico non deve andare da nessuna parte, ma "stare" nel posto dove ho messo la linea

Beh, prima ho fatto una variante fissa e poi l'ho sostituita :). Ero interessato, prima di tutto, alla dinamica del ridisegno. In realtà è facile aggiungere un parametro come

if (ModeMoving) HShift--;
Ma anche troppo buono non va bene, lasciate che la variante rimanga inattiva.