Biblioteca de clases genéricas - errores, descripción, preguntas, características de uso y sugerencias - página 28

 
Alexey Volchanskiy:

¿Qué coño está pasando aquí otra vez? Están borrando puestos perfectamente buenos de LinkedList. Me imagino a un moderador anónimo sentado en algún lugar de Europa borrando los mensajes de los odiados rusos, riéndose maliciosamente. Es un vertedero tan grande que hace que no quieras escribir.

Deja de luchar contra los molinos de viento: no hay mensajes borrados de este hilo.

 
Artyom Trishkin:

Deja de luchar contra los molinos de viento: no hay mensajes borrados de este hilo.

Artem, no estoy borracho ni bajo la influencia. Hace media hora escribí una breve respuesta que en MQL LinkedList se implementa como un buffer de anillo y el comportamiento descrito es simplemente normal. Y he implementado un buffer de anillo en mis filtros usando un array. Luego fui a las fuentes .NET para ver la implementación, y después de media hora mi mensaje ha sido borrado. Fue la primera vez que lo hice.

Sobre los moderadores rusos simplemente no creo.

Aquí está la clase de filtro con la función FIR, watch double FilterTick(double tick). Hay dos buffers de anillo - ticks de entrada y valores filtrados de salida. La diferencia con la lista enlazada es que es menos posible, pero es un orden de magnitud más rápido, lo cual es importante para mí.

#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, no estoy borracho ni drogado. Escribí una breve respuesta hace media hora que MQL LinkedList se implementa como un buffer de anillo y el comportamiento descrito es simplemente normal. Y he implementado un buffer de anillo en mis filtros usando un array. Luego fui a las fuentes .NET para ver la implementación, y después de media hora mi mensaje se ha borrado. Fue la primera vez que lo hice.

Sobre los moderadores rusos simplemente no creo.

Aquí está la clase de filtro con FIR, mira la función FilterTick(double tick). Hay dos buffers de anillo - ticks de entrada y valores filtrados de salida. La diferencia con la lista enlazada es de menos posibilidades, pero es mucho más rápida, lo cual es importante para mí.

No sé - miré en los mensajes borrados - nada de este hilo. Shaitan ...

También me parece lógico que una "lista enlazada" sea una lista enlazada. Una lista simple no tiene bucle y funciona como dijo Alexey Navoikov: "El Next del último nodo es cero, igual que elPrevious del primer nodo", mientras que una lista enlazada sí, y funciona como un buffer de anillo. Lo que para mí es conveniente.

 
Artyom Trishkin:

No sé - miré los mensajes borrados - nada de este hilo. Shaitan...

También me parece lógico que una "lista enlazada" sea una lista enlazada. Una lista simple no tiene bucle y funciona como dijo Alexey Navoikov: "El siguiente del último nodo es igual a cero y también lo es el anterior del primer nodo", mientras que una lista enlazada sí lo tiene y funciona como un buffer de anillo. Lo que para mí es conveniente.

Ah, es una posibilidad, no lo sabía. Bueno, puedo suponer que me distraje y, sin enviar un mensaje, pasé directamente de esa página a algún lugar. Pero estas quejas se producen con regularidad, y no soy el único. Vale, no hablemos más de ello.

 
Alexey Volchanskiy:

Ah, es una posibilidad, no lo sabía. Bueno, puedo suponer que me distraje y pasé directamente de esa página sin enviar un mensaje. Pero estas quejas se producen con regularidad, y no soy el único. Muy bien, no hablemos más de ello.

Aquí, aquí, hay que estar más atento, todos los botones bien apretados.

 
Artyom Trishkin:

También me parece lógico que una "lista enlazada" sea una lista enlazada. Una lista simple no tiene bucle y funciona como dijo Alexey Navoikov: "El último nodo anterior es cero, así que es el primero anterior", mientras que una lista enlazada tiene y funciona como un buffer de anillo. Lo que para mí es conveniente.

Una lista enlazada es una lista que almacena punteros a los elementos siguientes y anteriores. "El timbre no tiene nada que ver. De todos modos, esto es algo nuevo. ¿Dónde se ha visto?

Alexey Volchanskiy:
Aquí está la clase de filtro con FIR, ver la función FilterTick(double tick). Sólo hay dos buffers de anillo - ticks de entrada y valores filtrados de salida. La diferencia con la lista enlazada es de menos posibilidades, pero es mucho más rápida, lo cual es importante para mí.

No tiene nada que ver con una clase de filtro... Estamos hablando específicamente de una lista enlazada. Es un contenedor estándar que tiene ciertas propiedades. La iteración a través de la lista es unidireccional. No puede haber ningún timbre. No hay ninguno en C# (la clase LinkedList idéntica) ni en C++ (la clase std::list).

Además, esta librería está portada desde .Net, lo que implica compatibilidad con C#, si no, ¿para qué demonios necesitamos otra bicicleta casera? ¿No hemos tenido suficiente con las cutres bicicletas MQ? Lo único que necesitábamos era portar una librería ya hecha (aunque sea con restricciones específicas del lenguaje, pero al menos para conservar la lógica de trabajo). Pero no... Las manos traviesas también interfirieron aquí )

Lo más probable es que quien haya portado esas clases haya decidido simplificarse la vida, habiendo simplificado el código. En lugar de dos punteros m_first y m_last hizo un solo puntero m_head...

Por supuesto, he arreglado todo como debe ser, pero sin embargo...

 
Alexey Navoykov:

Una lista enlazada es una lista que almacena punteros a los elementos siguientes y anteriores. "El timbre no tiene nada que ver. De todos modos, esto es algo nuevo. ¿Dónde se ha visto?

No tiene nada que ver con una clase de filtro... Estamos hablando específicamente de una lista enlazada. Es un contenedor estándar que tiene ciertas propiedades. La iteración a través de la lista es unidireccional. No puede haber ningún timbre. No hay ninguno en C# (la clase LinkedList idéntica) ni en C++ (la clase std::list).

Además, esta librería está portada desde .Net, lo que implica compatibilidad con C#, si no, ¿para qué demonios necesitamos otra bicicleta casera? ¿No hemos tenido suficiente con las cutres bicicletas MQ? Lo único que necesitábamos era portar una librería ya hecha (aunque sea con restricciones específicas del lenguaje, pero al menos para conservar la lógica de trabajo). Pero no... Las manos traviesas también interfirieron aquí )

Lo más probable es que quien haya portado esas clases haya decidido simplificarse la vida, habiendo simplificado el código. En lugar de dos punteros m_first y m_last hizo un solo puntero m_head...

Por supuesto, arreglé todo como debía, pero sin embargo...

MSDN lo llama ring buffer, yo no he inventado el nombre.

Lo principal es no fijarlo en la carpeta Include, de lo contrario se borrará cuando se actualice a la nueva build de MT5.

 
Vladimir Karputov:

Ahí, ahí, tienes que ser más cuidadoso y pulsar todos los botones correctos con cuidado.

La probabilidad de que eso ocurra es casi nula. Pero es un hecho que mi rama en el hilo de la lengua inglesa fue asesinada anónimamente. ***

 
Alexey Volchanskiy:

La probabilidad de que eso ocurra es muy baja. Pero es un hecho que mi rama en el hilo de la lengua inglesa fue asesinada anónimamente. ***

Basta de hablar de esa rama. Si vuelves a sacar el tema, te daré una escoba de abedul. Estoy harto.

 
Alexey Volchanskiy:

Lo más importante es que no edites en la carpeta Include, o se sobrescribirá cuando actualices a una nueva versión de MT5.

Lo tengo en una carpeta separada Generic_. De hecho, tuve que hacer muchos cambios allí, empezando por la const para los métodos (los desarrolladores no lo consideraron necesario), y terminando con el rediseño para los argumentos por referencia, no sólo por valor.