feat: Implement idempotency and recovery mechanisms for order execution

- Add IdempotencyKeyFactory for generating unique user references based on execution legs.
- Introduce OrderReconciler to reconcile order statuses with historical data.
- Implement PartialFillRecovery to handle partial fills by canceling orders and placing hedges.
- Create TriangularExecutionSequencer for executing triangular arbitrage strategies.
- Enhance storage with new tables for trades, orders, and PnL events.
- Develop AsyncExecutionWriter for asynchronous writing of execution records to the database.
- Add unit tests for execution persistence, sequencer behavior, fill monitoring, and idempotency checks.
- Update KrakenRestClient to ensure proper payloads for order placement and querying.
This commit is contained in:
2026-06-01 11:59:13 +02:00
parent 240a591a64
commit 93f4f62d42
17 changed files with 1602 additions and 4 deletions
+136
View File
@@ -110,3 +110,139 @@ def test_compliance_detects_insecure_config() -> None:
assert any("below 1.0" in issue for issue in issues)
assert any("ATTEMPTS" in issue for issue in issues)
assert any("BASE_DELAY" in issue for issue in issues)
@pytest.mark.asyncio
async def test_place_market_order_posts_add_order_payload() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY="key",
KRAKEN_API_SECRET="c2VjcmV0", # base64("secret")
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
route = mock_router.post("/0/private/AddOrder").respond(
200,
json={"error": [], "result": {"txid": ["m1"]}},
)
payload = await client.place_market_order(
pair="XBTUSD",
side="buy",
volume=0.05,
)
await client.close()
request_body = route.calls.last.request.content.decode()
assert "pair=XBTUSD" in request_body
assert "type=buy" in request_body
assert "ordertype=market" in request_body
assert "volume=0.05" in request_body
assert payload["txid"] == ["m1"]
@pytest.mark.asyncio
async def test_place_limit_order_posts_add_order_payload() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY="key",
KRAKEN_API_SECRET="c2VjcmV0", # base64("secret")
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
route = mock_router.post("/0/private/AddOrder").respond(
200,
json={"error": [], "result": {"txid": ["l1"]}},
)
payload = await client.place_limit_order(
pair="ETHUSD",
side="sell",
volume=1.5,
price=3500.0,
)
await client.close()
request_body = route.calls.last.request.content.decode()
assert "pair=ETHUSD" in request_body
assert "type=sell" in request_body
assert "ordertype=limit" in request_body
assert "price=3500.0" in request_body
assert "volume=1.5" in request_body
assert payload["txid"] == ["l1"]
@pytest.mark.asyncio
async def test_place_order_validates_inputs() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY="key",
KRAKEN_API_SECRET="c2VjcmV0", # base64("secret")
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with pytest.raises(ValueError, match="side"):
await client.place_market_order(pair="XBTUSD", side="hold", volume=0.1)
with pytest.raises(ValueError, match="volume"):
await client.place_market_order(pair="XBTUSD", side="buy", volume=0.0)
with pytest.raises(ValueError, match="price"):
await client.place_limit_order(
pair="XBTUSD",
side="buy",
volume=0.1,
price=0.0,
)
await client.close()
@pytest.mark.asyncio
async def test_query_order_posts_query_orders_payload() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY="key",
KRAKEN_API_SECRET="c2VjcmV0", # base64("secret")
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
route = mock_router.post("/0/private/QueryOrders").respond(
200,
json={"error": [], "result": {"order-1": {"status": "closed"}}},
)
payload = await client.query_order(order_id="order-1", include_trades=False)
await client.close()
request_body = route.calls.last.request.content.decode()
assert "txid=order-1" in request_body
assert "trades=false" in request_body
assert payload["order-1"]["status"] == "closed"
@pytest.mark.asyncio
async def test_cancel_order_posts_cancel_order_payload() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY="key",
KRAKEN_API_SECRET="c2VjcmV0", # base64("secret")
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
route = mock_router.post("/0/private/CancelOrder").respond(
200,
json={"error": [], "result": {"count": 1}},
)
payload = await client.cancel_order(order_id="order-1")
await client.close()
request_body = route.calls.last.request.content.decode()
assert "txid=order-1" in request_body
assert payload["count"] == 1