¿Quién quiere una estrategia? Lotes y de forma gratuita) - página 58

 
1. Puedo reescribir los indicadores para sustituir float por double.
2. protected static float fMicron = 0.000075f; // Coef usado cuando comparamos dos flotantes
3. Constructor de la base del indicador:

/// <summary>
/// The default constructor
/// </summary>
public Indicator()
{
    sIndicatorName  = string. Empty;
    bSeparatedChart = false;
    bIsDescreteValues = false;
    afSpecValue     = new float[] { };
    fMinValue       = float. MaxValue;
    fMaxValue       = float. MinValue;
    bIsCalculated   = false;
    parameters      = new IndicatorParam();
    component       = new IndicatorComp[] { };
}




4. Precio base:



/// <summary>
/// Calculates the base price.
/// </summary>
/// <param name="price">The base price type.</param>
/// <returns>Base price.</returns>
protected static float[] Price( BasePrice price)
{
    float[] afPrice = new float[Bars];

    switch( price)
    {
        case BasePrice.Open:
            afPrice = Open;
            break;
        case BasePrice.High:
            afPrice = High;
            break;
        case BasePrice.Low:
            afPrice = Low;
            break;
        case BasePrice.Close:
            afPrice = Close;
            break;
        case BasePrice. Median:
            for (int iBar = 0; iBar < Bars; iBar++)
                afPrice[ iBar] = (Low[ iBar] + High[ iBar]) / 2;
            break;
        case BasePrice. Typical:
            for (int iBar = 0; iBar < Bars; iBar++)
                afPrice[ iBar] = (Low[ iBar] + High[ iBar] + Close[ iBar]) / 3;
            break;
        case BasePrice. Weighted:
            for (int iBar = 0; iBar < Bars; iBar++)
                afPrice[ iBar] = (Low[ iBar] + High[ iBar] + 2 * Close[ iBar]) / 4;
            break;
        default:
            break;
    }
    return afPrice;
}

6. He conseguido que funcione el puente NET <-> MT. Su metter de tiempo para hacer el comercio FSB a través de MT. Por supuesto, será sólo para cuentas de demostración hasta que se convierta en "roca sólida".

 

Como creo que el indicador Aroon sólo utiliza: bIsDescreteValues = true;


Sobre el RSI, recuerdo que me preguntaba sobre la fórmula. Fue hace 5-6 años. Creo que utilicé esta fórmula de un popular libro de AT. No recuerdo exactamente cuál.

 

"Utilizar el valor de la barra anterior"

Personalmente, creo que ésta es una de las características más importantes del FSB.


        /// <summary>
        /// Sets the "Use previous bar value" checkbox
        /// </summary>
        /// <returns>Is any Changes</returns>
        public bool SetUsePrevBarValueCheckBox(int iSlot)
        {
            bool isChanged = false;

            for (int iParam = 0; iParam < Slot[ iSlot]. IndParam. CheckParam. Length; iParam++)
            {
                if ( Slot[ iSlot]. IndParam. CheckParam[ iParam]. Caption == "Use previous bar value")
                {
                    bool bOrigChecked = Slot[ iSlot]. IndParam. CheckParam[ iParam]. Checked;
                    bool bChecked = true;

                    // Entry slot
                    if ( Slot[ iSlot]. SlotType == SlotTypes.Open)
                    {
                        bChecked = true;
                    }

                    // Open filter slot
                    else if ( Slot[ iSlot]. SlotType == SlotTypes. OpenFilter)
                    {
                        bChecked = EntryExecutionTime != TimeExecution. Closing;
                    }

                    // Close slot
                    else if ( Slot[ iSlot]. SlotType == SlotTypes.Close)
                    {
                        bChecked = true;
                    }

                    // Close filter slot
                    else if ( Slot[ iSlot]. SlotType == SlotTypes. CloseFilter)
                    {
                        bChecked = false;
                    }

                    if ( bChecked)
                    {
                        for (int iPar = 0; iPar < Slot[ iSlot]. IndParam. ListParam. Length; iPar++)
                        {
                            if ( Slot[ iSlot]. IndParam. ListParam[ iPar]. Caption == "Base price" &&
                                Slot[ iSlot]. IndParam. ListParam[ iPar]. Text    == "Open")
                            {
                                bChecked = false;
                            }
                        }
                    }

                    if ( bChecked != bOrigChecked)
                    {
                        isChanged = true;
                        Slot[ iSlot]. IndParam. CheckParam[ iParam]. Checked = bChecked;
                    }
                }
            }

            return isChanged;
        }
 

Para ver los valores de los indicadores con toda su precisión, pulse F12 en la ventana del gráfico.


Otra opción es utilizar la "consola de comandos". ind xxxx muestra los indicadores de la barra xxxx




No profundizo en las fórmulas de la MT. Probablemente no sean muy diferentes. Aquí están el FSB RSI y el MT RSI por defecto.







___________________--

Editar:

He intentado calcular el RSI sin este suavizado adicional:

            for (int iBar = 1; iBar < Bars; iBar++)
            {
                if ( afBasePrice[ iBar] > afBasePrice[ iBar - 1]) afPos[ iBar] = afBasePrice[ iBar] - afBasePrice[ iBar - 1];
                if ( afBasePrice[ iBar] < afBasePrice[ iBar - 1]) afNeg[ iBar] = afBasePrice[ iBar - 1] - afBasePrice[ iBar];
            }

            float[] afPosMA = MovingAverage( iPeriod, 0, maMethod, afPos);
            float[] afNegMA = MovingAverage( iPeriod, 0, maMethod, afNeg);

            //for (int iBar = iFirstBar; iBar < Bars; iBar++)
            //{
            //    afPosMA[iBar] = (afPosMA[iBar - 1] * (iPeriod - 1) + afPos[iBar]) / iPeriod;
            //    afNegMA[iBar] = (afNegMA[iBar - 1] * (iPeriod - 1) + afNeg[iBar]) / iPeriod;
            //}

            for (int iBar = iFirstBar; iBar < Bars; iBar++)
            {
                if ( afNegMA[ iBar] == 0)
                    afRSI[ iBar] = 100;
                else
                    afRSI[ iBar] = 100 - (100 / (1 + afPosMA[ iBar] / afNegMA[ iBar]));
            }


Pero en este caso el valor del RSI para 2009.3.24 salta a 74,800.



----------------------


¡Gracias Stellarator por las buenas palabras!

No voy a abandonar Forex Strategy Builder, y sólo por gente como tú. Incluso en el caso contrario, estoy abierto a la discusión para hacer que FSb sea más robusto y fácil de usar.

En esa dirección creo que puedo añadir indicadores MT en FSB. Algo así como el modo de compatibilidad de MT:)

MT_MACD, MT_RSI, ... Estos deben ser con los mismos parámetros que los de la norma MT.


Tenemos que encontrar la solución a los puntos de entrada/salida de la apertura de la barra y del cierre de la barra. Son vitales para la integración FSB -> MT.


 
Stellarator >> :

.........Combínalos (dos buffers) en uno (estaba pensando... No sólo puede haber 1/0 (que podría convertirse en una máscara de bits), sino también etiquetas de precio). Lo más probable es que tenga que hacer algo con los propios valores de los indicadores... Veremos... Como voy...

¿Por qué no puede funcionar?

Durante mucho tiempo he estado usando una sola llamada a icustom para obtener varios valores de diferentes buffers de indicadores, es demasiado desperdicio usar esta función varias veces en el código, especialmente durante la optimización, e incluso con indicadores "pesados". De hecho, todo lo que necesitamos (como máximo) es obtener la dirección de la operación y el nivel de SL & TP..... el problema se resuelve por simple aritmética.

Aquí hay un fragmento de código del indicador con sólo un búfer adicional (Señal):

// в самом кончике start такой фрагмент

      
   if ( Direction[0] !=0)
      {
      if ( Direction[0] > 0) Signal[0]= Set_TP[0]/Point*1000000 + Set_SL[0]/Point;
      if ( Direction[0] < 0) Signal[0]=-( Set_TP[0]/Point*1000000 + Set_SL[0]/Point);
      }
   return(0);

Y aquí está la conversión inversa en el código del Asesor Experto:

int start()
  {
   // Получение значений из буфера индикатора в последней фазе формирования бара
   if (TimeCurrent() > (Time[0]+ CP60)
      {
      Signal=iCustom(NULL, 0, "_iK_tay_v01M1", Discret,6,0)
      }     

   if(Time[0] != prevtime)
      { 
      Calcul();
      //if (Tral !=0) CalcLevel();
      prevtime = Time[0];
      }
   else return;

.........

void Calcul()
  {
   OpenSell=0; OpenBuy=0; CloseBuy=0; CloseSell=0;
   
   if( Signal > 0) 
      {
      OpenBuy=1; CloseSell=1;
      TP=NormalizeDouble ( Signal*Point/1000000, Digits-1);      
      SL=( Signal- TP/Point*1000000)*Point;   
      }
   if( Signal < 0) 
      {
      CloseBuy=1; OpenSell=1;
      TP=NormalizeDouble (MathAbs( Signal)*Point/1000000, Digits-1);      
      SL=(MathAbs( Signal)- TP/Point*1000000)*Point;   
      }   
   return;
  }

De este modo, obtenemos 3 valores del indicador (dirección, TP y SL) con una sola llamada del indicador. Los resultados obtenidos se pueden manipular como se quiera :)

Espero que entiendas el principio.

 

Buenos días a todos.


Miroslav_Popov писал(а) >>

1. Puedo reescribir los indicadores para sustituir float por double.

Miroslav, es importante. Ya he dado algunas de las razones en mis posts. Pero también soy consciente del trabajo que supone... Y que ahora (muy probablemente) estás trabajando en el puente que buscas o en algo sustancial.


Pero hay que encontrar tiempo. Mi predicción es de no más de un número de horas (dentro de un día). Porque no se trata sólo de sustituir una por otra al declarar las variables (lo que también implicará al menos una comprobación visual y una corrección visual "por belleza" (cuando las variables se describen con tabuladores, por ejemplo, etc.) :) - aunque no es una cuestión de principios).

En primer lugar, es posible que haya casos en los que la flotación se utilice a propósito (para forzar una disminución de la precisión). Tienes que ver el código completo aquí.

En segundo lugar, se trata de comparar estos números ("nuevos") y su correspondencia con el FSB (sobre ello, más adelante, en la sección 2).

Más corto - tendremos que revisar cuidadosamente todo el código y al menos pensar en los posibles inconvenientes asociados a la transición de las matemáticas reales a las dobles.


Miroslav_Popov escribió (a) >>.

2. protected static float fMicron = 0.000075f; // Coef usado cuando comparamos dos flotantes


(y abajo):

Para ver los valores del indicador en toda su precisión, pulse F12 en la ventana del gráfico.

Y este es uno de los problemas. ¿Por qué 0,000075? ¿Y no 0,00005? ¿O 0,000001? (como yo).

Un problema ampliado (para los interesados) y una pregunta:

Como sabes, la comparación de dos números reales para la igualdad nunca debe hacerse mediante este tipo de construcciones:

double Value1, Value2;

if (Value1 == Value2) {
  // Some useful code there
}

Esto se debe a que tras los resultados de algunos cálculos (especialmente las variaciones de multiplicar/dividir), los valores de estas variables pueden ser visualmente similares (1,0 y 1,0, por ejemplo), pero en realidad NO son los mismos. (1,000001 y 1,000000, de hecho). Esta propiedad se deriva de cierta discreción de la representación de los números reales en los ordenadores y con cierta discreción (precisión) (finita) del cálculo. En general, la comparación para la igualdad se realiza mediante variaciones sobre un tema clásico (que, por cierto, utiliza Miroslav):

if (Math.Abs(afIndValue[iCurrBar] - afIndValue[iBaseBar]) < fMicron) {
  // Some code there
}

Se trata de la comparación "clásica" de dos números reales para la igualdad con cierta precisión finita, definida por fMicron, en este caso.


Y aquí radica uno de los posibles problemas. ¿Cómo, quién y para qué casos debe determinar el valor de este mismo fMicron? ¿Es siempre una buena constante, como la de Miroslav (la cuestión de cuál es el valor también está en discusión)?


En general, si no es para añadir intriga, estoy a favor de la siguiente teoría:

1. En general hay dos tipos de comparación de dichas variables, por igualdad y por desigualdad (<, >).

2. Existen dos tipos de variables propiamente dichas: las variables con precisión fija garantizada (precios, lotes, etc.) y los valores abstractos sin precisión definida (como los valores indicadores).

Para la desigualdad, las variables (de cualquier tipo) se comparan (en general) "cabeza a cabeza" (si (Valor1 < Valor2) { ...}). Si es necesario limitar la precisión (lo que es bastante raro), se puede utilizar una construcción como la de Miroslav:

if (afIndValue[iBaseBar] < afIndValue[iCurrBar] - fMicron) {
  // Some code there
}

4. En cuanto a la igualdad, sin embargo, el problema se aborda (normalmente) de forma diferente, dependiendo de los datos en cuestión.

4.1 Si necesitamos comparar dos números con precisión fija (por ejemplo, dos valores de precio para decidir si se modifica o no el pedido (para evitar obtener un "Sin resultado")), solemos hacerlo así (también "clásico"):

int ComparePriceInt(double Value1, double Value2) {
   Value1 -= Value2;
   Value2 = Point / 2.0;
   if ( Value1 > Value2)
      return(1);
   if ( Value1 < - Value2)
      return(-1);
   return(0);
}

La función es redundante en nuestro caso, pero eso no es lo importante. La construcción clave en ella es Punto / 2.0. Es este fMicron el que nos da la precisión de cálculo necesaria, correcta y suficiente... ¡ EN ESTE CASO CONCRETO! Cuando se comparan dos precios (con los mismos Dígitos y, en consecuencia, Punto ). es decir, en el caso de (Punto = 0,0001), por ejemplo

fMicron = 0,00005

y comparando 1,2345 (precio del pedido) con 1,23451 (valor del indicador) - obtenemos igualdad, y 1,2345 con 1,23456 - desigualdad... ¿Adivina qué ocurre en el último caso cuando fMicron = 0,000075? ;) Por supuesto, se podrían normalizar previamente las variables con una precisión (menor). Pero ese no es nuestro método :D...

Una vez más, la elección de este parámetro es importante, y para cada caso "un poco único" :)1


Yo sugeriría el siguiente paradigma:

1. Las variables de precisión fija se comparan con un valor fMicron calculado (Punto / 2, por ejemplo, para el caso del precio)

2. Los valores de los indicadores y otras "bagatelas infinitamente precisas" :), se comparan con la constante fMicron, que es igual al valor mínimo de los instrumentos Point, utilizados, dividido por 10. Es decir, en el caso de los instrumentos en los que Dígitos no supera 4 - fMicron = 0,00001, si Dígitos = 5, fMicron = 0,000001 y de forma similar.

Miroslav - se necesita la opinión de un experto :)?


Ahora una pregunta para el público:

Cuando en todo tipo de DataWindow (en MT o en FSB (Indicator Charts)) - ¿los valores de los indicadores se muestran siempre con una precisión fija (Dígitos = 4)? ¿Por qué no 3 decimales? ¿O 5, 6, 7, ...? ¡:)?! No, ¿en serio?

Miroslav tenía una "característica oculta" ;)) - ¡Quiero decir F12! ¿Y en MT qué hay que pulsar?

Y en general, bueno, ¿quién definió esta constante? (4 decimales).

Mi opinión es que está casi directamente relacionada con la dimensión de las cotizaciones entrantes (1,2345), para la mayoría de los instrumentos (alguien acaba de rellenarla). Pero no es un secreto que muchas empresas de corretaje pasan a valores mayores (5 por ejemplo). Entonces, ¿por qué no mostrar los valores del indicador en la dimensión que coincide con la dimensión de las cotizaciones del instrumento (Dígitos)?

¡O tal vez no "entiendo" algo en principio en el tema (por favor - que alguien lo explique, tal vez es "necesario" porque...)!


Miroslav_Popov escribió (a) >>.

3. Constructor de la base del indicador:

4. Precio base:

Miroslav, he entendido muy bien el código de la página Source :). Entiendo bien lo que hace protected static float[] Price( BasePrice price). Si esto es un indicio de lo poco manejable de mi código - respondo que me negué intencionadamente a utilizar búferes adicionales para el almacenamiento (en el caso general - ya sea copias de búferes de precios o copias calculadas de los mismos (Típico, etc.)). Y se ahorra espacio, y donde hay todo tipo de tipicidades, ¡siempre hay que calcularlas!


Aquí debemos mencionar la diferencia crítica en el enfoque del cálculo de los valores de los indicadores en FSB y MT:

1. En primer lugar, al menos por el momento - las cotizaciones que se cargan en FSB son estáticas, se ha cargado una vez, calculado UNA vez los valores de los indicadores necesarios para toda la gama de barras y luego sólo "conduce" por ellos, emulando el comportamiento del robot de comercio. Una vez más, los valores de los indicadores se calculan sólo una vez, ANTES de ejecutar la virtualización del robot de trading. Esto, en particular, explica la velocidad de emulación de las transacciones comerciales. Pero las cotizaciones en MT vienen todo el tiempo y el probador de estrategias nativo no ve el futuro, es decir, tenemos que calcular los valores del indicador cada vez. Y si sólo utilizo el enfoque de Miroslav (cálculo del buffer completo)... Me tirarán huevos podridos :). Por lo tanto, ¡se presta especial atención al uso de IndicatorCounted()! Los indicadores se calculan casi con la máxima velocidad posible en cada caso (si hay que contar todas las barras, o sólo una). En algún lugar, algunas cosas todavía pueden ser optimizadas, pero a su gusto...

2. Por lo tanto, cada vez (cuando llega un nuevo tick), es redundante generar valores de precios en buffers adicionales. Hay que calcularlos todos de todas formas, así que deja que las funciones (el mismo MovingAverage, etc.) lo hagan por sí mismas. Ahorra espacio, simplifica la lógica (no es necesario analizar cada vez qué barras deben recalcularse en estos búferes) y ahorra velocidad (incluso en algún punto superior, en el caso general). "A mí me lo parece" (c) Winnie the Pooh


Si vamos a discutir de nuevo mis conversiones de indicadores, quizás lo importante es que conservo completamente la lógica de las funciones (y de los propios indicadores), pero la modifico ligeramente para un caso de uso específico en MT. También guardo el orden y los nombres de los parámetros para controlar el propio indicador.

Chicos, mirad el código fuente. Intenté hacerlo "bien" :).


La idea final de mi conversión es la siguiente. Por ejemplo, tenemos un punto de apertura de la posición y tres indicadores de lógica adicional. Así es como se verá el código para la realización de pedidos (bueno, a grandes rasgos, claro):

if ( IsSignal(iCustom(NULL, 0, "fsbIndicator1", SLOT_TYPE_LC, Param2, Param3, ..., 0, 0))
    && IsSignal(iCustom(NULL, 0, "fsbIndicator2", SLOT_TYPE_LC, Param2, Param3, ..., 0, 0))
    && IsSignal(iCustom(NULL, 0, "fsbIndicator3", SLOT_TYPE_LC, Param2, Param3, ..., 0, 0)) )
{    
// Открываем длинную позицию (предпоследний 0 в значениях индикаторов - указатель на буфер логики длинных позиций (1, соотв. - на буфер логики коротких))
    // Если у нас значение POP берется из еще одного индикатора, то это значение берется аналогично, только меняется логика поведения индикатора:
    // iCustom(NULL, 0, "fsbIndicator", SLOT_TYPE_POP, Param2, Param3, ..., 0, 0)
}

Algo así. Alimentas a iCustom con los valores de tus parámetros y esperas a que todos den una señal. Eso es todo. No hay un análisis de los valores de los indicadores en sí... ¿Para qué?

Parece agradable... ¿o no :)?

 

Sobre los indicadores:

Acerca de (Aroon y bIsDescreteValues = true;) tomado en cuenta.


Sobre RSI...

Miroslav - la construcción que buscas te ha confundido :). No tengas pereza de volver a poner comentarios y utiliza el indicador CORRECTAMENTE TRABAJADO para obtener valores "coincidentes" :). Permítame recordarle que la fórmula clásica para calcular el RSI se basa en la variedad exponencial del MA (suavizado, específicamente). Por lo tanto, especifique este modo de suavizado (smoothed) en los parámetros del indicador... y se verá "gratamente sorprendido" por los resultados :) ¡(por defecto, le recuerdo, se utiliza Simple, lo que da una divergencia del clásico)! No puedo hacer el procedimiento anterior yo mismo - pero estoy 100% seguro de lo que digo. ¿Convénzame :)?

Como resultado de las pruebas tenemos la siguiente sugerencia, para eliminar el código requerido y hacer el valor por defecto del parámetro maMethod en Smoothed en todos los indicadores, que utilizan RSI (y RSI en sí, respectivamente). Que por defecto los usuarios no tuvieran esas preguntas. ¡Pero al hacerlo haremos que la selección de este parámetro en los indicadores sea FUNCIONABLE! (por ejemplo, he convertido RSI MA Oscillator, que, sobre la base del resultado de los cálculos de RSI, también, con el comportamiento actual de la propia RSI - no importa lo que se especifica en el parámetro apropiado)

 
Miroslav_Popov >> :

"Utilizar el valor de la barra anterior"

Personalmente, creo que ésta es una de las características más importantes del FSB.

¡OH, SÍ!

Esta es una de las características más importantes del FSB. Y he tratado de prestar la debida atención a la comprobación de la corrección de la lógica de los indicadores, teniendo en cuenta esta característica.

Gracias por el código que muestra el cálculo del valor "por defecto". Lo tendré en cuenta...

 
rider >> :

¿Por qué no puede funcionar?

Durante mucho tiempo he estado usando una sola llamada a icustom para obtener varios valores de diferentes buffers de indicadores, es demasiado desperdicio usar esta función varias veces en el código, especialmente durante la optimización, e incluso con índices "pesados". De hecho, todo lo que necesitamos (a lo sumo) es obtener una dirección de negociación y los niveles de SL y TP..... el problema se resuelve por simple aritmética.

...

El principio, espero, está claro.




:), lo conseguirás (intencionalmente hice mi declaración más gruesa), sé sobre el problema con el colapso de los valores en un parámetro :). Y gracias por el código citado (una pregunta rápida: ¿ha habido alguna vez diferencias entre los valores originales y los "ampliados posteriormente"? todo el mismo doble...)

La pregunta clave es... ES NECESARIO EN ESTE CASO CONCRETO.

Puede haber dos razones:

1. 1... El propósito de la utilización de búferes adicionales (es importante para mí) - los indicadores no tienen tantos. Tengo bastantes PERO POR ahora (parece que tengo que usar ya Ishimoku - y todo se aclarará :)))

2. La velocidad de llamada del indicador desde su código (su ejemplo). Mi respuesta es: ¡No es esencial! Lo declaro con toda responsabilidad. Motivación:

Con cada nueva garrapata - usted tendrá que (tiene que) mirar en el indicador de todos modos. ¿Verdad? (por ejemplo, para tomar precios o cualquier otra cosa) Aunque no sea en cada tic, sino cuando lo necesite. La principal pista, quizás, es que una llamada múltiple de iCustom dentro de una iteración del EA lleva a un recálculo múltiple del indicador? ¡Me veo obligado a disuadirte! El punto clave es "un límite de una iteración del Asesor Experto". Así, dentro de este rango, el indicador se calcula UNA vez (en su primera llamada). Lo declaro con un 100% de confianza. Todas las llamadas posteriores no inician() en absoluto, sino que sólo toman los valores necesarios de los buffers necesarios. La condición es del 100% si los parámetros de entrada no cambian (excepto el buffer y el offset). La regla es válida para los cálculos dentro de los límites de una herramienta. Pero creo que el principio se mantiene incluso cuando iCustom se refiere a otros TFs y herramientas.


De todos modos, esta noche echaré un vistazo al Ishimoku y decidiré con seguridad si utilizaré dos buffers para la lógica... o uno :)

 

En fin, nos vemos todos esta noche (me fui a trabajar).

Sobre el problema.

We have to find solution to Bar Opening and Bar closing entry/exit points. They are vital for FSB -> MT integration.

Lo pensaré.


Pero lo más probable (dada la falta de señales de MT sobre este tema) - el código anterior (plantilla en la página anterior) es más o menos óptimo (puede necesitar un poco de ajuste... Intentaré "profundizar" en el problema por la noche)

Razón de la queja: