Broker
Broker
Broker class for managing trading positions and order execution.
This class simulates a brokerage environment, handling position management, order processing, commission calculations, and P&L tracking. It provides the core trading infrastructure for backtesting strategies.
The broker manages: - Current position and average price - Cash/balance management (realized P&L + commissions) - Order execution (market and limit orders) - Commission calculations - Stop loss and take profit order management - P&L record tracking - Leverage for amplified position sizing - Margin tracking separate from equity
Accounting Model: - balance: Realized account balance after P&L and commissions - used_margin = abs(position) * mark_price / leverage - unrealized_pnl = position * (mark_price - position_avg_price) - equity = balance + unrealized_pnl - free_cash = equity - used_margin
Example
source = CSVDataSource("data.csv")
broker = Broker(source)
broker.buy(quantity=0.1) # Buy 10% of available cash
broker.sell(quantity=0.5) # Sell 50% of available position
__init__(source)
Initialize the broker with a data source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
DataSource
|
The data source providing market data (OHLCV prices and timestamps) for the broker to operate on. |
required |
buy(quantity=1, limit=None, amount=None, stop_loss=None, take_profit=None)
Place a buy order for a specified quantity.
This method creates a buy order with optional limit price, stop loss, and take profit conditions. The quantity can be specified as a percentage of available cash or as an absolute amount.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quantity
|
float
|
Quantity to buy as fraction of available cash (0 < quantity <= 1). Defaults to 1 (full cash amount). For example: 0.5 = buy with 50% of available cash. |
1
|
limit
|
float64 | None
|
Limit price for the order. If None, creates a market order. Defaults to None. |
None
|
amount
|
float64 | None
|
Absolute number of shares to buy. If provided, overrides quantity calculation. Defaults to None. |
None
|
stop_loss
|
float64 | None
|
Stop loss price. If provided, creates a stop loss order that executes when price falls to this level. Defaults to None. |
None
|
take_profit
|
float64 | None
|
Take profit price. If provided, creates a take profit order that executes when price rises to this level. Defaults to None. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If quantity is not in (0, 1] range. |
ValueError
|
If limit price is negative. |
ValueError
|
If amount is negative. |
ValueError
|
If attempting to buy more than available cash balance. |
Note
- If both quantity and amount are provided, amount takes precedence.
- Orders are added to the broker's order queue and processed during the next iteration.
- Market orders execute immediately at current open price.
- Limit orders only execute when price reaches the specified level.
- Leverage amplifies position size - with 2x leverage and quantity=1, you control 2x the shares while only using 1x cash as margin.
- Opening positions deducts only commission from cash; equity remains continuous because unrealized P&L is properly tracked.
Example
broker = Broker(source)
Buy with 25% of available cash
broker.buy(quantity=0.25)
Buy exactly 100 shares at limit price $50
broker.buy(amount=100, limit=50.0)
Buy with stop loss and take profit
broker.buy(quantity=0.1, stop_loss=45.0, take_profit=55.0)
close()
Close all current positions with market orders.
This method creates market orders to liquidate the entire current position, regardless of whether it's long or short. It's commonly used at the end of a backtest or when exiting all positions.
The method creates: - A sell order if holding a long position (positive shares) - A buy order if holding a short position (negative shares)
Note
- This method only creates orders; they are executed during the next iteration cycle.
- No parameters are required as it closes the entire position.
- Commission and slippage will apply to the closing trades.
- Existing stop loss and take profit orders remain active unless explicitly cancelled.
Example
broker = Broker(source)
broker.buy(quantity=1) # Open long positionLater, close all positions
broker.close()
is_closed()
Check if currently not holding any position.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True if position is zero (no open position), False otherwise. |
Example
broker.close()
broker.is_closed()
True
is_long()
Check if currently holding a long position.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True if position is positive (long), False otherwise. |
Example
broker.buy(quantity=0.5)
broker.is_long()
True
is_short()
Check if currently holding a short position.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True if position is negative (short), False otherwise. |
Example
broker.sell(quantity=0.5)
broker.is_short()
True
sell(quantity=1, limit=None, amount=None, stop_loss=None, take_profit=None)
Place a sell order for a specified quantity.
This method creates a sell order with optional limit price, stop loss, and take profit conditions. The quantity can be specified as a percentage of available cash or as an absolute amount.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quantity
|
float
|
Quantity to sell as fraction of available cash (0 < quantity <= 1). Defaults to 1 (full cash amount). For example: 0.5 = sell shares worth 50% of available cash. |
1
|
limit
|
optional
|
Limit price for the order (same as limit parameter in buy method). If None, creates a market order. Defaults to None. |
None
|
amount
|
float64 | None
|
Absolute number of shares to sell. If provided, overrides quantity calculation. Defaults to None. |
None
|
stop_loss
|
float64 | None
|
Stop loss price for the position. Defaults to None. |
None
|
take_profit
|
float64 | None
|
Take profit price for the position. Defaults to None. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If quantity is not in (0, 1] range. |
ValueError
|
If limit price is negative. |
ValueError
|
If amount is negative. |
ValueError
|
If attempting to sell more shares than currently held. |
Note
- If both quantity and amount are provided, amount takes precedence.
- Orders are added to the broker's order queue and processed during the next iteration.
- Selling reduces the current position and increases cash balance.
- Stop loss and take profit apply to remaining position after sale.
- Realized P&L is credited to cash immediately on close.
- Leverage amplifies short position size - with 2x leverage and quantity=1, you can short 2x the shares while only using 1x cash as margin.
Example
broker = Broker(source)
broker.buy(quantity=1) # First buy full positionSell 50% of position
broker.sell(quantity=0.5)
Sell exactly 100 shares at limit price $52
broker.sell(amount=100, limit=52.0)
CommissionType
Bases: Enum
Enumeration for commission calculation types.
This enum defines how commissions are calculated for trades in the backtesting framework.
Attributes:
| Name | Type | Description |
|---|---|---|
PERCENTAGE |
int
|
Commission calculated as percentage of trade value (0). Commission = trade_value * commission_rate |
CASH |
int
|
Commission calculated as fixed cash amount per lot (1). Commission = quantity * commission_rate / lot_size |
Order
dataclass
Dataclass representing a trading order.
This class encapsulates all the information needed to define and track a trading order, including its side, quantity, type, execution conditions, and current status.
Attributes:
| Name | Type | Description |
|---|---|---|
side |
OrderSide
|
Whether this is a buy or sell order. |
quantity |
float64
|
Number of shares/contracts to trade. |
type |
OrderType
|
Order execution type (market or limit). |
price |
float64 | None
|
Limit price for limit orders, None for market orders. |
stop_loss |
float64 | None
|
Stop loss price, if any. |
take_profit |
float64 | None
|
Take profit price, if any. |
status |
OrderStatus
|
Current status of the order. |
timestamp |
datetime
|
Time when the order was created. |
OrderSide
Bases: Enum
Enumeration for order side (buy/sell direction).
This enum defines whether an order is a buy (long) or sell (short) order.
Attributes:
| Name | Type | Description |
|---|---|---|
BUY |
int
|
Represents a buy order (1). |
SELL |
int
|
Represents a sell order (-1). |
OrderStatus
Bases: Enum
Enumeration for order execution status.
This enum tracks the current state of an order during its lifecycle.
Attributes:
| Name | Type | Description |
|---|---|---|
ACTIVE |
int
|
Order is active with stop loss or take profit conditions (0). |
COMPLETE |
int
|
Order has been fully executed and no further actions needed (1). |
PENDING |
int
|
Order is pending execution, waiting for price or time trigger (2). |
OrderType
Bases: Enum
Enumeration for order execution types.
This enum defines how an order should be executed in the market.
Attributes:
| Name | Type | Description |
|---|---|---|
MARKET |
int
|
Market order that executes immediately at current market price (0). |
LIMIT |
int
|
Limit order that executes only at specified price or better (1). |
Source code
The broker module handles order execution and position management:
src/quantex/broker/broker.py- Broker class for order executionsrc/quantex/broker/types.py- Type definitions (Order, OrderSide, OrderStatus, OrderType)