trading/tests/shared/schemas/test_kevin.py
Viktor Barzin 9d752aa0a2
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was canceled
feat(kevin): KevinDecision + KevinAccountState schemas
Standalone schemas (no BaseStrategy coupling) used by both the live
signal bridge and the backtest mini-engine.
2026-05-24 00:44:57 +00:00

59 lines
1.6 KiB
Python

"""Tests for KevinDecision + KevinAccountState pydantic schemas."""
from decimal import Decimal
import pytest
from pydantic import ValidationError
from shared.schemas.kevin import (
KevinAccountState,
KevinDecision,
KevinDecisionType,
)
def test_kevin_decision_open_long_requires_target_dollars():
d = KevinDecision(
decision=KevinDecisionType.OPEN_LONG,
symbol="NVDA",
target_dollars=Decimal("2000"),
holding_days=10,
effective_conviction=Decimal("0.75"),
rationale="conv 0.7 + 1 boost",
)
assert d.symbol == "NVDA"
assert d.target_dollars == Decimal("2000")
def test_kevin_decision_close_long_does_not_require_target_dollars():
d = KevinDecision(
decision=KevinDecisionType.CLOSE_LONG,
symbol="NVDA",
rationale="kevin reverse",
)
assert d.target_dollars is None
def test_kevin_decision_open_long_rejects_missing_target_dollars():
with pytest.raises(ValidationError, match="target_dollars"):
KevinDecision(
decision=KevinDecisionType.OPEN_LONG,
symbol="NVDA",
rationale="missing $",
)
def test_kevin_account_state_held_symbols_lookup():
state = KevinAccountState(
equity_usd=Decimal("100000"),
cash_usd=Decimal("80000"),
held_positions={"NVDA": Decimal("5000"), "INTC": Decimal("2000")},
blocklisted_symbols={"WMT"},
daily_trade_count=2,
daily_alloc_usd=Decimal("4000"),
paused=False,
)
assert state.is_held("NVDA")
assert not state.is_held("AAPL")
assert state.is_blocklisted("WMT")
assert not state.is_blocklisted("NVDA")