Files
CryptoTrading/AGENTS.md
bnair123 17d51c4f78 Add test suite and fix configuration for Python 3.12
- Add AGENTS.md with coding guidelines for AI agents
- Add comprehensive unit tests for Binance adapter (mocked)
- Add integration tests for Binance testnet connectivity
- Fix pydantic-settings v2 compatibility for nested settings
- Fix MarginType enum to handle lowercase API responses
- Update Python requirement to 3.12+ (pandas-ta dependency)
- Update ruff config to new lint section format
- Update PLAN.md to reflect completed milestones 1.1-1.3

32 tests passing with 81% coverage
2025-12-27 14:09:14 +04:00

5.0 KiB

AGENTS.md - AI Coding Agent Guidelines for TradeFinder

Automated crypto trading system for BTC/ETH perpetual futures on Binance USDM.

Quick Reference

Task Command
Install pip install -e ".[dev]" or uv pip install -e ".[dev]"
Run all tests pytest
Run single test pytest tests/test_config.py::TestOrderRequest::test_valid_limit_order -v
Run test file pytest tests/test_config.py -v
Lint ruff check .
Lint fix ruff check . --fix
Format ruff format .
Type check mypy src/
Full check ruff check . && ruff format --check . && mypy src/ && pytest

Build & Environment

  • Python: 3.12+ required (3.12, 3.13 supported) - pandas-ta requires 3.12+
  • Build system: hatchling with pyproject.toml
  • Prefer uv for faster installs: uv pip install -e ".[dev]"
# Setup
uv venv .venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"

Testing (pytest + pytest-asyncio)

pytest                                    # All tests with coverage
pytest tests/test_config.py -v            # Single file
pytest tests/test_config.py::TestOrderRequest::test_valid_limit_order -v  # Single test
pytest -k "test_valid" -v                 # By keyword
  • asyncio_mode = "auto" - no @pytest.mark.asyncio needed
  • Test files: tests/test_*.py
  • Type hints required: def test_xxx(self) -> None:

Linting & Type Checking

Ruff (line-length: 100, target: py311):

  • Rules: E, W, F, I, B, C4, UP (pycodestyle, pyflakes, isort, bugbear, comprehensions, pyupgrade)

MyPy: strict = true, uses pydantic.mypy plugin


Code Style Guidelines

Imports (isort-ordered)

from abc import ABC, abstractmethod        # 1. stdlib
from decimal import Decimal

import httpx                               # 2. third-party
import structlog

from tradefinder.adapters.types import Order  # 3. first-party

Type Hints (Required - strict mypy)

async def get_balance(self, asset: str = "USDT") -> AccountBalance: ...

# Use | for unions, built-in generics
def cancel_order(self, order_id: str | None = None) -> Order: ...
list[str]       # Not List[str]
dict[str, Any]  # Not Dict[str, Any]

Numeric Values - Always Decimal

price = Decimal("50000.00")   # String input for precision
# NEVER: price = 50000.00     # Float loses precision

Data Structures

@dataclass
class Position:
    symbol: str
    quantity: Decimal
    raw: dict[str, Any] = field(default_factory=dict)

# Pydantic for config/validation only
class Settings(BaseSettings): ...

Enums

class Side(str, Enum):
    BUY = "BUY"
    SELL = "SELL"

params["side"] = request.side.value  # Use .value for API

Logging (structlog)

logger = structlog.get_logger(__name__)
logger.info("Order created", order_id=order.id, symbol=symbol)
# NEVER log secrets: logger.info(f"API Key: {api_key}")

Async Patterns

async def connect(self) -> None:
    self._client = httpx.AsyncClient(timeout=30.0)

async def disconnect(self) -> None:
    if self._client:
        await self._client.aclose()
        self._client = None

Error Handling

class ExchangeError(Exception): pass
class AuthenticationError(ExchangeError): pass

try:
    await self._request(...)
except httpx.RequestError as e:
    raise ExchangeError(f"Request failed: {e}") from e

Naming Conventions

Type Convention Example
Modules snake_case binance_usdm.py
Classes PascalCase BinanceUSDMAdapter
Functions/Variables snake_case get_open_orders
Constants UPPER_SNAKE MAX_LEVERAGE
Private leading underscore _client, _sign()

Project Structure

src/tradefinder/
    adapters/       # Exchange connectivity (base.py, binance_usdm.py, types.py)
    core/           # Core engine (config.py)
    data/           # Market data (TODO)
    strategies/     # Trading strategies (TODO)
    ui/             # Streamlit dashboard (TODO)
tests/
    test_*.py       # Test files

Security Rules (CRITICAL)

  1. NEVER commit .env or secrets - .gitignore enforces this
  2. NEVER log API keys - mask sensitive data
  3. Use SecretStr for credentials in Pydantic settings
  4. Use Decimal for all financial values - never float
  5. Validate trading mode before any exchange operations

Common Patterns

# Configuration
from tradefinder.core.config import get_settings
settings = get_settings()

# Creating orders
request = OrderRequest(
    symbol="BTCUSDT", side=Side.BUY, position_side=PositionSide.LONG,
    order_type=OrderType.LIMIT, quantity=Decimal("0.001"), price=Decimal("50000"),
)
request.validate()

# Exchange adapter
adapter = BinanceUSDMAdapter(settings)
await adapter.connect()
await adapter.configure_hedge_mode(True)
await adapter.configure_margin_type("BTCUSDT", MarginType.ISOLATED)
await adapter.disconnect()