- Crear y eliminar símbolos personalizados
- Propiedades de símbolos personalizados
- Fijación de coeficientes de margen
- Configurar sesiones de cotización y trading
- Añadir, sustituir y suprimir cotizaciones
- Añadir, sustituir y eliminar ticks
- Conversión de los cambios en el libro de órdenes
- Particularidades del trading con símbolos personalizados
Añadir, sustituir y suprimir cotizaciones
Un símbolo personalizado se rellena de cotizaciones mediante dos funciones integradas: CustomRatesUpdate y CustomRatesReplace. En la entrada, además del nombre del símbolo, ambos esperan un array de estructuras MqlRates para el marco temporal M1 (los marcos temporales superiores se completan automáticamente a partir de M1). CustomRatesReplace tiene un par de parámetros adicionales (from y to) que definen el intervalo de tiempo al que se limita la edición del historial.
int CustomRatesUpdate(const string symbol, const MqlRates &rates[], uint count = WHOLE_ARRAY)
int CustomRatesReplace(const string symbol, datetime from, datetime to, const MqlRates &rates[], uint count = WHOLE_ARRAY)
CustomRatesUpdate añade las barras que faltan al historial y sustituye las barras coincidentes existentes por datos del array.
CustomRatesReplace sustituye completamente el historial en el intervalo de tiempo especificado por los datos del array.
La diferencia entre las funciones se debe a los distintos escenarios de la aplicación prevista. Las diferencias se detallan en el cuadro siguiente:
CustomRatesUpdate |
CustomRatesReplace |
---|---|
Aplica los elementos del array MqlRates pasada al historial, independientemente de sus marcas de tiempo. |
Aplica solo aquellos elementos del array MqlRates pasada que se encuentren dentro del intervalo especificado. |
Deja intactas en el historial aquellas barras M1 que ya estaban ahí antes de la llamada a la función y no coinciden en el tiempo con las barras del array. |
Deja intacta todo el historial fuera del intervalo. |
Sustituye las barras del historial existentes por las barras del array cuando las marcas de tiempo coinciden. |
Borra completamente las barras del historial existentes en el rango especificado. |
Inserta elementos del array como barras «nuevas» si no hay coincidencias con las barras antiguas. |
Inserta las barras del array que se encuentran dentro del intervalo pertinente en el intervalo histórico especificado. |
Los datos del array rates deben estar representados por precios OHLC válidos, y las horas de apertura de las barras no deben contener segundos.
Se establece un intervalo dentro de from y to inclusive: from es igual al tiempo de la primera barra que se procesa y to es igual al tiempo de la última.
En el siguiente diagrama se ilustran estas reglas con mayor claridad. Cada marca de tiempo única de un compás se designa con su propia letra latina. Las barras disponibles en el historial se muestran en mayúsculas, mientras que las barras del array se muestran en minúsculas. El carácter '-' es un hueco en el historial o en el array para la hora correspondiente.
History ABC-EFGHIJKLMN-PQRST------ B
|
El parámetro opcional count establece el número de elementos del array rates que deben utilizarse (se ignorarán los demás). Esto le permite procesar parcialmente el array pasado. El valor predeterminado WHOLE_ARRAY significa el array completo.
El historial de cotizaciones de un símbolo personalizado puede borrarse total o parcialmente mediante la función CustomRatesDelete.
int CustomRatesDelete(const string symbol, datetime from, datetime to)
Aquí, los parámetros from y to también establecen el intervalo de tiempo de las barras eliminadas. Para cubrir todo el historial, especifique 0 y LONG_MAX.
Las tres funciones devuelven el número de barras procesadas: actualizadas o eliminadas. En caso de error, el resultado es -1.
Cabe señalar que las cotizaciones de un símbolo personalizado pueden formarse no solo añadiendo barras ya hechas, sino también mediante arrays de ticks o incluso una secuencia de ticks individuales. Las funciones pertinentes se presentarán en la sección siguiente. Al añadir ticks, el terminal calculará automáticamente barras basadas en ellos. La diferencia entre estos métodos es que el historial de ticks personalizado le permite probar los programas MQL en el modo de ticks «reales», mientras que el historial de barras únicamente le obligará a limitarse a los modos OHLC M1 o de precio abierto o a confiar en la emulación de ticks implementada por el probador.
Además, añadir ticks de uno en uno permite simular eventos estándar OnTick y OnCalculate en el gráfico de un símbolo personalizado, lo que «anima» el gráfico de forma similar a las herramientas disponibles en línea, y lanza las funciones de manejador correspondientes en los programas MQL si se trazan en el gráfico. Pero hablaremos de ello en la próxima sección.
Como ejemplo de uso de nuevas funciones, vamos a considerar el script CustomSymbolRandomRates.mq5, diseñado para generar cotizaciones aleatorias según el principio del «paseo aleatorio» o cotizaciones existentes de ruido. Esto último puede utilizarse para evaluar la estabilidad de un Asesor Experto.
Para comprobar la corrección de la formación de las cotizaciones, también se admite el modo en el que se crea una copia completa del instrumento original, en el gráfico del que se lanzó el script.
Todos los modos se recogen en la enumeración RANDOMIZATION.
enum RANDOMIZATION
|
Aplicamos ruido de cotizaciones con dos niveles de intensidad: débil y fuerte.
En los parámetros de entrada, puede elegir, además del modo, una carpeta en la jerarquía de símbolos, un intervalo de fechas y un número para inicializar el generador aleatorio (para poder reproducir los resultados).
input string CustomPath = "MQL5Book\\Part7"; // Custom Symbol Folder
|
De manera predeterminada, cuando no se especifican fechas, el script genera las cotizaciones de los últimos 120 días. El valor 0 en el parámetro RandomSeed significa inicialización aleatoria.
El nombre del símbolo se genera en función del símbolo del gráfico actual y de los ajustes seleccionados.
const string CustomSymbol = _Symbol + "." + EnumToString(RandomFactor)
|
Al principio de OnStart prepararemos y comprobaremos los datos.
datetime From;
|
Dado que lo más probable es que el script deba ejecutarse varias veces, ofreceremos la posibilidad de eliminar el símbolo personalizado creado anteriormente con una solicitud de confirmación preliminar por parte del usuario.
bool custom = false;
|
La función de ayuda CloseChartsForSymbol no se muestra aquí (quien lo desee puede consultar el código fuente adjunto): su propósito es ver la lista de gráficos abiertos y cerrar aquellos en los que el símbolo de trabajo es el símbolo personalizado que se está borrando (sin esto, el borrado no funcionará).
Lo más importante es prestar atención a la llamada a CustomRatesDelete con un intervalo completo de fechas. Si no se hace así, los datos del símbolo de usuario anterior permanecerán en el disco durante un tiempo en la base de datos del historial (carpeta bases/Custom/history/<symbol-name>). En otras palabras: la llamada a CustomSymbolDelete, que se muestra en la última línea anterior, no es suficiente para borrar realmente el símbolo personalizado del terminal.
Si el usuario decide volver a crear inmediatamente un símbolo con el mismo nombre (y en el código que aparece a continuación ofrecemos esa posibilidad), las cotizaciones antiguas pueden mezclarse con las nuevas.
Además, tras la confirmación del usuario, se inicia el proceso de generación de cotizaciones. De ello se encarga la función GenerateQuotes (véase más adelante).
if(IDYES == MessageBox(StringFormat("Create new custom symbol '%s'?", CustomSymbol),
|
Si tiene éxito, el símbolo recién creado se selecciona en Observación de Mercado y se abre un gráfico para él. Por el camino, aquí se demuestra el establecimiento de un par de propiedades: SYMBOL_DIGITS y SYMBOL_DESCRIPTION.
En la función GenerateQuotes es necesario solicitar las cotizaciones del símbolo original para todos los modos excepto RANDOM_WALK.
int GenerateQuotes()
|
Es importante recordar que CopyRates se ve afectado por el límite en el número de barras del gráfico, que se establece en la configuración del terminal.
En el caso del modo ORIGINAL, simplemente reenviamos el array resultante rates a la función CustomRatesReplace. Para los modos de ruido, establecemos las variables price y start especialmente seleccionadas en los valores iniciales de precio y tiempo de la primera barra.
price = rates[0].open;
|
En el modo de paseo aleatorio, las cotizaciones no son necesarias, por lo que sólo asignamos el array rates para futuras barras aleatorias M1.
else
|
Más adelante en el bucle a través del array rates, se añaden valores aleatorios a los precios ruidosos del símbolo original o «tal cual». En el modo RANDOM_WALK, nosotros mismos nos encargamos de aumentar el tiempo en la variable start. En otros modos, el tiempo ya está en las cotizaciones iniciales.
const int size = ArraySize(rates);
|
A partir del precio de cierre de la última barra, se generan 3 valores aleatorios (utilizando la función RandomWalk). El máximo y el mínimo de ellos se convierten, respectivamente, en los precios High y Low de una nueva barra. La media es el precio Close.
Al final del bucle, pasamos el array a CustomRatesReplace.
return PRTF(CustomRatesReplace(CustomSymbol, From, To, rates));
|
En la función RandomWalk se ha intentado simular una distribución con colas anchas, típica de las cotizaciones reales.
double RandomWalk(const double p)
|
Los coeficientes de dispersión de las variables aleatorias dependen del modo. Por ejemplo, el ruido débil añade (o resta) un máximo de 1 centésima de porcentaje, y el ruido fuerte añade 5 centésimas de porcentaje del precio.
Mientras se ejecuta, el script muestra un registro detallado como éste:
Create new custom symbol 'GBPUSD.RANDOM_WALK'?
|
Veamos qué obtenemos como resultado.
En la siguiente imagen se muestran varias implementaciones de un paseo aleatorio (la superposición visual se realiza en un editor gráfico; en realidad, cada símbolo personalizado se abre en una ventana independiente, como es habitual).
Opciones de cotización para símbolos personalizados con paseo aleatorio
Y así es como se ven las cotizaciones GBPUSD ruidosas (original en negro, color con ruido). Primero, en una versión débil.
Cotizaciones GBPUSD con poco ruido
Y después con ruido intenso.
Cotizaciones GBPUSD con ruido intenso
Las mayores discrepancias son evidentes, aunque con la preservación de las características locales.