Submitting a Stock Bracket Order with Lumibot
Summary
The example shows how to submit a bracket order for a stock through Lumibot. On the strategy's first trading iteration, it reads configurable values for the symbol, quantity, take-profit price, and stop-loss price, creates a buy order with secondary limit and stop prices, and submits it. It also stores the submitted order object, which can be useful if the strategy later needs to update or cancel the order. The sample defaults to SPY, a quantity of 10, a take-profit price of 405, and a stop-loss price of 395.
The strategy checks and logs the latest price on each iteration, but does not use that price to decide when to enter; it submits once on the first iteration. The file includes paths for running live with Alpaca or backtesting with Yahoo data over a short date range, but it provides no backtest results. It does not explain broker-specific bracket behavior, order fill handling, or how the sample's fixed exit prices should be adapted to changing market conditions.
Key ideas
- A bracket order pairs an entry with secondary take-profit and stop-loss prices.
- The example submits a buy bracket for a configured symbol and quantity on its first iteration.
- The submitted order is stored so it can potentially be updated or canceled later.
- The strategy includes both a live Alpaca path and a Yahoo-data backtest path but reports no results.
- The sample does not describe fill management or a method for choosing exit prices.
Tags
Full text
# stock_bracket.py
```py
from datetime import datetime
from lumibot.entities import Order
from lumibot.strategies.strategy import Strategy
"""
Strategy Description
An example strategy for how to use bracket orders.
"""
class StockBracket(Strategy):
parameters = {
"buy_symbol": "SPY",
"take_profit_price": 405,
"stop_loss_price": 395,
"quantity": 10,
}
# =====Overloading lifecycle methods=============
def initialize(self):
# Set the initial variables or constants
# Built in Variables
self.sleeptime = "1D"
# Our Own Variables
self.counter = 0
self.submitted_bracket_order = None # Useful for updating/canceling orders
def on_trading_iteration(self):
"""Buys the self.buy_symbol once, then never again"""
buy_symbol = self.parameters["buy_symbol"]
take_profit_price = self.parameters["take_profit_price"]
stop_loss_price = self.parameters["stop_loss_price"]
quantity = self.parameters["quantity"]
# What to do each iteration
current_value = self.get_last_price(buy_symbol)
self.log_message(f"The value of {buy_symbol} is {current_value}")
if self.first_iteration:
# Bracket order
order = self.create_order(
buy_symbol,
quantity,
Order.OrderSide.BUY,
secondary_limit_price=take_profit_price,
secondary_stop_price=stop_loss_price,
order_class=Order.OrderClass.BRACKET,
)
self.submitted_bracket_order = self.submit_order(order)
if __name__ == "__main__":
is_live = False
if is_live:
from credentials import ALPACA_CONFIG
from lumibot.brokers import Alpaca
broker = Alpaca(ALPACA_CONFIG)
strategy = StockBracket(broker=broker)
strategy.run_live()
else:
from lumibot.backtesting import YahooDataBacktesting
# Backtest this strategy
backtesting_start = datetime(2023, 3, 3)
backtesting_end = datetime(2023, 3, 10)
results = StockBracket.backtest(
YahooDataBacktesting,
backtesting_start,
backtesting_end,
benchmark_asset="SPY",
)
```Shown in full with attribution under the source's licence. Licence: GPL-3.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.