Problem Description
Solution
To sell all holdings for a specific stock in QuantConnect, the most efficient and robust method is to use self.liquidate().
The liquidate Method
The liquidate method automatically calculates the quantity required to close your position (whether long or short) and submits a market order to flatten the position. By default, it also cancels any open pending orders for that specific symbol.
Here is the syntax:
# Basic usage
self.liquidate(symbol)
# Usage with a custom order tag
self.liquidate(symbol, tag="Selling all shares")
Full Algorithm Example
Below is a complete, runnable example. This algorithm buys SPY and then liquidates the specific position when it reaches a 5% profit.
from AlgorithmImports import *
class LiquidationExampleAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2023, 1, 1)
self.set_end_date(2023, 6, 1)
self.set_cash(100000)
# Add Equity and keep the Symbol object
self.spy = self.add_equity("SPY", Resolution.DAILY).symbol
def on_data(self, data: Slice):
# 1. Entry Logic: If not invested, buy 100% SPY
if not self.portfolio.invested:
self.set_holdings(self.spy, 1.0)
return
# 2. Exit Logic: Sell specific stock if profit > 5%
# We access the specific holding using self.portfolio[symbol]
holding = self.portfolio[self.spy]
if holding.invested and holding.unrealized_profit_percent > 0.05:
# LIQUIDATE SPECIFIC STOCK
# This sells all shares of SPY and cancels open SPY orders
self.liquidate(self.spy, "Target Reached")
self.log(f"Liquidated {self.spy} at profit: {holding.unrealized_profit_percent}")
Alternative Method: set_holdings
You can also use set_holdings with a target weight of 0. This calculates the order size needed to reach 0% allocation.
# Sets the target allocation of this stock to 0%
self.set_holdings(self.spy, 0, tag="Exit Position")
Key Differences
| Feature | self.liquidate(symbol) |
self.set_holdings(symbol, 0) |
|---|---|---|
| Action | Sells entire position immediately. | Sells entire position immediately. |
| Open Orders | Cancels open orders for the symbol by default. | Does not cancel open orders automatically. |
| Intent | Explicitly designed for exiting. | Designed for portfolio rebalancing. |
Q&A
What happens if I call liquidate on a symbol I don't own?
Nothing happens. The method checks if self.portfolio[symbol].invested is true. If you have no position, it simply returns without sending an order or throwing an error.
How do I liquidate my entire portfolio (all stocks)?
If you call self.liquidate() without passing any arguments, it will sell every holding in your portfolio and cancel all open orders for all securities.
Does liquidate work for Short positions?
Yes. If you are Short (e.g., -100 shares), liquidate will automatically Buy to Cover (buy +100 shares) to bring your quantity to 0.
Can I use Limit Orders to liquidate?
No, liquidate uses Market Orders to ensure immediate execution. If you require a Limit Order to exit, you must manually calculate the quantity and use self.limit_order(symbol, -quantity, price).