La estrategia de comercio de la red
(www.fmz.com)
La idea básica del comercio en red es muy sencilla. En lugar de colocar un comercio, colocamos múltiples operaciones formando un patrón de red. Por lo general, estos se ingresan como órdenes
¿Qué es el comercio de redes y cómo funciona? El comercio en red es un juego sobre la volatilidad del mercado. Hay dos razones por las que es favorecido por los operadores. El primero es que no requiere que tenga una predicción definitiva sobre la dirección del mercado.
La segunda es que funciona bien en mercados volátiles, donde no hay una tendencia clara. Estas condiciones son muy comunes en los mercados de divisas.
El comercio en rejilla es un tipo de análisis técnico basado en el movimiento dentro de patrones específicos de la red. El comercio en rejilla es popular en el comercio de divisas. En general, la técnica busca capitalizar la volatilidad normal de los precios en los mercados mediante la colocación de órdenes de compra y venta a ciertos intervalos regulares por encima y por debajo de un precio base predefinido.
La cuadrícula puede personalizar la dirección
Operación comercial básica: comprar primero y luego vender.
La red comenzará a enviar órdenes de compra al precio que está por debajo del primer precio, que es el precio seguido por el primer precio (segundo último precio de compra, tercer último precio de compra... y así sucesivamente). Cada orden de compra está separada por el parámetro
Después de que se complete cualquier orden de compra, el programa se basará en el precio de compra, añadir el precio del parámetro
Vender en corto primero y luego comprar para cubrir: la operación es exactamente lo contrario
El mayor riesgo de esta estrategia es cuando la tendencia del mercado se mueve unilateralmente y las fluctuaciones de precios exceden la cuadrícula.
El siguiente código ha hecho la cuadrícula con pérdida automática de parada y función de movimiento.
Comentarios:
La estrategia utiliza un diseño de orden pendiente virtual, que proporciona una gran cantidad de procesamiento para el intercambio para limitar el número de órdenes pendientes, y resuelve el problema de manera flexible.
La lógica de la red es flexible en diseño y inteligente en estructura.
Cálculo de ganancias y pérdidas, cada algoritmo estadístico numérico se puede utilizar como referencia, y cada diseño de detección de condiciones es riguroso. (para minimizar la posibilidad de BUG)
El código fuente vale mucho la pena aprenderlo.
Para más información, véase:
https://www.fmz.com/strategy/112633
Código de origen:
// Código de origen: /* Parámetros de interfaz (que se muestran como variables globales en el código) OpType Grid Dirección Caja desplegable (seleccionada) Compra primero y luego vende. FirstPriceAuto precio inicial automático booleano (verdadero/falso) verdadero El precio inicial automático numérico (número) 100 Todos Número total número numérico (número) 10 Precio de la red de precios Intervalo numérico (número) 1 Diferencia de precios numérica (número) Cuadro desplegable de tamaño de orden (seleccionado) comprar y vender la misma cantidad cantidad personalizada Cantidad de transacción única (número) 0.1 BAmountOnce@AmountType==1 Orden de compra Tamaño numérico (número) 0.1 SAmountOnce@AmountType==1 Tamaño numérico de la orden de venta (número) 0.1 CantidadCoefficient@AmountType==0 Diferencia de cantidad Correa (correa) *1 CantidadDot Número con punto decimal 3 HabilitarProtectDiff Activar la protección de propagación Booleano (verdadero/falso) falso ProtectDiff@EnableProtectDiff Proporción de entrada Protección de precios numérica (número) 20 CancelAllWS stop cancela todas las órdenes pendientes booleano (verdadero/falso) verdadero CheckInterval número numérico del intervalo de votación (número) 2000 Intervalo de reintentos de fallo numérico (número) 1300 RestoreProfit restaura el último beneficio booleano (verdadero/falso) falso Última ganancia (número) 0 ProfitAsOrg@RestoreProfit Última ganancia contada como precio medio Booleano (verdadero/falso) falso HabilitarAccountCheck habilitar la verificación del saldo booleano (verdadero/falso) verdadero ActivarStopLoss@EnableAccountCheck abierto Detener pérdida booleana (verdadero/falso) falso Pérdida máxima flotante numérica (número) 100 StopLossMode@EnableStopLoss Operación de pérdida post-stop Caja desplegable (seleccionada) Reciclar y salir. HabilitarStopWin@EnableAccountCheck Activar la toma de ganancias Booleano (verdadero/falso) falso StopWin@EnableStopWin Ganancia variable máxima Tipo de número (número) 120 StopWinMode@EnableStopWin cuadro desplegable de operaciones posteriores a la obtención de ganancias (seleccionado) Reciclar y salir. AutoMove@EnableAccountCheck automático Mover Booleano (verdadero/falso) falso MaxDistance@AutoMove distancia máxima numérica (número) 20 MaxIdle@AutoMove máximo tiempo de inactividad (segundos) numérico (número) 7200 Habilitar Dinámico Vueltas en ordenes dinámicas pendientes Booleano (verdadero/falso) falso Distancia de vencimiento de la orden DynamicMax@EnableDynamic Número (número) 30 ResetData borra todos los datos en el inicio Boolean (verdadero/falso) verdadero Precisión del precio longitud decimal numérica (número) 5 */
función hasOrder ((ordenes, orderId) { // Compruebe si hay un orden con orden ID en los pedidos de parámetros para (var i = 0; i < ordes.length; i++) { // Cruzar órdenes para comprobar si hay idénticos ids, si hay, a continuación, devuelva verdadero si (orden[i].Id == ordenId) { devuelve verdadero; ¿ Por qué? ¿ Por qué? Retorno falso; // Todo atravesado, sin disparador si significa que no ha encontrado el orden con el orden ID, retorno falso ¿ Por qué?
función cancelarPending() { // Cancelar todas las funciones de orden pendientes var ret = false; // Establecer la variable de la etiqueta de éxito de retorno mientras (verdadero) { // mientras el bucle si (ret) { // Si ret es verdadero entonces dormir por un cierto tiempo el sueño (intervalo de tiempo); ¿ Por qué? var órdenes = _C ((exchange.GetOrders); // Llame a la API para obtener la información de orden que el intercambio no ejecutó. si (orders.length == 0) { // Si se devuelve una matriz vacía, el intercambio no tiene órdenes no ejecutadas. Break; // Salta del bucle mientras ¿ Por qué?
for (var j = 0; j < orders.length; j++) { // Traverse the unfinished order array and use orders[j].Id one by one to cancel the order based on the index j.
exchange.CancelOrder(orders[j].Id, orders[j]);
ret = true; // Once there is a cancel operation, ret is assigned a value of true. Used to trigger above Sleep, wait for re-exchange.GetOrders detection
}
}
return ret; // return ret
}
valores de funciónToString(valores, pos) { // Valor convertido a una cadena
var result =
Función Trader() { // Función Trader, con el uso de cierres.
var vId = 0; // ID del incremento de orden
var ordenBooks = []; // libro de pedidos
var hisBooks = []; // Libro de orden histórico
var orderBooksLen = 0; // longitud del libro de pedidos
este.Comprar = función ((precio, cantidad, extra) { // Función de compra, parámetros: precio, cantidad, información ampliada
si (typeof(extra) ===
si (ordenes[i].Id == order.Id) { // Cuando encuentre un orden con el mismo orden id en orderBooks, asignar un valor de verdad a encontrar, lo que significa encontrar.
encontrada = verdadera;
Break; // Salta fuera del bucle actual
¿ Por qué?
¿ Por qué?
si (! encontrado) { // Si no se encuentra, empuje orderBooks[orderId] a las órdenes.
orden.push ((orderBooks[orderId]); // ¿Por qué quieres presionar así?
¿ Por qué?
¿ Por qué?
ordenes de devolución; // ordenes de devolución
¿ Por qué?
Esto.GetOrder = función ((orderId) { // Obtener orden
si (typeof(orderId) ===
var pfn = order.Type == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; // Assign the corresponding API function reference to pfn according to the type of the order.
// That is, if the order type is a buy order, pfn is a reference to the exchange.Buy function, the same as the sell order.
if (order.Id == 0 && diff <= priceDiff) { // If the order order in the order book is not activated (ie Id is equal to 0) and the current price is less than or
// equal to the order plan price, the priceDiff passed in the parameter.
var realId = pfn(order.Price, order.Amount, order.Extra + "(distance: " + diff + (order.Type == ORDER_TYPE_BUY ? (" ask price: " + ticker.Buy) : (" bid price: " + ticker.Sell))+")");
// Execute order function, parameter passing price, quantity, order extension information + pending order distance + market data (ask price or bid price), return exchange order id
if (typeof(realId) === 'number') { // If the returned realId is a numeric type
order.Id = realId; // Assign the Id attribute of the current order order to the order book.
}
} else if (order.Id > 0 && diff > (priceDiff + 1)) { // If the order is active and the current distance is greater than the distance passed in by the parameter
var ok = true; // Declare a variable for tagging Initially set true
do { // Execute "do" first and then judge while
ok = true; // Ok assign true
exchange.CancelOrder(order.Id, "unnecessary" + (order.Type == ORDER_TYPE_BUY ? "buying" : "selling"), "placed order price:", order.Price, "volume:", order.Amount, ", distance:",
diff, order.Type == ORDER_TYPE_BUY ? ("ask price: " + ticker.Buy) : ("bid price: " + ticker.Sell));
// Cancel the pending order that is out of range. After canceling the order, print the current order information and the current distance diff.
Sleep(200); // Wait 200 milliseconds
orders = _C(exchange.GetOrders); // Call the API to get an uncompleted order in the exchange.
for (var i = 0; i < orders.length; i++) { // Traverse these unfinished orders.
if (orders[i].Id == order.Id) { // If the cancelled order is found in the list of orders that have not been completed by the exchange
ok = false; // Assign ok this variable to false, that is, no cancellation is successful.
}
}
} while (!ok); // If ok is false, then !ok is true and while will continue to repeat the loop, continue to cancel the order,
// and check if the cancellation is successful.
order.Id = 0; // Assigning a value of 0 to order.Id means that the current order is inactive.
}
}
};
}
function balanceAccount ((orgAccount, initAccount) { // Balance Account Function Parameter Información inicial de la cuenta cuando se inicia la estrategia
Call the custom function cancelPending ((() to cancel all pending orders (Call the custom function cancelPending ((()) para cancelar todos los pedidos pendientes) // Llama a la función de cancelación de pedidos para cancelar todos los pedidos pendientes.
var nowAccount = _C ((exchange.GetAccount); // Declare a variable nowAccount para registrar la última información sobre la cuenta en el momento.
Var slidePrice = 0.2; // Set the slip price when placing the order as 0.2 El precio del deslizamiento cuando se coloca el pedido es 0.2
var ok = true; // variable de etiqueta inicialmente establecida como verdadera
mientras (verdadero) { // mientras el bucle
var diff = _N ((nowAccount.Stocks - initAccount.Stocks); // Calcula la diferencia entre la cuenta actual y la cuenta inicial
If (Math.abs(diff) < exchange.GetMinStock()) { // If the absolute value of the currency difference is less than the minimum transaction volume of the exchange, entonces el valor absoluto de la diferencia de moneda es menor que el volumen mínimo de transacción del exchange, y el valor absoluto de la diferencia de moneda es menor que el volumen mínimo de transacción del exchange.
// el break salta fuera del bucle y no realiza operaciones de equilibrio.
¿Qué es lo que está pasando?
¿Por qué no?
var depth = _C ((exchange.GetDepth); // Obtenga la información de profundidad de intercambio Asignála a la variable de profundidad declarada
var books = diff > 0? depth.Bids : depth.Asks; // According the difference of the currency is greater than 0 or less than 0, extract the buy order array or
// sell order array in depth (equal to 0 no será procesado, se rompe cuando se juzga que es menor que GetMinStock)
// La diferencia entre las monedas es mayor que 0 para vender el saldo, así que mira la matriz de órdenes de compra,
// la diferencia entre las monedas es menor que 0 es la opuesta.
var n = 0; // La declaración n inicial es 0
El precio inicial de la declaración es 0.
para (var i = 0; i < books.length; i++) { // Traversing the buy or sell order array
n += books[i].Amount; // Accumulate Amount (order quantity) for each order based on the index i traversed (Cuantidad acumulada para cada orden basada en el índice que he atravesado)
If (n >= Math.abs ((diff)) { // If the cumulative order quantity n is greater than or equal to the currency difference, then: Si la cantidad de orden acumulativa n es mayor o igual a la diferencia de moneda, entonces:
Price = books[i].Price; // Obtener el precio del orden indexado actual, asignarlo al precio
break; // salta fuera de la corriente para el ciclo de travesía
¿Por qué no?
¿Por qué no?
Var pfn = diff > 0? exchange.Sell : exchange.Buy; // Pasa la API de orden de venta (exchange.Sell) o la siguiente API de orden de compra (exchange.Buy) referencia al pfn declarado
// Basado en la diferencia de moneda mayor que 0 o menor que 0
var amount = Math.abs(diff); // La cantidad del orden a ser equilibrado es diff, la diferencia en la moneda, asignada a la variable de cantidad declarada.
var price = diff > 0? (price - slidePrice) : (price + slidePrice); // The direction of buying and selling according to the difference in the currency, increase or decrease the
// Slip price basado en el precio (slip price is to make it easier to trade), y luego asignarlo al precio
Log ((
var STATE_WAIT_OPEN = 0; // Se utiliza para el estado de cada nodo en el fishTable var STATE_WAIT_COVER = 1; //... el estado de espera de cierre = 2; var ProfitCount = 0; // Registro de pérdidas y ganancias var BuyFirst = verdadero; // Parámetros iniciales de la interfaz var IsSupportGetOrder = true; // determina el soporte de intercambio de la función GetOrder API, una variable global, utilizada para determinar el inicio de la función principal var LastBusy = 0; // Registra el último objeto de tiempo procesado
función setBusy() { // Establecer el tiempo de actividad LastBusy = new Date(); // Asignar LastBusy al objeto de tiempo actual ¿ Por qué?
Función isTimeout() { // Determina si tiene tiempo de espera si (MaxIdle <= 0) { // Tiempo máximo de inactividad (basado en si la red se mueve automáticamente), // si el tiempo máximo de inactividad MaxIdle se establece menor o igual a 0 return false; // devuelve false, no juzga el tiempo de espera. es decir, siempre devuelve false sin tiempo de espera. ¿ Por qué? var now = new Date ((); // Obtener el objeto de tiempo actual si (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) { // Utilice la función getTime del objeto de tiempo actual para obtener la marca de tiempo y la marca de tiempo de LastBusy para calcular la diferencia, // Divida por 1000 para calcular el número de segundos entre los dos objetos de tiempo. // Determine si es mayor que el tiempo de inactividad máximo MaxIdle LastBusy = ahora; // Si es mayor que, actualizar LastBusy al objeto de tiempo actual ahora devuelve true; // devuelve true, que es un tiempo de espera. ¿ Por qué? Retorno falso; // Retorno falso sin tiempo de espera ¿ Por qué?
función onexit ((() { // La función de cierre cuando el programa sale.
si (CancelAllWS) { // Para cancelar todas las órdenes pendientes cuando se detiene, llame a cancelPending() para cancelar todas las órdenes pendientes.
Registro ((
Función de pesca ((orgCuenta, pescadoCuenta) { // Parámetros de lanzamiento: información sobre la cuenta, número de lanzamientos
SetBusy(); // Establezca LastBuys en la marca de tiempo actual
var cuenta = _C(exchange.GetAccount); // Declare una variable de cuenta para obtener la información de la cuenta corriente y asignarla.
Log ((cuenta); // Saca la información de la cuenta al comienzo de la llamada a la función de pesca.
var InitAccount = cuenta; // Declarar una variable InitAccount y asignarlo con cuenta.
// este moldeado, utilizado para calcular las ganancias y pérdidas flotantes.
var ticker = _C(exchange.GetTicker); // Obtener el valor de cotización asignado a la variable ticker declarada
var amount = _N(AmountOnce); // De acuerdo con el número de parámetros de interfaz, use _N para procesar los decimales (_N por defecto a 2 bits) y asignarlos a amount.
var amountB = [amount]; // Declare una variable llamada amountB es una matriz, inicializa un elemento con amount
var amountS = [amount]; // Declare una variable llamada amountS...
si (typeof(AmountType)!==
¿ Por qué?
// Inicie la tabla de peces
var fishTable = {}; // Declarar un objeto de cuadrícula
var uuidTable = {}; // Objeto de la tabla de código de identificación
var needStocks = 0; // Monedas requeridas variable
var needMoney = 0; // Variable dinero requerido
var actualNeedMoney = 0; // En realidad necesitaba dinero
var actualNeedStocks = 0; // Monedas realmente necesarias
var notEnough = false; // Variable de etiqueta subfinanciada, inicialmente establecida en false
var canNum = 0; // Cuadrícula disponible
para (var idx = 0; idx < AllNum; idx++) { // La estructura se recorre de acuerdo con el número de la cuadrícula AllNum.
el precio var = _N((ComprarPrimero? PrimeroPrecio - (idx * PriceGrid) : PrimeroPrecio + (idx * PriceGrid)), Precisión);
// Al atravesar el constructo, la configuración del precio del índice idx actual se establece de acuerdo con BuyFirst.
needStocks += amountS[idx]; // El número de monedas vendidas se acumula gradualmente con el ciclo.
needMoney += precio * cantidadB[idx]; // La cantidad de dinero requerida para comprar se acumula gradualmente con el ciclo. (....compra la matriz de cantidad de orden una por una...)
si (comprar primero) { // manejar comprar primero
si (_N(needMoney) <= _N ((account.Balance)) { // Si la red requiere menos dinero que la cantidad disponible en la cuenta
actualNeedMondy = needMoney; // asignado a la cantidad real de dinero requerido
actualNeedStocks = needStocks; // Asignación al número real de monedas requeridas. ¿Hay algo malo en esto?
canNum++; // Número acumulado de cuadrículas disponibles
} else { // _N(needMoney) <= _N(account.Balance) Si no se cumple esta condición, establecer la variable de etiqueta de insuficiencia de financiación en verdadero
noEnough = verdadero;
¿ Por qué?
} otro { // manejar la venta primero
si (_N(needStocks) <= _N(account.Stocks)) { // Compruebe si el número de monedas requerido es menor que el número de monedas disponibles en la cuenta
actualNeedMondy = needMoney; // asignación
actualNeedStocks = needStocks;
canNum++; // Número acumulado de cuadrículas disponibles
No lo sé.
notEnough = true; // Establecer true si no se cumplen las condiciones de financiación
¿ Por qué?
¿ Por qué?
fishTable[idx] = STATE_WAIT_OPEN; // De acuerdo con el índice idx actual, establece el estado del miembro idx (nodo de la red) del objeto de la red,
// inicialmente STATE_WAIT_OPEN (esperando para abrir la posición)
uuidTable[idx] = -1; // El objeto numerado también inicializa su propio valor idx (el nodo correspondiente al fishTable) a -1 basado en el idx actual.
¿ Por qué?
si (!EnableAccountCheck && (canNum < AllNum)) { // Si la verificación de fondos no está habilitada, y el número de cuadrículas (el número total de nodos) donde el nodo es menor
// que el parámetro de configuración de la interfaz puede ser abierto.
Log ((
lanzar
var trader = new Trader(); // Constructs a Trader object, assigning it to the trader variable declared here.
var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell; // According to whether to buy and sell first, set the open function OpenFunc to refer to exchange.Buy or exchange.Sell
var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy; // same as above
if (EnableDynamic) { // Set OpenFunc/CoverFunc again according to whether the interface parameter EnableDynamic is enabled.
OpenFunc = BuyFirst ? trader.Buy : trader.Sell; // The member function Buy that references the trader object is used for dynamic pending orders (mainly because
// some exchanges limit the number of pending orders, so virtual dynamic pending orders are required)
CoverFunc = BuyFirst ? trader.Sell : trader.Buy; // same as above
}
var ts = new Date(); // Create a time object at this time (assigned to ts) to record the time at the moment.
var preMsg = ""; // Declare a variable to record the last message, the initial set to empty string
var profitMax = 0; // Maximum return
while (true) { // The main logic after the grid is casted
var now = new Date(); // Record the time when the current cycle started
var table = null; // Declare a variable
if (now.getTime() - ts.getTime() > 5000) { // Calculate whether the difference between the current time now and the recorded time ts is greater than 5000 milliseconds
if (typeof(GetCommand) == 'function' && GetCommand() == "Receiving grid") { // Check if the strategy interaction control command "receives the grid" is received,
// stops and balances to the initial state.
Log("Start executing commands to perform grid operations"); // Output information
balanceAccount(orgAccount, InitAccount); // Perform a balancing function to balance the number of coins to the initial state
return false; // This time the grid function is fishing and return false
}
ts = now; // Update ts with current time now for next comparison time
var nowAccount = _C(exchange.GetAccount); // Declare the nowAccount variable and initially been set as the current account information.
var ticker = _C(exchange.GetTicker); // Declare the ticker variable and initially been set as the current market information.
if (EnableDynamic) { // If you enable dynamic pending orders
trader.Poll(ticker, DynamicMax); // Call the Poll function of the trader object to detect and process all orders based on the
// current ticker market and the interface parameter DynamicMax.
}
var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks); // Calculate the current coin difference
var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance); // Calculate the current money difference
var floatProfit = _N(money_diff + (amount_diff * ticker.Last)); // Calculate the current floating profit and loss of this time of casting grid
var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks
- orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last));
// Calculate the overall floating profit and loss
var isHold = Math.abs(amount_diff) >= exchange.GetMinStock(); // If the absolute value of the coin difference at this moment is greater than the minimum trading
// volume of the exchange, it means that the position has been held.
if (isHold) { // If you have already held a position, execute the setBusy() function, which will update the LastBusy time.
setBusy(); // That is, after opening the position, the opening of the opening mechanism is started.
}
profitMax = Math.max(floatProfit, profitMax); // Refresh the maximum floating profit and loss
if (EnableAccountCheck && EnableStopLoss) { // If you initiate account detection and start a stop loss
if ((profitMax - floatProfit) >= StopLoss) { // If the maximum floating profit or loss minus the current floating profit or loss is greater than or equal to
// the maximum floating loss value, execute the code inside the curly braces
Log("Current floating profit a