Presión antes de que el precio se mueva
Un precio rara vez se mueve solo; se mueve porque llegan órdenes y retiran liquidez. Mirar solo las operaciones deja fuera gran parte de la historia, pues casi toda la acción son órdenes colocadas y canceladas en la cima del libro. El desequilibrio del flujo de órdenes (OFI) resume cada actualización del mejor bid y ask en un número con signo: positivo cuando los compradores añaden o los vendedores se retiran, negativo en el caso contrario. En horizontes cortos predice notablemente bien los siguientes cambios de precio.
def book_imbalance(bid_size, ask_size):
total = bid_size + ask_size
if total == 0:
return 0.0
return (bid_size - ask_size) / total
print(book_imbalance(450, 200)) # 0.3846 more size on the bid: upward pressure
print(book_imbalance(100, 400)) # -0.6 sellers dominate
print(book_imbalance(0, 0)) # 0.0 an empty top does not divide by zeroUna actualización, un número
Compara dos cotizaciones sucesivas. En el bid: si el precio del bid sube o se mantiene, se suma su nuevo tamaño; si baja o se mantiene, se resta su tamaño anterior (con precio sin cambios se aplican ambos, así que cuenta la variación de tamaño). En el ask los signos se invierten: un ask menor o igual añade presión vendedora (- nuevo tamaño ask), uno mayor o igual retira la anterior (+ tamaño anterior ask). Los cuatro términos son (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as + (a >= pa) * pas, donde cada comparación vale 1 o 0.
# The order-flow imbalance of one quote update, tried on four changes of the top of the book
def ofi_event(prev, cur):
pb, pbs, pa, pas_ = prev
b, bs, a, as_ = cur
return (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as_ + (a >= pa) * pas_
q0 = (99.5, 300, 100.0, 200)
print(ofi_event(q0, (99.5, 450, 100.0, 200))) # 150 more size on the same bid
print(ofi_event(q0, (99.6, 100, 100.0, 200))) # 100 a higher bid: the whole new size counts
print(ofi_event(q0, (99.4, 300, 100.0, 200))) # -300 the bid price fell: the old size is gone
print(ofi_event(q0, (99.5, 300, 100.1, 200))) # 200 the ask retreated: less selling pressureUna serie y lo que explica
Aplicar la regla a cada par de cotizaciones sucesivas da una serie de OFI. En una ventana corta, como un segundo, suma los eventos y compáralos con el cambio del precio medio: la relación es casi lineal, d_mid = slope * OFI. La pendiente dice cuánto mueve el precio cada unidad de flujo, y se reduce cuando el libro es profundo. Se ajusta como una recta de mínimos cuadrados por el origen: sum(ofi * dmid) / sum(ofi ** 2).
# A series of events from consecutive quotes, set beside the change of the mid price
import numpy as np
def ofi_event(prev, cur):
pb, pbs, pa, pas_ = prev
b, bs, a, as_ = cur
return (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as_ + (a >= pa) * pas_
quotes = [(99.5, 300, 100.0, 200), (99.5, 450, 100.0, 200), (99.6, 100, 100.0, 150), (99.6, 100, 100.1, 400)]
events = np.array([ofi_event(prev, cur) for prev, cur in zip(quotes, quotes[1:])], dtype=float)
print(events) # [150. 150. 150.]
mid = np.array([(q[0] + q[2]) / 2 for q in quotes])
dmid = np.diff(mid)
print(np.round(dmid, 3)) # the mid moved in the direction of the flow# Recover the price impact of the flow with a slope through the origin
import numpy as np
def impact_slope(ofi, dmid):
return float(np.sum(ofi * dmid) / np.sum(ofi ** 2))
rng = np.random.default_rng(1)
flow = rng.normal(0, 200, size=500) # order-flow imbalance per second
price_change = 0.00005 * flow + rng.normal(0, 0.004, size=500) # the mid moves with the flow, plus noise
print(round(impact_slope(flow, price_change), 6)) # 5e-05, the true impact per unit of flow- El desequilibrio del libro
(bid - ask) / (bid + ask)está entre -1 y +1; proteja el caso vacío. - OFI de una actualización:
(b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as + (a >= pa) * pas; una serie lo aplica a cada par consecutivo. - Los cambios del precio medio son casi lineales en el OFI:
slope = sum(ofi * dmid) / sum(ofi**2); es una señal de corto horizonte, útil sobre todo para la ejecución.
A continuación: el código asíncrono con asyncio, manejar muchos flujos de datos sin esperar a cada uno.
Lab: qué se califica
- Comparar los dos lados con
book_imbalance25 pts - Puntuar una actualización con
ofi_event25 pts - Seguir la presión continuamente con
ofi_series25 pts - Poner precio al flujo con
impact_slope25 pts