# Estimate optimal portfolio: model = 'Classic' # Could be Classic (historical), BL (Black Litterman) or FM (Factor Model) rm = 'MV' # Risk measure used, this time will be variance obj = 'Sharpe' # Objective function, could be MinRisk, MaxRet, Utility or Sharpe hist = True # Use historical scenarios for risk measures that depend on scenarios rf = 0 # Risk free rate l = 0 # Risk aversion factor, only useful when obj is 'Utility' w = port.optimization(model=model, rm=rm, obj=obj, rf=rf, l=l, hist=hist) print(w.T) # Plotting the composition of the portfolio ax = plf.plot_pie(w=w, title='Sharpe Mean Variance', others=0.05, nrow=25, cmap="tab20", height=6, width=10, ax=None) points = 50 # Number of points of the frontier frontier = port.efficient_frontier(model=model, rm=rm, points=points, rf=rf, hist=hist) print(frontier.T.head()) # Plotting the efficient frontier label = 'Max Risk Adjusted Return Portfolio' # Title of point mu = port.mu # Expected returns cov = port.cov # Covariance matrix
rf=0, alpha=0.01, cmap="viridis", w=w2_1, label="Portfolio", marker="*", s=16, c="r", height=6, width=10, ax=None, ) ax = plf.plot_pie(w=w2_1, title="Portafolio", height=6, width=10, cmap="tab20", ax=None) # # # w0 = pd.DataFrame(np.ones((100,1))/100) # # # ax = plf.plot_pie(w=w0, title='Portafolio', height=6, width=10, cmap = "tab20", ax=None) # # ax = plf.plot_frontier_area(w_frontier=w_5, cmap="tab20", height=6, width=10, ax=None) # ax = plf.plot_hist(data=Y, w=w1, alpha=0.01, bins=50, height=6, width=10, # ax=None) # ax = plf.plot_drawdown(data=Y, w=w1, alpha=0.01, height=8, width=10, ax=None) # # ax = plf.plot_series(data=Y, w=w_5, cmap='tab20', height=6, width=10, ax=None)
def portfolio_optimizer( rm='CVaR', alpha=0.1, risk_free=0.02, strategy='sharpe_scale_patterns_day', ): pd.options.display.float_format = '{:.1%}'.format # 股票代码,我直接用我的选股程序获取选股列表。 position_signals = position(portfolio=strategy, frequency='day', market_type=QA.MARKET_TYPE.STOCK_CN, verbose=False) if (position_signals is not None) and \ (len(position_signals) > 0): datestamp = position_signals.index[0][0] position_signals_best = position_signals.loc[ position_signals[FLD.LEVERAGE_ONHOLD].gt(0.99), :] if (len(position_signals_best) > 20): position_signals = position_signals_best else: pass codelist = position_signals.index.get_level_values(level=1).to_list() # 获取股票中文名称,只是为了看得方便,交易策略并不需要股票中文名称 stock_names = QA.QA_fetch_stock_name(codelist) codename = [stock_names.at[code, 'name'] for code in codelist] codename_T = {codename[i]: codelist[i] for i in range(len(codelist))} data_day = QA.QA_fetch_stock_day_adv( codelist, start='2014-01-01', end='{}'.format(datetime.date.today())).to_qfq() # 收益率序列 rets_jotion = data_day.add_func(kline_returns_func) returns = pd.DataFrame( columns=codelist, index=sorted( data_day.data.index.get_level_values(level=0).unique())) for code in codelist: returns[code] = rets_jotion.loc[(slice(None), code), :].reset_index(level=[1], drop=True) returns = returns.fillna(0) returns = returns.rename( columns={codelist[i]: codename[i] for i in range(len(codelist))}) import riskfolio.Portfolio as pf # Building the portfolio object port = pf.Portfolio(returns=returns) # Calculating optimum portfolio # Select method and estimate input parameters: method_mu = 'hist' # Method to estimate expected returns based on historical data. method_cov = 'hist' # Method to estimate covariance matrix based on historical data. port.assets_stats(method_mu=method_mu, method_cov=method_cov, d=0.94) ## Estimate optimal portfolio: model = 'Classic' # Could be Classic (historical), BL (Black Litterman) or FM (Factor Model) obj = 'Sharpe' # Objective function, could be MinRisk, MaxRet, Utility or Sharpe hist = True # Use historical scenarios for risk measures that depend on scenarios rf = risk_free / 365 # Risk free rate l = 0 # Risk aversion factor, only useful when obj is 'Utility' port.alpha = alpha # 暗色主题 plt.style.use('Solarize_Light2') # 正常显示中文字体 plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] import riskfolio.PlotFunctions as plf # Plotting the composition of the portfolio w = port.optimization(model=model, rm=rm, obj=obj, rf=rf, l=l, hist=hist) opt_weights = w.copy() opt_weights['code'] = opt_weights.apply(lambda x: codename_T[x.name], axis=1) opt_weights['name'] = opt_weights.apply(lambda x: x.name, axis=1) opt_weights = opt_weights.set_index(['code'], drop=False) print(u'交易日', datestamp) show_verbose(opt_weights, obj, rm) if (rm == 'CVaR'): # Risk measure CVaR title = 'Sharpe Mean CVaR' elif (rm == 'MV'): # Risk measure used, this time will be variance title = 'Sharpe Mean Variance' elif (rm == 'WR'): title = 'Sharpe Mean WR' elif (rm == 'Sortino'): title = 'Sortino Mean WR' else: rm = 'CVaR' title = 'Sharpe Mean CVaR' ax = plf.plot_pie(w=w, title=title, others=0.05, nrow=25, cmap="tab20", height=6, width=10, ax=None) plt.show() ## Plotting efficient frontier composition #points = 10 # Number of points of the frontier #frontier = port.efficient_frontier(model=model, rm=rm, points=points, #rf=rf, hist=hist) ##print(frontier.T.head()) #ax = plf.plot_frontier_area(w_frontier=frontier, cmap="tab20", height=6, #width=10, ax=None) #plt.show() else: print(u'没有可用的选股数据。')
def jupyter_report( returns, w, rm="MV", rf=0, alpha=0.05, others=0.05, nrow=25, height=6, width=14, t_factor=252, ): r""" Create a matplotlib report with useful information to analyze risk and profitability of investment portfolios. Parameters ---------- returns : DataFrame Assets returns. w : DataFrame of shape (n_assets, 1) Portfolio weights. rm : str, optional Risk measure used to estimate risk contribution. The default is 'MV'. Posible values are: - 'MV': Standard Deviation. - 'MAD': Mean Absolute Deviation. - 'MSV': Semi Standard Deviation. - 'FLPM': First Lower Partial Moment (Omega Ratio). - 'SLPM': Second Lower Partial Moment (Sortino Ratio). - 'CVaR': Conditional Value at Risk. - 'EVaR': Conditional Value at Risk. - 'WR': Worst Realization (Minimax) - 'MDD': Maximum Drawdown of uncompounded returns (Calmar Ratio). - 'ADD': Average Drawdown of uncompounded returns. - 'DaR': Drawdown at Risk of uncompounded returns. - 'CDaR': Conditional Drawdown at Risk of uncompounded returns. - 'UCI': Ulcer Index of uncompounded returns. rf : float, optional Risk free rate or minimum aceptable return. The default is 0. alpha : float, optional Significante level of VaR, CVaR, EVaR, DaR and CDaR. The default is 0.05. others : float, optional Percentage of others section. The default is 0.05. nrow : int, optional Number of rows of the legend. The default is 25. height : float, optional Average height of charts in the image in inches. The default is 6. width : float, optional Width of the image in inches. The default is 14. t_factor : float, optional Factor used to annualize expected return and expected risks for risk measures based on returns (not drawdowns). The default is 252. .. math:: \begin{align} \text{Annualized Return} & = \text{Return} \, \times \, \text{t_factor} \\ \text{Annualized Risk} & = \text{Risk} \, \times \, \sqrt{\text{t_factor}} \end{align} ax : matplotlib axis of size (6,1), optional If provided, plot on this axis. The default is None. Raises ------ ValueError When the value cannot be calculated. Returns ------- ax : matplotlib axis Returns the Axes object with the plot for further tweaking. Example ------- :: ax = rp.jupyter_report(returns, w, rm='MV', rf=0, alpha=0.05, height=6, width=14, others=0.05, nrow=25) .. image:: images/Report_1.png .. image:: images/Report_2.png .. image:: images/Report_3.png .. image:: images/Report_4.png """ cov = returns.cov() nav = returns.cumsum() fig, ax = plt.subplots( nrows=6, figsize=(width, height * 6), gridspec_kw={"height_ratios": [2, 1, 1.5, 1, 1, 1]}, ) ax[0] = plf.plot_table(returns, w, MAR=rf, alpha=alpha, t_factor=t_factor, ax=ax[0]) ax[2] = plf.plot_pie( w=w, title="Portfolio Composition", others=others, nrow=nrow, cmap="tab20", ax=ax[2], ) ax[3] = plf.plot_risk_con( w=w, cov=cov, returns=returns, rm=rm, rf=rf, alpha=alpha, ax=ax[3] ) ax[4] = plf.plot_hist(returns=returns, w=w, alpha=alpha, bins=50, ax=ax[4]) ax[[1, 5]] = plf.plot_drawdown(nav=nav, w=w, alpha=0.05, ax=ax[[1, 5]]) year = str(datetime.datetime.now().year) title = "Riskfolio-Lib Report" subtitle = "Copyright (c) 2020-" + year + ", Dany Cajas. All rights reserved." fig.suptitle(title, fontsize="xx-large", y=1.011, fontweight="bold") ax[0].set_title(subtitle, fontsize="large", ha="center", pad=10) return ax