Introduction
Algorithmic trading has revolutionized the stock market by offering several advantages over manual trading. Trading bots have become a critical tool for traders who are looking to gain a competitive edge. Platforms like Lumibot provide a robust solution by allowing traders to automate their strategies with speed and precision that manual traders cannot match by responding instantly to market conditions and taking advantage of fleeting opportunities.
At its core, Lumibot is a Python-based open-source trading platform designed for those who want to automate their stock trades using algorithms. It integrates with various brokers like Alpaca and Interactive Brokers, making it accessible to a wide range of users. In this blog, we’ll explore the practical steps to place stock orders using Lumibot.
Let’s explore the installation process, how to connect with your brokerage and the different types of stock orders you can place, such as market, limit, and stop orders.
Why is Lumibot a Smart Choice For Placing Stock Orders?
Lumibot is a highly flexible algorithmic trading framework that provides distinct advantages for those looking to enhance their stock trading experience. Let’s see some of its powerful benefits below:
1. Automation of Trading Strategies
Lumibot ensures consistent execution of a pre-defined logic without constant monitoring. Once a strategy is coded and deployed, it can operate 24/7, maximizing opportunities in the stock market. For example, strategies like “buy low, sell high” or “buy and hold” can be automatically executed based on real-time market conditions, without the need for human intervention.
2. Speed and Precision in Order Execution
Timing is critical in the stock market. Lumibot’s algorithmic approach ensures that trades are placed almost instantly as soon as market conditions trigger the predefined criteria. This speed and precision allow traders to capitalize on short-lived opportunities, such as sudden market shifts or price gaps, that would be impossible to execute manually.
Moreover, Lumibot integrates with multiple brokers, including Alpaca and Interactive Brokers, ensuring that orders are routed through highly reliable platforms, reducing the risk of trade failure or slippage.
3. Backtesting for Strategy Optimization
One of the most powerful features of Lumibot is its ability to backtest trading strategies. Backtesting allows traders to evaluate their strategies against historical market data, providing a clear picture of the strategy’s performance before it is deployed in live markets. By using historical data to simulate past market conditions, traders can identify the strengths and weaknesses of their strategies, refine them, and improve profitability.
4. Integration with Various Brokers and Data Providers
Another advantage of using Lumibot is its seamless integration with popular brokerage platforms such as Alpaca, Interactive Brokers, and others. This allows traders to connect their trading bots directly to their brokerage accounts, making it easy to execute trades across different asset classes including stocks, ETFs, and options.
5. Paper Trading for Low-Risk Strategy Testing
For those hesitant to dive into live trading with real money, Lumibot offers a paper trading feature. This allows users to simulate real-world trading conditions without putting actual capital at risk. By executing their strategies in paper trading mode, traders can gain confidence in their algorithms, observe how they perform in real-time markets, and make adjustments before switching to live trading.
The Prerequisites Before Placing a Stock Order
To start placing stock orders using Lumibot, a user needs to follow the preparatory steps mentioned below. This installation process is quite straightforward if you are familiar with Python
Step 1: Install Python
The user must install Python in their system with version 3.10 or above. You can download the recent version of Python here.
Step 2: Set Up Lumibot
The user must first install Lumibot using pip: pip install Lumibot from the terminal.
pip install lumibot
Step 3: Run Python
Once Lumibot has been installed, you have to run the Python file by importing the classes below.
import lumibot
from lumibot.strategies import Strategy
from lumibot.entities import Asset
from lumibot.traders import Trader
from datetime import datetime
Step 4: Create ALPACA_CONFIG
Finally, the user has to create ALPACA_CONFIG with API KEY and API SECRET by logging in or signing up at https://alpaca.markets/.
Steps to Placing Stock Orders Using Lumibot
Step 1: Import the Required Libraries
Begin by importing necessary modules, such as datetime to handle date and time functionalities, and Strategy from the Lumibot framework to define the trading strategy.
from datetime import datetime
from lumibot.strategies.strategy import Strategy
Step 2: Define the Buy-and-Hold Strategy Class
Create a class BuyAndHoldStock that inherits from the Strategy class provided by Lumibot. This class contains the core logic for the strategy.
class BuyAndHoldStock(Strategy):
Step 3: Set Parameters for the Strategy
Define a parameters dictionary to specify the stock symbol you want to buy. In this example, the stock symbol is set to “AAPL” by default.
# Parameters for the strategy, currently only the stock symbol to buy
parameters = {
"buy_symbol": "AAPL", # The stock symbol to buy, default is AAPL
}
Step 4: Initialize the Strategy
Define the initialize method to set how often the trading loop will run. Here, the bot will execute the strategy iteration every minute, which is indicated by the “1M” sleeptime.
def initialize(self):
# Set how often the trading iteration will run (e.g., every 1 minute)
self.sleeptime = "1M"
Step 5: Implement the Trading Logic in on_trading_iteration
The on_trading_iteration method is the core function where the strategy executes its logic on each trading iteration. In this step:
- Log Current Time: The bot logs the current datetime to track when the trade is being executed.
def on_trading_iteration(self):
"""Buys the specified stock once, then holds it"""
# Log the current datetime
current_time = self.get_datetime()
self.log_message(f"Current datetime: {current_time}")
- Retrieve Stock Symbol: Extract the stock symbol (e.g., “AAPL”) from the parameters.
# Retrieve the stock symbol from the parameters
stock_symbol = self.parameters["buy_symbol"]
- Fetch Current Stock Price: The bot gets the latest stock price for the specified symbol and logs it.
# Get the latest price of the stock
stock_price = self.get_last_price(stock_symbol)
self.log_message(f"The price of {stock_symbol} is {stock_price}")
- Visualize Stock Price: Add the stock price to a custom line chart for monitoring and visualization purposes.
# Add the stock price to a custom line chart for visualization
self.add_line(f"{stock_symbol} Price", stock_price)
Step 6: Check Existing Portfolio Positions
Check the current positions in the portfolio.
# Get the current portfolio positions
current_positions = self.get_positions()
Step 7: Calculate Quantity and Place a Buy Order
If there are no stock holdings, the bot calculates how many shares of the stock to buy based on the available portfolio value. It then creates and submits a buy order.
- Calculate Quantity: Divide the portfolio value by the stock price to determine how many shares to buy.
# If the only position is USD, buy the stock
if len(current_positions) <= 1: # Assuming only USD is present
# Calculate how much stock to buy based on available portfolio value
quantity_to_buy = int(self.portfolio_value // stock_price)
self.log_message(f"Quantity to buy: {quantity_to_buy}")
- Create and Submit the Buy Order: Once the quantity is calculated, the bot creates and submits the buy order for execution.
# Create and submit the buy order
buy_order = self.create_order(stock_symbol, quantity_to_buy, "buy")
self.submit_order(buy_order)
This will allow the bot to monitor the market automatically and place a buy order for the stock, holding it after the first purchase.
Backtesting Your Strategy With Lumibot
One of the greatest advantages of using Lumibot is the ability to backtest your strategies before deploying them in live trading environments. The backtest will simulate how the strategy would have performed over a historical period.
if __name__ == "__main__":
IS_BACKTESTING = True
if IS_BACKTESTING:
from lumibot.backtesting import PolygonDataBacktesting
# Set up the backtest period
backtest_start = datetime(2024, 1, 1)
backtest_end = datetime(2024, 9, 1)
# Run the backtest with SPY as the benchmark asset
results = BuyAndHoldStock.run_backtest(
PolygonDataBacktesting,
backtest_start,
backtest_end,
benchmark_asset="SPY",
polygon_api_key="", # Add your Polygon API key here
)
print(results)
else:
# Check if Alpaca API keys are set
ALPACA_CONFIG = {
"API_KEY": "", # Add your Alpaca API Key here
"API_SECRET": "", # Add your Alpaca API Secret here
"PAPER": False, # Set to True for paper trading, False for live trading
}
# Throw an error if the API keys are not set
if not ALPACA_CONFIG["API_KEY"] or not ALPACA_CONFIG["API_SECRET"]:
raise ValueError("Please set your Alpaca API key and secret in the ALPACA_CONFIG.")
from lumibot.brokers import Alpaca
from lumibot.traders import Trader
# Set up the Alpaca broker and run the strategy
broker = Alpaca(ALPACA_CONFIG)
strategy = BuyAndHoldStock(broker=broker)
trader = Trader()
trader.add_strategy(strategy)
trader.run_all()
Key Points in the Backtesting Code
- IS_BACKTESTING = True: his flag determines whether the script runs in backtesting mode or live trading mode. When set to backtesting mode, it uses historical data to simulate trades. In live mode, the strategy interacts with a real broker to execute actual trades.
- Backtest Period: The strategy is tested between January 1, 2023, and September 1, 2024.
Complete Code
from datetime import datetime
from lumibot.strategies.strategy import Strategy
class BuyAndHoldStock(Strategy):
# Parameters for the strategy, currently only the stock symbol to buy
parameters = {
"buy_symbol": "AAPL", # The stock symbol to buy, default is AAPL
}
def initialize(self):
# Set how often the trading iteration will run (e.g., every 1 minute)
self.sleeptime = "1M"
def on_trading_iteration(self):
"""Buys the specified stock once, then holds it"""
# Log the current datetime
current_time = self.get_datetime()
self.log_message(f"Current datetime: {current_time}")
# Retrieve the stock symbol from the parameters
stock_symbol = self.parameters["buy_symbol"]
# Get the latest price of the stock
stock_price = self.get_last_price(stock_symbol)
self.log_message(f"The price of {stock_symbol} is {stock_price}")
# Add the stock price to a custom line chart for visualization
self.add_line(f"{stock_symbol} Price", stock_price)
# Get the current portfolio positions
current_positions = self.get_positions()
# If the only position is USD, buy the stock
if len(current_positions) <= 1: # Assuming only USD is present
# Calculate how much stock to buy based on available portfolio value
quantity_to_buy = int(self.portfolio_value // stock_price)
self.log_message(f"Quantity to buy: {quantity_to_buy}")
# Create and submit the buy order
buy_order = self.create_order(stock_symbol, quantity_to_buy, "buy")
self.submit_order(buy_order)
if __name__ == "__main__":
IS_BACKTESTING = True
if IS_BACKTESTING:
from lumibot.backtesting import PolygonDataBacktesting
# Set up the backtest period
backtest_start = datetime(2024, 1, 1)
backtest_end = datetime(2024, 9, 1)
# Run the backtest with SPY as the benchmark asset
results = BuyAndHoldStock.run_backtest(
PolygonDataBacktesting,
backtest_start,
backtest_end,
benchmark_asset="SPY",
polygon_api_key="", # Add your Polygon API key here
)
print(results)
else:
# Check if Alpaca API keys are set
ALPACA_CONFIG = {
"API_KEY": "", # Add your Alpaca API Key here
"API_SECRET": "", # Add your Alpaca API Secret here
"PAPER": False, # Set to True for paper trading, False for live trading
}
# Throw an error if the API keys are not set
if not ALPACA_CONFIG["API_KEY"] or not ALPACA_CONFIG["API_SECRET"]:
raise ValueError("Please set your Alpaca API key and secret in the ALPACA_CONFIG.")
from lumibot.brokers import Alpaca
from lumibot.traders import Trader
# Set up the Alpaca broker and run the strategy
broker = Alpaca(ALPACA_CONFIG)
strategy = BuyAndHoldStock(broker=broker)
trader = Trader()
trader.add_strategy(strategy)
trader.run_all()
Output and Key Metrics Explained
After completing the backtest, Lumibot produces several key output files that provide in-depth insights into the strategy’s performance. These files include a tearsheet, indicators, and a trades file. Below is a summary of each file’s contents and how to understand the results.
1. Tearsheet.html / Tearsheet.csv
The tearsheet offers a detailed report on the strategy’s performance, featuring essential metrics that assess profitability and risk. Key metrics include:
- Total Return: The overall profit generated by the strategy during the backtesting period.
- CAGR (Compound Annual Growth Rate): The average annual growth rate over the backtest duration.
- Sharpe Ratio: A metric that evaluates risk-adjusted returns.
- Max Drawdown: The largest drop in portfolio value from its highest point to its lowest.
- Sortino Ratio: A modified version of the Sharpe Ratio that focuses specifically on downside risk.
Output for Stock Order Backtesting
2. Indicators.html / Indicators.csv
The indicators file logs all technical indicators utilized in the strategy. Reviewing these values allows you to see how the strategy responds to different market conditions. Key contents of indicators file include:
- Indicator Values Over Time:This section includes moving averages, RSI, MACD, Bollinger Bands, and other indicators used by the strategy, showing how these values change over time and relate to the strategy’s buy/sell actions.
- Custom Strategy Metrics: If the strategy tracks custom metrics such as portfolio value, cash position, or specific thresholds, these will also be included in the file.
Output for Stock Order Backtesting
3. Trades.html / Trades.csv
The trades file documents every trade made by the strategy during the backtest, detailing information such as the trade timestamp, symbol, buy/sell action, trade price, and the profit or loss for each transaction. Key contents of trades file include:
- Trade Timestamp: The date and time each trade was executed.
- Symbol: The asset being traded (e.g., QQQ).
- Buy/Sell Action: Indicates if the trade was a buy or sell.
- Trade Price: The price at which the asset was traded.
- Quantity: The number of units (e.g., shares or contracts) involved.
- Profit/Loss: The profit or loss from each trade, helping identify successful trades.
- Order Type: Specifies whether the order was market, limit, or another type.
Output for Stock Order Backtesting
Conclusion
Placing stock orders using Lumibot can be a highly efficient way to automate your trading strategies. Whether you are executing simple market orders or more complex limit and stop orders, Lumibot provides the flexibility and precision that is needed to optimize your trading approach. Moreover, it has features like backtesting and paper trading, making it possible for you to refine your strategies without risking capital.
By understanding the different types of stock orders, setting up your brokerage account, and utilizing Lumibot’s rich functionality, you can take advantage of algorithmic trading and improve your overall market performance.