Exemplo n.º 1
0
def broadcast_to_array_of(arg1, arg2):
    """Broadcast `arg1` to the shape `(1, *arg2.shape)`.

    `arg1` must be either a scalar, a 1-dim array, or have 1 dimension more than `arg2`.

    ## Example

    ```python-repl
    >>> import numpy as np
    >>> from vectorbt.base.reshape_fns import broadcast_to_array_of

    >>> broadcast_to_array_of([0.1, 0.2], np.empty((2, 2)))
    [[[0.1 0.1]
      [0.1 0.1]]

     [[0.2 0.2]
      [0.2 0.2]]]
    ```
    """
    arg1 = np.asarray(arg1)
    arg2 = np.asarray(arg2)
    if arg1.ndim == arg2.ndim + 1:
        if arg1.shape[1:] == arg2.shape:
            return arg1
    # From here on arg1 can be only a 1-dim array
    if arg1.ndim == 0:
        arg1 = to_1d(arg1)
    checks.assert_ndim(arg1, 1)

    if arg2.ndim == 0:
        return arg1
    for i in range(arg2.ndim):
        arg1 = np.expand_dims(arg1, axis=-1)
    return np.tile(arg1, (1, *arg2.shape))
Exemplo n.º 2
0
 def test_assert_ndim(self):
     checks.assert_ndim(0, 0)
     checks.assert_ndim(np.zeros(1), 1)
     checks.assert_ndim(pd.Series([1, 2, 3]), (1, 2))
     checks.assert_ndim(pd.DataFrame([1, 2, 3]), (1, 2))
     with pytest.raises(Exception) as e_info:
         checks.assert_ndim(np.zeros((3, 3, 3)), (1, 2))
Exemplo n.º 3
0
    def wrap(self, a, index=None, columns=None, dtype=None, group_by=None):
        """Wrap a NumPy array using the stored metadata."""
        checks.assert_ndim(a, (1, 2))
        _self = self.resolve(group_by=group_by)

        a = np.asarray(a)
        a = reshape_fns.soft_to_ndim(a, self.ndim)
        if index is None:
            index = _self.index
        if columns is None:
            columns = _self.columns
        if columns is not None and len(columns) == 1:
            name = columns[0]
            if name == 0:  # was a Series before
                name = None
        else:
            name = None
        if index is not None:
            checks.assert_shape_equal(a, index, axis=(0, 0))
        if a.ndim == 2 and columns is not None:
            checks.assert_shape_equal(a, columns, axis=(1, 0))
        if a.ndim == 1:
            return pd.Series(a, index=index, name=name, dtype=dtype)
        if a.ndim == 2:
            if a.shape[1] == 1 and _self.ndim == 1:
                return pd.Series(a[:, 0], index=index, name=name, dtype=dtype)
            return pd.DataFrame(a, index=index, columns=columns, dtype=dtype)
        raise ValueError(f"{a.ndim}-d input is not supported")
Exemplo n.º 4
0
    def wrap(self, a, index=None, columns=None, ndim=None, dtype=None):
        """Wrap a NumPy array using the stored metadata."""
        checks.assert_ndim(a, (1, 2))

        a = np.asarray(a)
        if ndim is None:
            ndim = self.ndim
        if ndim is not None:
            a = reshape_fns.soft_to_ndim(a, self.ndim)
        if index is None:
            index = self.index
        if columns is None:
            columns = self.columns
        if columns is not None and len(columns) == 1:
            name = columns[0]
            if name == 0:  # was a Series before
                name = None
        else:
            name = None

        # Perform checks
        if index is not None:
            checks.assert_same_shape(a, index, axis=(0, 0))
        if a.ndim == 2 and columns is not None:
            checks.assert_same_shape(a, columns, axis=(1, 0))

        if a.ndim == 1:
            return pd.Series(a, index=index, name=name, dtype=dtype)
        return pd.DataFrame(a, index=index, columns=columns, dtype=dtype)
Exemplo n.º 5
0
    def __init__(self,
                 main_price,
                 init_capital,
                 orders,
                 cash,
                 shares,
                 freq=None,
                 year_freq=None,
                 levy_alpha=None,
                 risk_free=None,
                 required_return=None,
                 cutoff=None,
                 factor_returns=None,
                 incl_unrealized_stats=False):
        # Perform checks
        checks.assert_type(main_price, (pd.Series, pd.DataFrame))
        if checks.is_frame(main_price):
            checks.assert_type(init_capital, pd.Series)
            checks.assert_same(main_price.columns, init_capital.index)
        else:
            checks.assert_ndim(init_capital, 0)
        checks.assert_same_meta(main_price, cash)
        checks.assert_same_meta(main_price, shares)

        # Store passed arguments
        self._main_price = main_price
        self._init_capital = init_capital
        self._orders = orders
        self._cash = cash
        self._shares = shares
        self._incl_unrealized_stats = incl_unrealized_stats

        freq = main_price.vbt(freq=freq).freq
        if freq is None:
            raise ValueError(
                "Couldn't parse the frequency of index. You must set `freq`.")
        self._freq = freq

        year_freq = main_price.vbt.returns(year_freq=year_freq).year_freq
        if freq is None:
            raise ValueError("You must set `year_freq`.")
        self._year_freq = year_freq

        # Parameters
        self._levy_alpha = defaults.portfolio[
            'levy_alpha'] if levy_alpha is None else levy_alpha
        self._risk_free = defaults.portfolio[
            'risk_free'] if risk_free is None else risk_free
        self._required_return = defaults.portfolio[
            'required_return'] if required_return is None else required_return
        self._cutoff = defaults.portfolio[
            'cutoff'] if cutoff is None else cutoff
        self._factor_returns = defaults.portfolio[
            'factor_returns'] if factor_returns is None else factor_returns

        # Supercharge
        PandasIndexer.__init__(self, _indexing_func)
        self.wrapper = ArrayWrapper.from_obj(main_price, freq=freq)
Exemplo n.º 6
0
 def test_assert_ndim(self):
     checks.assert_ndim(0, 0)
     checks.assert_ndim(np.zeros(1), 1)
     checks.assert_ndim(pd.Series([1, 2, 3]), (1, 2))
     checks.assert_ndim(pd.DataFrame([1, 2, 3]), (1, 2))
     try:
         checks.assert_ndim(np.zeros((3, 3, 3)), (1, 2))
         raise Exception
     except:
         pass
Exemplo n.º 7
0
def broadcast_to_array_of(arg1, arg2):
    """Bring first argument to the shape of an array of second argument."""
    arg1 = np.asarray(arg1)
    arg2 = np.asarray(arg2)
    if arg1.ndim == arg2.ndim + 1:
        if arg1.shape[1:] == arg2.shape:
            return arg1
    # From here on arg1 can be only a 1-dim array
    if arg1.ndim == 0:
        arg1 = to_1d(arg1)
    checks.assert_ndim(arg1, 1)

    if arg2.ndim == 0:
        return arg1
    for i in range(arg2.ndim):
        arg1 = np.expand_dims(arg1, axis=-1)
    return np.tile(arg1, (1, *arg2.shape))
Exemplo n.º 8
0
    def wrap(self,
             a: tp.ArrayLike,
             index: tp.Optional[tp.IndexLike] = None,
             columns: tp.Optional[tp.IndexLike] = None,
             dtype: tp.Optional[tp.PandasDTypeLike] = None,
             group_by: tp.GroupByLike = None) -> tp.SeriesFrame:
        """Wrap a NumPy array using the stored metadata."""
        checks.assert_ndim(a, (1, 2))
        _self = self.resolve(group_by=group_by)

        if index is None:
            index = _self.index
        if not isinstance(index, pd.Index):
            index = pd.Index(index)
        if columns is None:
            columns = _self.columns
        if not isinstance(columns, pd.Index):
            columns = pd.Index(columns)
        if len(columns) == 1:
            name = columns[0]
            if name == 0:  # was a Series before
                name = None
        else:
            name = None

        arr = np.asarray(a)
        arr = reshape_fns.soft_to_ndim(arr, self.ndim)
        checks.assert_shape_equal(arr, index, axis=(0, 0))
        if arr.ndim == 2:
            checks.assert_shape_equal(arr, columns, axis=(1, 0))
        if arr.ndim == 1:
            return pd.Series(arr, index=index, name=name, dtype=dtype)
        if arr.ndim == 2:
            if arr.shape[1] == 1 and _self.ndim == 1:
                return pd.Series(arr[:, 0],
                                 index=index,
                                 name=name,
                                 dtype=dtype)
            return pd.DataFrame(arr, index=index, columns=columns, dtype=dtype)
        raise ValueError(f"{arr.ndim}-d input is not supported")
Exemplo n.º 9
0
 def _wrap(arr):
     arr = np.asarray(arr)
     checks.assert_ndim(arr, (1, 2))
     if fillna is not None:
         arr[pd.isnull(arr)] = fillna
     arr = reshape_fns.soft_to_ndim(arr, self.ndim)
     checks.assert_shape_equal(arr, index, axis=(0, 0))
     if arr.ndim == 2:
         checks.assert_shape_equal(arr, columns, axis=(1, 0))
     if arr.ndim == 1:
         return pd.Series(arr, index=index, name=name, dtype=dtype)
     if arr.ndim == 2:
         if arr.shape[1] == 1 and _self.ndim == 1:
             return pd.Series(arr[:, 0],
                              index=index,
                              name=name,
                              dtype=dtype)
         return pd.DataFrame(arr,
                             index=index,
                             columns=columns,
                             dtype=dtype)
     raise ValueError(f"{arr.ndim}-d input is not supported")
Exemplo n.º 10
0
    def wrap(self,
             a,
             index=None,
             columns=None,
             dtype=None,
             collapse=None,
             **kwargs):
        """Wrap a NumPy array using the stored metadata."""
        checks.assert_ndim(a, (1, 2))
        group_by = self.grouper.resolve_group_by(**kwargs)

        a = np.asarray(a)
        a = reshape_fns.soft_to_ndim(a, self.ndim)
        if index is None:
            index = self.index
        if columns is None:
            columns = self.grouper.get_columns(**kwargs)
        if collapse is None:
            collapse = group_by is not None and group_by is not False and self.grouped_ndim == 1
        if columns is not None and len(columns) == 1:
            name = columns[0]
            if name == 0:  # was a Series before
                name = None
        else:
            name = None

        # Perform checks
        if index is not None:
            checks.assert_shape_equal(a, index, axis=(0, 0))
        if a.ndim == 2 and columns is not None:
            checks.assert_shape_equal(a, columns, axis=(1, 0))

        if a.ndim == 1:
            return pd.Series(a, index=index, name=name, dtype=dtype)
        if a.ndim == 2 and a.shape[1] == 1 and collapse:
            return pd.Series(a[:, 0], index=index, name=name, dtype=dtype)
        return pd.DataFrame(a, index=index, columns=columns, dtype=dtype)
Exemplo n.º 11
0
    def __init__(self,
                 data=None,
                 x_labels=None,
                 y_labels=None,
                 z_labels=False,
                 trace_kwargs=None,
                 add_trace_kwargs=None,
                 scene_name='scene',
                 fig=None,
                 **layout_kwargs):
        """Create a volume plot.

        Args:
            data (array_like): Data in any format that can be converted to NumPy.

                Must be a 3-dim array.
            x_labels (array_like): X-axis labels.
            y_labels (array_like): Y-axis labels.
            z_labels (array_like): Z-axis labels.
            trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Volume`.
            add_trace_kwargs (dict): Keyword arguments passed to `add_trace`.
            scene_name (str): Reference to the 3D scene.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.

        !!! note
            Figure widgets have currently problems displaying NaNs.
            Use `.show()` method for rendering.

        ## Example

        ```python-repl
        >>> import vectorbt as vbt
        >>> import numpy as np

        >>> volume = vbt.plotting.Volume(
        ...     data=np.random.randint(1, 10, size=(3, 3, 3)),
        ...     x_labels=['a', 'b', 'c'],
        ...     y_labels=['d', 'e', 'f'],
        ...     z_labels=['g', 'h', 'i']
        ... )
        >>> volume.fig
        ```

        ![](/vectorbt/docs/img/Volume.png)
        """
        Configured.__init__(self,
                            data=data,
                            x_labels=x_labels,
                            y_labels=y_labels,
                            z_labels=z_labels,
                            trace_kwargs=trace_kwargs,
                            add_trace_kwargs=add_trace_kwargs,
                            scene_name=scene_name,
                            fig=fig,
                            **layout_kwargs)

        from vectorbt.settings import layout

        if trace_kwargs is None:
            trace_kwargs = {}
        if add_trace_kwargs is None:
            add_trace_kwargs = {}
        if data is None:
            if x_labels is None or y_labels is None or z_labels is None:
                raise ValueError(
                    "At least x_labels, y_labels and z_labels must be passed")
            x_len = len(x_labels)
            y_len = len(y_labels)
            z_len = len(z_labels)
        else:
            checks.assert_ndim(data, 3)
            data = np.asarray(data)
            x_len, y_len, z_len = data.shape
        if x_labels is None:
            x_labels = np.arange(x_len)
        else:
            x_labels = clean_labels(x_labels)
        if y_labels is None:
            y_labels = np.arange(y_len)
        else:
            y_labels = clean_labels(y_labels)
        if z_labels is None:
            z_labels = np.arange(z_len)
        else:
            z_labels = clean_labels(z_labels)
        x_labels = np.asarray(x_labels)
        y_labels = np.asarray(y_labels)
        z_labels = np.asarray(z_labels)

        if fig is None:
            fig = FigureWidget()
            if 'width' in layout:
                # Calculate nice width and height
                fig.update_layout(width=layout['width'],
                                  height=0.7 * layout['width'])

        # Non-numeric data types are not supported by go.Volume, so use ticktext
        # Note: Currently plotly displays the entire tick array, in future versions it will be more sensible
        more_layout = dict()
        if not np.issubdtype(x_labels.dtype, np.number):
            x_ticktext = x_labels
            x_labels = np.arange(x_len)
            more_layout[scene_name] = dict(xaxis=dict(
                ticktext=x_ticktext, tickvals=x_labels, tickmode='array'))
        if not np.issubdtype(y_labels.dtype, np.number):
            y_ticktext = y_labels
            y_labels = np.arange(y_len)
            more_layout[scene_name] = dict(yaxis=dict(
                ticktext=y_ticktext, tickvals=y_labels, tickmode='array'))
        if not np.issubdtype(z_labels.dtype, np.number):
            z_ticktext = z_labels
            z_labels = np.arange(z_len)
            more_layout[scene_name] = dict(zaxis=dict(
                ticktext=z_ticktext, tickvals=z_labels, tickmode='array'))
        fig.update_layout(**more_layout)
        fig.update_layout(**layout_kwargs)

        # Arrays must have the same length as the flattened data array
        x = np.repeat(x_labels, len(y_labels) * len(z_labels))
        y = np.tile(np.repeat(y_labels, len(z_labels)), len(x_labels))
        z = np.tile(z_labels, len(x_labels) * len(y_labels))

        volume = go.Volume(
            x=x,
            y=y,
            z=z,
            opacity=0.2,
            surface_count=15,  # keep low for big data
            colorscale='Plasma')
        volume.update(**trace_kwargs)
        fig.add_trace(volume, **add_trace_kwargs)

        TraceUpdater.__init__(self, fig, [fig.data[-1]])

        if data is not None:
            self.update(data)
Exemplo n.º 12
0
def create_volume(data=None, x_labels=None, y_labels=None, z_labels=False,
                  trace_kwargs={}, fig=None, **layout_kwargs):
    """Create a volume plot.

    Args:
        data (array_like): Data in any format that can be converted to NumPy.

            Must be a 3-dim array.
        x_labels (array_like): X-axis labels.
        y_labels (array_like): Y-axis labels.
        z_labels (array_like): Z-axis labels.
        trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Volume`.
        fig (plotly.graph_objects.Figure): Figure to add traces to.
        **layout_kwargs: Keyword arguments for layout.

    !!! note
        Figure widgets have currently problems displaying NaNs.
        Use `.show()` method for rendering.

    Example:
        ```py
        import vectorbt as vbt
        import numpy as np

        vbt.plotting.create_volume(
            data=np.random.randint(1, 10, size=(3, 3, 3)),
            x_labels=['a', 'b', 'c'],
            y_labels=['d', 'e', 'f'],
            z_labels=['g', 'h', 'i']
        )
        ```
        ![](/vectorbt/docs/img/create_volume.png)
        """

    if data is None:
        raise ValueError("Data must be passed")
    data = np.asarray(data)
    checks.assert_ndim(data, 3)
    if x_labels is None:
        x_labels = np.arange(data.shape[0])
    if y_labels is None:
        y_labels = np.arange(data.shape[1])
    if z_labels is None:
        z_labels = np.arange(data.shape[2])
    x_labels = np.asarray(x_labels)
    y_labels = np.asarray(y_labels)
    z_labels = np.asarray(z_labels)

    if fig is None:
        fig = CustomFigureWidget()
        fig.update_layout(
            width=700,
            height=450
        )

    # Non-numeric data types are not supported by go.Volume, so use ticktext
    # Note: Currently plotly displays the entire tick array, in future versions it will be more sensible
    if not np.issubdtype(x_labels.dtype, np.number):
        x_ticktext = x_labels
        x_labels = np.arange(data.shape[0])
        fig.update_layout(scene=dict(xaxis=dict(ticktext=x_ticktext, tickvals=x_labels, tickmode='array')))
    if not np.issubdtype(y_labels.dtype, np.number):
        y_ticktext = y_labels
        y_labels = np.arange(data.shape[1])
        fig.update_layout(scene=dict(yaxis=dict(ticktext=y_ticktext, tickvals=y_labels, tickmode='array')))
    if not np.issubdtype(z_labels.dtype, np.number):
        z_ticktext = z_labels
        z_labels = np.arange(data.shape[2])
        fig.update_layout(scene=dict(zaxis=dict(ticktext=z_ticktext, tickvals=z_labels, tickmode='array')))

    # Arrays must have the same length as the flattened data array
    x = np.repeat(x_labels, len(y_labels) * len(z_labels))
    y = np.tile(np.repeat(y_labels, len(z_labels)), len(x_labels))
    z = np.tile(z_labels, len(x_labels) * len(y_labels))

    fig.update_layout(**layout_kwargs)
    volume = go.Volume(
        x=x,
        y=y,
        z=z,
        value=data.flatten(),
        opacity=0.15,
        surface_count=15,  # keep low for big data
        colorscale='Plasma'
    )
    volume.update(**trace_kwargs)
    fig.add_trace(volume)
    return fig
Exemplo n.º 13
0
def create_volume(data=None,
                  x_labels=None,
                  y_labels=None,
                  z_labels=False,
                  trace_kwargs=None,
                  return_trace_idx=False,
                  row=None,
                  col=None,
                  scene_name='scene',
                  fig=None,
                  **layout_kwargs):
    """Create a volume plot.

    Args:
        data (array_like): Data in any format that can be converted to NumPy.

            Must be a 3-dim array.
        x_labels (array_like): X-axis labels.
        y_labels (array_like): Y-axis labels.
        z_labels (array_like): Z-axis labels.
        trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Volume`.
        return_trace_idx (bool): Whether to return trace index for `update_volume_data`.
        row (int): Row position.
        col (int): Column position.
        scene_name (str): Reference to the 3D scene.
        fig (plotly.graph_objects.Figure): Figure to add traces to.
        **layout_kwargs: Keyword arguments for layout.

    !!! note
        Figure widgets have currently problems displaying NaNs.
        Use `.show()` method for rendering.

    ## Example

    ```python-repl
    >>> import vectorbt as vbt
    >>> import numpy as np

    >>> vbt.plotting.create_volume(
    ...     data=np.random.randint(1, 10, size=(3, 3, 3)),
    ...     x_labels=['a', 'b', 'c'],
    ...     y_labels=['d', 'e', 'f'],
    ...     z_labels=['g', 'h', 'i']
    ... )
    ```

    ![](/vectorbt/docs/img/create_volume.png)
    """
    from vectorbt.settings import layout

    if trace_kwargs is None:
        trace_kwargs = {}
    if data is None:
        raise ValueError("Data must be passed")
    data = np.asarray(data)
    checks.assert_ndim(data, 3)
    if x_labels is None:
        x_labels = np.arange(data.shape[0])
    if y_labels is None:
        y_labels = np.arange(data.shape[1])
    if z_labels is None:
        z_labels = np.arange(data.shape[2])
    x_labels = np.asarray(x_labels)
    y_labels = np.asarray(y_labels)
    z_labels = np.asarray(z_labels)

    if fig is None:
        fig = CustomFigureWidget()
        if 'width' in layout:
            # Calculate nice width and height
            fig.update_layout(width=layout['width'],
                              height=0.7 * layout['width'])

    # Non-numeric data types are not supported by go.Volume, so use ticktext
    # Note: Currently plotly displays the entire tick array, in future versions it will be more sensible
    more_layout = dict()
    if not np.issubdtype(x_labels.dtype, np.number):
        x_ticktext = x_labels
        x_labels = np.arange(data.shape[0])
        more_layout[scene_name] = dict(xaxis=dict(
            ticktext=x_ticktext, tickvals=x_labels, tickmode='array'))
    if not np.issubdtype(y_labels.dtype, np.number):
        y_ticktext = y_labels
        y_labels = np.arange(data.shape[1])
        more_layout[scene_name] = dict(yaxis=dict(
            ticktext=y_ticktext, tickvals=y_labels, tickmode='array'))
    if not np.issubdtype(z_labels.dtype, np.number):
        z_ticktext = z_labels
        z_labels = np.arange(data.shape[2])
        more_layout[scene_name] = dict(zaxis=dict(
            ticktext=z_ticktext, tickvals=z_labels, tickmode='array'))
    fig.update_layout(**more_layout)
    fig.update_layout(**layout_kwargs)

    # Arrays must have the same length as the flattened data array
    x = np.repeat(x_labels, len(y_labels) * len(z_labels))
    y = np.tile(np.repeat(y_labels, len(z_labels)), len(x_labels))
    z = np.tile(z_labels, len(x_labels) * len(y_labels))

    volume = go.Volume(
        x=x,
        y=y,
        z=z,
        value=data.flatten(),
        opacity=0.2,
        surface_count=15,  # keep low for big data
        colorscale='Plasma')
    volume.update(**trace_kwargs)
    fig.add_trace(volume, row=row, col=col)
    trace_idx = len(fig.data) - 1
    if return_trace_idx:
        return fig, trace_idx
    return fig