El comercio de alta frecuencia es un campo desafiante y competitivo que se basa en la ejecución rápida de las operaciones y en una visión sensible de la microestructura del mercado. Una estrategia notable es Penny Jump, que se centra en explotar
En el mercado de valores,
Por ejemplo, supongamos que la profundidad original de un mercado de acciones era así: 200 ∙ $1.01 x $1.03 ∙ 200. Entonces un "elefante" entra y coloca una orden de compra de 3000 acciones a $1.01 cada una. En este punto, la profundidad del mercado cambiará a 3,200 ∙ $1.01 x $1.03 ∙ 200. Esta acción es como introducir un "elefante", que se convierte en el foco de otros participantes en el mercado.
Mercado competitivo Para los operadores de alta frecuencia, sus ganancias provienen principalmente del análisis de la microestructura del mercado para especular sobre las intenciones de otros operadores.
El dilema del elefante Aunque los elefantes pueden desear operar a gran escala en el mercado, sus acciones también revelan sus intenciones comerciales, lo que los convierte en objetivos para los operadores de alta frecuencia. Los operadores de alta frecuencia intentan establecer posiciones con anticipación y luego beneficiarse de las fluctuaciones de precios. La presencia de elefantes en el mercado podría desencadenar reacciones en mercados competitivos, afectando así sus estrategias comerciales.
El engaño en el mercado En realidad, los grandes inversores institucionales generalmente no colocan un gran número de órdenes de compra o venta en el mercado de manera descarada, ya que tal comportamiento podría llevar a otros participantes en el mercado a tomar contramedidas o incluso manipular el mercado.
La idea central de la estrategia de Penny Jump es que una vez que un
No solo eso, sino que los operadores de alta frecuencia también pueden obtener ganancias después de comprar incluso si el precio no aumenta, porque saben que el gran jugador ha apoyado el precio base; por lo tanto, pueden vender rápidamente sus acciones a este gran jugador y obtener pequeñas ganancias de arbitraje.
Código fuente de la estrategia:https://www.fmz.com/strategy/358
El código de estrategia proporcionado anteriormente es un ejemplo, utilizado para implementar la estrategia Penny Jump. A continuación hay una explicación detallada del código, lo que permite a los principiantes entender cómo funciona:
var Counter = {
i: 0,
w: 0,
f: 0
};
// Variables
var InitAccount = null;
function CancelAll() {
while (true) {
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
Sleep(Interval);
}
}
function updateStatus(msg) {
LogStatus("Number of debugging sessions:", Counter.i, "succeeded:", Counter.w, "failed:", Counter.f, "\n"+msg+"#0000ff\n"+new Date());
}
function main() {
if (DisableLog) {
EnableLog(false);
}
CancelAll();
InitAccount = _C(exchange.GetAccount);
Log(InitAccount);
var i = 0;
var locks = 0;
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
// skip Bids[0]
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount +", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price-(STTick*PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
}
Analizaré su código de estrategia línea por línea para ayudarle a entender su funcionamiento en detalle.
var Counter = {
i: 0,
w: 0,
f: 0
};
Este código inicializa un objeto llamado Contador, que se utiliza para rastrear la información estadística de una estrategia.
Estos atributos se registrarán y actualizarán durante el proceso de ejecución de la estrategia.
var InitAccount = null;
Esta línea de código inicializa una variable llamada InitAccount, que almacenará información de la cuenta cuando la estrategia comience a ejecutarse.
function CancelAll() {
while (true) {
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
Sleep(Interval);
}
}
Esta es una función llamadaCancelAll()
, su propósito es cancelar todos los pedidos no cumplidos en el mercado.
while (true)
: Este es un bucle infinito, continuará funcionando hasta que no haya órdenes incompletas.var orders = _C(exchange.GetOrders)
: Esta línea de código utiliza la función exchange.GetOrders para recuperar todas las órdenes pendientes en la cuenta corriente y las almacena en la variable órdenes.if (orders.length == 0)
Si la longitud de la matriz de órdenes es 0, significa que no hay órdenes inacabadas y el bucle se interrumpirá (ruptura).for (var i = 0; i < orders.length; i++)
: Este es un bucle for que se repite a través de todos los pedidos incompletos.exchange.CancelOrder(orders[i].Id)
: Esta línea de código utiliza la función exchange.CancelOrder() para cancelar cada orden por su ID.Sleep(Interval)
: Esta línea de código introduce un período de espera, con una pausa de cierto tiempo (en milisegundos), para garantizar que la operación de cancelación de órdenes no sea demasiado frecuente.Esta línea de código introduce un período de espera, con una pausa de cierto tiempo (en milisegundos), para garantizar que la operación de cancelación de órdenes no sea demasiado frecuente.
function updateStatus(msg) {
LogStatus("Number of debugging sessions:", Counter.i, "succeeded:", Counter.w, "failed:", Counter.f, "\n" + msg + "#0000ff\n" + new Date());
}
Esta es una función llamadaupdateStatus(msg)
, que se utiliza para actualizar y registrar información sobre el estado de las transacciones. Acepta un parámetro msg, que generalmente contiene información sobre el estado actual del mercado. Las operaciones específicas de la función incluyen:
Utilizando elLogStatus()
Función para registrar la información que se muestra en la barra de estado durante la ejecución de la estrategia.
Elmsg
Se añade un parámetro que contiene información sobre la situación actual del mercado.
El sello de tiempo actual (new Date()
) se adjunta para mostrar la información sobre el tiempo.
El objetivo de esta función es registrar y actualizar la información sobre el estado de las transacciones para su seguimiento y análisis durante la ejecución de la estrategia.
function main() {
if (DisableLog) {
EnableLog(false);
}
CancelAll();
InitAccount = _C(exchange.GetAccount);
Log(InitAccount);
var i = 0;
var locks = 0;
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
// skip Bids[0]
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount +", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price-(STTick*PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
}
Esta es la función de ejecución principalmain()
En este sentido, el Consejo Europeo de Bruselas ha aprobado una propuesta de directiva sobre la protección de los consumidores en el sector de la alimentación.
if (DisableLog)
: Esta línea de código comprueba si la variable DisableLog es verdadera, y si es así, deshabilitará la grabación de registros.
CancelAll()
: Llame a la función CancelAll( explicada anteriormente para asegurarse de que no haya pedidos pendientes.
InitAccount = _C(exchange.GetAccount)
: Esta línea de código recupera la información de la cuenta corriente y la almacena en la variable InitAccount. Esto se utilizará para registrar el estado de la cuenta cuando la estrategia comience a ejecutarse.
var i = 0;
yvar locks = 0;
: Iniciar dos variables, i y bloqueos, que se utilizarán en la lógica de la estrategia posterior.
while (true)
: Este es un bucle infinito, utilizado principalmente para la ejecución continua de estrategias.
A continuación, explicaremos la lógica estratégica principal dentro delwhile (true)
Loops línea por línea.
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
Sleep(Interval)
El parámetro Interval define el intervalo de sueño (en milisegundos).
var depth = _C(exchange.GetDepth)
: Obtener la información actual sobre la profundidad del mercado, incluidos los precios y las cantidades de órdenes de venta y de compra.
if (depth.Asks.length === 0 || depth.Bids.length === 0)
: Esta línea de código comprueba la información de profundidad del mercado, asegurándose de que existen órdenes de venta y órdenes de compra.
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks)
: Esta línea de código llama a la función updateStatus para actualizar la información de estado de la estrategia. Registra el estado actual del mercado, incluido el precio de oferta más alto, el precio de compra más bajo y los tiempos de bloqueo anteriores (bloques).
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
var askPrice = 0;
: Iniciar la variable askPrice, se utilizará para almacenar el precio de las órdenes de venta que cumplen con las condiciones.
for (i = 0; i < depth.Asks.length; i++)
: Se trata de un bucle for utilizado para recorrer la información de precio y cantidad de las órdenes de venta en el mercado.
if (depth.Asks[i].Amount >= Lot)
: En el bucle, compruebe si la cantidad de cada orden de venta es mayor o igual al lote especificado (cuento manual). Si es así, almacene el precio de esa orden de venta en askPrice y termine el bucle.
if (askPrice === 0)
: Si no se encuentran órdenes de venta que cumplan con las condiciones (el precio de compra sigue siendo 0), la estrategia continuará esperando y saltará operaciones posteriores.
var elephant = null;
: Iniciar la variable elefante, se utilizará para almacenar la información de la orden de compra identificada como
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
Continuar recorriendo la información sobre precios y cantidades de las órdenes de compra del mercado, omitiendo la primera orden de compra (Oferta[0]).
if ((askPrice - depth.Bids[i].Price) > ElephantSpace)
: Compruebe si la diferencia entre el precio de oferta actual y el precio de compra es mayor que el de ElephantSpace.
if (depth.Bids[i].Amount >= ElephantAmount)
: Compruebe si la cantidad de la orden de compra actual es mayor o igual a ElephantAmount. Si es así, almacene la información de la orden de compra en la variable elephant.
if (!elephant)
: Si no se encuentra el
locks++
: Si se encuentra el
if (locks < LockCount)
: Compruebe si el número de tiempos de bloqueo ha cumplido con el requisito (LockCount).
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant))
: Llama a la función updateStatus para registrar el estado actual de la estrategia, incluida la posición del engranaje del
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant)
: Utilice la función exchange.Buy para comprar el encontrado
var ts = new Date().getTime()
: Obtener la marca de tiempo de la hora actual para el cálculo posterior de los intervalos de tiempo.
while (true)
: Introduzca un nuevo bucle infinito, utilizado para esperar a la ejecución de las órdenes de compra
Sleep(CheckInterval)
: La estrategia duerme durante un tiempo para controlar la frecuencia de verificación del estado de la orden.
var orders = _C(exchange.GetOrders)
Obtener toda la información de pedido de la cuenta corriente.
if (orders.length == 0)
Revisa si hay pedidos pendientes, si no, rompe el bucle.
(new Date().getTime() - ts) > WaitInterval
: Calcule el intervalo de tiempo entre la hora actual y cuando se compró el
for (var i = 0; i < orders.length; i++)
Revisa todos los pedidos incompletos.
exchange.CancelOrder(orders[i].Id)
: Utilice la función exchange.CancelOrder para cancelar cada pedido no terminado.
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount + ", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price - (STTick * PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
var account = _C(exchange.GetAccount)
: Obtener información de la cuenta corriente.
var opAmount = _N(account.Stocks - InitAccount.Stocks)
: Calcular el cambio en los activos de la cuenta después de comprar el
updateStatus("Successful payment: " + opAmount + ", Start taking action...")
: Registre la información sobre la compra exitosa de
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount)
: Utilice la función de intercambio.Vender para vender el
Introduzca un nuevo bucle infinito, utilizado para esperar la ejecución de las órdenes de venta.
var depth = _C(exchange.GetDepth)
Obtener información profunda sobre el mercado.
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price - (STTick * PennyTick)))
: Compruebe la información de profundidad del mercado, si el precio de mercado ya ha caído al nivel de stop-loss, y luego ejecute la operación de stop-loss.
CancelAll()
: Llame a la función CancelAll() para cancelar todas las órdenes no completadas, con el fin de evitar el riesgo de posición.
if (opAmount < 0.001)
: Revise la cantidad de compra, si es inferior a 0,001, indica que la compra ha fracasado, salga del bucle.
exchange.Sell(depth.Bids[0].Price, opAmount)
: Ejecutar una operación de stop-loss, vender los activos restantes al precio más bajo del mercado actual.
Por último, actualizar el número de transacciones exitosas y fallidas en función de si la transacción fue exitosa o no, y registrar las ganancias comerciales.
Esta es una explicación línea por línea de toda la estrategia. La idea central de esta estrategia es encontrar
En general, esta estrategia es una estrategia de comercio de alta frecuencia destinada a utilizar información de profundidad del mercado para identificar grandes órdenes de compra y llevar a cabo transacciones de compra y venta en un corto período de tiempo. Necesita un monitoreo constante del mercado y la ejecución de operaciones de compra y venta para obtener rápidamente pequeñas ganancias. Sin embargo, también es una estrategia de alto riesgo, ya que requiere respuestas rápidas a las fluctuaciones del mercado mientras considera la gestión del riesgo y los mecanismos de stop-loss para evitar pérdidas significativas.
Tenga en cuenta que la estrategia se basa en mercados y plataformas comerciales específicos. Para diferentes mercados y intercambios, pueden ser necesarios ajustes y optimizaciones apropiados. En la aplicación práctica, los inversores deben probar y evaluar cuidadosamente el rendimiento de la estrategia para garantizar que se alinee con sus objetivos de inversión y tolerancia al riesgo.
A medida que continúa ejecutando la estrategia, realizará repetidamente las siguientes operaciones:
En primer lugar, la estrategia comprobará la información profunda del mercado para comprender la situación actual de las órdenes de venta y de compra.
A continuación, la estrategia intentará encontrar órdenes de venta que cumplan con los criterios, específicamente órdenes de venta con una cantidad mayor o igual a Lot.
Luego, la estrategia continuará buscando
Si se encuentra un número suficiente de
La estrategia completa lleva a cabo continuamente las operaciones anteriores para capturar a la mayor cantidad posible de "elefantes" y obtener pequeñas ganancias. Esta es una estrategia de negociación de alta frecuencia que requiere respuestas rápidas a los cambios del mercado, al tiempo que considera la gestión de riesgos y los mecanismos de stop-loss para proteger el capital. Los inversores deben considerar cuidadosamente el uso de esta estrategia, especialmente en mercados altamente volátiles.
La estrategia Penny Jump es un ejemplo típico en el comercio de alta frecuencia, que demuestra el juego sutil y la competencia entre los participantes del mercado. Esta estrategia es particularmente prominente en el mercado de criptomonedas debido a sus grandes fluctuaciones, donde los inversores institucionales y los operadores de alta frecuencia buscan ganancias rápidas. Sin embargo, esto también hace que el mercado esté lleno de desafíos, lo que requiere una constante adaptación y ajuste de estrategias para mantener ventajas competitivas.