feat(kevin): KevinDecision + KevinAccountState schemas
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was canceled
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was canceled
Standalone schemas (no BaseStrategy coupling) used by both the live signal bridge and the backtest mini-engine.
This commit is contained in:
parent
c83f13625b
commit
9d752aa0a2
4 changed files with 125 additions and 0 deletions
0
tests/shared/__init__.py
Normal file
0
tests/shared/__init__.py
Normal file
0
tests/shared/schemas/__init__.py
Normal file
0
tests/shared/schemas/__init__.py
Normal file
59
tests/shared/schemas/test_kevin.py
Normal file
59
tests/shared/schemas/test_kevin.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
"""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")
|
||||
Loading…
Add table
Add a link
Reference in a new issue