(weights, y, input_type='log', output_type='simple', rebalance=False)
Compute portfolio returns.

    Parameters
    ----------
    weights : torch.Tensor
        Tensor of shape (n_samples, n_assets) representing the simple buy and hold strategy over the horizon.

    y : torch.Tensor
        Tensor of shape (n_samples, horizon, n_assets) representing single period non-cumulative returns.

    input_type : str, {'log', 'simple'}
        What type of returns are we dealing with in `y`.

    output_type : str, {'log', 'simple'}
        What type of returns are we dealing with in the output.

    rebalance : bool
        If True, each timestep the weights are adjusted to be equal to be equal to the original ones. Note that
        this assumes that we tinker with the portfolio. If False, the portfolio evolves untouched.

    Returns
    -------
    portfolio_returns : torch.Tensor
        Of shape (n_samples, horizon) representing per timestep portfolio returns.
Compute portfolio returns.
Compute portfolio returns .
def portfolio_returns(weights, y, input_type='log', output_type='simple', rebalance=False):
    """Compute portfolio returns.

    Parameters
    ----------
    weights : torch.Tensor
        Tensor of shape (n_samples, n_assets) representing the simple buy and hold strategy over the horizon.

    y : torch.Tensor
        Tensor of shape (n_samples, horizon, n_assets) representing single period non-cumulative returns.

    input_type : str, {'log', 'simple'}
        What type of returns are we dealing with in `y`.

    output_type : str, {'log', 'simple'}
        What type of returns are we dealing with in the output.

    rebalance : bool
        If True, each timestep the weights are adjusted to be equal to be equal to the original ones. Note that
        this assumes that we tinker with the portfolio. If False, the portfolio evolves untouched.

    Returns
    -------
    portfolio_returns : torch.Tensor
        Of shape (n_samples, horizon) representing per timestep portfolio returns.

    """
    if input_type == 'log':
        simple_returns = log2simple(y)

    elif input_type == 'simple':
        simple_returns = y

    else:
        raise ValueError('Unsupported input type: {}'.format(input_type))

    n_samples, horizon, n_assets = simple_returns.shape

    weights_ = weights.view(n_samples, 1, n_assets).repeat(1, horizon, 1)  # (n_samples, horizon, n_assets)

    if not rebalance:
        weights_unscaled = (1 + simple_returns).cumprod(1)[:, :-1, :] * weights_[:, 1:, :]
        weights_[:, 1:, :] = weights_unscaled / weights_unscaled.sum(2, keepdim=True)

    out = (simple_returns * weights_).sum(-1)

    if output_type == 'log':
        return simple2log(out)

    elif output_type == 'simple':
        return out

    else:
        raise ValueError('Unsupported output type: {}'.format(output_type))
def portfolio_returns ( weights , y , input_type = 'log' , output_type = 'simple' , rebalance = False ) : if input_type == 'log' : simple_returns = log2simple ( y ) elif input_type == 'simple' : simple_returns = y else : raise ValueError ( 'Unsupported input type: {}' . format ( input_type ) ) n_samples , horizon , n_assets = simple_returns . shape weights_ = weights . view ( n_samples , 1 , n_assets ) . repeat ( 1 , horizon , 1 ) # (n_samples, horizon, n_assets) if not rebalance : weights_unscaled = ( 1 + simple_returns ) . cumprod ( 1 ) [ : , : - 1 , : ] * weights_ [ : , 1 : , : ] weights_ [ : , 1 : , : ] = weights_unscaled / weights_unscaled . sum ( 2 , keepdim = True ) out = ( simple_returns * weights_ ) . sum ( - 1 ) if output_type == 'log' : return simple2log ( out ) elif output_type == 'simple' : return out else : raise ValueError ( 'Unsupported output type: {}' . format ( output_type ) )