Source code for finsim.portfolio.create


from datetime import datetime, timedelta
import warnings
from os import PathLike
from typing import Optional

import numpy as np
import pandas as pd

from .optimize.numerics import get_BlackScholesMerton_stocks_estimation, get_stocks_timeweighted_estimation
from .portfolio import OptimizedPortfolio
from .optimize.policy import OptimizedWeightingPolicyUsingMPTSharpeRatio, \
    OptimizedWeightingPolicyUsingMPTCostFunction, OptimizedWeightingPolicyUsingMPTEntropyCostFunction


[docs] def get_optimized_portfolio_on_sharpe_ratio( rf: float, symbols: list[str], totalworth: float, presetdate: str, estimating_startdate: str, estimating_enddate: str, minweight: float=0., lazy: bool=False, cacheddir: Optional[PathLike | str]=None, include_dividends: bool=False ) -> OptimizedPortfolio: """Create an optimized portfolio based on the Sharpe ratio optimization method. This function creates a portfolio optimized using the Sharpe ratio maximization approach from Modern Portfolio Theory (MPT). It estimates asset returns and covariances using the Black-Scholes-Merton model and then optimizes weights to maximize the Sharpe ratio. Args: rf: Risk-free rate symbols: List of stock symbols to include in the portfolio totalworth: Total value of the portfolio presetdate: Date for which to calculate the portfolio composition estimating_startdate: Start date for return estimation estimating_enddate: End date for return estimation minweight: Minimum weight for each asset (default: 0.0) lazy: Deprecated parameter (default: False) cacheddir: Directory for cached data (optional) include_dividends: Whether to include dividends in calculations (default: False) Returns: OptimizedPortfolio: An optimized portfolio object with calculated weights """ if lazy: warnings.warn('Setting lazy=True is meaningless! Parameter deprecated!') r, cov = get_BlackScholesMerton_stocks_estimation( symbols, estimating_startdate, estimating_enddate, cacheddir=cacheddir, include_dividends=include_dividends ) optimized_weighting_policy = OptimizedWeightingPolicyUsingMPTSharpeRatio(rf, r, cov, symbols, minweight=minweight) optimized_portfolio = OptimizedPortfolio(optimized_weighting_policy, totalworth, presetdate, cacheddir=cacheddir) return optimized_portfolio
[docs] def get_optimized_portfolio_on_mpt_costfunction( rf: float, symbols: list[str], totalworth: float, presetdate: str, estimating_startdate: str, estimating_enddate: str, lamb: float, V0: float=10., cacheddir: Optional[PathLike | str]=None, include_dividends: bool=False ) -> OptimizedPortfolio: """Create an optimized portfolio based on the MPT cost function optimization method. This function creates a portfolio optimized using a cost function approach from Modern Portfolio Theory (MPT). It estimates asset returns and covariances using the Black-Scholes-Merton model and then optimizes weights using a cost function. Args: rf: Risk-free rate symbols: List of stock symbols to include in the portfolio totalworth: Total value of the portfolio presetdate: Date for which to calculate the portfolio composition estimating_startdate: Start date for return estimation estimating_enddate: End date for return estimation lamb: Lambda parameter for the cost function V0: Initial portfolio value (default: 10.0) cacheddir: Directory for cached data (optional) include_dividends: Whether to include dividends in calculations (default: False) Returns: OptimizedPortfolio: An optimized portfolio object with calculated weights """ r, cov = get_BlackScholesMerton_stocks_estimation( symbols, estimating_startdate, estimating_enddate, cacheddir=cacheddir, include_dividends=include_dividends ) optimized_weighting_policy = OptimizedWeightingPolicyUsingMPTCostFunction(rf, r, cov, symbols, lamb, V0=V0) optimized_portfolio = OptimizedPortfolio(optimized_weighting_policy, totalworth, presetdate, cacheddir=cacheddir) return optimized_portfolio
[docs] def get_optimized_portfolio_on_mpt_entropy_costfunction( rf: float, symbols: list[str], totalworth: float, presetdate: str, estimating_startdate: str, estimating_enddate: str, lamb0: float, lamb1: float, V: float=10., cacheddir: Optional[PathLike | str]=None, include_dividends: bool=False ) -> OptimizedPortfolio: """Create an optimized portfolio based on the MPT entropy cost function optimization method. This function creates a portfolio optimized using an entropy cost function approach from Modern Portfolio Theory (MPT). It estimates asset returns and covariances using the Black-Scholes-Merton model and then optimizes weights using an entropy cost function. Args: rf: Risk-free rate symbols: List of stock symbols to include in the portfolio totalworth: Total value of the portfolio presetdate: Date for which to calculate the portfolio composition estimating_startdate: Start date for return estimation estimating_enddate: End date for return estimation lamb0: Lambda 0 parameter for the entropy cost function lamb1: Lambda 1 parameter for the entropy cost function V: Portfolio value parameter (default: 10.0) cacheddir: Directory for cached data (optional) include_dividends: Whether to include dividends in calculations (default: False) Returns: OptimizedPortfolio: An optimized portfolio object with calculated weights """ r, cov = get_BlackScholesMerton_stocks_estimation( symbols, estimating_startdate, estimating_enddate, cacheddir=cacheddir, include_dividends=include_dividends ) optimized_weighting_policy = OptimizedWeightingPolicyUsingMPTEntropyCostFunction(rf, r, cov, symbols, lamb0, lamb1, V=V) optimized_portfolio = OptimizedPortfolio(optimized_weighting_policy, totalworth, presetdate, cacheddir=cacheddir) return optimized_portfolio
########### Time-weighted portfolio ##############
[docs] def get_exponential_timeweightdf( startdate: str, enddate: str, yearscale: float ) -> pd.DataFrame: """Generate exponential time weights for portfolio optimization. This function creates a DataFrame with exponentially decaying weights over time, which can be used for time-weighted portfolio optimization. Args: startdate: Start date in 'YYYY-MM-DD' format enddate: End date in 'YYYY-MM-DD' format yearscale: Time scale parameter for exponential decay Returns: pd.DataFrame: DataFrame with 'TimeStamp' and 'weight' columns """ startdateobj = datetime.strptime(startdate, '%Y-%m-%d') enddateobj = datetime.strptime(enddate, '%Y-%m-%d') timestamps = np.arange(startdateobj, enddateobj+timedelta(days=1), timedelta(days=1), dtype='datetime64[ns]') weights = np.exp(-(len(timestamps)-1-np.arange(len(timestamps)))/365/yearscale) timeweightdf = pd.DataFrame({ 'TimeStamp': timestamps, 'weight': weights }) return timeweightdf
[docs] def get_optimized_exponential_timeweighted_portfolio_on_mpt_entropy_costfunction( rf: float, symbols: list[str], totalworth: float, presetdate: str, estimating_startdate: str, estimating_enddate: str, yearscale: float, lamb0: float, lamb1: float, V: float=10., cacheddir: Optional[PathLike | str]=None, include_dividends: bool=False ) -> OptimizedPortfolio: """Create an optimized time-weighted portfolio using exponential weights and entropy cost function. This function creates a portfolio optimized using an entropy cost function approach from Modern Portfolio Theory (MPT) with exponential time weighting. It estimates asset returns and covariances using the Black-Scholes-Merton model with time weights and then optimizes weights using an entropy cost function. Args: rf: Risk-free rate symbols: List of stock symbols to include in the portfolio totalworth: Total value of the portfolio presetdate: Date for which to calculate the portfolio composition estimating_startdate: Start date for return estimation estimating_enddate: End date for return estimation yearscale: Time scale parameter for exponential decay lamb0: Lambda 0 parameter for the entropy cost function lamb1: Lambda 1 parameter for the entropy cost function V: Portfolio value parameter (default: 10.0) cacheddir: Directory for cached data (optional) include_dividends: Whether to include dividends in calculations (default: False) Returns: OptimizedPortfolio: An optimized time-weighted portfolio object with calculated weights """ timeweightdf = get_exponential_timeweightdf(estimating_startdate, estimating_enddate, yearscale) r, cov = get_stocks_timeweighted_estimation( symbols, timeweightdf, cacheddir=cacheddir, include_dividends=include_dividends ) optimized_weighting_policy = OptimizedWeightingPolicyUsingMPTEntropyCostFunction(rf, r, cov, symbols, lamb0, lamb1, V=V) optimized_portfolio = OptimizedPortfolio(optimized_weighting_policy, totalworth, presetdate, cacheddir=cacheddir) return optimized_portfolio