Files
momentum-system/tests/test_pick_journal.py
T
momentum devandClaude Fable 5 40e51c8dd5 feat: morning pick journal — prospective human/LLM forecast experiment
Tests whether a PROSPECTIVE forecaster (owner or local LLM) carries signal
the machine levers never found. Picks land premarket via dashboard panel or
research/llm_picker.py (Ollama); research/pick_scoring.py judges them under
a pre-registered bar (n>=40, >=30 sessions, mean >=+0.5%/pick net, median>0,
both halves positive). Picks after 9:30 ET stored but flagged invalid.
Shadow-only: human_picks is never read by the live loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 10:52:39 -05:00

56 lines
1.9 KiB
Python

"""Pick journal + scorer: the smallest checks that fail if the logic breaks."""
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
import pytest
from research.pick_journal import add_pick, ensure_schema, list_picks
from research.pick_scoring import score_pick
from storage.db_pg import get_connection
ET_ = ZoneInfo("America/New_York")
@pytest.fixture()
def con():
c = get_connection(":memory:")
yield c
c.close()
def test_pick_validity_locks_at_open(con):
early = datetime(2026, 8, 20, 9, 29, tzinfo=ET_)
late = datetime(2026, 8, 20, 9, 31, tzinfo=ET_)
assert add_pick(con, "aapl", now=early)["valid"] is True
assert add_pick(con, "TSLA", now=late)["valid"] is False
picks = list_picks(con, early.date())
assert [p["symbol"] for p in picks] == ["AAPL", "TSLA"]
assert [p["valid"] for p in picks] == [True, False]
def test_pick_rejects_garbage(con):
with pytest.raises(ValueError):
add_pick(con, "")
with pytest.raises(ValueError):
add_pick(con, "TOOLONGG")
with pytest.raises(ValueError):
add_pick(con, "AAPL", direction="sideways")
def test_score_pick_long_and_short(con):
ensure_schema(con)
d = datetime(2026, 8, 20).date()
base = datetime(2026, 8, 20, 9, 30)
for i, (o, c) in enumerate([(10.0, 10.2), (10.2, 10.5), (10.5, 11.0)]):
con.execute(
"INSERT INTO minute_bars (symbol, timestamp, session_date, is_premarket, "
"is_regular_hours, is_afterhours, open, high, low, close, volume) "
"VALUES (?, ?, ?, false, true, false, ?, ?, ?, ?, 1000)",
["TEST", base + timedelta(minutes=i), d, o, max(o, c), min(o, c), c])
s = score_pick(con, "TEST", d, "long")
# entry 10.0 open, exit 11.0 close: raw +10%, minus 2% cost (>=$3)
assert abs(s["net"] - 0.08) < 1e-9
s2 = score_pick(con, "TEST", d, "short")
assert abs(s2["net"] - (-0.12)) < 1e-9
assert score_pick(con, "NOPE", d, "long") is None