Estructura básica de un sistema en VBA

A la hora de diseñar un sistema utilizando el entorno VBA se suelen repetir ciertos patrones de diseño, lo cual nos permite generar un modelo básico de estructura de sistemas, facilitándonos la labor de desarrollo y disminuyendo el nivel de errores a la hora de programar.

Un ejemplo en el que se utiliza este modelo lo observamos en el sistema Default System al que pueden acceder desde el siguiente enlace:


También tenemos disponible el sistema en PDV:

Default System en PDV

La finalidad del sistema Default System  no es otra sino la de acercar a los usuarios de Visual Chart los métodos más utilizados a la hora de realizar un sistema automático de trading.

Funcionamiento del sistema

Este sistema se basa en un cruce de Medias para decidir el punto de entrada, así como en distintos stops de pérdida y beneficio para decidir el punto de salida.


El sistema tiene, además, la opción de liquidar posiciones al finalizar la sesión para cuando se desea operar en intradía.


Diseño del sistema

Tal y como decíamos, lo más interesante de éste sistema es que sigue la estructura básica que nos va a servir como modelo para cualquier estrategia de características similares, que son:

    1.  Entrada a mercado.
    2.  Utilización de stoploss, objetivo de beneficios y trailingstop.

Distinguiremos entres la zona de órdenes de salida y la zona de órdenes de entrada.

Zona de ordenes de salida.
A la hora de colocar los stops y el objetivo, el diseño siempre se repite:


'-- Market of Current Entry
gmp = .GetMarketPosition
'--- EXITS
If gmp <> 0 Then
    gep = .GetEntryPrice
    '-- Init Trailing Price
    If Lastgmp <> gmp Then PriceTS = gep
    '-- Exit Long
    If gmp = 1 And Not CrossT = -1 Then
        If TargetProfit <> 0 Then
            .ExitLong AtLimit, ContractsNumber, gep + TargetProfit * pip
        End If
        If TrailingStop <> 0 Then
            If .High > PriceTS Then PriceTS = .High
            .ExitLong AtStop, ContractsNumber, PriceTS - TrailingStop * pip
        End If
        If StopLoss <> 0 Then .ExitLong AtStop, ContractsNumber, gep - StopLoss * pip
    '-- Exit Short
    ElseIf gmp = -1 And Not CrossT = 1 Then
        If TargetProfit <> 0 Then
            .ExitShort AtLimit, ContractsNumber, gep - TargetProfit * pip
        End If
        If TrailingStop <> 0 Then
            If .Low < PriceTS Then PriceTS = .Low
            .ExitShort AtStop, ContractsNumber, PriceTS + TrailingStop * pip
        End If
        If StopLoss <> 0 Then .ExitShort AtStop, ContractsNumber, gep + StopLoss * pip
    End If
End If

De donde cabe destacar que:

1. Primero comprobamos si estamos abiertos (gmp <> 0). Luego lanzamos las órdenes para la posición abierta a largos o bien para la posición abierta a cortos.

2. La variable PriceTS se utiliza para llevar el control de la mejor posición alcanzada: De manera que el trailingstop la utiliza como referencia. Cuando se produce un cambio de posición (Lastgmp<> gmp), actualizamos la variable con el precio de la nueva entrada.

3. A fin de sólo enviar una orden en STOP por cada entrada, comparamos el precio de salida del stoploss y del trailingstop y sólo enviamos aquel que esté más próximo al precio de entrada.

Zona de órdenes de entrada
Para este tipo de sistemas, las órdenes de entrada son lanzadas a mercado. La señal que activa la compra o la venta, en el caso del sistema DefaultSystem, es la variable CrossT. Esta variable cambia su estado a 1 cuando el cruce es alcista y a -1 cuando el cruce es bajista. El resto del tiempo permanece a cero.

Cabe recordar a los usuarios, que los sistemas no ejecutan las órdenes a mercado en el momento de producirse la señal (en este caso, el cruce de las medias), sino que sucede una vez que finaliza la barra donde se ha producido la señal.

El diseño de la zona de órdenes de entrada es el siguiente:


'--- ENTRIES
If gmp <> 1 Then
    '-- Case of Cross Up, entry long
    If CrossT = 1 Then
        .Buy AtClose, ContractsNumber
        If StopLoss <> 0 Then .ExitLong AtStop, ContractsNumber, .Close - StopLoss * pip
        If TargetProfit <> 0 Then .ExitLong AtLimit, ContractsNumber, .Close + TargetProfit * pip
    End If
End If
If gmp <> -1 Then
    '-- Case of Cross Down, entry short
    If CrossT = -1 Then
        .Sell AtClose, ContractsNumber
        If StopLoss <> 0 Then .ExitShort AtStop, ContractsNumber, .Close + StopLoss * pip
        If TargetProfit <> 0 Then .ExitShort AtLimit, ContractsNumber, .Close - TargetProfit * pip
    End If
End If

De donde cabe destacar que:

1. Una vez que estamos abiertos a largo o corto, no permitimos que vuelva a entrar en el mismo sentido.

2. Volvemos a repetir el lanzamiento de las órdenes de salida. Esto es necesario hacerlo si queremos tener activas las órdenes de salida en la primera barra en la que estamos abiertos.

3. La diferencia entre las órdenes de salida lanzadas para la primera barra y las órdenes lanzadas para el resto de barras, es que el precio de referencia será el precio de cierre de la barra, pues aún no disponemos del valor que nos devuelve la función GetEntryPrice.

3 comentarios:

Visual Chart dijo...

Si les surge alguna pregunta o necesitan alguna aclaración, no duden en dejar sus comentarios: Entre todos trataremos de solucionarlos.

avdarie dijo...

Hola, he estado mirando un poco el código para poder saber como funciona. Quería preguntar la variable Bar que se pasa en System_OnCalculateBar
Que és ? No se si teneis algún esquema para ver el funcionamiento de como se ejecuta el sistema sobre los gráficos. Algo más gráfico o una doc de las funciones.

Saludos,

Visual Chart dijo...

La variable BAR marca el número de barra en la que nos encontramos en cada iteración. Cuando insertamos un sistema, el sistema primero aplica el método OnCalculateBar sobre las n barras históricas del gráfico, y a partir de ahí, sobre las siguientes barras que vayan dándose en tiempo real. De modo que:
La primera barra del histórico vale 0, y por tanto, Bar = 0 para OnCalculateBar sobre esa barra.
La segunda barra del histórico vale 1, y por tanto, Bar =1 para OnCalculateBar sobre esa barra.
La n-ésima barra del histórico vale (n-1), y por tanto, Bar =(n-1) para OnCalculateBar sobre esa barra.
Si no le ha quedado algo claro, no dude en volver a consultarnos, ok?
Respecto al documento que nos solicita sobre cómo se aplica el sistema al gráfico, tendremos en cuenta su solicitud y desarrollaremos un diagrama explicativo que publicaremos en posteriores entradas.
Gracias por el comentario!

Publicar un comentario en la entrada

España: 902 34 11 34 · USA: 866 497 5537 · UK: 020 7153 8936 · 020 7153 8937
020 7153 8938 · 020 7153 8939 · Deutschland: 01805 35 40 30 · Österreich: 0820 40 0038
Schweiz: 0 800 56 10 15 · France: 0 821 23 00 99 · Belgique: 078 79 01 79
Suisse: 0 800 56 10 15 · Canada: 800 210 7889 · Italy: 848 390 458
síguenos en
2000 - 2011.
ESPAÑOL - ENGLISH - DEUTSCH - FRANÇAIS - ITALIANO
Todos los derechos reservados. Visual Chart™ es una marca registrada de Visual Chart.