Skip to content
All library documents

Submitting a Stock Bracket Order with Lumibot

Code 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.