Exclude open paper trades from discovery
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 1m25s
Deploy / deploy (push) Successful in 43s

This commit is contained in:
2026-07-04 13:01:58 +02:00
parent edc1a9757b
commit 23d1db1f30
4 changed files with 113 additions and 1 deletions
@@ -21,12 +21,14 @@ from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.ohlcv import OHLCVRecord
from app.models.paper_trade import PaperTrade
from app.models.signal_context_snapshot import SignalContextSnapshot
from app.models.sr_level import SRLevel
from app.models.ticker import Ticker
from app.models.trade_setup import TradeSetup
from app.models.score import CompositeScore, DimensionScore
from app.models.sentiment import SentimentScore
from app.models.user import User
from app.services.rr_scanner_service import scan_ticker, get_trade_setups
@@ -442,6 +444,100 @@ async def test_get_trade_setups_sorting_rr_desc_composite_desc(db_session: Async
)
@pytest.mark.asyncio
async def test_get_trade_setups_can_exclude_tickers_with_open_paper_trades(
db_session: AsyncSession,
):
now = datetime.now(timezone.utc)
if await db_session.get(User, 1) is None:
db_session.add(
User(id=1, username="u", password_hash="x", role="user", has_access=True)
)
await db_session.flush()
open_ticker = Ticker(symbol="OPENQ")
closed_ticker = Ticker(symbol="CLOSEDQ")
free_ticker = Ticker(symbol="FREEQ")
db_session.add_all([open_ticker, closed_ticker, free_ticker])
await db_session.flush()
db_session.add_all([
TradeSetup(
ticker_id=open_ticker.id,
direction="long",
entry_price=100.0,
stop_loss=95.0,
target=112.0,
rr_ratio=2.4,
composite_score=80.0,
detected_at=now,
),
TradeSetup(
ticker_id=closed_ticker.id,
direction="long",
entry_price=100.0,
stop_loss=95.0,
target=113.0,
rr_ratio=2.6,
composite_score=70.0,
detected_at=now,
),
TradeSetup(
ticker_id=free_ticker.id,
direction="long",
entry_price=100.0,
stop_loss=95.0,
target=114.0,
rr_ratio=2.8,
composite_score=60.0,
detected_at=now,
),
PaperTrade(
user_id=1,
ticker_id=open_ticker.id,
direction="long",
entry_price=100.0,
shares=10.0,
stop_loss=95.0,
target=112.0,
status="open",
opened_at=now,
),
PaperTrade(
user_id=1,
ticker_id=closed_ticker.id,
direction="long",
entry_price=100.0,
shares=10.0,
stop_loss=95.0,
target=113.0,
status="closed",
opened_at=now - timedelta(days=2),
close_price=113.0,
closed_at=now - timedelta(days=1),
close_reason="target",
),
])
await db_session.flush()
default_rows = await get_trade_setups(db_session)
assert {"OPENQ", "CLOSEDQ", "FREEQ"}.issubset(
{row["symbol"] for row in default_rows}
)
discovery_rows = await get_trade_setups(
db_session,
exclude_open_trade_tickers=True,
)
discovery_symbols = {row["symbol"] for row in discovery_rows}
assert "OPENQ" not in discovery_symbols
assert {"CLOSEDQ", "FREEQ"}.issubset(discovery_symbols)
ticker_rows = await get_trade_setups(db_session, symbol="OPENQ")
assert [row["symbol"] for row in ticker_rows] == ["OPENQ"]
async def _seed_stale_setup_with_current_scores(db_session: AsyncSession) -> TradeSetup:
"""Stored setup frozen at scan time (conf 82, neutral) vs. current context
(bullish sentiment, composite 96) that yields live confidence 97."""