2026-02-22 15:26:41 +00:00
|
|
|
"""Abstract base class for brokerage integrations.
|
|
|
|
|
|
|
|
|
|
All broker implementations must inherit from ``BaseBroker`` and provide
|
|
|
|
|
concrete implementations for order management, position tracking, and
|
|
|
|
|
account information retrieval. This abstraction layer allows the trading
|
|
|
|
|
bot to swap brokerages (Alpaca, Interactive Brokers, Tradier, ...) without
|
|
|
|
|
changing strategy or execution logic.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
2026-06-04 22:31:24 +00:00
|
|
|
from shared.schemas.trading import (
|
|
|
|
|
AccountInfo,
|
|
|
|
|
BrokerOrder,
|
|
|
|
|
OrderRequest,
|
|
|
|
|
OrderResult,
|
|
|
|
|
PositionInfo,
|
|
|
|
|
)
|
2026-02-22 15:26:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class BaseBroker(ABC):
|
|
|
|
|
"""Interface that every brokerage adapter must implement."""
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def submit_order(self, order: OrderRequest) -> OrderResult:
|
|
|
|
|
"""Submit a new order to the brokerage.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
order:
|
|
|
|
|
The order details including ticker, side, quantity, and order type.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
OrderResult
|
|
|
|
|
Result containing the order ID, status, and fill information.
|
|
|
|
|
"""
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def cancel_order(self, order_id: str) -> bool:
|
|
|
|
|
"""Cancel an open order.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
order_id:
|
|
|
|
|
The brokerage-assigned order identifier.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
bool
|
|
|
|
|
``True`` if the cancellation was accepted, ``False`` otherwise.
|
|
|
|
|
"""
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def get_positions(self) -> list[PositionInfo]:
|
|
|
|
|
"""Return all currently open positions.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
list[PositionInfo]
|
|
|
|
|
One entry per open position with quantity, average entry, current
|
|
|
|
|
price, and unrealized P&L.
|
|
|
|
|
"""
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def get_account(self) -> AccountInfo:
|
|
|
|
|
"""Return account-level summary information.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
AccountInfo
|
|
|
|
|
Equity, cash, buying power, and total portfolio value.
|
|
|
|
|
"""
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def get_order_status(self, order_id: str) -> OrderResult:
|
|
|
|
|
"""Fetch the current status of an existing order.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
order_id:
|
|
|
|
|
The brokerage-assigned order identifier.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
OrderResult
|
|
|
|
|
Current state of the order including fill price if applicable.
|
|
|
|
|
"""
|
|
|
|
|
...
|
2026-06-04 22:31:24 +00:00
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def get_order(
|
|
|
|
|
self, order_id: str, *, nested: bool = True
|
|
|
|
|
) -> BrokerOrder | None:
|
|
|
|
|
"""Fetch an order including its bracket child legs.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
order_id:
|
|
|
|
|
The brokerage-assigned order identifier.
|
|
|
|
|
nested:
|
|
|
|
|
When ``True`` (the default), child legs (stop-loss / take-profit)
|
|
|
|
|
are populated on the returned :class:`BrokerOrder` so callers can
|
|
|
|
|
tell which leg filled and at what price.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
BrokerOrder | None
|
|
|
|
|
The order with its legs, or ``None`` if the order does not exist.
|
|
|
|
|
"""
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
async def list_orders(
|
|
|
|
|
self, *, status: str = "all", limit: int = 100
|
|
|
|
|
) -> list[OrderResult]:
|
|
|
|
|
"""List orders, optionally filtered by status.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
status:
|
|
|
|
|
One of ``"open"``, ``"closed"``, or ``"all"`` (the default).
|
|
|
|
|
limit:
|
|
|
|
|
Maximum number of orders to return.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
list[OrderResult]
|
|
|
|
|
One entry per matching order.
|
|
|
|
|
"""
|
|
|
|
|
...
|