- 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
5.0 KiB
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:
hatchlingwithpyproject.toml - Prefer
uvfor 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.asyncioneeded- 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)
- NEVER commit
.envor secrets -.gitignoreenforces this - NEVER log API keys - mask sensitive data
- Use
SecretStrfor credentials in Pydantic settings - Use
Decimalfor all financial values - neverfloat - 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()