Files
CryptoTrading/AGENTS.md
bnair123 e17c3bf508 Add Supertrend strategy and Risk Engine (Phase 2 Milestones 2.2, 2.3)
- Implement SupertrendStrategy with pandas-ta indicator, ATR-based stops
- Add RiskEngine with position sizing, risk limits, portfolio heat tracking
- Add comprehensive tests for both modules (32 new tests)
- Update AGENTS.md with accurate project structure and py312 target
2025-12-27 18:24:20 +04:00

4.6 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 uv pip install -e ".[dev]" (or pip install -e ".[dev]")
All tests pytest
Single test pytest tests/test_config.py::TestOrderRequest::test_valid_limit_order -v
Test file pytest tests/test_config.py -v
Test by keyword pytest -k "test_valid" -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 (pandas-ta requires 3.12+)
  • Build: hatchling via pyproject.toml
  • Prefer uv: 10-100x faster than pip
uv venv .venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"

Testing

  • asyncio_mode = "auto" - no @pytest.mark.asyncio needed
  • Type hints required: def test_xxx(self) -> None:
  • Integration tests marked with @pytest.mark.integration (require testnet API keys)

Linting & Type Checking

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

  • Rules: E, W, F, I, B, C4, UP

MyPy: strict = true, uses pydantic.mypy plugin

Code Style

Imports (isort-ordered)

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

import httpx                               # 2. third-party

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

Type Hints (Required - strict mypy)

async def get_balance(self, asset: str = "USDT") -> AccountBalance: ...
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)

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

Enums

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

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

Logging (structlog)

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

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()

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, binance_spot.py, types.py)
    core/           # Core engine (config.py, regime.py)
    data/           # Market data (fetcher.py, storage.py, streamer.py, validator.py, schemas.py)
    strategies/     # Trading strategies (base.py, signals.py)
    ui/             # Streamlit dashboard
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()