Build a dollar neutral portfolio and avoid market volatility

Build a dollar neutral portfolio and avoid market volatility
There are several ways to protect portfolios against volatility, including hedging, buying put options, or reducing market exposure by moving into cash.
Each strategy has its trade-offs. Hedging reduces potential upside returns. Buying put options gives you downside protection but can be expensive. Selling assets to move into cash might trigger taxable capital gains.
A great way to manage volatility is building a dollar-neutral portfolio.
This involves holding both long and short positions in equal amounts offsetting market exposure. By doing this, portfolio performance largely depends on relative price movements rather than overall market direction.
In today's newsletter, you will learn how to build a dollar-neutral portfolio using Riskfolio in just a few lines of Python.
Let's get started!
Build a dollar neutral portfolio and avoid market volatility
Dollar neutral portfolios balance investments with equal dollar amounts in long and short positions. They reduce risk and enhance returns by focusing on price disparities, not market direction.
This strategy is great for investors seeking stability during market volatility.
In practice, investors invest equally in stocks expected to rise and fall. They profit from the performance difference between these stocks which reduces exposure to market fluctuations.
Dollar neutral strategies rely on models and frequent rebalancing to maintain neutrality.
Professionals use dollar neutral portfolios to hedge against market volatility and achieve consistent returns.This approach is a great framework for managing risk while pursuing enhanced returns.
Let's see how it works with Python.
Import libraries and set up
We import the necessary libraries for data manipulation, visualization, and financial analysis.
1import warnings
2import matplotlib.pyplot as plt
3import pandas as pd
4import yfinance as yf
5import riskfolio as rp
6
7warnings.filterwarnings("ignore")
These libraries provide tools for working with financial data, creating visualizations, and performing portfolio optimization. We import them to use their functionality in our analysis. We also suppress warnings to keep our output clean.
Download the price data and compute returns
We set the date range and select the stocks for our portfolio.
1start = "2016-01-01"
2end = "2024-12-30"
3
4tickers = [
5 "JCI", "TGT", "CMCSA", "CPB", "MO", "APA", "MMC", "JPM", "ZION", "PSA",
6 "BAX", "BMY", "LUV", "PCAR", "TXT", "TMO", "DE", "MSFT", "HPQ", "SEE",
7 "VZ", "CNP", "NI", "T", "BA"
8]
9tickers.sort()
10
11data = yf.download(tickers, start=start, end=end).Close
12Y = data.pct_change().dropna()
We define the start and end dates for our historical data, spanning from January 1, 2016, to December 30, 2024. We also create a list of stock tickers for our portfolio, including a diverse range of companies from various sectors. The tickers are sorted alphabetically for easier reference.
We use the yfinance library to download the closing prices for our selected stocks within the specified date range. Then, we calculate the percentage change in prices to get the returns. Any rows with missing data are removed to ensure clean data for our analysis.
Create and optimize portfolio
We build a portfolio object and set optimization parameters. We’ll use the excellent Riskfolio-Lib to do the heavy lifting.
1port = rp.Portfolio(returns=Y)
2
3port.assets_stats(method_mu="hist", method_cov="ledoit")
4
5port.sht = True
6port.uppersht = 1
7port.upperlng = 1
8port.budget = 0
9port.upperdev = 0.20 / 252**0.5
10
11w = port.optimization(model="Classic", rm="CVaR", obj="Sharpe", hist=True)
We create a portfolio object using our returns data. We set parameters for the portfolio, including allowing short positions, setting upper bounds for short and long positions, and specifying a budget constraint. We also set a maximum daily standard deviation. Finally, we optimize the portfolio to maximize the Sharpe ratio using the CVaR risk measure.
Visualize portfolio composition
We create pie and bar charts to display the optimized portfolio weights.
1title = "Max Return Dollar Neutral with Variance Constraint"
2ax = rp.plot_pie(
3 w=w, title=title, others=0.05, nrow=25, cmap="tab20", height=7, width=10, ax=None
4)
The result is a chart that looks like this.
.png)
To show the portfolio weights, we use the plot_bar method.
1ax = rp.plot_bar(
2 w,
3 title="Max Return Dollar Neutral with Variance Constraint",
4 kind="v",
5 others=0.05,
6)
The result is a chart that looks like this.

We use the riskfolio library to create two visualizations of our optimized portfolio. The pie chart shows the allocation of weights across different assets, while the bar chart provides a vertical representation of the same information.
These visualizations help us understand the composition of our optimized portfolio at a glance.
Next steps
As a next step, replace the tickers with stocks in your own portfolio. You can see how far off your portfolio is from a dollar neutral one. The next step, would be to test the allocation of the symbols over different time frames. In practice, portfolio managers would rebalance the portfolio on a monthly basis.
