Libreria di classi generiche - bug, descrizione, domande, caratteristiche d'uso e suggerimenti - pagina 28

 
Alexey Volchanskiy:

Che cazzo sta succedendo di nuovo qui? Stanno cancellando post LinkedList perfettamente validi. Posso solo immaginare un moderatore anonimo seduto da qualche parte in Europa che cancella i post degli odiati russi, ridacchiando maliziosamente. È una tale discarica che ti fa passare la voglia di scrivere.

Smettete di combattere i mulini a vento - non ci sono post cancellati da questo thread.

 
Artyom Trishkin:

Smettete di combattere i mulini a vento - non ci sono post cancellati da questo thread.

Artem, non sono ubriaco o sotto l'influenza. Ho scritto una breve risposta mezz'ora fa che in MQL LinkedList è implementato come un ring buffer e il comportamento descritto è semplicemente normale. E ho implementato un ring buffer nei miei filtri usando un array. Poi sono andato ai sorgenti .NET per vedere l'implementazione, e dopo mezz'ora il mio messaggio è stato cancellato. Era la prima volta che lo facevo.

Sui moderatori russi non credo proprio.

Ecco la classe filtro con FIR, guarda la funzione FilterTick(double tick). Ci sono due buffer ad anello - ticchettii in ingresso e valori filtrati in uscita. La differenza con la linked list è che è meno possibile, ma è un ordine di grandezza più veloce, il che è importante per me.

#ifndef  Filter
#define  Filter

//+------------------------------------------------------------------+
//|                                                       Filter.mqh |
//|                                               Alexey Volchanskiy |
//|                                      https://mql4.wordpress.com/ |
//+------------------------------------------------------------------+
#property copyright "Alexey Volchanskiy"
#property link      "https://mql4.wordpress.com/"
#property version   "1.04"
#property strict
#include <Object.mqh>
#include <AvLib-4-5\coeff.mqh>
#include <AvLib-4-5\Errors.mqh>

/*
Формат массива или файла коэффициентов фильтра
double coeff[] = {FiltersCount, FilterAddr, FilterLen, FilterAddr, FilterLen..., coeff1, coeff2, coeff3...};
*/
enum EErrors {EOk, ENumFilterOutOfRange};

class CFilter : CObject
{
#define  TICK_BUF_SIZE       0x1000              // 4096
#define  TICK_BUF_MAX_IDX    (TICK_BUF_SIZE - 1) // 0xFFF
#define  OUT_BUF_SIZE        0x10000             // 65536
#define  OUT_BUF_MAX_IDX     (OUT_BUF_SIZE - 1)  // 0xFFFF   

private:
    double  TickBuf[TICK_BUF_SIZE]; // промежуточный кольцевой буфер для хранения тиков
    double  OutBuf[OUT_BUF_SIZE];   // выходной кольцевой буфер
    double  Coeff[];                // массив коэффициентов
    int     TickBufIdx;             // индекс для нового входящего тика в TickBuf
    int     OutBufIdx;              // индекс для выходного буфера 
public:
    enum Errors {OK, NUM_FILTER_OUT_OF_RANGE };  
public:
    CFilter() {}
    ~CFilter() 
    {
        ArrayFree(Coeff);
    }
    
    double  GetOutBuf(const int idx)
    {
        int tmp = OutBufIdx-idx-1;
        double out = tmp >= 0 ? OutBuf[tmp] : OutBuf[OUT_BUF_SIZE+(tmp)]; 
        return out;
    }

    void    Init()
    {
        TickBufIdx = TICK_BUF_MAX_IDX;
        OutBufIdx = 0;
        for(int n = 0; n < TICK_BUF_SIZE; n++)
            TickBuf[n] = 0;
        for(int n = 0; n < OUT_BUF_SIZE; n++)
            OutBuf[n] = 0;
    }        

    EErrors  LoadCoeffFromArray(int numFilter, double &coeffArray[])
    {
        if(numFilter >= coeffArray[0])  // количество фильтров в массиве
            return ENumFilterOutOfRange;
        uint addr = (uint)coeffArray[1 + numFilter * 2];
        uint len = (uint)coeffArray[2 + numFilter * 2];   
        ArrayResize(Coeff, len);
        for(uint n = 0; n < len; n++)
            Coeff[n] = coeffArray[addr++];
        Init();    
        return EOk;
    }

    void    LoadCoeffFromArray(double &coeffArray[])
    {
        int len = ArraySize(coeffArray); 
        ArrayResize(Coeff, len);
        for(int n = 0; n < len; n++)
            Coeff[n] = coeffArray[n];
        Init();    
    }
    
    bool    LoadCoeffFromFile(int numFilter, string fileName)
    {
        // не реализовано
        return true;
    }
    
    // фильтрация одного тика
    double  FilterTick(double tick)
    {
        TickBuf[TickBufIdx] = tick;
        if (TickBufIdx == 0)
            TickBufIdx = TICK_BUF_MAX_IDX;
        else
            TickBufIdx--;
        int asize = ArraySize(Coeff); // вынести из функции!!!
        double acc = 0;
        int tbIdx = TickBufIdx;
        // делаем фильтрацию в цикле for
        for (int n = 0; n < asize; n++)
        {
            tbIdx++;
            /* вместо
            if(tbIdx > TICK_BUF_MAX_IDX)
            tbIdx = 0;
            */
            tbIdx &= TICK_BUF_MAX_IDX; // небольшая оптимизация вместо if
            acc += TickBuf[tbIdx] * Coeff[n];
        }
        OutBuf[OutBufIdx] = acc;
        OutBufIdx++;
        OutBufIdx &= OUT_BUF_MAX_IDX;
        return acc;
    }
    
    // фильтрация массива
    void    FilterTickSeries(double &ticks[], int count)
    {
        for(int n = 0; n < count; n++)
            ticks[n] = FilterTick(ticks[n]);
    }
};
#endif
 
Alexey Volchanskiy:

Artem, non sono ubriaco e non sono drogato. Ho scritto una breve risposta mezz'ora fa che MQL LinkedList è implementato come un ring buffer e il comportamento descritto è semplicemente normale. E ho implementato un ring buffer nei miei filtri usando un array. Poi sono andato ai sorgenti .NET per guardare l'implementazione, e dopo mezz'ora il mio messaggio è stato cancellato. Era la prima volta che lo facevo.

Sui moderatori russi non credo proprio.

Ecco la classe filtro con FIR, guarda la funzione FilterTick(double tick). Ci sono due buffer ad anello - ticchettii in ingresso e valori filtrati in uscita. La differenza con la linked list è meno possibilità, ma è molto più veloce, il che è importante per me.

Non lo so - ho guardato tra i post cancellati - niente da questo thread. Shaitan ...

Anche a me sembra logico che una "lista collegata" sia una lista collegata. Una lista semplice non ha looping e funziona come ha detto Alexey Navoikov: "Il Next dell'ultimo nodo è zero, proprio come ilPrevious del primo nodo", mentre una lista collegata sì, e funziona come un ring buffer. Il che per me è conveniente.

 
Artyom Trishkin:

Non lo so - ho guardato tra i post cancellati - niente da questo thread. Shaitan...

Mi sembra anche logico che una "lista collegata" sia una lista collegata. Una lista semplice non ha looping e funziona come ha detto Alexey Navoikov: "Il prossimo dell'ultimo nodo è uguale a zero e così il precedente del primo nodo" mentre una lista collegata ha e funziona come un ring buffer. Il che per me è conveniente.

Ah, è una possibilità, non lo sapevo. Beh, posso supporre che mi sono distratto e, senza inviare un messaggio, sono andato direttamente da quella pagina da qualche parte. Ma queste lamentele avvengono regolarmente, e non sono l'unico. Ok, non parliamone più.

 
Alexey Volchanskiy:

Ah, è una possibilità, non lo sapevo. Beh, posso supporre che mi sono distratto e sono andato direttamente da quella pagina senza inviare un messaggio. Ma queste lamentele avvengono regolarmente, e non sono l'unico. Va bene, non parliamone più.

Qui, qui, bisogna essere più attenti, tutti i pulsanti ben premuti.

 
Artyom Trishkin:

Mi sembra anche logico che una "lista collegata" sia una lista collegata. Una lista semplice non ha looping e funziona come ha detto Alexey Navoikov: "Il prossimo dell'ultimo nodo è zero, così come il precedente del primo", mentre una lista collegata ha e funziona come un ring buffer. Il che per me è conveniente.

Una lista collegata è una lista che memorizza puntatori agli elementi successivi e precedenti. "La suoneria non c'entra niente. Comunque, questo è qualcosa di nuovo. Dove è stato visto?

Alexey Volchanskiy:
Ecco la classe filtro con FIR, guarda la funzione FilterTick(double tick). Ci sono solo due buffer ad anello - ticchettii in ingresso e valori filtrati in uscita. La differenza con la linked list è meno possibilità, ma è molto più veloce, il che è importante per me.

Non ha niente a che vedere con una classe filtro... Stiamo parlando specificamente di una lista collegata. È un contenitore standard che ha certe proprietà. L'iterazione attraverso la lista è unidirezionale. Non ci possono essere squilli. Non ce ne sono in C# (l'identica classe LinkedList) o in C++ (la classe std::list).

Inoltre, questa libreria è portata da .Net, il che implica la compatibilità con C#, altrimenti perché diavolo abbiamo bisogno di un'altra bicicletta fatta in casa? Non ne abbiamo abbastanza di biciclette MQ scadenti? Tutto ciò di cui avevamo bisogno era portare una libreria già pronta (anche se con restrizioni specifiche per il linguaggio, ma almeno per preservare la logica del lavoro). Ma no... Le mani birichine hanno interferito anche qui)

Molto probabilmente, chi ha fatto il porting di quelle classi ha deciso di semplificarsi la vita, avendo semplificato il codice. Invece di due puntatori m_primo e m_ultimo ha fatto un solo puntatore m_head...

Certo, ho sistemato tutto come dovrebbe essere, ma comunque...

 
Alexey Navoykov:

Una lista collegata è una lista che memorizza puntatori agli elementi successivi e precedenti. "La suoneria non c'entra niente. Comunque, questo è qualcosa di nuovo. Dove è stato visto?

Non ha niente a che vedere con una classe filtro... Stiamo parlando specificamente di una lista collegata. È un contenitore standard che ha certe proprietà. L'iterazione attraverso la lista è unidirezionale. Non ci possono essere squilli. Non ce ne sono in C# (l'identica classe LinkedList) o in C++ (la classe std::list).

Inoltre, questa libreria è portata da .Net, il che implica la compatibilità con C#, altrimenti perché diavolo abbiamo bisogno di un'altra bicicletta fatta in casa? Non ne abbiamo abbastanza di biciclette MQ scadenti? Tutto ciò di cui avevamo bisogno era portare una libreria già pronta (anche se con restrizioni specifiche per il linguaggio, ma almeno per conservare la logica del lavoro). Ma no... Le mani birichine hanno interferito anche qui)

Molto probabilmente, chi ha fatto il porting di quelle classi ha deciso di semplificarsi la vita, avendo semplificato il codice. Invece di due puntatori m_primo e m_ultimo ha fatto un solo puntatore m_head...

Naturalmente, ho sistemato tutto come dovevo, ma tuttavia...

MSDN lo chiama ring buffer, io non ho inventato il nome.

La cosa principale è non fissarlo nella cartella Include, altrimenti sarà cancellato quando si aggiorna alla nuova build di MT5.

 
Vladimir Karputov:

Lì, lì, devi stare più attento e premere tutti i tasti giusti con attenzione.

La probabilità che questo accada è vicina allo zero. Ma è un fatto che il mio ramo nel thread di lingua inglese è stato ucciso anonimamente. ***

 
Alexey Volchanskiy:

La probabilità che ciò accada è molto bassa. Ma il fatto che il mio ramo nel thread di lingua inglese sia stato ucciso anonimamente è un fatto. ***

Basta parlare di quel ramo. Tiralo fuori di nuovo e ti do una scopa di betulla. Non ne posso più.

 
Alexey Volchanskiy:

Soprattutto, non modificare la cartella Include, o verrà sovrascritta quando si aggiorna a una nuova build di MT5.

L'ho in una cartella separata Generic_. In effetti, ho dovuto fare un sacco di modifiche lì, a partire da const per i metodi (gli sviluppatori non lo consideravano necessario), e finendo con la riprogettazione per gli argomenti per riferimento, non solo per valore.