fix: harden post-stop reentry lockdown
This commit is contained in:
@@ -48,6 +48,74 @@ async def test_create_and_list_open(session):
|
||||
assert row["current_price"] == 110.0 # marked to the latest close
|
||||
|
||||
|
||||
async def test_create_trade_enforces_post_stop_lockdown_at_service_boundary(session):
|
||||
blocked_id = await _seed(session, "LOCKQ", close=100.0)
|
||||
released_id = await _seed(session, "FREEQ", close=100.0)
|
||||
today = date.today()
|
||||
market_sessions = [
|
||||
today - timedelta(days=8),
|
||||
today - timedelta(days=7),
|
||||
today - timedelta(days=6),
|
||||
today - timedelta(days=3),
|
||||
today - timedelta(days=2),
|
||||
today - timedelta(days=1),
|
||||
]
|
||||
for market_date in market_sessions:
|
||||
session.add(BenchmarkPrice(symbol="SPY", date=market_date, close=400.0))
|
||||
|
||||
def stopped_trade(ticker_id: int, closed_on: date) -> PaperTrade:
|
||||
return PaperTrade(
|
||||
user_id=1,
|
||||
ticker_id=ticker_id,
|
||||
direction="long",
|
||||
entry_price=100.0,
|
||||
shares=10.0,
|
||||
stop_loss=95.0,
|
||||
target=115.0,
|
||||
status="closed",
|
||||
opened_at=datetime.combine(
|
||||
closed_on - timedelta(days=1), datetime.min.time(), tzinfo=timezone.utc
|
||||
),
|
||||
close_price=95.0,
|
||||
closed_at=datetime.combine(
|
||||
closed_on, datetime.min.time(), tzinfo=timezone.utc
|
||||
),
|
||||
close_reason="stop",
|
||||
)
|
||||
|
||||
session.add_all(
|
||||
[
|
||||
stopped_trade(blocked_id, market_sessions[1]),
|
||||
stopped_trade(released_id, market_sessions[0]),
|
||||
]
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
with pytest.raises(ValidationError, match="1 market session remaining"):
|
||||
await svc.create_trade(
|
||||
session,
|
||||
1,
|
||||
symbol="LOCKQ",
|
||||
direction="long",
|
||||
entry_price=100.0,
|
||||
shares=10.0,
|
||||
stop_loss=95.0,
|
||||
target=115.0,
|
||||
)
|
||||
|
||||
trade = await svc.create_trade(
|
||||
session,
|
||||
1,
|
||||
symbol="FREEQ",
|
||||
direction="long",
|
||||
entry_price=100.0,
|
||||
shares=10.0,
|
||||
stop_loss=95.0,
|
||||
target=115.0,
|
||||
)
|
||||
assert trade.ticker_id == released_id
|
||||
|
||||
|
||||
async def test_close_uses_current_price(session):
|
||||
await _seed(session, "AAA", close=112.0)
|
||||
trade = await svc.create_trade(session, 1, symbol="AAA", direction="long",
|
||||
|
||||
Reference in New Issue
Block a user