Dos líneas temporales en Ninja Trader

Foro dedicado a esta excelente herramienta de desarrollo e implementación de sistemas de trading
Responder
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Dos líneas temporales en Ninja Trader

Mensaje por bolsa1 »

He estado echándole un ojo a la forma de hacer que las optimizaciones en Ninja Trader tengan en cuenta la "intra-barra", y no den por buenas las operaciones que se puedan cerrar en la misma barra. He encontrado la instrucción "BarsInProgress", que permite jugar con dos líneas temporales (o más). Estoy haciendo las primeras pruebas, pero básicamente esto es lo que entiendo:

Para resumir el funcionamiento, pongo el ejemplo que viene en la ayuda, e intentaré explicarlo. Puede que me pierda algo, por eso invito a los que programen en NT a que me corrijan o complementen la información.

Código: Seleccionar todo

// Asumimos que esta estrategia se ejecutará sobre un gráfico ES 12-06 con barras de 1 minuto

protected override void Initialize()
{
    // Añadimos una segunda línea temporal de 5 minutos: Cuyo índice "BarsInProgress" será "1". La línea principal es la del gráfico (1 minuto), será Barsinprogress=0
    Add(PeriodType.Minute, 5);
}

protected override void OnBarUpdate()
{
    // Comprobamos a qué línea temporal está llamando el método "OnBarUpdate()" 
    if (BarsInProgress == 0)
    {
        // Un valor de cero representa la línea principal del gráfico ES 12-06, en este caso 1 minuto
        // Aquí pondríamos las intrucciones a ejecutar sobre las barras de 1 minuto

    }
   else if (BarsInProgress == 1)
    {
        // Un valor de uno representa la línea secundaria, en este caso 5 minutos
        // Aquí pondríamos las intrucciones a ejecutar sobre las barras de 5 minutos
    }
}
Según esto entiendo que la forma de que un backtest o un WFO compruebe los movimientos dentro de las barras es dejando la línea principal del gráfico en la escala en la que queremos ejecutar el sistema, y añadiendo otra más pequeña, que el sistema también comprobará, aunque no realicemos ninguna orden sobre ella, sólo la utilizaremos para ejecutar la órdenes lanzadas delsde la línea temporal principal. En este enlace que me dejó Wave el otro día lo explican:

http://www.ninjatrader-support.com/vb/s ... rid&t=6652

Este es el ejemplo que ponen:

Código: Seleccionar todo

protected override void Initialize()
        {
			/* Añadimos una segunda línea temporal al sistema. 
			MUY IMPORTANTE: debe ser menor que la principal
			
			Nota: En este ejemplo partiremos de que el gráfico principal es de 5 minutos, y ahora añadiremos una línea temporal de 1 minuto */
			Add(PeriodType.Minute, 1);
			
			// Añadimos dos indicadores EMA
			Add(EMA(Fast));
			Add(EMA(Slow));
			
			/* Ajustamos el color de los indicadores */
			EMA(Fast).Plots[0].Pen.Color = Color.Blue;
			EMA(Slow).Plots[0].Pen.Color = Color.Green;
			
            CalculateOnBarClose = true;
        }

        /// <summary>
        /// Called on each bar update event (incoming tick)
        /// </summary>
        protected override void OnBarUpdate()
        {
			/* Cuando se llama a "OnBarUpdate()" siempre se llamará primero a la primera línea temporal, la principal, seguida de las otras series secundarias.

En este caso el orden sería el siguiente:

				12:00PM 5min
				12:00PM 1min
				12:01PM 1min
				12:02PM 1min
				12:03PM 1min
				12:04PM 1min
				12:05PM 5min
				12:05PM 1min 
			
			Cuando OnBarUpdate() sea llamado por la línea de tiempo principal (5min en este ejemplo), haz lo siguiente:*/
			if (BarsInProgress == 0)
			{
				// Cuando la media rápida cruce al alza a la lenta... lanza la orden para ser ejecutada en la línea de tiempo secundaria:
				if (CrossAbove(EMA(Fast), EMA(Slow), 1))
				{
					/* La condición de entrada es lanzada en la línea de tiempo primaria, pero es enviada y ejecutada en la secundaria (1 minuto)

La forma de determinar sobre que serie se lanzará la orden es por el primer parámetro:  0 = línea primaria,	1 = secundaria, 2 = terciaria, etc. */

					EnterLong(1, 1, "Long: 1min");
				}
				
				// Si se cruza a la baja, entra en corto en la segunda línea de tiempo (1 minuto)
				else if (CrossBelow(EMA(Fast), EMA(Slow), 1))
				{
					/* Exáctamente lo mismo de antes */
					EnterShort(1, 1, "Short: 1min");
				}
			}
			
			// Cuando OnBarUpdate() sea llamado por la línea de tiempo secundaria, no hagas nada.
			else
			{
				return;
			}
        }
Este es el ejemplo que ponen... si alguien tiene experiencia y ve algún error, o quiere comentar algo, seré el primer agradecido. Por mi parte estoy haciendo las primeras pruebas de backtest para ver als diferencias (la primera diferencia es el tiempo que tarda... buffff).

La clave para lanzar la orden sobre la segunda línea de tiempo es la instrucción:

EnterLong(1, 1, "Long: 1min");

Si fuera "0" la lanzaría sobre la linea de tiempo principal. Para órdenes limitadas se utiliza la nomenclatura:

EnterLongLimit(int barsInProgressIndex, bool liveUntilCancelled, int quantity, double limitPrice, string signalName)

de forma que para comprar un contrato limitado al mínimo de la barra, a ejecutar sobre la segunda línea temporal, sería:

EnterLongLimit(1, true, 1, Low[0], "Venta Limitada");

.................

A ver si mejoramos de esta forma los backtests.

Saludos!

Edito: Gracias por el enlace, Wave!
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
Txen
Mensajes: 135
Registrado: 22 Nov 2007 21:44

Re: Dos líneas temporales en Ninja Trader

Mensaje por Txen »

...muy interesante...
Avatar de Usuario
cls
Mensajes: 1336
Registrado: 24 May 2007 18:46
Contactar:

Mensaje por cls »

Hola,
por si ayuda a aclarar este tema pongo un ejemplo de cómo corre el OnBarUpdate.
Cuando se utiliza el multi-timeframe en estrategias, se va entrando en el OnBarUpdate a medida que se cierran las barras.
Las primeras barras que se cierran son las que tienen el timeframe más bajo, en este caso las de 1min, independientemente de qué orden tengan en el BarInProgress.
Por ejemplo, tenemos una serie0 (la principal) de 5min y una serie1 de 1min, la correspondencia de las barras sería:
serie0 : 0 -------------- 1 ------------------------ 2 ----------------------- 3
serie1 0-1-2-3-4 --- 5-6-7-8-9 ------10-11-12-13-14 ---- 15-16-17-18-19

La barra0 de la serie0 estaría formada por las barras de la 0 a la 4 de la serie1.
La secuencia de ejecución del OnBarUpdate para el caso de la barra1 de la serie0 sería: primero la barra5(serie1), luego la 6, 7, 8 y ahora tocaría la 9. Y después la barra1(serie0).
Y vuelta a empezar: barra10(serie1), 11, 12, 13, 14 y barra2(serie0) y así sucesivamente.

Excepciones: cuando toca cerrar la última barra en realidad se entra primero en la que tenga más prioridad. Después de la barra8(serie1) viene la barra1(serie0) y luego la barra9(serie1). Primero cierra la serie con más prioridad.

S2
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

cls escribió: Por ejemplo, tenemos una serie0 (la principal) de 5min y una serie1 de 1min, la correspondencia de las barras sería:
serie0 : 0 -------------- 1 ------------------------ 2 ----------------------- 3
serie1 0-1-2-3-4 --- 5-6-7-8-9 ------10-11-12-13-14 ---- 15-16-17-18-19

La barra0 de la serie0 estaría formada por las barras de la 0 a la 4 de la serie1.
La secuencia de ejecución del OnBarUpdate para el caso de la barra1 de la serie0 sería: primero la barra5(serie1), luego la 6, 7, 8 y ahora tocaría la 9. Y después la barra1(serie0).
Y vuelta a empezar: barra10(serie1), 11, 12, 13, 14 y barra2(serie0) y así sucesivamente.
S2
Hola Cls!

El ejemplo que pones, se podría representar así?


12:00 Serie0
12:00 Serie1
12.01 Serie1
12:02 Serie1
12:03 Serie1
12:04 Serie1
12:05 Serie0
12:05 Serie1
12:06 Serie1
12:07 Serie1

La barra de las 12:05 de la serie0, es la que lleva la OHLCV desde las 12:00 a las 12:04:59, ¿no?

Saludos!
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
Avatar de Usuario
cls
Mensajes: 1336
Registrado: 24 May 2007 18:46
Contactar:

Mensaje por cls »

bolsa1 escribió:
cls escribió: Por ejemplo, tenemos una serie0 (la principal) de 5min y una serie1 de 1min, la correspondencia de las barras sería:
serie0 : 0 -------------- 1 ------------------------ 2 ----------------------- 3
serie1 0-1-2-3-4 --- 5-6-7-8-9 ------10-11-12-13-14 ---- 15-16-17-18-19

La barra0 de la serie0 estaría formada por las barras de la 0 a la 4 de la serie1.
La secuencia de ejecución del OnBarUpdate para el caso de la barra1 de la serie0 sería: primero la barra5(serie1), luego la 6, 7, 8 y ahora tocaría la 9. Y después la barra1(serie0).
Y vuelta a empezar: barra10(serie1), 11, 12, 13, 14 y barra2(serie0) y así sucesivamente.
S2
Hola Cls!

El ejemplo que pones, se podría representar así?


12:00 Serie0
12:00 Serie1
12.01 Serie1
12:02 Serie1
12:03 Serie1
12:04 Serie1
12:05 Serie0
12:05 Serie1
12:06 Serie1
12:07 Serie1

La barra de las 12:05 de la serie0, es la que lleva la OHLCV desde las 12:00 a las 12:04:59, ¿no?

Saludos!
Hola bolsa1,
la respuesta a te pregunta es que sí.

la barra0 de la serie0 (5min) no termina hasta que cierra su quinta barra de la serie1 (1min). Así que terminará a las 12:04:59 y estará formada por cinco barras de 1min que van desde las 12:00 hasta las 12:04:59.
Esto es como debería ser.

Sin embargo, en histórico - no en tiempo real - las cinco barras de 1min (desde las 12:00 hasta las 12:04:59) tienen acceso al OHLC de la barra de 5min que termina a las 12:04:59. Es decir, que la barra de 1min de las 12:00 sabe cómo terminará las barra de 5min de las 12:04:59. Esto debes tenerlo en cuenta para programar correctamente la estrategia.


Según la secuencia que has puesto la primera 12:00 Serie0 sobra y va entre las 12:03:59 Serie 1y 12:04:59 Serie 1, por lo que comenté antes de que primero cierra la principal.

S2

(PD: lo mejor para salir de dudas es debugar. Usa un print que te diga la CurrentBar y el BarInProgress. Ten en cuenta que la CurrentBar se referirá a la serie en que estés en ese momento y que te la indica el BarInProgress ).

Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

Ok!

Voy a cambiar la estrategia que tengo corriendo en la página... a ver qué resultados me da el WFO.

Saludos, y gracias!
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

Creo que algo me falla...

Estos son los resultados de un sistema en el que estoy trabajando, eprimero es antes de hacer las pruebas con dos líneas de tiempo, el segundo es "después" es con los cambios hechos...

Imagen

Y ahora la debacle:

Imagen

Aparte de hundirse en la miseria, los resultados de "después" arrojan un valor medio de duranción de "-978 barras"

Algo se pudre en Dinamarca... ¿dónde puede estar el error?:

Código: Seleccionar todo

        protected override void Initialize()
        {
			Add(PeriodType.Range, 2);
            SetProfitTarget(Ganancia);
            SetStopLoss(Perdida, false);
            CalculateOnBarClose = true;
		}

        /// <summary>
        /// Called on each bar update event (incoming tick)
        /// </summary>
        protected override void OnBarUpdate()
        {
            // Condition set 1
			if (BarsInProgress == 0)
			{
            if (XXXXXXXXXXXXX)
            {
                EnterLongLimit(1, true, DefaultQuantity, XXXXXXXXXXXXX, "");
            }

            // Condition set 2
            if (XXXXXXXXXXXXX)
            {
                EnterShortLimit(1, true, DefaultQuantity, XXXXXXXXXXXXXX, "");
            }
			}
			 else
         {
            return;
         } 
        }

Ya no digo que el sistema sea malo o bueno, lo que no entiendo es el dato de las "-978" barras...
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
wave
Mensajes: 210
Registrado: 26 Nov 2007 23:21
Ubicación: Londres

Mensaje por wave »

Bolsa1,

yo alucino con los ratios que pones, eso no esta sobreoptimizado?

S2
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

La verdad es que no está ni optimizado.

El sistema tiene tres parámetros: Ganancia, pérdida, y otro que sólo puede tener como valor 2 o 3.

El sistema me gusta por simple, aunque probablemente no valga para nada. Estos resultados tan espectaculares mucho me temo que se deben a que el Ninja Trader da como buenas todas las operaciones que se puedan cerrar dentro de las barras donde se abren las posiciones, sin saber si la barra va en ese sentido o no... a ver si me explico...

Hay una barra bajista con cierre en 100 y apertura en 200. Tengo una orden de compra en 120 con objetivo de beneficios en 180. Cuando la cotización llega a 120 la orden de compra entra, y luego sigue bajando y me salta el StopLoss. Sin embargo, en los backtestings me hubiera dado la orden como exitosa, por el simple hecho de que el máximo de la barra está en 200, y el objetivo de beneficios era 180... no tiene en cuenta los movimientos "intra-barra".

Para evitar ésto es para lo que quiero utilizar la doble línea temporal... para comprobar hacia donde va la cotización dentro de la barra, con un intervalo de tiempo más pequeño.

Los primeros resultados son irreales... y seguramente los segundos son los que se acercan más a la realidad (aunque yo me esperaba algo mejor, aún siendo la primera prueba y estando sin optimizar ni depurar). La única duda que me queda es si he implementado bien el código de la segunda línea temporal, dado el dato de "-972" barras en la duranción media por operación... a ver si Cls o otro programador encuentran algún fallo...

Saludos!
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

Fijándome en el gráfico he encontrado un montón de entradas incongruentes (después de aplicarle la segunda línea temporal):

Imagen

Primero he pensado que podían ser entradas de la siguiente barra... o que estaban mal formuladas... pero repasando el código veo que es imposible...

¿Alguien le encuentra lógica?
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
Avatar de Usuario
Javi
Mensajes: 179
Registrado: 17 Sep 2004 20:30

Mensaje por Javi »

En tradestation , puedes probarlo con la funcion lookinsidebar , te mira tick a tick , lo que ha hecho dentro la barra . ¿Estas estadisticas de cual de las 3 operativas del articulo son?
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

Pretende ser una variación de la operativa3.

Ya tengo 4 sistemas funcionando sobre las tres operativas, pero me gustaría depurar algunos comportamientos, por lo que he cambiado el indicador y el intervalo temporal. A raíz de esto ha empezado a fallar... cuando en teoría debería mejorar los anteriores resultados...

Sigo buscando el error, a ver si me da tiempo antes del partido! :-D

Saludos!
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
Avatar de Usuario
cls
Mensajes: 1336
Registrado: 24 May 2007 18:46
Contactar:

Mensaje por cls »

bolsa1, para encontrar el error lo mejor es que debuges con el visualStudio. No tardarás ni 5min en encontrarlo.

A lo mejor el problema lo tienes con el SetProfit y el SetStop que los tienes definidos en la serie de 5min. Cuando toda la gestión de órdenes la haces en 1min.

De todas formas los primeros ratios que has puesto son poco menos que increíbles. Esa fiabilidad con semejante número de operaciones y ratio (casi 1:3) no puede ser real (aunque el stop sea 6 veces el target). Con un riesgo del 1% en 10 días doblas la cuenta.
Como has comentado antes, si abres y cierras una ope con limitadas en la misma barra y no tienes multi-timeframe, el sistema te la da por buena siempre. Así que a lo mejor por eso te han salido esas estadísticas.

S2
Última edición por cls el 10 Jun 2008 18:17, editado 1 vez en total.
Avatar de Usuario
bolsa1
Mensajes: 1347
Registrado: 13 May 2008 09:53
Ubicación: Gallaecia

Mensaje por bolsa1 »

cls escribió:bolsa1, para encontrar el error lo mejor es que debuges con el visualStudio. No tardarás nin 5min en encontrarlo.

A lo mejor el problema lo tienes con el SetProfit y el SetStop que los tienes definidos en la serie de 5min. Cuando toda la gestión de órdenes la haces en 1min.

De todas formas los primeros ratios que has puesto son poco menos que increíbles. Esa fiabilidad con semejante número de operaciones y ratio (casi 1:3) no puede ser real. Con un riesgo del 1% en 10 días doblas la cuenta.
Como has comentado antes, si abres y cierras una ope con limitadas en la misma barra y no tienes multi-timeframe, el sistema te la da por buena siempre. Así que a lo mejor por eso te han salido esas estadísticas.

S2
Si, si... eso seguro. Como explicaba antes, esas estadísticas son totalmente irreales.

Voy a probar a debuggear... a ver que encuentro...

Saludos!
"Mercaderes e industriales no deben ser admitidos a la ciudadanía; porque su género de vida es abyecto y contrario a la virtud."

Aristóteles.
wave
Mensajes: 210
Registrado: 26 Nov 2007 23:21
Ubicación: Londres

Mensaje por wave »

Ok bolsa1,

el tema del backtest es muy delicado y yo he encontrado algunos problemas con el NT tambien.

Por ejemplo si ves las baras de rango estas no tienen gaps y en una estrategia abria al comienzo de la siguiente pero en realidad no habia ticks ahi.

Que desilucion al ver lo que pasaba :(

Lo mejor creo que es lo que estas haciendo tu, probarlo tambien con una demo en TR.

un abrazo
Si te ha gustado este hilo del Foro, ¡compártelo en redes!


Responder

Volver a “Ninja Trader”