trading/tests/shared/broker/test_alpaca_bracket.py

90 lines
2.7 KiB
Python
Raw Normal View History

"""Unit tests for BRACKET order support in OrderRequest + AlpacaBroker.
No network exercises the request-building path only.
"""
from __future__ import annotations
import pytest
from alpaca.trading.enums import OrderClass as AlpacaOrderClass
from alpaca.trading.requests import MarketOrderRequest
from pydantic import ValidationError
from shared.broker.alpaca_broker import AlpacaBroker
from shared.schemas.trading import OrderRequest, OrderSide, OrderType
def _broker() -> AlpacaBroker:
return AlpacaBroker(api_key="test", secret_key="test", paper=True)
def test_order_request_defaults_to_simple_class():
o = OrderRequest(ticker="NVDA", side=OrderSide.BUY, qty=10)
assert o.order_class == "simple"
assert o.take_profit_price is None
assert o.stop_loss_price is None
def test_order_request_bracket_requires_both_legs():
with pytest.raises(ValidationError, match="bracket orders require"):
OrderRequest(
ticker="NVDA",
side=OrderSide.BUY,
qty=10,
order_class="bracket",
take_profit_price=200.0,
# stop_loss_price missing
)
with pytest.raises(ValidationError, match="bracket orders require"):
OrderRequest(
ticker="NVDA",
side=OrderSide.BUY,
qty=10,
order_class="bracket",
stop_loss_price=150.0,
# take_profit_price missing
)
def test_order_request_bracket_with_both_legs_validates():
o = OrderRequest(
ticker="NVDA",
side=OrderSide.BUY,
qty=10,
order_class="bracket",
take_profit_price=200.0,
stop_loss_price=150.0,
)
assert o.order_class == "bracket"
assert o.take_profit_price == 200.0
assert o.stop_loss_price == 150.0
def test_build_order_request_simple_market():
o = OrderRequest(ticker="NVDA", side=OrderSide.BUY, qty=10)
req = _broker()._build_order_request(o)
assert isinstance(req, MarketOrderRequest)
assert req.symbol == "NVDA"
assert req.qty == 10
# default MarketOrderRequest has order_class=None or SIMPLE
assert getattr(req, "order_class", None) in (None, AlpacaOrderClass.SIMPLE)
def test_build_order_request_bracket_attaches_legs():
o = OrderRequest(
ticker="NVDA",
side=OrderSide.BUY,
qty=10,
order_class="bracket",
take_profit_price=200.0,
stop_loss_price=150.0,
)
req = _broker()._build_order_request(o)
assert isinstance(req, MarketOrderRequest)
assert req.order_class == AlpacaOrderClass.BRACKET
assert req.take_profit is not None
assert float(req.take_profit.limit_price) == 200.0
assert req.stop_loss is not None
assert float(req.stop_loss.stop_price) == 150.0