From 33b14aaa2344b0fd95d1629627c3d135b24ae102 Mon Sep 17 00:00:00 2001 From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:56:35 +0900 Subject: feat: initial trading platform implementation Binance spot crypto trading platform with microservices architecture: - shared: Pydantic models, Redis Streams broker, asyncpg DB layer - data-collector: Binance WebSocket/REST market data collection - strategy-engine: Plugin-based strategy execution (RSI, Grid) - order-executor: Order execution with risk management - portfolio-manager: Position tracking and PnL calculation - backtester: Historical strategy testing with simulator - cli: Click-based CLI for all operations - Docker Compose orchestration with Redis and PostgreSQL - 24 test files covering all modules --- shared/tests/test_broker.py | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 shared/tests/test_broker.py (limited to 'shared/tests/test_broker.py') diff --git a/shared/tests/test_broker.py b/shared/tests/test_broker.py new file mode 100644 index 0000000..d3a3569 --- /dev/null +++ b/shared/tests/test_broker.py @@ -0,0 +1,66 @@ +"""Tests for the Redis broker.""" +import pytest +import json +from unittest.mock import AsyncMock, MagicMock, patch + + +@pytest.mark.asyncio +async def test_broker_publish(): + """Test that publish calls xadd on the redis connection.""" + with patch("redis.asyncio.from_url") as mock_from_url: + mock_redis = AsyncMock() + mock_from_url.return_value = mock_redis + + from shared.broker import RedisBroker + broker = RedisBroker("redis://localhost:6379") + data = {"type": "CANDLE", "symbol": "BTCUSDT"} + await broker.publish("candles", data) + + mock_redis.xadd.assert_called_once() + call_args = mock_redis.xadd.call_args + assert call_args[0][0] == "candles" + payload = call_args[0][1] + assert "payload" in payload + parsed = json.loads(payload["payload"]) + assert parsed["type"] == "CANDLE" + + +@pytest.mark.asyncio +async def test_broker_subscribe_returns_messages(): + """Test that read parses xread response correctly.""" + with patch("redis.asyncio.from_url") as mock_from_url: + mock_redis = AsyncMock() + mock_from_url.return_value = mock_redis + + payload_data = {"type": "CANDLE", "symbol": "ETHUSDT"} + mock_redis.xread.return_value = [ + [ + b"candles", + [ + (b"1234567890-0", {b"payload": json.dumps(payload_data).encode()}), + ], + ] + ] + + from shared.broker import RedisBroker + broker = RedisBroker("redis://localhost:6379") + messages = await broker.read("candles", last_id="$") + + mock_redis.xread.assert_called_once() + assert len(messages) == 1 + assert messages[0]["type"] == "CANDLE" + assert messages[0]["symbol"] == "ETHUSDT" + + +@pytest.mark.asyncio +async def test_broker_close(): + """Test that close calls aclose on the redis connection.""" + with patch("redis.asyncio.from_url") as mock_from_url: + mock_redis = AsyncMock() + mock_from_url.return_value = mock_redis + + from shared.broker import RedisBroker + broker = RedisBroker("redis://localhost:6379") + await broker.close() + + mock_redis.aclose.assert_called_once() -- cgit v1.2.3