En la carga de los recursos... Cargando...

Commodity Futures High Frequency Trading Strategy escrito por C++

El autor:La bondad, Creado: 2020-05-22 15:28:11, Actualizado: 2023-11-02 19:54:28

img

Penny Jump Commodity Futures High Frequency Trading Strategy escrito por C++

Resumen de las actividades

El mercado es el campo de batalla, el comprador y el vendedor están siempre en el juego, que también es el tema eterno del negocio comercial.

Clasificación de la estrategia de alta frecuencia

En el comercio de alta frecuencia, hay dos tipos principales de estrategias. La estrategia del lado del comprador y la estrategia del lado del vendedor. La estrategia del lado del vendedor es generalmente una estrategia de creación de mercado, y los dos lados de estas estrategias son oponentes. Por ejemplo, la estrategia del comprador de arbitraje de alta frecuencia de suavizar todos los fenómenos irrazonables en el mercado a la velocidad más rápida, tomar la iniciativa de atacar el precio rápidamente, o comer el precio equivocado de otros creadores de mercado.

También hay una forma de analizar los datos históricos o las reglas de orden del mercado, para enviar las órdenes pendientes a un precio irrazonable por adelantado, y para enviar las órdenes de retiro con el rápido cambio del precio del mercado. Tales estrategias son comunes en el mercado pasivo, una vez que las órdenes pendientes se ejecutan, y después de un cierto beneficio o después de alcanzar la condición de stop-loss, la posición se cerrará.

¿Cuál es la estrategia de Penny Jump?

Penny Jump se traduce en inglés es el significado de aumento de micro-precio. El principio es realizar un seguimiento del precio de compra y el precio de venta del mercado. Luego, de acuerdo con el precio del mercado, más o menos el aumento de micro-precio del precio de seguimiento, es obvio que esta es una estrategia de negociación pasiva, pertenece a la estrategia de creación de mercado del lado del vendedor. Su modelo de negocio y lógica es llevar a cabo transacciones bilaterales en órdenes de límite listadas en bolsa para proporcionar liquidez.

La estrategia de creación de mercado requiere una cierta cantidad de inventario en la mano, y luego se negocia tanto en el lado del comprador como del vendedor. El principal ingreso de esta estrategia es el retorno de la comisión proporcionada por el intercambio, así como la diferencia de precio obtenida comprando bajo y vendiendo alto.

Principio de la estrategia Penny Jump

Sabemos que hay muchos inversores minoristas en el mercado de operaciones, y también hay muchos inversores grandes, como: hot money, fondos públicos, fondos privados, etc. Los inversores minoristas generalmente tienen menos fondos, sus órdenes tienen un impacto muy pequeño en el mercado, pueden comprar y vender fácilmente un objetivo comercial en cualquier momento.

Si un gran inversor quiere comprar 500 lotes de petróleo crudo, no hay tantas órdenes al precio actual para vender, y el inversor no quiere comprarlos al precio más alto. Si insisten en enviar la orden de compra al precio actual, el costo de los puntos de deslizamiento será demasiado. por lo tanto, tiene que enviar una orden pendiente al precio deseado. Todos los participantes en el mercado verán una orden de compra hugh que muestra el precio determinado.

Debido a este enorme pedido, parece torpe en el mercado, a veces lo llamamos "órdenes de elefante".

Selling Price 400.3, Order volume 50; buying price 400.1, Order volume 10. 

De repente este elefante engorroso salta al mercado, y el precio de la oferta fue enviado al precio de 400.1.

Selling Price 400.3, Order volume 50; Buying price 400.1, Order volume 510.

Todos los traders saben que si hay una gran cantidad de órdenes pendientes a cierto precio, entonces este precio formará un fuerte soporte ((o resistencia).

Selling Price 400.3, Order volume 50; Buying price 400.2, Order volume 1,

el precio 400.1 se convierte en el precio de compra 2 en la profundidad de la cartera de órdenes.

Incluso si el precio no sube, en la posición de comprar 2, todavía hay un elefante que sostiene el precio, y se puede vender rápidamente al elefante al precio de 400.1. Esta es la idea general de la estrategia Penny Jump. Su lógica es tan simple como esta, al monitorear el estado de la orden del mercado, especular con las intenciones del oponente, y luego tomar la delantera en la construcción de una posición favorable, y finalmente beneficiarse de un pequeño spread en un corto período de tiempo.

Implementación de la estrategia de Penny Jump

En primer lugar, observar las oportunidades de negociación con una probabilidad muy baja del mercado, y hacer las estrategias correspondientes de acuerdo con la lógica de negociación. Si la lógica es compleja, es necesario utilizar el conocimiento matemático existente, utilizar el modelo para describir la naturaleza del fenómeno irracional tanto como sea posible, y reducir al mínimo el sobreajuste. Además, debe ser verificado por un motor de backtest que puede cumplir con el Price first then Volume first principio.

¿Cuál es el significado de soportar Price first then Volume first backtest engine? Puede entenderlo como: envía una orden pendiente a 400.1 para comprar, solo cuando el precio de venta en la profundidad del libro de pedidos es 400.1 o menor, su orden pendiente puede cerrarse. Solo calcula los datos de precios de las órdenes pendientes, y no calcula los datos de volumen de las órdenes pendientes, que solo cumple con la prioridad de precio ((precio primero) en las reglas de coincidencia de órdenes de intercambio.

El Volume first es una versión mejorada del price first. Es a la vez priorizado por el precio y por el tiempo. Se puede decir que este modo de correspondencia es exactamente el mismo que el modelo de intercambio.

Además, algunos lectores pueden encontrar que la estrategia Penny Jump requiere oportunidades de comercio de mercado, es decir, la necesidad del mercado tiene al menos dos brechas de precio hop. En circunstancias normales, el contrato comercial principal de futuros de productos básicos es relativamente busy. La diferencia entre Comprar 1 y Vender 1hop es que casi no hay oportunidad de comercio. Por lo tanto, ponemos nuestra energía en el contrato subprimario donde el comercio no es demasiado activo. Este tipo de contrato comercial ocasionalmente tiene dos o incluso tres oportunidades de hop. Por ejemplo, en el contrato MA (código Metanol en futuros de productos básicos chinos) 1909, se produce la siguiente situación:

img

Vender 1 precio 2225 con volumen 551, Comprar 1 precio 2223 con volumen 565, mirar hacia abajo durante unos segundos. Después de que esto suceda, desaparecerá después de varios ticks. En este caso, consideramos el mercado como autocorrección. Lo que tenemos que hacer es ponernos al día. Antes de que el mercado lo corrija activamente. si lo hacemos manualmente, sería imposible, con la ayuda del comercio automático, podemos hacerlo posible.

La situación de aparición de la brecha de precios de dos hop ocurre muy a menudo, pero los tres saltos son los más seguros, pero los tres saltos rara vez ocurren, lo que resulta en que la frecuencia de negociación es demasiado baja.

A continuación, observamos la diferencia entre el anterior Vender 1 Comprar 1 y el Comprar 1 Vender 1 ahora. Para llenar la brecha de precios entre el mercado, si la velocidad es lo suficientemente rápida, se puede colocar a la vanguardia de otras órdenes. Además, el tiempo de mantenimiento de la posición es muy corto, con esta lógica de negociación, después de la realización de la estrategia, tome el MA909 como ejemplo, la prueba de mercado real recomienda Esunny en lugar de la interfaz CTP, el mecanismo de cambio de posición y situación de fondos para Esunny es por datos empujados, muy adecuado para la negociación de alta frecuencia.

Código de estrategia

Después de limpiar la lógica de negociación, podemos usar el código para lograrlo. Dado que la plataforma FMZ Quant utiliza ejemplos de estrategia de escritura en C ++, aquí usamos C ++ para escribir esta estrategia, que es conveniente para que todos aprendan, y la variedad es los futuros de productos básicos.fmz.com> Iniciar sesión > Tablero > Biblioteca de estrategias > Nueva estrategia > Haga clic en el menú desplegable en la esquina superior izquierda > Seleccione C ++ para comenzar a escribir la estrategia, preste atención a los comentarios en el código a continuación.

  • Paso 1: primero construye el marco de la estrategia, en el que se definen una clase HFT y una función principal. La primera línea de la función principal es borrar el registro. El propósito de esto es borrar la información del registro que se ejecuta anteriormente cada vez que se reinicia la estrategia. La segunda línea es filtrar algunos mensajes de error que no son necesarios, como retraso de la red y algunos consejos aparecen, de modo que el registro sólo registra información importante y se ve más limpio; la tercera línea es imprimir el mensaje Init OK, lo que significa que el programa ha comenzado a comenzar. La cuarta línea es crear un objeto de acuerdo con la clase HFT, y el nombre del objeto es hft; la quinta línea del programa entra en el bucle mientras, y siempre ejecuta el bucle en el objeto de método hft, se puede ver que el método Loop es la lógica de este programa.

A continuación, veamos la clase HFT, que tiene cinco métodos. El primer método es el método de construcción; el segundo método es obtener el día actual de la semana para determinar si es una nueva línea K; el tercer método es principalmente cancelar todos los pedidos no cumplidos y obtener información detallada de la posición, porque antes de que se coloque la orden, primero debe determinar el estado de la posición actual; el cuarto método se utiliza principalmente para imprimir cierta información, para esta estrategia, este método no es el principal; el más importante es el quinto método, Este método es principalmente responsable del procesamiento de la lógica de negociación y la colocación de pedidos.

/ / Define the HFT class
Class HFT {
     Public:
         HFT() {
             // Constructor
         }
        
         Int getTradingWeekDay() {
             // Get the current day of the week to determine if it is a new K line
         }
        
         State getState() {
             / / Get order data
         }

         Void stop() {
             // Print orders and positions
         }
        
         Bool Loop() {
             // Strategy logic and placing orders
         }
};

// main function
Void main() {
     LogReset(); // clear the log
     SetErrorFilter("ready|timeout"); // Filter error messages
     Log("Init OK"); // Print the log
     HFT hft; // Create HFT object
     While (hft.Loop()); // enter loop
     Log("Exit"); // Program exits, prints the log
}

Así que vamos a ver cómo se implementa cada uno de los métodos en esta clase HFT, y cómo funciona el método más básico de Loop. De arriba a abajo, implementaremos la implementación específica de cada método uno por uno, y encontrarás que la estrategia original de alta frecuencia es muy simple. Antes de hablar sobre la clase HFT, primero definimos varias variables globales para almacenar los resultados del cálculo del objeto hft. Son: almacenamiento de estado de orden, estado de posición, mantenimiento de posición larga, mantenimiento de posición corta, precio de compra, cantidad de compra, precio de venta, cantidad de venta. Por favor, vea el código a continuación:

/ / Define the global enumeration type State
Enum State {
     STATE_NA, // store order status
     STATE_IDLE, // store position status
     STATE_HOLD_LONG, // store long position directions
     STATE_HOLD_SHORT, // store short position direction
};

/ / Define global floating point type variable
Typedef struct {
     Double bidPrice; // store the buying price
     Double bidAmount; // store the buying amount
     Double askPrice; // store the selling price
     Double askAmount; // store the selling amount
} Book;

Con las variables globales anteriores, podemos almacenar los resultados calculados por el objeto hft por separado, lo que es conveniente para llamadas posteriores por el programa. A continuación, hablaremos sobre la implementación específica de cada método en la clase HFT. Primero, el primer método HFT es un constructor que llama al segundo método getTradingWeekDay e imprime el resultado en el registro. El segundo método getTradingWeekDay obtiene el día actual de la semana para determinar si es una nueva línea K. También es muy simple de implementar, obtener la marca de tiempo, calcular la hora y la semana y, finalmente, devolver el número de semanas; el tercer método getState es un poco largo, solo describiré la idea general, para una explicación específica, puede ver los comentarios en el siguiente bloque de codificación.

A continuación, vamos a obtener todos los pedidos primero, devolver el resultado es una matriz normal, a continuación, atravesar esta matriz, uno por uno para cancelar el orden, a continuación, obtener los datos de posición, devolver una matriz, y luego atravesar esta matriz, obtener información de posición detallada, incluyendo: dirección, posición, ayer o posición actual, etc., y finalmente devolver el resultado; el cuarto método de parada es imprimir información; el código es el siguiente:

Public:
    // Constructor
    HFT() {
        _tradingDay = getTradingWeekDay();
        Log("current trading weekday", _tradingDay);
    }
    
    // Get the current day of the week to determine if it is a new K line
    Int getTradingWeekDay() {
        Int seconds = Unix() + 28800; // get the timestamp
        Int hour = (seconds/3600)%24; // hour
        Int weekDay = (seconds/(60*60*24))%7+4; // week
        If (hour > 20) {
            weekDay += 1;
        }
        Return weekDay;
    }
    
    / / Get order data
    State getState() {
        Auto orders = exchange.GetOrders(); // Get all orders
        If (!orders.Valid || orders.size() == 2) { // If there is no order or the length of the order data is equal to 2
            Return STATE_NA;
        }
        
        Bool foundCover = false; // Temporary variable used to control the cancellation of all unexecuted orders
        // Traverse the order array and cancel all unexecuted orders
        For (auto &order : orders) {
            If (order.Id == _coverId) {
                If ((order.Type == ORDER_TYPE_BUY && order.Price < _book.bidPrice - _toleratePrice) ||
                    (order.Type == ORDER_TYPE_SELL && order.Price > _book.askPrice + _toleratePrice)) {
                    exchange.CancelOrder(order.Id, "Cancel Cover Order"); // Cancel order based on order ID
                    _countCancel++;
                    _countRetry++;
                } else {
                    foundCover = true;
                }
            } else {
                exchange.CancelOrder(order.Id); // Cancel order based on order ID
                _countCancel++;
            }
        }
        If (foundCover) {
            Return STATE_NA;
        }
        
        // Get position data
        Auto positions = exchange.GetPosition(); // Get position data
        If (!positions.Valid) { // if the position data is empty
            Return STATE_NA;
        }

        // Traverse the position array to get specific position information
        For (auto &pos : positions) {
            If (pos.ContractType == Symbol) {
                _holdPrice = pos.Price;
                _holdAmount = pos.Amount;
                _holdType = pos.Type;
                Return pos.Type == PD_LONG || pos.Type == PD_LONG_YD ? STATE_HOLD_LONG : STATE_HOLD_SHORT;
            }
        }
        Return STATE_IDLE;
    }
    
    // Print orders and positions information
    Void stop() {
        Log(exchange.GetOrders()); // print order
        Log(exchange.GetPosition()); // Print position
        Log("Stop");
    }

Finalmente, nos centramos en cómo la función Loop controla la lógica de estrategia y el orden. Si desea ver más cuidadosamente, puede consultar los comentarios en el código. Primero determine si la transacción CTP y el servidor del mercado están conectados; luego obtenga el saldo disponible de la cuenta y obtenga el número de semanas; luego establezca el código de variedad a negociar, llamando a la función oficial de SetContractType de FMZ Quant, y puede usar esta función para devolver los detalles de la variedad de negociación; luego llame a la función GetDepth para obtener los datos de profundidad del mercado actual. Los datos de profundidad incluyen: precio de compra, volumen de compra, precio de venta, volumen de venta, etc., y los almacenamos con variables, porque serán utilizados más adelante; Luego saque estos datos a la barra de estado para facilitar al usuario ver el estado actual del mercado; el código es el siguiente:

// Strategy logic and placing order
Bool Loop() {
    If (exchange.IO("status") == 0) { // If the CTP and the quote server are connected
        LogStatus(_D(), "Server not connect ...."); // Print information to the status bar
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    If (_initBalance == 0) {
        _initBalance = _C(exchange.GetAccount).Balance; // Get account balance
    }
    
    Auto day = getTradingWeekDay(); // Get the number of weeks
    If (day != _tradingDay) {
        _tradingDay = day;
        _countCancel = 0;
    }
    
    // Set the futures contract type and get the contract specific information
    If (_ct.is_null()) {
        Log(_D(), "subscribe", Symbol); // Print the log
        _ct = exchange.SetContractType(Symbol); // Set futures contract type
        If (!_ct.is_null()) {
            Auto obj = _ct["Commodity"]["CommodityTickSize"];
            Int volumeMultiple = 1;
            If (obj.is_null()) { // CTP
                Obj = _ct["PriceTick"];
                volumeMultiple = _ct["VolumeMultiple"];
                _exchangeId = _ct["ExchangeID"];
            } else { // Esunny
                volumeMultiple = _ct["Commodity"]["ContractSize"];
                _exchangeId = _ct["Commodity"]["ExchangeNo"];
            }
            If (obj.is_null() || obj <= 0) {
                Panic("PriceTick not found");
            }
            If (_priceTick < 1) {
                exchange.SetPrecision(1, 0); // Set the decimal precision of the price and the quantity of the order.
            }
            _priceTick = double(obj);
            _toleratePrice = _priceTick * TolerateTick;
            _ins = _ct["InstrumentID"];
            Log(_ins, _exchangeId, "PriceTick:", _priceTick, "VolumeMultiple:", volumeMultiple); // print the log
        }
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    // Check orders and positions to set status
    Auto depth = exchange.GetDepth(); // Get depth data
    If (!depth.Valid) { // if no depth data is obtained
        LogStatus(_D(), "Market not ready"); // Print status information
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    _countTick++;
    _preBook = _book;
    _book.bidPrice = depth.Bids[0].Price; // "Buying 1" price
    _book.bidAmount = depth.Bids[0].Amount; // "Buying 1" amount
    _book.askPrice = depth.Asks[0].Price; // "Selling 1" price
    _book.askAmount = depth.Asks[0].Amount; // "Selling 1" amount
    // Determine the state of the port data assignment
    If (_preBook.bidAmount == 0) {
        Return true;
    }
    Auto st = getState(); // get the order data
    
    // Print the port data to the status bar
    LogStatus(_D(), _ins, "State:", st,
                "Ask:", depth.Asks[0].Price, depth.Asks[0].Amount,
                "Bid:", depth.Bids[0].Price, depth.Bids[0].Amount,
                "Cancel:", _countCancel,
                "Tick:", _countTick);
}

Después de haber hecho tanto, finalmente podemos colocar órdenes. Antes de la negociación, primero juzgamos el estado actual de la posición de retención del programa (sin posición de retención, órdenes de posición larga, órdenes de posición corta), aquí usamos el control de lógica si... si... si. Son muy simples, Si no hay posición de retención, la posición se abrirá de acuerdo con la condición lógica. Si hay posición de retención, la posición se cerrará de acuerdo con la condición lógica. Para facilitar la comprensión de todos, usamos tres párrafos para explicar la lógica, Para la parte de posición de apertura:

Primero declaramos una variable booleana, la usamos para controlar la posición de cierre; a continuación, necesitamos obtener la información de la cuenta corriente y registrar el valor de ganancia, luego determinar el estado de la orden de retiro, si el número de retiros excede el máximo establecido, imprimir la información relacionada en el registro; luego calcular el valor absoluto de la oferta actual y la diferencia de precio de oferta para determinar si hay más de 2 saltos entre el precio de oferta actual y el precio de compra.

A continuación, obtenemos el Precio de compra 1 y el Precio de venta 1, si el precio de compra anterior es mayor que el precio de compra actual, y el volumen de venta actual es menor que el volumen de compra, significa que el precio de compra 1 desaparece. el precio de apertura de la posición larga y la cantidad de orden se establecen; de lo contrario, si el precio de venta anterior es menor que el precio de venta actual, y el volumen de compra actual es menor que El volumen de venta demuestra que el precio de venta 1 desaparece, se establecen el precio de apertura de la posición corta y la cantidad de orden; al final, la posición larga y las órdenes cortas entran al mercado al mismo tiempo.

Bool forceCover = _countRetry >= _retryMax; // Boolean value used to control the number of closings
If (st == STATE_IDLE) { // if there is no holding position
    If (_holdAmount > 0) {
        If (_countRetry > 0) {
            _countLoss++; // failure count
        } else {
            _countWin++; // success count
        }
        Auto account = exchange.GetAccount(); // Get account information
        If (account.Valid) { // If get account information
            LogProfit(_N(account.Balance+account.FrozenBalance-_initBalance, 2), "Win:", _countWin, "Loss:", _countLoss); // Record profit value
        }
    }
    _countRetry = 0;
    _holdAmount = 0;
    
    // Judging the status of withdrawal
    If (_countCancel > _cancelMax) {
        Log("Cancel Exceed", _countCancel); // Print the log
        Return false;
    }

    Bool canDo = false; // temporary variable
    If (abs(_book.bidPrice - _book.askPrice) > _priceTick * 1) { // If there is more than 2 hops between the current bid and ask price
        canDo = true;
    }
    If (!canDo) {
        Return true;
    }
    
    Auto bidPrice = depth.Bids[0].Price; // Buying 1 price
    Auto askPrice = depth.Asks[0].Price; // Selling 1 price
    Auto bidAmount = 1.0;
    Auto askAmount = 1.0;
    
    If (_preBook.bidPrice > _book.bidPrice && _book.askAmount < _book.bidAmount) { // If the previous buying price is greater than the current buying price and the current selling volume is less than the buying volume
        bidPrice += _priceTick; // Set the opening long position price
        bidAmount = 2; // set the opening long position volume
    } else if (_preBook.askPrice < _book.askPrice && _book.bidAmount < _book.askAmount) { // If the previous selling price is less than the current selling price and the current buying volume is less than the selling volume
        askPrice -= _priceTick; // set the opening short position volume
        askAmount = 2; // set the opening short position volume
    } else {
        Return true;
    }
    Log(_book.bidPrice, _book.bidAmount, _book.askPrice, _book.askAmount); // Print current market data
    exchange.SetDirection("buy"); // Set the order type to buying long
    exchange.Buy(bidPrice, bidAmount); // buying long and open position
    exchange.SetDirection("sell"); // Set the order type to selling short
    exchange.Sell(askPrice, askAmount); // short sell and open position
}

A continuación, hablaremos sobre cómo cerrar una posición larga, primero establecer el tipo de orden de acuerdo con el estado actual de la posición, y luego obtener el precio de Venta 1. Si el precio de Venta 1 actual es mayor que el precio de apertura de compra larga, establecer el precio de cierre de la posición larga. Si el precio de Venta 1 actual es menor que el precio de apertura de la posición larga, luego restablecer la variable de cantidad de cierre a verdad, luego cerrar toda la posición larga.

Else if (st == STATE_HOLD_LONG) { // if holding long position
     exchange.SetDirection((_holdType == PD_LONG && _exchangeId == "SHFE") ? "closebuy_today" : "closebuy"); // Set the order type, and close position
     Auto sellPrice = depth.Asks[0].Price; // Get "Selling 1" price
     If (sellPrice > _holdPrice) { // If the current "selling 1" price is greater than the long position opening price
         Log(_holdPrice, "Hit #ff0000"); // Print long position opening price 
         sellPrice = _holdPrice + ProfitTick; // Set closing long position price
     } else if (sellPrice < _holdPrice) { // If the current "selling 1" price is less than the long position opening price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Sell(forceCover ? depth.Bids[0].Price : sellPrice, _holdAmount); // close long position
     If (!_coverId.Valid) {
         Return false;
     }
}

Finalmente, veamos cómo cerrar una posición corta. El principio es el opuesto a la posición larga de cierre mencionada anteriormente. Primero, según el estado de la posición actual, establezca el tipo de orden, y luego obtenga el precio de compra 1, si el precio de compra 1 actual es menor que el precio de apertura de la posición corta, se establecerá el precio de la posición corta de cierre. Si el precio de compra 1 actual es mayor que el precio de apertura de la posición corta, restablezca la variable de cantidad de cierre a verdad, luego cierre todas las posiciones cortas.

Else if (st == STATE_HOLD_SHORT) { // if holding short position
     exchange.SetDirection((_holdType == PD_SHORT && _exchangeId == "SHFE") ? "closesell_today" : "closesell"); // Set the order type, and close position
     Auto buyPrice = depth.Bids[0].Price; // Get "buying 1" price
     If (buyPrice < _holdPrice) { // If the current "buying 1" price is less than the opening short position price
         Log(_holdPrice, "Hit #ff0000"); // Print the log
         buyPrice = _holdPrice - ProfitTick; // Set the close short position price
     } else if (buyPrice > _holdPrice) { // If the current "buying 1" price is greater than the opening short position price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Buy(forceCover ? depth.Asks[0].Price : buyPrice, _holdAmount); // close short position
     If (!_coverId.Valid) {
         Return false;
     }
}

Lo anterior es un análisis completo de esta estrategia.https://www.fmz.com/strategy/163427) para copiar el código fuente de la estrategia completa sin configurar el entorno de backtest en FMZ Quant.

Resultados de las pruebas de retroceso

img

Lógica de negociación

img

Declaración de la estrategia

Para satisfacer la curiosidad de la negociación de alta frecuencia y ver los resultados con más claridad, esta estrategia de entorno de prueba de retroceso de la tarifa de transacción se establece en 0, lo que conduce a una lógica simple de velocidad rápida. si desea cubrir la tarifa de transacción para lograr rentabilidad en el mercado real. Se necesita más optimización.

Sobre nosotros

FMZ Quant es un equipo basado exclusivamente en la tecnología que proporciona un mecanismo de backtest disponible y altamente eficiente para los entusiastas del comercio cuantitativo. Nuestro mecanismo de backtest simula un intercambio real, en lugar de una simple coincidencia de precios.


Relacionados

Más.