Skip to content

Commit

Permalink
fix: Fix limit order request validation for oco (#489)
Browse files Browse the repository at this point in the history
* fix: add unit test of limit order request validation for oco

* fix: set limit_price optional for oco order

* fix: remove unused import
  • Loading branch information
hiohiohio authored Jul 23, 2024
1 parent 8be5201 commit 4123932
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
12 changes: 10 additions & 2 deletions alpaca/trading/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,17 +359,25 @@ class LimitOrderRequest(OrderRequest):
order_class (Optional[OrderClass]): The class of the order. Simple orders have no other legs.
take_profit (Optional[TakeProfitRequest]): For orders with multiple legs, an order to exit a profitable trade.
stop_loss (Optional[StopLossRequest]): For orders with multiple legs, an order to exit a losing trade.
limit_price (float): The worst fill price for a limit or stop limit order.
limit_price (Optional[float]): The worst fill price for a limit or stop limit order.
position_intent (Optional[PositionIntent]): An enum to indicate the desired position strategy: BTO, BTC, STO, STC.
"""

limit_price: float
limit_price: Optional[float] = None

def __init__(self, **data: Any) -> None:
data["type"] = OrderType.LIMIT

super().__init__(**data)

@model_validator(mode="before")
def root_validator(cls, values: dict) -> dict:
if values.get("order_class", "") != OrderClass.OCO:
limit_price = values.get("limit_price", None)
if limit_price is None:
raise ValueError("limit_price is required")
return values


class StopLimitOrderRequest(OrderRequest):
"""
Expand Down
72 changes: 71 additions & 1 deletion tests/trading/trading_client/test_order_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
from alpaca.common.enums import BaseURL
from alpaca.common.exceptions import APIError
from alpaca.trading.client import TradingClient
from alpaca.trading.enums import OrderSide, OrderStatus, PositionIntent, TimeInForce
from alpaca.trading.enums import (
OrderClass,
OrderSide,
OrderStatus,
PositionIntent,
TimeInForce,
)
from alpaca.trading.models import Order
from alpaca.trading.requests import (
CancelOrderResponse,
Expand All @@ -12,6 +18,8 @@
LimitOrderRequest,
MarketOrderRequest,
ReplaceOrderRequest,
StopLossRequest,
TakeProfitRequest,
)


Expand Down Expand Up @@ -421,6 +429,68 @@ def test_limit_order(reqmock, trading_client):
assert lo_response.status == OrderStatus.ACCEPTED


def test_limit_order_request_validation() -> None:
# missing limit_price for non-OCOC
with pytest.raises(ValueError):
# order_class is not specified (default: simple)
LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.SELL,
time_in_force=TimeInForce.DAY,
)
with pytest.raises(ValueError):
# simple
LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.SELL,
time_in_force=TimeInForce.DAY,
order_class=OrderClass.SIMPLE,
)
with pytest.raises(ValueError):
# oto with take_profit
LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.SELL,
time_in_force=TimeInForce.DAY,
order_class=OrderClass.OTO,
take_profit=TakeProfitRequest(limit_price=100),
)
with pytest.raises(ValueError):
# oto with stop_loss
LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.SELL,
time_in_force=TimeInForce.DAY,
order_class=OrderClass.OTO,
stop_loss=StopLossRequest(stop_price=300),
)
with pytest.raises(ValueError):
# bracket
LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.SELL,
time_in_force=TimeInForce.DAY,
order_class=OrderClass.BRACKET,
take_profit=TakeProfitRequest(limit_price=100),
stop_loss=StopLossRequest(stop_price=300),
)
# no limit_price for OCO
LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.SELL,
time_in_force=TimeInForce.DAY,
order_class=OrderClass.OCO,
take_profit=TakeProfitRequest(limit_price=300),
stop_loss=StopLossRequest(stop_price=100),
)


def test_order_position_intent(reqmock, trading_client: TradingClient):
reqmock.post(
f"{BaseURL.TRADING_PAPER.value}/v2/orders",
Expand Down

0 comments on commit 4123932

Please sign in to comment.