Portfolio Optimization and Quantitative Strategic Asset Allocation in Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive visualization tools for portfolios, efficient frontiers, risk contributions, cluster analysis, and performance attribution. The plotting module provides publication-quality charts for portfolio analysis and presentation.
Visualization of efficient frontiers and portfolio optimization results.
def plot_frontier(w_frontier, mu, cov, returns, rm='MV', rf=0, alpha=0.05,
cmap='viridis', w=None, label='Portfolio', marker='*',
s=16, c='r', height=6, width=10, ax=None):
"""
Plot efficient frontier with risk-return profile.
Parameters:
- w_frontier (DataFrame): Efficient frontier weights matrix
- mu (DataFrame): Expected returns vector
- cov (DataFrame): Covariance matrix
- returns (DataFrame): Historical returns
- rm (str): Risk measure for frontier calculation
- rf (float): Risk-free rate
- alpha (float): Significance level for risk measures
- cmap (str): Colormap for frontier points
- w (DataFrame): Specific portfolio to highlight
- label (str): Label for highlighted portfolio
- marker (str): Marker style for highlighted portfolio
- s (float): Marker size for highlighted portfolio
- c (str): Color for highlighted portfolio
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes object
Returns:
matplotlib.axes: Axes object with frontier plot
"""
def plot_frontier_area(w_frontier, cov, returns, rm='MV', rf=0, alpha=0.05,
cmap='viridis', height=6, width=10, ax=None):
"""
Plot efficient frontier as filled area.
Parameters:
- w_frontier (DataFrame): Efficient frontier weights
- cov (DataFrame): Covariance matrix
- returns (DataFrame): Historical returns
- rm (str): Risk measure
- rf (float): Risk-free rate
- alpha (float): Significance level
- cmap (str): Colormap
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object
"""Visualization of portfolio allocations and weights.
def plot_pie(w, title='Portfolio Composition', others=0.05, nrow=25,
cmap='tab20', height=6, width=8, ax=None):
"""
Plot portfolio allocation as pie chart.
Parameters:
- w (DataFrame): Portfolio weights
- title (str): Chart title
- others (float): Threshold for grouping small positions
- nrow (int): Maximum number of assets to show individually
- cmap (str): Colormap
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with pie chart
"""
def plot_bar(w, title='Portfolio Composition', kind='v', others=0.05,
nrow=25, cmap='tab20', height=6, width=10, ax=None):
"""
Plot portfolio allocation as bar chart.
Parameters:
- w (DataFrame): Portfolio weights
- title (str): Chart title
- kind (str): Bar orientation ('v' for vertical, 'h' for horizontal)
- others (float): Threshold for grouping small positions
- nrow (int): Maximum number of assets to show
- cmap (str): Colormap
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with bar chart
"""Charts for risk contribution analysis and risk decomposition.
def plot_risk_con(w, cov, returns, rm='MV', rf=0, alpha=0.05, color='tab:blue',
height=6, width=10, ax=None):
"""
Plot risk contributions by asset.
Parameters:
- w (DataFrame): Portfolio weights
- cov (DataFrame): Covariance matrix
- returns (DataFrame): Historical returns
- rm (str): Risk measure
- rf (float): Risk-free rate
- alpha (float): Significance level
- color (str): Bar color
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with risk contribution chart
"""
def plot_factor_risk_con(w, cov, B, rm='MV', rf=0, alpha=0.05,
color='tab:blue', height=6, width=10, ax=None):
"""
Plot factor risk contributions.
Parameters:
- w (DataFrame): Portfolio weights
- cov (DataFrame): Factor covariance matrix
- B (DataFrame): Factor loadings
- rm (str): Risk measure
- rf (float): Risk-free rate
- alpha (float): Significance level
- color (str): Bar color
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with factor risk chart
"""Time series plots and distribution analysis.
def plot_series(returns, w=None, cmap='tab20', height=6, width=10, ax=None):
"""
Plot portfolio returns time series.
Parameters:
- returns (DataFrame): Returns data
- w (DataFrame): Portfolio weights (optional)
- cmap (str): Colormap for multiple series
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with time series plot
"""
def plot_hist(returns, w=None, alpha=0.05, bins=50, height=6, width=10, ax=None):
"""
Plot returns histogram with risk measures.
Parameters:
- returns (DataFrame): Returns data
- w (DataFrame): Portfolio weights for weighted returns
- alpha (float): Significance level for VaR/CVaR
- bins (int): Number of histogram bins
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with histogram
"""
def plot_drawdown(returns, w=None, alpha=0.05, height=6, width=10, ax=None):
"""
Plot drawdown time series.
Parameters:
- returns (DataFrame): Returns data
- w (DataFrame): Portfolio weights
- alpha (float): Significance level for drawdown measures
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with drawdown plot
"""
def plot_range(returns, w=None, alpha=0.05, height=6, width=10, ax=None):
"""
Plot returns range over time.
Parameters:
- returns (DataFrame): Returns data
- w (DataFrame): Portfolio weights
- alpha (float): Significance level
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with range plot
"""Visualization of asset relationships and clustering analysis.
def plot_clusters(returns, codependence='pearson', linkage='ward', k=None,
max_k=10, leaf_order=True, cmap='viridis', height=8, width=10, ax=None):
"""
Plot clustered correlation matrix.
Parameters:
- returns (DataFrame): Returns data
- codependence (str): Codependence measure
- linkage (str): Linkage method for clustering
- k (int): Number of clusters (optional)
- max_k (int): Maximum clusters for optimization
- leaf_order (bool): Optimize leaf order
- cmap (str): Colormap for correlation matrix
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with clustered heatmap
"""
def plot_dendrogram(returns, codependence='pearson', linkage='ward',
k=None, max_k=10, leaf_order=True, height=6, width=10, ax=None):
"""
Plot hierarchical clustering dendrogram.
Parameters:
- returns (DataFrame): Returns data
- codependence (str): Codependence measure
- linkage (str): Linkage method
- k (int): Number of clusters to highlight
- max_k (int): Maximum clusters
- leaf_order (bool): Optimize leaf order
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with dendrogram
"""
def plot_network(returns, codependence='pearson', network='MST', k=None,
max_k=10, alpha_tail=0.05, gs_threshold=0.5, node_color='lightblue',
height=8, width=10, ax=None):
"""
Plot correlation network graph.
Parameters:
- returns (DataFrame): Returns data
- codependence (str): Codependence measure
- network (str): Network method ('MST', 'PMFG', 'TN', 'DBHT')
- k (int): Number of clusters
- max_k (int): Maximum clusters
- alpha_tail (float): Significance for tail dependence
- gs_threshold (float): Threshold for network connections
- node_color (str): Color for network nodes
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with network plot
"""
def plot_network_allocation(returns, w, codependence='pearson', network='MST',
cmap='viridis', height=8, width=10, ax=None):
"""
Plot network with portfolio allocation overlay.
Parameters:
- returns (DataFrame): Returns data
- w (DataFrame): Portfolio weights
- codependence (str): Codependence measure
- network (str): Network method
- cmap (str): Colormap for weight visualization
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with allocation network
"""Visualization of performance attribution analysis.
def plot_BrinsonAttribution(Ra, Rb, Wa, Wb, height=6, width=10, ax=None):
"""
Plot Brinson performance attribution analysis.
Parameters:
- Ra (DataFrame): Portfolio returns
- Rb (DataFrame): Benchmark returns
- Wa (DataFrame): Portfolio weights
- Wb (DataFrame): Benchmark weights
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with attribution chart
"""
def plot_table(returns, w, MAR=0, alpha=0.05, height=9, width=12, ax=None):
"""
Plot portfolio statistics table.
Parameters:
- returns (DataFrame): Returns data
- w (DataFrame): Portfolio weights
- MAR (float): Minimum acceptable return
- alpha (float): Significance level
- height (float): Figure height
- width (float): Figure width
- ax (matplotlib.axes): Existing axes
Returns:
matplotlib.axes: Axes object with statistics table
"""import riskfolio as rp
import pandas as pd
import matplotlib.pyplot as plt
# Load data and create portfolio
returns = pd.read_csv('returns.csv', index_col=0, parse_dates=True)
port = rp.Portfolio(returns=returns)
port.assets_stats()
# Optimize portfolio
w = port.optimization(model='Classic', rm='MV', obj='Sharpe', rf=0.02)
# Plot portfolio composition
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))
rp.plot_pie(w, title='Portfolio Allocation', ax=ax1)
rp.plot_bar(w, title='Portfolio Weights', kind='v', ax=ax2)
plt.tight_layout()
plt.show()
# Plot risk contributions
fig, ax = plt.subplots(figsize=(12, 6))
rp.plot_risk_con(w, port.cov, returns, rm='MV', ax=ax)
plt.show()import riskfolio as rp
import pandas as pd
# Create portfolio and generate frontier
returns = pd.read_csv('returns.csv', index_col=0, parse_dates=True)
port = rp.Portfolio(returns=returns)
port.assets_stats()
# Generate efficient frontier
frontier = port.efficient_frontier(model='Classic', rm='MV', points=100)
# Plot frontier with specific portfolio highlighted
w_optimal = port.optimization(model='Classic', rm='MV', obj='Sharpe', rf=0.02)
ax = rp.plot_frontier(
w_frontier=frontier,
mu=port.mu,
cov=port.cov,
returns=returns,
rm='MV',
rf=0.02,
w=w_optimal,
label='Optimal Portfolio',
marker='*',
s=100,
c='red'
)
plt.show()
# Compare multiple risk measures
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
axes = axes.flatten()
risk_measures = ['MV', 'CVaR', 'MDD', 'CDaR']
for i, rm in enumerate(risk_measures):
frontier_rm = port.efficient_frontier(model='Classic', rm=rm, points=50)
rp.plot_frontier(
w_frontier=frontier_rm,
mu=port.mu,
cov=port.cov,
returns=returns,
rm=rm,
rf=0.02,
ax=axes[i]
)
axes[i].set_title(f'Efficient Frontier - {rm}')
plt.tight_layout()
plt.show()import riskfolio as rp
import pandas as pd
import matplotlib.pyplot as plt
# Load returns
returns = pd.read_csv('returns.csv', index_col=0, parse_dates=True)
# Plot clustering analysis
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))
# Dendrogram
rp.plot_dendrogram(
returns=returns,
codependence='pearson',
linkage='ward',
k=5,
ax=ax1
)
ax1.set_title('Hierarchical Clustering Dendrogram')
# Clustered correlation matrix
rp.plot_clusters(
returns=returns,
codependence='pearson',
linkage='ward',
k=5,
ax=ax2
)
ax2.set_title('Clustered Correlation Matrix')
# Network plot
rp.plot_network(
returns=returns,
codependence='pearson',
network='MST',
k=5,
ax=ax3
)
ax3.set_title('Minimum Spanning Tree Network')
# Portfolio allocation on network
port = rp.Portfolio(returns=returns)
port.assets_stats()
w = port.optimization(obj='Sharpe', rm='MV', rf=0.02)
rp.plot_network_allocation(
returns=returns,
w=w,
codependence='pearson',
network='MST',
ax=ax4
)
ax4.set_title('Portfolio Allocation Network')
plt.tight_layout()
plt.show()import riskfolio as rp
import pandas as pd
import matplotlib.pyplot as plt
# Load returns
returns = pd.read_csv('returns.csv', index_col=0, parse_dates=True)
# Create equal-weight and optimized portfolios
port = rp.Portfolio(returns=returns)
port.assets_stats()
w_equal = pd.DataFrame(1/len(returns.columns), index=returns.columns, columns=['weights'])
w_optimal = port.optimization(obj='Sharpe', rm='MV', rf=0.02)
# Calculate portfolio returns
ret_equal = (returns * w_equal.T).sum(axis=1)
ret_optimal = (returns * w_optimal.T).sum(axis=1)
# Plot comparisons
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))
# Time series
combined_returns = pd.DataFrame({
'Equal Weight': ret_equal,
'Optimized': ret_optimal
})
rp.plot_series(combined_returns, ax=ax1)
ax1.set_title('Portfolio Returns Comparison')
# Histograms
rp.plot_hist(combined_returns, alpha=0.05, ax=ax2)
ax2.set_title('Returns Distribution')
# Drawdowns
rp.plot_drawdown(combined_returns, alpha=0.05, ax=ax3)
ax3.set_title('Drawdown Analysis')
# Rolling performance
rp.plot_range(combined_returns, alpha=0.05, ax=ax4)
ax4.set_title('Rolling Performance Range')
plt.tight_layout()
plt.show()Install with Tessl CLI
npx tessl i tessl/pypi-riskfolio-lib