from datetime import date, timedelta from decimal import Decimal import pytest from grid_trading.domain.models import Instrument, Trade, TradeGroup, TradeSide from grid_trading.services.trading_service import TradingService def test_service_creates_default_account_and_computes_summary(tmp_path): service = TradingService(tmp_path / "grid.db") service.ensure_defaults() account = service.get_active_account() assert account.name == "默认账户" account = service.save_account(account.__class__(id=account.id, name="主账户", initial_cash=Decimal("100000"))) instrument = service.add_instrument( Instrument(id=None, code="510300", name="沪深300ETF", market="ETF", manual_price=Decimal("4.00")) ) service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 7), side=TradeSide.BUY, price=Decimal("3.90"), quantity=1000, commission=Decimal("5"), trade_group=TradeGroup.GRID, ) ) service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 8), side=TradeSide.SELL, price=Decimal("4.10"), quantity=500, commission=Decimal("5"), stamp_tax=Decimal("1.03"), trade_group=TradeGroup.GRID, ) ) positions = service.get_position_summaries(as_of=date(2026, 7, 8)) summary = service.get_account_summary(as_of=date(2026, 7, 8)) assert len(positions) == 1 assert positions[0].total_quantity == 500 assert positions[0].grid_profit == Decimal("91.47") assert summary.cash == Decimal("98138.97") assert summary.market_value == Decimal("2000.00") assert summary.total_assets == Decimal("100138.97") def test_service_validates_lot_size_and_available_sell_quantity(tmp_path): service = TradingService(tmp_path / "grid.db") service.ensure_defaults() account = service.get_active_account() instrument = service.add_instrument(Instrument(id=None, code="600000", name="浦发银行")) with pytest.raises(ValueError, match="100"): service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 8), side=TradeSide.BUY, price=Decimal("10"), quantity=50, trade_group=TradeGroup.BASE, ) ) service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 8), side=TradeSide.BUY, price=Decimal("10"), quantity=100, trade_group=TradeGroup.BASE, ) ) with pytest.raises(ValueError, match="T\\+1"): service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 8), side=TradeSide.SELL, price=Decimal("10.1"), quantity=100, trade_group=TradeGroup.BASE, ) ) service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 8) - timedelta(days=1), side=TradeSide.BUY, price=Decimal("9.9"), quantity=100, trade_group=TradeGroup.BASE, ) ) saved_sell = service.save_trade( Trade( id=None, account_id=account.id, instrument_id=instrument.id, trade_date=date(2026, 7, 8), side=TradeSide.SELL, price=Decimal("10.1"), quantity=100, trade_group=TradeGroup.BASE, ) ) assert saved_sell.id is not None