Asesores Expertos: Arbitrage Synthetic - página 3

[Eliminado]  
bas:

Maxim Dmitrievsky, si no es un secreto, ¿cuál fue el ping al servidor de este bot? ¿Y cuál es el tiempo medio de ejecución? Tengo 10ms y 200ms, y esto a menudo no es suficiente para ser ejecutado mientras exista el arbitraje.

¿Y cómo se determina cuál de los dos pares restantes, aparte del líder, "alcanzará"? Yo por ejemplo sólo uso estadísticas históricas, normalmente si el EURUSD va en cabeza, no es el cruce el que le alcanza, sino la segunda pata del usd, pero esto no es así en todos los triples.


por desgracia este tema ya esta muerto. los pings eran cero. 200 ms ya es mucho para el arbitraje de latencia (considere 400 ms, porque el trato todavía tiene que ser cerrado + slippages/markups).

La idea principal era que si el sintético ya ha cambiado y el par de divisas no lo ha hecho, entonces lo más probable es que haya una caída en la cotización y pronto se igualará con ella. y no tendría sentido gastar mucho tiempo en ello. Operado con este bot por un corto tiempo, poner en un par de reales - en uno un poco ganado en el otro un poco perdido, hecho deducciones.

Puse el bot principalmente por el hecho de que una gran cantidad de preguntas que surgieron en esta estrategia en el último medio año la gente. Para compartir mi opinión. Muchas personas escriben o piensan en ello, pero no había ejemplos libres para sentir. Una mayor optimización no tiene sentido, ya que los corredores modernos no están diseñados para hft, y en general el arbitraje de 3 puntos es un mito, no hay tal arbitraje, ya sea en una o 3 patas.

 

En algunas divisas (TRY, NZD) los sesgos pueden durar horas), pero no se puede saber de antemano, y no es interesante quedarse en una operación durante tanto tiempo.

Synthetic consta de dos pares. Normalmente sólo uno de ellos "se pone al día", y el tercero se queda quieto. Por eso he preguntado cómo determinar cuál de los dos pares se pondrá al día.

Y el cierre se hace después de que el arbitraje se desplome, donde el tiempo de ejecución no es tan importante.

¿Por qué "no existe"? Lo observo regularmente) pero no tengo suficiente velocidad.

[Eliminado]  
bas:

En algunas divisas (TRY, NZD) los sesgos pueden durar horas), pero no se puede saber de antemano, y no es interesante quedarse en una operación durante tanto tiempo.

Synthetic consta de dos pares. Normalmente sólo uno de ellos "se pone al día", y el tercero se queda quieto. Por eso he preguntado cómo determinar cuál de los dos pares se pondrá al día.

Y el cierre se hace después de que el arbitraje se desplome, donde el tiempo de ejecución no es tan importante.

¿Por qué "no existe"? Lo veo regularmente) pero no tengo suficiente velocidad.


No existe debido a la velocidad.

y a menudo se produce por retrasos en la cotización, se obtiene una cotización indicativa que, o bien está retrasada, o bien no es real en absoluto.

Esas distorsiones de las que hablas las arreglan después las empresas de corretaje cuando se dan cuenta....

Por eso preguntaba cómo determinar cuál de las dos se pondrá al día.

Básicamente, no se puede, sólo experimentalmente o el comercio en tres patas. O al menos con un 33% de probabilidad de que sea nuestro par el que se quede atrás, que no es poco :)

 
Vale, no existe así que no existe)
[Eliminado]  
bas:
De acuerdo, no existe así que no existe)

No pero lo sigues intentando, si quieres, yo no soy la verdad en última instancia :))

Todo lo compruebo con mi propia experiencia... y con la de los demás también. Y si el tiempo es una pena, es mejor no hacerlo.

Como en Yeralash - "¡Aquí no hay peces!" (varias veces)

- ¿Quién dice eso?

- Quién es quién, ¡el director del estadio!

 
Maxim Dmitrievsky:

No bueno tu sigue intentandolo si quieres, yo no soy la verdad en ultima instancia :)

Yo lo compruebo todo con mi propia experiencia... y con la de los demás también. Y si el tiempo es una pena, es mejor no hacerlo.

Como en Yeralash - "¡Aquí no hay peces!" (varias veces)

- ¿Quién dice eso?

- Quién es quién, ¡el director del estadio!


- El director de la pista de hielo.

 

Si publica un ejemplo de un triángulo, puede hacer que sea más agradable estéticamente, a saber, sustituir OnTimer, que se salta los ticks, con OnChartEvent, que recibirá los ticks de todos los instrumentos, el indicador de aquí - https://www.mql5.com/en/articles/234

En general, sí, no hay peces, pipsing no es para el comercio minorista, si se tiene en cuenta la propagación + comisión, en el triángulo principal sólo habrá 3 operaciones al año con un beneficio escaso, y que el corredor no puede dar porque en un mundo ideal EURUSD / GBPUSD = EURGBP, y si sucedió lo contrario, es una cotización no de mercado :)

#include <AIV/Trades.mqh>
#include <AIV/Charts.mqh>

input int InpMagic = 0;
input double InpFactor = 2;
input double InpVolume = 0.01;
input double InpCommission = 30;
input string iACName = "EURUSD";
input string iBCName = "GBPUSD";
input string iABName = "EURGBP";

int iDirection;

SSymbol iACData = {0};
SSymbol iBCData = {0};
SSymbol iABData = {0};

SSeries iSeries[];

CSets * iSets;
CHelpers * iHelpers;
CPositions * iPositions;

void OnDeinit(const int reason)
{
    delete(iSets);
    delete(iHelpers);
    delete(iPositions);
}

int OnInit()
{
    long chart = ChartID();

    iSets = new CSets();
    iHelpers = new CHelpers();
    iPositions = new CPositions();

    iCustom(iACName, PERIOD_M1, "AIV\\Spy", chart, 1);
    iCustom(iBCName, PERIOD_M1, "AIV\\Spy", chart, 2);
    iCustom(iABName, PERIOD_M1, "AIV\\Spy", chart, 3);

    return 0;
}

void Trade()
{
    int positions = PositionsTotal();

    double incomeAC = iPositions.getPositionsIncome(iACName, 0, InpMagic);
    double incomeBC = iPositions.getPositionsIncome(iBCName, 0, InpMagic);
    double incomeAB = iPositions.getPositionsIncome(iABName, 0, InpMagic);

    // Alinear la volatilidad de los instrumentos

    double sizeAC = InpVolume / iHelpers.getTickCost(iACName);
    double sizeBC = InpVolume / iHelpers.getTickCost(iBCName);
    double sizeAB = InpVolume / iHelpers.getTickCost(iABName);

    // Si tenemos beneficios en el triángulo, cerramos posiciones

    if (positions > 0)
    {
        if (incomeAC + incomeBC + incomeAB > 0) 
        {
            iPositions.closePositions(NULL, 0, InpMagic);
            return;
        }
    }
    else
    {
        int direction = isGap();

        // Cuando sintético está por encima de EURGBP

        if (direction == 1) 
        {
            iDirection = direction;
            iPositions.openSimplePosition(iACName, iDirection * -1, sizeAC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iBCName, iDirection, sizeBC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iABName, iDirection, sizeAB, 0, 0, 0, InpMagic);
        }
        else if (direction == -1) // Cuando EURGBP está más alto
        {
            iDirection = direction;
            iPositions.openSimplePosition(iACName, iDirection, sizeAC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iBCName, iDirection * -1, sizeBC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iABName, iDirection * -1, sizeAB, 0, 0, 0, InpMagic);
        }
    }
}

int isGap()
{
    if (iACData.mUnit <= 0 || iBCData.mUnit <= 0 || iABData.mUnit <= 0)
    {
        return 0;
    }

    double X = iACData.mUnit / iBCData.mUnit;
    double Y = iABData.mUnit;
    double spread = 2 * (iACData.mMean + iBCData.mMean + iABData.mMean);

    double commission = 
        2 * iACData.mUnit * iHelpers.moneyToPips(iACName, InpVolume, InpCommission * InpVolume) + 
        2 * iBCData.mUnit * iHelpers.moneyToPips(iBCName, InpVolume, InpCommission * InpVolume) + 
        2 * iABData.mUnit * iHelpers.moneyToPips(iABName, InpVolume, InpCommission * InpVolume);

    // Cuando distancia EURUSD / GBPUSD - EURGBP > Comisión + Spread

    if (X - Y - spread - commission > 0)
    {
        return 1;
    }
    else if (Y - X - spread - commission > 0) // Viceversa.
    {
        return -1;
    }

    return 0;
}

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
    if (id > CHARTEVENT_CUSTOM) 
    {
        string message[];

        // Aggregate prices from 3 charts here, every "sparam" contains data in format "EURUSD:1.22350:30" or "GBPUSD:1.52450:15" or "EURGBP:1.22350:3"

        StringSplit(sparam, ':', message);

        if (ArraySize(message) < 3)
        {
            return;
        }

        string symbol = message[0];
        int event = id - CHARTEVENT_CUSTOM;
        double close = StringToDouble(message[1]);
        double spread = StringToDouble(message[2]) * SymbolInfoDouble(symbol, SYMBOL_POINT);

        if (symbol == iACName)
        {
            iACData.mName = symbol;
            iACData.mUnit = close;
            iACData.mMean = spread;
        }
        else if (symbol == iBCName)
        {
            iBCData.mName = symbol;
            iBCData.mUnit = close;
            iBCData.mMean = spread;
        }
        else if (symbol == iABName)
        {
            iABData.mName = symbol;
            iABData.mUnit = close;
            iABData.mMean = spread;
        }
 
        // Comercio sólo cuando tenemos los precios de los 3 pares

        if (iACData.mUnit > 0 && iBCData.mUnit > 0 && iABData.mUnit > 0)
        {
            Trade();
        }
    }
}

Por si acaso y código simplificado del indicador Spy :)

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1

input long InpChart = 0;
input ushort InpEventId = 0;

int OnCalculate (
    const int bars,
    const int counted,
    const datetime& times[],
    const double& opens[],
    const double& highs[],
    const double& lows[],
    const double& closes[],
    const long& ticks[],
    const long& volumes[],
    const int& spreads[])
{
    string close = DoubleToString(closes[bars - 1]);
    string spread = DoubleToString(spreads[bars - 1]);
    EventChartCustom(InpChart, InpEventId, (long) Period(), bars, Symbol() + ":" + close + ":" + spread); // Trasladar los ticks de todos los gráficos a un único manejador de eventos
    return bars;
}
 
Andy Sanders:

Por si acaso y código simplificado del indicador Espía :)

Variante alternativa.

Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2018.01.28
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 

Puedes hacerlo de esta manera, pero en mi caso paso un montón de datos "EURUSD:1.22350:30" a través de sparam, para no saturar el código del EA con llamadas SymbolInfoTick separadas para cada símbolo

 

Y si alguien está interesado, hay una interesante implementación de Pair Trading con rebalanceo y holding, que no es para cuentas swap, sólo en acciones reales
https://www.quantconnect.com/forum/discussion/1257/pairs-trading-with-coke--pepsi.