This example builds upon concepts introduced in the Resampling data and End-of-day pricing and portfolio evaluation examples.
Benchmark portfolio performance
Info
Overview
This example shows how to use the Historical client to benchmark a hypothetical portfolio. To do this, we will request daily open and close price data. We will then calculate the daily returns of our portfolio for one year and benchmark against a risk-free rate of 2.5% per year, and calculate the Sharpe ratio.
OHLCV-1d schema
We'll demonstrate this example using the OHLCV-1d schema.
The OHLCV family of schemas contain the opening, high, low and closing prices as well
as the aggregated volume of trades within a time interval. Since we are interested in
end-of-day evaluation, we'll use an interval of one day, which is specified by the
suffix -1d
.
Many users will prefer to use the official daily settlement prices found in the
statistics
schema for this purpose.
Example
import databento as db
# A hypothetical portfolio mapping symbols to a quantity of shares
portfolio = {
"DVN": 300,
"MRO": 200,
"FTNT": 100,
}
# Assume a risk-free rate of 2.5% per year
annual_benchmark_return = 0.025
daily_benchmark_return = ((1 + annual_benchmark_return) ** (1 / 252)) - 1
# First, create a historical client
client = db.Historical("$YOUR_API_KEY")
# Next, we will request the ohlcv-1d data
data = client.timeseries.get_range(
dataset="XNAS.ITCH",
start="2020-12-31T00:00:00",
end="2022-01-01T00:00:00",
symbols=list(portfolio.keys()),
stype_in="raw_symbol",
schema="ohlcv-1d",
)
# Then, convert the DBNStore to a pandas DataFrame
daily_data = data.to_df()
# Reshape the data with one column per symbol, propagating the previous price forward for dates without trades.
# Note: this does not account for corporate actions such as dividends or splits.
close_prices = daily_data.pivot(columns="symbol", values="close").fillna(method="ffill")
portfolio_value = sum(close_prices[sym] * qty for sym, qty in portfolio.items())
# Calculate some simple properties of the strategy
cost_basis = portfolio_value.iloc[0]
final_value = portfolio_value.iloc[-1]
total_return = (final_value - cost_basis) / cost_basis
# Calculate the arithmetic mean and standard deviation of the daily returns
daily_returns = portfolio_value.pct_change().dropna()
avg_return = daily_returns.mean()
std_return = daily_returns.std()
# Finally, we calculate the annualized ex-post Sharpe ratio
sharpe_ratio = (252**0.5) * (avg_return - daily_benchmark_return) / std_return
print(f"Cost basis: ${cost_basis:,.02f}")
print(f"Final portfolio value: ${final_value:,.02f}")
print(f"Total return: {total_return:.1%}")
print(f"Average of daily returns: {avg_return:.4%}")
print(f"Stdev of daily returns: {std_return:.4%}")
print(f"Annualized Sharpe ratio: {sharpe_ratio:.2f}")
Result
Cost basis: $20,989.00
Final portfolio value: $52,326.00
Total return: 149.3%
Average of daily returns: 0.3830%
Stdev of daily returns: 2.0029%
Annualized Sharpe ratio: 2.96