feat: use realtime quotes in summaries

This commit is contained in:
王鹏
2026-07-08 22:02:56 +08:00
parent 653ac46e9d
commit f8cd9a92ab
4 changed files with 112 additions and 4 deletions

View File

@@ -4,7 +4,7 @@ from decimal import Decimal
import pytest
from grid_trading.domain.calculations import CalculationError, calculate_positions, estimate_fees
from grid_trading.domain.models import FeeRules, Instrument, Trade, TradeGroup, TradeSide
from grid_trading.domain.models import FeeRules, Instrument, QuoteSnapshot, Trade, TradeGroup, TradeSide
def make_trade(
@@ -111,6 +111,36 @@ def test_t_plus_one_available_quantity_excludes_today_buys():
assert summary.available_quantity == 200
def test_quote_snapshot_overrides_manual_price_for_position_value():
today = date(2026, 7, 8)
instrument = Instrument(id=1, code="510300", name="沪深300ETF", manual_price=Decimal("3.90"))
trades = [
make_trade(
trade_id=1,
trade_date=today - timedelta(days=1),
side=TradeSide.BUY,
price="4.00",
quantity=1000,
trade_group=TradeGroup.BASE,
)
]
quotes = {
1: QuoteSnapshot(
symbol="sh510300",
code="510300",
name="沪深300ETF",
price=Decimal("4.12"),
source="tencent",
)
}
[summary] = calculate_positions([instrument], trades, as_of=today, quote_snapshots=quotes)
assert summary.current_price == Decimal("4.12")
assert summary.price_source == "tencent"
assert summary.market_value == Decimal("4120.00")
def test_sell_more_than_group_position_raises():
today = date(2026, 7, 8)
instrument = Instrument(id=1, code="159915", name="创业板ETF")

View File

@@ -3,10 +3,24 @@ from decimal import Decimal
import pytest
from grid_trading.domain.models import Instrument, Trade, TradeGroup, TradeSide
from grid_trading.domain.models import Instrument, QuoteSnapshot, Trade, TradeGroup, TradeSide
from grid_trading.services.trading_service import TradingService
class FakeQuoteProvider:
def fetch_quotes(self, instruments):
return {
"510300": QuoteSnapshot(
symbol="sh510300",
code="510300",
name="沪深300ETF",
price=Decimal("4.12"),
source="tencent",
quote_time="20260708150000",
)
}
def test_service_creates_default_account_and_computes_summary(tmp_path):
service = TradingService(tmp_path / "grid.db")
service.ensure_defaults()
@@ -177,3 +191,33 @@ def test_service_rejects_historical_changes_that_break_future_sells(tmp_path):
with pytest.raises(ValueError, match="后续成交"):
service.delete_trade(buy.id)
def test_service_refresh_quotes_uses_realtime_price_in_summaries(tmp_path):
service = TradingService(tmp_path / "grid.db", quote_provider=FakeQuoteProvider())
service.ensure_defaults()
account = service.get_active_account()
instrument = service.add_instrument(
Instrument(id=None, code="510300", name="沪深300ETF", market="ETF", manual_price=Decimal("3.90"))
)
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("4.00"),
quantity=1000,
trade_group=TradeGroup.BASE,
)
)
quotes = service.refresh_quotes()
[position] = service.get_position_summaries(as_of=date(2026, 7, 8))
summary = service.get_account_summary(as_of=date(2026, 7, 8))
assert quotes["510300"].price == Decimal("4.12")
assert position.current_price == Decimal("4.12")
assert position.price_source == "tencent"
assert summary.market_value == Decimal("4120.00")