Пример #1
0
def price_Loss(beta, df, coupons_cf, streak_data,
               rho=0.2, weight_scheme='rev_span', tau=None):
    '''
    Parameters
    ---------------
    beta: array-like
        Nelson-Siegel's vector of parameters
    df: Pandas Dataframe
        Dataframe of bonds' data
    coupons_cf: Pandas Dataframe
        Dataframe containing bonds' payment cash flows
    streak_data: Pandas Dataframe
        Dataframe containing bonds' payment calendar
    rho: float from 0 to 1, default 0.2
        Weight of oldest deal - only used in
        'vol_time', 'full_vol_time', 'volume_kzt', 'complex_volume' weight schemes
    weight_scheme: str, default 'no_weight'
        weight function used to weight deals
    tau: float, default None
        Use this parameter if only you do 3-variablie minimization.
        Parameter is only used in grid search optimization
    '''
    #if tau is given, then beta is array
    if tau is not None:
        assert beta.shape[0] == 3
        beta = np.append(beta, [tau])
    ind = df.index
    Price = (D(streak_data[ind], beta) * coupons_cf[ind]).sum().values
    Loss = np.linalg.norm(weight(beta, df=df, rho=rho, weight_scheme=weight_scheme) *
           (df.stand_price.values - Price))
    return Loss
Пример #2
0
def naive_yield_Loss(beta, df, coupons_cf, streak_data, rho=0.2,
                     weight_scheme='no_weight', tau=None):
    '''
    Parameters
    ---------------
    beta: array-like
        Nelson-Siegel's vector of parameters
    df: Pandas Dataframe
        Dataframe of bonds' data
    coupons_cf: Pandas Dataframe
        Dataframe containing bonds' payment cash flows
    streak_data: Pandas Dataframe
        Dataframe containing bonds' payment calendar
    rho: float from 0 to 1, default 0.2
        Weight of oldest deal - only used in
        'vol_time', 'full_vol_time', 'volume_kzt', 'complex_volume' weight schemes
    weight_scheme: str, default 'no_weight'
        weight function used to weight deals
    tau: float, default None
        Use this parameter if only you do 3-variablie minimization.
        Parameter is only used in grid search optimization
    '''
    #if tau is given, then beta is array
    if tau is not None:
        assert beta.shape[0] == 3
        beta = np.append(beta, [tau])
    #estimating price
    #calculatting Loss
    W = weight(beta, df=df, rho=rho, weight_scheme=weight_scheme)
    Loss = (W * np.square(df.ytm.values - Z(df.span / 365, beta))).sum()
    return Loss
Пример #3
0
def grad(beta,
         data,
         coupons_cf,
         streak_data,
         rho=0.2,
         weight_scheme='no_weight'):
    m = data['span']
    grad_z = []
    teta_m = m / beta[3]
    grad_z.append(1)
    grad_z.append((1 / teta_m) * (1 - np.exp(-teta_m)))
    grad_z.append((1 / teta_m) * (1 - np.exp(-teta_m)) - np.exp(-teta_m))

    teta_m_der = m / (beta[3]**2)
    grad_z.append(
        ((beta[1] + beta[2]) *
         ((1 / m) * (1 - np.exp(-teta_m)) - np.exp(-teta_m) / beta[3]) -
         beta[2] * np.exp(-teta_m) * teta_m_der))
    #calculatting Loss
    W = weight(beta, df=data, rho=rho, weight_scheme=weight_scheme)

    non_grad = W * (data['ytm'] / 100 - Z(m, beta))
    loss_grad = np.zeros_like(beta)
    for i in range(beta.shape[0]):
        loss_grad[i] = -2 * (non_grad * grad_z[i]).sum()
    return loss_grad
Пример #4
0
def yield_Loss(beta,
               df,
               coupons_cf,
               streak_data,
               rho=0.2,
               weight_scheme='no_weight',
               tau=None):
    '''
    Parameters
    ---------------
    beta: array-like
        Nelson-Siegel's vector of parameters
    df: Pandas Dataframe
        Dataframe of bonds' data
    coupons_cf: Pandas Dataframe
        Dataframe containing bonds' payment cash flows
    streak_data: Pandas Dataframe
        Dataframe containing bonds' payment calendar
    rho: float from 0 to 1, default 0.2
        Weight of oldest deal - only used in 
        'vol_time', 'full_vol_time', 'volume_kzt', 'complex_volume' weight schemes
    weight_scheme: str, default 'no_weight'
        weight function used to weight deals
    tau: float, default None
        Use this parameter if only you do 3-variablie minimization.
        Parameter is only used in grid search optimization
    '''
    #if tau is given, then beta is array
    if tau is not None:
        assert beta.shape[0] == 3
        beta = np.append(beta, [tau])
    ind = df.index
    #estimating price
    Price = (D(streak_data[ind], beta) * coupons_cf[ind]).sum().values
    if (Price <= 0).any():
        Loss = 1e100
    else:
        ytm_hat = np.array([
            newton_estimation(df.iloc[i],
                              Price[i],
                              coupons_cf,
                              streak_data,
                              maxiter=200) for i in range(df.shape[0])
        ])
        #calculatting Loss
        W = weight(beta, df=df, rho=rho, weight_scheme=weight_scheme)
        Loss = (W * np.square(df['ytm'].values - ytm_hat)).sum()
    return Loss
Пример #5
0
#Parameters bounds for constraint optimization
bounds = ((0, 1), (None, None), (None, None), (CONFIG.TETA_MIN, CONFIG.TETA_MAX))

#Maturity limit for Zero-curve plot
longest_maturity_year = max([max_deal_span, 20])
theor_maturities = np.linspace(0.001, longest_maturity_year, 10000)
options = {'maxiter': 500, 'eps': 9e-5, 'disp': True}

#Tuple of arguments for loss function            
loss_args = (filtered_data, coupons_cf, streak_data, CONFIG.RHO, CONFIG.WEIGHT_SCHEME)

#defining loss
loss = yield_Loss

filtered_data['weight'] = weight([1, 1, 1, 1], filtered_data, CONFIG.WEIGHT_SCHEME)

###### OPTIMIZATION
print('start optimization\n')
res_ = iter_minimizer(Loss=loss, beta_init=x0, 
                loss_args=loss_args, method='SLSQP',  
                bounds=bounds,
                constraints=constr,
                max_deal_span=max_deal_span, options=options)
beta_best = res_.x
print('end optimization\n')

### Showing results of work

draw(beta_best, filtered_data, theor_maturities, f'{CONFIG.SETTLE_DATE:%d.%m.%Y}', 
     longest_maturity_year, draw_points=True, 
Пример #6
0
def draw(beta,
         df,
         theor_maturities,
         title_date,
         longest_maturity_year,
         weight_scheme=None,
         ax=None,
         draw_points=True,
         label=None,
         shift=False,
         **kwargs):
    '''
    Drawing spot curve based on beta
    
    Parameters
    ------------
    beta: list-like
        Should be length of 4. Nelson-Siegel's vector of parameters
    df: Pandas Dataframe
        Dataframe of bonds' data
    theor_maturities: list-like
        Vector of maturities
    title_date: str or datetime
        Settle date of the curve's construction
    longest_maturity_year: int
        Maximum tenor on which plot will be drawn
    weight_scheme: 'str', default: None
        Weights of deals
    ax: Matplotlib Axes, default: None
    draw_points: bool
        Whether to draw deals' ytm on plot or not
    label: str, default: None
    shift: bool, default: False
        If shift true transforms spot rate curve from discrete to continuous
    '''
    #defining zero curbe
    beta = beta.copy()
    spot_rates = spot_nelson(theor_maturities, beta)
    if shift:
        spot_rates = (np.exp(spot_rates) - 1)

    #setting axes
    if ax is None:
        fig, ax = plt.subplots(figsize=(15, 10))
    if label is None:
        beta[:3] *= 100
        label = f'{beta.round(2)}'
    ax.plot(theor_maturities, spot_rates, label=label, **kwargs)
    #draw scatterplot of deals or not?
    if draw_points:
        y_scatter = df['ytm'].values
        x_scatter = df['span'].values / 365
        #size of points; depends on weight of transaction
        s = (weight(beta, df, weight_scheme=weight_scheme) /
             weight(beta, df, weight_scheme=weight_scheme).sum())
        ax.scatter(x_scatter,
                   y_scatter,
                   s=s * 15 * 1e3,
                   facecolors='none',
                   edgecolors='grey',
                   alpha=0.9)
    #setting labels, ticks, legend and title
    ax.set_title(f'Curves at {title_date} for {df.shape[0]} deals')
    ax.set_ylabel('%')
    ax.set_xlabel('Tenor in years')
    ax.set_xticks(np.arange(0, longest_maturity_year + 1, 1))
    ax.legend()