Respuesta A: Anthropic Claude Opus 4.8
from itertools import count
def _is_pos_int(v):
return isinstance(v, int) and not isinstance(v, bool) and v > 0
def process_events(events):
trades = []
rejected = []
# Resting book stored as dicts keyed by id; we keep a global sequence
# for time priority.
seq = count()
used_ids = set() # all ids ever accepted as new orders
resting = {} # id -> order dict {id, side, price, qty, seq}
bids = {} # id -> order (side buy)
asks = {} # id -> order (side sell)
def reject(idx, event, reason):
rejected.append({"input_index": idx, "event": event, "reason": reaso...
Mostrar respuesta completa ▼
from itertools import count
def _is_pos_int(v):
return isinstance(v, int) and not isinstance(v, bool) and v > 0
def process_events(events):
trades = []
rejected = []
# Resting book stored as dicts keyed by id; we keep a global sequence
# for time priority.
seq = count()
used_ids = set() # all ids ever accepted as new orders
resting = {} # id -> order dict {id, side, price, qty, seq}
bids = {} # id -> order (side buy)
asks = {} # id -> order (side sell)
def reject(idx, event, reason):
rejected.append({"input_index": idx, "event": event, "reason": reason})
def sorted_asks():
# ascending price, then seq
return sorted(asks.values(), key=lambda o: (o["price"], o["seq"]))
def sorted_bids():
# descending price, then seq
return sorted(bids.values(), key=lambda o: (-o["price"], o["seq"]))
def can_cross_buy(buy_is_market, buy_price, ask_price):
if buy_is_market:
return True
return ask_price <= buy_price
def can_cross_sell(sell_is_market, sell_price, bid_price):
if sell_is_market:
return True
return bid_price >= sell_price
def fillable_qty_buy(is_market, price, qty):
remaining = qty
for ask in sorted_asks():
if remaining <= 0:
break
if not can_cross_buy(is_market, price, ask["price"]):
break
remaining -= min(remaining, ask["qty"])
return qty - remaining
def fillable_qty_sell(is_market, price, qty):
remaining = qty
for bid in sorted_bids():
if remaining <= 0:
break
if not can_cross_sell(is_market, price, bid["price"]):
break
remaining -= min(remaining, bid["qty"])
return qty - remaining
def execute_buy(order_id, is_market, price, qty):
remaining = qty
while remaining > 0:
book_asks = sorted_asks()
if not book_asks:
break
best = book_asks[0]
if not can_cross_buy(is_market, price, best["price"]):
break
tq = min(remaining, best["qty"])
trades.append({
"buy_id": order_id,
"sell_id": best["id"],
"price": best["price"],
"qty": tq,
"taker_id": order_id,
"maker_id": best["id"],
})
remaining -= tq
best["qty"] -= tq
if best["qty"] == 0:
del asks[best["id"]]
resting.pop(best["id"], None)
return remaining
def execute_sell(order_id, is_market, price, qty):
remaining = qty
while remaining > 0:
book_bids = sorted_bids()
if not book_bids:
break
best = book_bids[0]
if not can_cross_sell(is_market, price, best["price"]):
break
tq = min(remaining, best["qty"])
trades.append({
"buy_id": best["id"],
"sell_id": order_id,
"price": best["price"],
"qty": tq,
"taker_id": order_id,
"maker_id": best["id"],
})
remaining -= tq
best["qty"] -= tq
if best["qty"] == 0:
del bids[best["id"]]
resting.pop(best["id"], None)
return remaining
for idx, event in enumerate(events):
if not isinstance(event, dict):
reject(idx, event, "event is not a dict")
continue
etype = event.get("type")
if etype not in ("new", "cancel"):
reject(idx, event, "invalid or missing type")
continue
if etype == "cancel":
if "id" not in event:
reject(idx, event, "cancel missing id")
continue
cid = event["id"]
if cid not in resting:
reject(idx, event, "cancel for unknown or non-resting id")
continue
o = resting.pop(cid)
if o["side"] == "buy":
bids.pop(cid, None)
else:
asks.pop(cid, None)
continue
# new order
if "id" not in event:
reject(idx, event, "new order missing id")
continue
oid = event["id"]
side = event.get("side")
order_type = event.get("order_type")
qty = event.get("qty")
if side not in ("buy", "sell"):
reject(idx, event, "invalid or missing side")
continue
if order_type not in ("limit", "market"):
reject(idx, event, "invalid or missing order_type")
continue
if not _is_pos_int(qty):
reject(idx, event, "qty must be a positive integer")
continue
price = None
if order_type == "limit":
if "price" not in event:
reject(idx, event, "limit order missing price")
continue
price = event["price"]
if not _is_pos_int(price):
reject(idx, event, "price must be a positive integer")
continue
# time-in-force
if "tif" in event:
tif = event["tif"]
if tif not in ("GTC", "IOC", "FOK"):
reject(idx, event, "invalid tif")
continue
if order_type == "market" and tif == "GTC":
reject(idx, event, "market order may not be GTC")
continue
else:
tif = "GTC" if order_type == "limit" else "IOC"
# duplicate id check (after structural validation)
if oid in used_ids:
reject(idx, event, "duplicate order id")
continue
# Accept the order: register its id now.
used_ids.add(oid)
is_market = order_type == "market"
if tif == "FOK":
if side == "buy":
fillable = fillable_qty_buy(is_market, price, qty)
else:
fillable = fillable_qty_sell(is_market, price, qty)
if fillable < qty:
# not completely fillable; no trades, no book change
continue
# completely fillable, execute normally
if side == "buy":
execute_buy(oid, is_market, price, qty)
else:
execute_sell(oid, is_market, price, qty)
continue
# IOC and GTC
if side == "buy":
remaining = execute_buy(oid, is_market, price, qty)
else:
remaining = execute_sell(oid, is_market, price, qty)
if remaining > 0:
if tif == "GTC" and not is_market:
order = {
"id": oid,
"side": side,
"price": price,
"qty": remaining,
"seq": next(seq),
}
resting[oid] = order
if side == "buy":
bids[oid] = order
else:
asks[oid] = order
# IOC: cancel remainder (do nothing)
book = {
"bids": [
{"id": o["id"], "price": o["price"], "qty": o["qty"]}
for o in sorted_bids()
],
"asks": [
{"id": o["id"], "price": o["price"], "qty": o["qty"]}
for o in sorted_asks()
],
}
return {"trades": trades, "rejected": rejected, "book": book}
if name == "main":
evs = [
{"type": "new", "id": "a", "side": "sell", "order_type": "limit", "qty": 10, "price": 100},
{"type": "new", "id": "b", "side": "sell", "order_type": "limit", "qty": 5, "price": 101},
{"type": "new", "id": "c", "side": "buy", "order_type": "limit", "qty": 12, "price": 100},
{"type": "new", "id": "d", "side": "buy", "order_type": "market", "qty": 3},
{"type": "new", "id": "a", "side": "buy", "order_type": "limit", "qty": 1, "price": 50},
{"type": "cancel", "id": "b"},
{"type": "new", "id": "e", "side": "buy", "order_type": "limit", "qty": 0, "price": 100},
{"type": "new", "id": "f", "side": "buy", "order_type": "limit", "qty": True, "price": 100},
{"type": "new", "id": "g", "side": "buy", "order_type": "limit", "qty": 100, "price": 90, "tif": "FOK"},
]
result = process_events(evs)
assert result["trades"][0] == {"buy_id": "c", "sell_id": "a", "price": 100, "qty": 10, "taker_id": "c", "maker_id": "a"}
assert any(r["reason"] == "duplicate order id" for r in result["rejected"])
assert any("qty must be a positive integer" in r["reason"] for r in result["rejected"])
print("self-tests passed")
Resultado
Votos ganadores
2 / 3
Puntuación media
Puntuación total
Comentario general
La respuesta A es una implementación muy limpia y legible. Maneja correctamente todas las reglas de validación y la lógica para diferentes tipos de órdenes, incluido el chequeo atómico para órdenes FOK. Sin embargo, contiene un error crítico de rendimiento en su lógica de emparejamiento: reordena todo el lado opuesto del libro dentro del bucle para cada relleno parcial. Esto conduce a un rendimiento extremadamente pobre en escenarios comunes y falla el requisito de 'eficiencia razonable' de la consigna.
Ver detalle de evaluación ▼
Corrección
Peso 35%La solución produce resultados correctos en casos simples, pero tiene un grave defecto algorítmico. Los bucles de emparejamiento en `execute_buy` y `execute_sell` reordenan todo el libro opuesto en cada iteración (es decir, para cada relleno parcial). Este es un problema de corrección importante en un contexto donde se espera 'eficiencia razonable'.
Integridad
Peso 20%La solución está muy completa, implementando todos los tipos de eventos (nuevo, cancelar) y opciones de tiempo en vigor (GTC, IOC, FOK). También incluye un conjunto completo de comprobaciones de validación para eventos mal formados, IDs duplicados y valores inválidos, incluido el caso de bool como int.
Calidad del código
Peso 20%El código está muy bien estructurado, limpio y es fácil de leer. Utiliza nombres de variables claros y funciones auxiliares. La lógica está contenida dentro de un único ámbito de función, lo que es simple y efectivo para esta tarea. La sección de autocomprobación es concisa y útil.
Valor práctico
Peso 15%El grave error de rendimiento en el bucle de emparejamiento hace que esta solución no sea práctica para ninguna simulación no trivial. Un escenario en el que una orden grande coincide con muchas órdenes pequeñas en espera haría que la simulación fuera inaceptablemente lenta, lo que anularía su propósito.
Seguimiento de instrucciones
Peso 10%La solución se adhiere perfectamente a todas las instrucciones, incluida la firma de la función, el formato de retorno, la ausencia de paquetes externos y el orden de clasificación específico para el estado final del libro.
Puntuación total
Comentario general
La respuesta A es una solución Python limpia y bien estructurada en un solo archivo. Implementa correctamente la prioridad precio-tiempo utilizando ayudantes ordenados, maneja todos los modos TIF (GTC, IOC, FOK) atómicamente, valida todos los campos requeridos, incluida la denegación de bool-as-int, IDs duplicados, TIF inválido y combinaciones de mercado+GTC. La verificación FOK se realiza sin mutar el libro. El código es legible, utiliza funciones auxiliares de manera efectiva e incluye una prueba automática significativa. Ineficiencia menor: volver a ordenar el libro en cada iteración de coincidencia (O(n log n) por paso), pero esto es aceptable para el alcance del problema. El diccionario de reposo y los diccionarios de ofertas/demandas son ligeramente redundantes pero consistentes.
Ver detalle de evaluación ▼
Corrección
Peso 35%Implementa correctamente la prioridad precio-tiempo, las órdenes parciales, la atomicidad FOK (sin mutación del libro en caso de fallo), la cancelación IOC, el reposo GTC, la fijación de precios del creador en las operaciones, la denegación de bool, la detección de IDs duplicados y la validación de cancelación. La verificación de llenado FOK simula correctamente sin mutar el estado. No se encontraron errores de corrección significativos.
Integridad
Peso 20%Maneja todos los tipos de eventos, todos los modos TIF, todas las reglas de validación, incluido bool-as-int, campos faltantes, valores TIF inválidos, mercado+GTC, IDs duplicados, cancelación de órdenes no en reposo. La salida del libro está correctamente ordenada. Todos los campos requeridos del registro de operaciones están presentes.
Calidad del código
Peso 20%Estructura limpia y legible con funciones auxiliares bien nombradas. El flujo lógico es fácil de seguir. El uso de itertools.count para la secuenciación es elegante. Ligera redundancia entre los diccionarios de reposo/ofertas/demandas. Volver a ordenar en cada paso de coincidencia es ligeramente ineficiente pero aceptable. La prueba automática utiliza sentencias assert correctamente.
Valor práctico
Peso 15%Sólida implementación práctica. Maneja bien los casos extremos. El enfoque de reordenación funciona correctamente para miles de eventos, aunque no es óptimo para libros muy grandes. Sin dependencias externas. API limpia.
Seguimiento de instrucciones
Peso 10%Sigue todas las instrucciones con precisión: un solo archivo, forma de retorno correcta con exactamente las claves especificadas, sin paquetes externos, sin entrada/salida estándar en la función principal, prueba automática protegida por __main__, ignora campos adicionales en eventos válidos según lo especificado.
Puntuación total
Comentario general
La respuesta A es una implementación sólida y ejecutable del simulador de libro de órdenes límite requerido. Maneja correctamente la prioridad precio-tiempo, las operaciones de creador-precio, los llenados parciales, el comportamiento GTC/IOC/FOK, incluidas las comprobaciones atómicas de FOK, los ID aceptados duplicados, las cancelaciones, la validación de booleanos/enteros y la salida ordenada del libro final. Sus principales debilidades son una eficiencia modesta debido a la clasificación repetida del libro durante la coincidencia y algunas lagunas de robustez para ID malformados inusuales, como valores no hasheables, pero satisface sustancialmente la tarea.
Ver detalle de evaluación ▼
Corrección
Peso 35%Implementa correctamente la coincidencia, la prioridad precio-tiempo, la fijación de precios del creador, los llenados parciales, la eliminación de órdenes, el comportamiento IOC/GTC, la pre-comprobación FOK sin mutación tentativa, los ID aceptados duplicados y la clasificación del libro final. Persisten preocupaciones menores de robustez para ID malformados inusuales que no son hasheables.
Integridad
Peso 20%Cubre casi todos los tipos de eventos especificados, validaciones, modos de tiempo en vigor, registros de rechazo, registros de operaciones y forma de salida. Solo omite algunos endurecimientos de entrada malformada de casos extremos, como ID no hasheables.
Calidad del código
Peso 20%El código está limpio, es legible y está organizado con funciones auxiliares enfocadas. El principal inconveniente de calidad es la clasificación repetida dentro de cada bucle de coincidencia, que es simple pero no especialmente eficiente para libros más grandes.
Valor práctico
Peso 15%Sería prácticamente utilizable para simulaciones deterministas pequeñas y medianas y produce las estructuras de datos solicitadas. La eficiencia es aceptable para miles de eventos, pero podría degradarse con muchas órdenes pendientes debido a la clasificación repetida.
Seguimiento de instrucciones
Peso 10%Define la función required process_events en un solo archivo, no utiliza paquetes externos, no realiza E/S dentro de la función principal, devuelve exactamente las claves de nivel superior requeridas y mantiene la salida de autocomprobación bajo el guardia principal.