Portfolio
Holdings
Introduction
The Portfolioportfolio 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 SettledProfitsettled_profit and UnsettledProfitunsettled_profit properties.
Get Total Close Profit
To get the profit of a position holding if you closed the position, call the TotalCloseProfittotal_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 TotalCloseProfittotal_close_profit method accepts the following optional arguments:
| Argument | Data Type | Description | Default Value |
|---|---|---|---|
includeFeesinclude_fees | bool | Whether to reduce the profit based on the estimated fee from the fee model. | trueTrue |
exitPriceexit_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. | nullNone |
entryPriceentry_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. | nullNone |
quantity | decimal?float/NoneType | The quantity to liquidate. If you don't provide a value, it uses the quantity of the SecurityHolding. | nullNone |
LEAN uses this method to define the UnrealizedProfitunrealized_profit property.
Get Quantity Value
To get the value of a security at any quantity, call the GetQuantityValueget_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 SetCashset_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.SetHoldingsSecurityHolding.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, 9, 1);
SetEndDate(2024, 12, 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);
// Add a security initializer that seeds the price of each asset with its
// last known price. This ensures the holdings we add below will initialize
// with a non-zero value.
SetSecurityInitializer(
new BrokerageModelSecurityInitializer(BrokerageModel, new FuncSecuritySeeder(GetLastKnownPrices))
);
// 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, 9, 1)
self.set_end_date(2024, 12, 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)
# Add a security initializer that seeds the price of each asset with its
# last known price. This ensures the holdings we add below will initialize
# with a non-zero value.
self.set_security_initializer(
BrokerageModelSecurityInitializer(
self.brokerage_model,
FuncSecuritySeeder(self.get_last_known_prices)
)
)
# 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)