Portfolio
Holdings
Introduction
The Portfolio
portfolio
is a dictionary where the key is a Symbol
and the value is a SecurityHolding
.
// Create shortcut helper to the SPY SecurityHolding object from the Portfolio collection. var securityHolding = Portfolio["SPY"];
# Create shortcut helper to the SPY SecurityHolding object from the Portfolio collection. security_holding = self.portfolio["SPY"]
Properties
SecurityHolding
objects have the following properties:
// Save shortcut to SecurityHolding object, and fetch quantity and invested status. var securityHolding = Portfolio["SPY"]; var quantity = securityHolding.Quantity; var invested = securityHolding.Invested;
# Save shortcut to SecurityHolding object, and fetch quantity and invested status. security_holding = self.portfolio["SPY"] quantity = security_holding.quantity invested = security_holding.invested
FutureHolding
objects also have SettledProfit
settled_profit
and UnsettledProfit
unsettled_profit
properties.
Get Total Close Profit
To get the profit of a position holding if you closed the position, call the TotalCloseProfit
total_close_profit
method. The value this method returns is denominated in your account currency and accounts for order fees.
var profit = Portfolio["SPY"].TotalCloseProfit();
profit = self.portfolio["SPY"].total_close_profit()
The TotalCloseProfit
total_close_profit
method accepts the following optional arguments:
Argument | Data Type | Description | Default Value |
---|---|---|---|
includeFees include_fees | bool | Whether to reduce the profit based on the estimated fee from the fee model. | true True |
exitPrice exit_price | decimal? float/NoneType | A hypothetical exit price to use for the profit calculation. If you don't provide a value, it uses the bid price for sell orders or the ask price for buy orders. | null None |
entryPrice entry_price | decimal? float/NoneType | A hypothetical exit price to use for the profit calculation. If you don't provide a value, it uses the average price of the SecurityHolding . | null None |
quantity | decimal? float/NoneType | The quantity to liquidate. If you don't provide a value, it uses the quantity of the SecurityHolding . | null None |
LEAN uses this method to define the UnrealizedProfit
unrealized_profit
property.
Get Quantity Value
To get the value of a security at any quantity, call the GetQuantityValue
get_quantity_value
method. The value this method returns is denominated in your account currency.
// Get the quantity value at the current price var valueAtCurrentPrice = Portfolio["SPY"].GetQuantityValue(100); // Get the quantity value at a specific price var valueAtSpecificPrice = Portfolio["SPY"].GetQuantityValue(100, price: 30);
# Get the quantity value at the current price value_at_current_price = self.portfolio["SPY"].get_quantity_value(100) # Get the quantity value at a specific price value_at_specific_price = self.portfolio["SPY"].get_quantity_value(100, price=30)
Set Initial Holdings
When you deploy a backtest or a new paper trading algorithm, the default initial portfolio state contains $100,000 USD.
However, in the Initializeinitialize method, you can define the initial portfolio state to something else.
To set the initial cash balances, call SetCash
set_cash
with the currency ticker and quantity.
To set multiple currencies, call the method multiple times.
SetCash(100000); // Set the quantity of the account currency to 100,000 SetCash("BTC", 10); // Set the Bitcoin quantity to 10 SetCash("EUR", 10000); // Set the EUR quantity to 10,000
self.set_cash(100000) # Set the quantity of the account currency to 100,000 self.set_cash("BTC", 10) # Set the Bitcoin quantity to 10 self.set_cash("EUR", 10000) # Set the EUR quantity to 10,000
To set the initial security holdings, subscribe to the security so that it enters your portfolio, then call the SecurityHolding.SetHoldings
SecurityHolding.set_holdings
method with the average purchase price and quantity.
if (!LiveMode) { Portfolio["SPY"].SetHoldings(averagePrice: 500, quantity: 100); }
if not self.live_mode: self.portfolio["SPY"].set_holdings(average_price=500, quantity=100)
Examples
The following examples demonstrate common practices for setting the portfolio holdings.
Example 1: Initial Holdings
The following algorithm simulates an account with multiple initial positions and cash. Note that these initial holdings will affect the algorithm's performance.
public class PortfolioExampleAlgorithm : QCAlgorithm { public override void Initialize() { SetStartDate(2024, 1, 1); SetEndDate(2024, 1, 31); // Simulate initial cash in multiple currencies. // Note that all currencies other than the account currency will affect the performance. SetAccountCurrency("USD", 10000); SetCash("EUR", 1000); SetCash("JPY", 1000000); SetCash("HKD", 10000); // Request data for some securities in the account already. var spy = AddEquity("SPY").Symbol; var aapl = AddEquity("AAPL").Symbol; var btcusd = AddCrypto("BTCUSD").Symbol; var xauusd = AddCfd("XAUUSD").Symbol; // Simulate that the account holds some assets initially. // Note that all initial holdings will affect the performance. Portfolio[spy].SetHoldings(averagePrice: 420m, quantity: 102m); Portfolio[aapl].SetHoldings(averagePrice: 102m, quantity: 25m); Portfolio[btcusd].SetHoldings(averagePrice: 45000m, quantity: 0.125m); Portfolio[xauusd].SetHoldings(averagePrice: 1000m, quantity: 100m); } }
class PortfolioExampleAlgorithm(QCAlgorithm): def initialize(self) -> None: self.set_start_date(2024, 1, 1) self.set_end_date(2024, 1, 31) # Simulate initial cash in multiple currencies. # Note that all currencies other than the account currency will affect the performance. self.set_account_currency("USD", 10000) self.set_cash("EUR", 1000) self.set_cash("JPY", 1000000) self.set_cash("HKD", 10000) # Request data for some securities in the account already. spy = self.add_equity("SPY").symbol aapl = self.add_equity("AAPL").symbol btcusd = self.add_crypto("BTCUSD").symbol xauusd = self.add_cfd("XAUUSD").symbol # Simulate that the account initially holds some assets. # Note that all initial holdings will affect the performance. self.portfolio[spy].set_holdings(average_price=420, quantity=102) self.portfolio[aapl].set_holdings(average_price=120, quantity=25) self.portfolio[btcusd].set_holdings(average_price=45000, quantity=0.125) self.portfolio[xauusd].set_holdings(average_price=1000, quantity=100)