Example #1
0
    def savefig(self):
        returns = self.port.returns

        model = 'Classic'

        # 포트폴리오 수익률과 비중 저장
        with open(
                'returns-{}_{}.pkl'.format(self.risk_profile,
                                           self.current_date), 'wb') as f:
            pl.dump(returns, f)

        with open('w-{}_{}.pkl'.format(self.risk_profile, self.current_date),
                  'wb') as f:
            pl.dump(self.w, f)

        # Efficient fronter 저장
        points = 50  # Number of points of the frontier
        frontier = self.port.efficient_frontier(model=model,
                                                rm=self.rm,
                                                points=points,
                                                rf=self.rf,
                                                hist=True)

        label = 'Max-return Portfolio' if self.risk_profile == 4 else 'Min-risk Portfolio'
        mu = self.port.mu  # Expected returns
        cov = self.port.cov  # Covariance matrix

        fig1, ax1 = plt.subplots()

        ax1 = plf.plot_frontier(w_frontier=frontier,
                                mu=mu,
                                cov=cov,
                                returns=returns,
                                rm=self.rm,
                                rf=self.rf,
                                alpha=0.05,
                                cmap='viridis',
                                w=self.w,
                                label=label,
                                marker='*',
                                s=16,
                                c='r',
                                height=6,
                                width=10,
                                ax=ax1)

        fig1.savefig('ef-{}_{}.png'.format(self.risk_profile,
                                           self.current_date))

        fig2, ax2 = plt.subplots(nrows=1, ncols=1)
        # Plotting efficient frontier composition
        ax2 = plf.plot_frontier_area(w_frontier=frontier,
                                     cmap="tab20",
                                     height=6,
                                     width=10,
                                     ax=None)
        fig2.savefig('ef_area-{}_{}.png'.format(self.risk_profile,
                                                self.current_date))
# 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
Example #3
0
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'没有可用的选股数据。')
Example #4
0
#%%

label = "Max Risk Adjusted Return Portfolio"
mu = port.mu
cov = port.cov
returns = port.returns

ax = plf.plot_frontier(
    w_frontier=w_5,
    mu=mu,
    cov=cov,
    returns=returns,
    rm=rm,
    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)
Example #5
0
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