Example #1
0
def copy_dict(dct: InConfigLikeT,
              copy_mode: str = 'shallow',
              nested: bool = True) -> OutConfigLikeT:
    """Copy dict based on a copy mode.

    The following modes are supported:

    * 'shallow': Copies keys only.
    * 'hybrid': Copies keys and values using `copy.copy`.
    * 'deep': Copies the whole thing using `copy.deepcopy`.

    Set `nested` to True to copy all child dicts in recursive manner."""
    if dct is None:
        dct = {}
    checks.assert_type(copy_mode, str)
    copy_mode = copy_mode.lower()
    if copy_mode not in ['shallow', 'hybrid', 'deep']:
        raise ValueError(f"Copy mode '{copy_mode}' not supported")

    if copy_mode == 'deep':
        return deepcopy(dct)
    if isinstance(dct, Config):
        return dct.copy(copy_mode=copy_mode, nested=nested)
    dct_copy = copy(dct)  # copy structure using shallow copy
    for k, v in dct_copy.items():
        if nested and isinstance(v, dict):
            _v = copy_dict(v, copy_mode=copy_mode, nested=nested)
        else:
            if copy_mode == 'hybrid':
                _v = copy(v)  # copy values using shallow copy
            else:
                _v = v
        set_dict_item(dct_copy, k, _v, force=True)
    return dct_copy
Example #2
0
def update_dict(x: InConfigLikeT,
                y: InConfigLikeT,
                nested: bool = True,
                force: bool = False) -> None:
    """Update dict with keys and values from other dict.

    Set `nested` to True to update all child dicts in recursive manner.
    For `force`, see `set_dict_item`.

    If you want to treat any dict as a single value, wrap it with `atomic_dict`.

    !!! note
        If the child dict is not atomic, it will copy only its values, not its meta."""
    if x is None:
        return
    if y is None:
        return
    checks.assert_type(x, dict)
    checks.assert_type(y, dict)

    for k, v in y.items():
        if nested \
                and k in x \
                and isinstance(x[k], dict) \
                and isinstance(v, dict) \
                and not isinstance(v, atomic_dict):
            update_dict(x[k], v, force=force)
        else:
            set_dict_item(x, k, v, force=force)
Example #3
0
    def plot(self,
             tr_trace_kwargs={},
             atr_trace_kwargs={},
             fig=None,
             **layout_kwargs):
        """Plot `ATR.tr` and `ATR.atr`.

        Args:
            tr_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `ATR.tr`.
            atr_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `ATR.atr`.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.
        Returns:
            vectorbt.widgets.common.DefaultFigureWidget
        Example:
            ```py
            atr[(10, False)].plot()
            ```

            ![](/vectorbt/docs/img/ATR.png)"""
        checks.assert_type(self.tr, pd.Series)
        checks.assert_type(self.atr, pd.Series)

        tr_trace_kwargs = {**dict(
            name=f'TR ({self.name})'
        ), **tr_trace_kwargs}
        atr_trace_kwargs = {**dict(
            name=f'ATR ({self.name})'
        ), **atr_trace_kwargs}

        fig = self.tr.vbt.timeseries.plot(trace_kwargs=tr_trace_kwargs, fig=fig, **layout_kwargs)
        fig = self.atr.vbt.timeseries.plot(trace_kwargs=atr_trace_kwargs, fig=fig, **layout_kwargs)

        return fig
Example #4
0
def create_param_combs(op_tree: tp.Tuple, depth: int = 0) -> tp.List[tp.List]:
    """Create arbitrary parameter combinations from the operation tree `op_tree`.

    `op_tree` is a tuple with nested instructions to generate parameters.
    The first element of the tuple should be a callable that takes remaining elements as arguments.
    If one of the elements is a tuple itself and its first argument is a callable, it will be
    unfolded in the same way as above.

    ## Example

    ```python-repl
    >>> import numpy as np
    >>> from itertools import combinations, product

    >>> create_param_combs((product, (combinations, [0, 1, 2, 3], 2), [4, 5]))
    [[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2],
     [1, 1, 2, 2, 3, 3, 2, 2, 3, 3, 3, 3],
     [4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5]]
    ```
    """
    checks.assert_type(op_tree, tuple)
    checks.assert_type(op_tree[0], Callable)
    new_op_tree: tp.Tuple = (op_tree[0],)
    for elem in op_tree[1:]:
        if isinstance(elem, tuple) and isinstance(elem[0], Callable):
            new_op_tree += (create_param_combs(elem, depth=depth + 1),)
        else:
            new_op_tree += (elem,)
    out = list(new_op_tree[0](*new_op_tree[1:]))
    if depth == 0:
        # do something
        return flatten_param_tuples(out)
    return out
Example #5
0
def create_param_combs(op_tree, depth=0):
    """Create arbitrary parameter combinations from the operation tree `op_tree`.

    `op_tree` must be a tuple of tuples, each being an instruction to generate parameters.
    The first element of each tuple should a function that takes remaining elements as arguments.
    If one of the elements is a tuple, it will be unfolded in the same way.

    ## Example

    ```python-repl
    >>> import numpy as np
    >>> from itertools import combinations, product

    >>> create_param_combs((product, (combinations, [0, 1, 2, 3], 2), [4, 5]))
    [[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2],
     [1, 1, 2, 2, 3, 3, 2, 2, 3, 3, 3, 3],
     [4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5]]
    ```
    """
    checks.assert_type(op_tree, tuple)
    new_op_tree = (op_tree[0], )
    for elem in op_tree[1:]:
        if isinstance(elem, tuple):
            new_op_tree += (create_param_combs(elem, depth=depth + 1), )
        else:
            new_op_tree += (elem, )
    out = list(new_op_tree[0](*new_op_tree[1:]))
    if depth == 0:
        # do something
        return flatten_param_tuples(out)
    return out
Example #6
0
    def plot(self,
             mstd_trace_kwargs={},
             fig=None,
             **layout_kwargs):
        """Plot `MSTD.mstd`.

        Args:
            mstd_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `MSTD.mstd`.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.
        Returns:
            vectorbt.widgets.common.DefaultFigureWidget
        Example:
            ```py
            mstd[(10, False)].plot()
            ```

            ![](/vectorbt/docs/img/MSTD.png)"""
        checks.assert_type(self.mstd, pd.Series)

        mstd_trace_kwargs = {**dict(
            name=f'MSTD ({self.name})'
        ), **mstd_trace_kwargs}

        fig = self.mstd.vbt.timeseries.plot(trace_kwargs=mstd_trace_kwargs, fig=fig, **layout_kwargs)

        return fig
Example #7
0
    def align_to(self, other):
        """Align to `other` by their indexes and columns.

        Example:
            ```python-repl
            >>> import pandas as pd
            >>> df1 = pd.DataFrame([[1, 2], [3, 4]], index=['x', 'y'], columns=['a', 'b'])
            >>> df2 = pd.DataFrame([[5, 6, 7, 8], [9, 10, 11, 12]], index=['x', 'y'], 
            ...     columns=pd.MultiIndex.from_arrays([[1, 1, 2, 2], ['a', 'b', 'a', 'b']]))

            >>> print(df1.vbt.align_to(df2))
                  1     2   
               a  b  a  b
            x  1  2  1  2
            y  3  4  3  4
            ```"""
        checks.assert_type(other, (pd.Series, pd.DataFrame))
        obj = reshape_fns.to_2d(self._obj)
        other = reshape_fns.to_2d(other)

        aligned_index = index_fns.align_index_to(obj.index, other.index)
        aligned_columns = index_fns.align_index_to(obj.columns, other.columns)
        obj = obj.iloc[aligned_index, aligned_columns]
        return self.wrap_array(obj.values,
                               index=other.index,
                               columns=other.columns)
Example #8
0
    def plot(self,
             obv_trace_kwargs={},
             fig=None,
             **layout_kwargs):
        """Plot `OBV.obv`.

        Args:
            obv_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `OBV.obv`.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.
        Returns:
            vectorbt.widgets.common.DefaultFigureWidget
        Example:
            ```py
            obv.plot()
            ```

            ![](/vectorbt/docs/img/OBV.png)"""
        checks.assert_type(self.obv, pd.Series)

        obv_trace_kwargs = {**dict(
            name=f'OBV ({self.name})'
        ), **obv_trace_kwargs}

        fig = self.obv.vbt.timeseries.plot(trace_kwargs=obv_trace_kwargs, fig=fig, **layout_kwargs)

        return fig
Example #9
0
    def annual(self):
        """Annual returns."""
        checks.assert_type(self._obj.index, DatetimeTypes)

        if self.freq == self.year_freq:
            return self._obj
        return self.resample_apply(self.year_freq, nb.total_return_apply_nb)
Example #10
0
    def daily(self, **kwargs) -> tp.SeriesFrame:
        """Daily returns."""
        checks.assert_type(self.wrapper.index, DatetimeIndexes)

        if self.wrapper.freq == pd.Timedelta('1D'):
            return self._obj
        return self.resample_apply('1D', nb.total_return_apply_nb, **kwargs)
Example #11
0
def make_symmetric(arg):
    """Make object symmetric along the diagonal."""
    checks.assert_type(arg, (pd.Series, pd.DataFrame))
    arg = to_2d(arg)
    checks.assert_same_type(arg.index, arg.columns)
    if isinstance(arg.index, pd.MultiIndex):
        checks.assert_same_len(arg.index.names, arg.columns.names)
        names1, names2 = tuple(arg.index.names), tuple(arg.columns.names)
    else:
        names1, names2 = arg.index.name, arg.columns.name

    if names1 == names2:
        new_name = names1
    else:
        if isinstance(arg.index, pd.MultiIndex):
            new_name = tuple(zip(*[names1, names2]))
        else:
            new_name = (names1, names2)
    idx_vals = np.unique(np.concatenate((arg.index, arg.columns)))
    arg = arg.copy()
    if isinstance(arg.index, pd.MultiIndex):
        unique_index = pd.MultiIndex.from_tuples(idx_vals, names=new_name)
        arg.index.names = new_name
        arg.columns.names = new_name
    else:
        unique_index = pd.Index(idx_vals, name=new_name)
        arg.index.name = new_name
        arg.columns.name = new_name
    df_out = pd.DataFrame(index=unique_index, columns=unique_index)
    df_out.loc[:, :] = arg
    df_out[df_out.isnull()] = arg.transpose()
    return df_out
Example #12
0
    def __init__(self, scheduler: tp.Optional[AsyncScheduler] = None) -> None:
        if scheduler is None:
            scheduler = AsyncScheduler()
        checks.assert_type(scheduler, AsyncScheduler)

        self._scheduler = scheduler
        self._async_task = None
Example #13
0
def merge_dicts(*dicts: tp.DictLike) -> dict:
    """Merge dicts."""
    x, y = dicts[0], dicts[1]
    if x is None:
        x = {}
    if y is None:
        y = {}
    checks.assert_type(x, dict)
    checks.assert_type(y, dict)

    if len(x) == 0:
        z = y.copy()
    elif len(y) == 0:
        z = x.copy()
    else:
        z = {}
        overlapping_keys = [k for k in x if k in y]  # order matters
        for k in overlapping_keys:
            if isinstance(x[k], dict) and isinstance(
                    y[k], dict) and not isinstance(y[k], atomic_dict):
                z[k] = merge_dicts(x[k], y[k])
            else:
                z[k] = y[k]
        for k in [k for k in x if k not in y]:
            z[k] = x[k]
        for k in [k for k in y if k not in x]:
            z[k] = y[k]

    if len(dicts) > 2:
        return merge_dicts(z, *dicts[2:])
    return z
Example #14
0
    def __init__(self,
                 wrapper,
                 data,
                 tz_localize=None,
                 tz_convert=None,
                 missing_index=None,
                 missing_columns=None,
                 download_kwargs=None,
                 **kwargs):
        Wrapping.__init__(self,
                          wrapper,
                          data=data,
                          tz_localize=tz_localize,
                          tz_convert=tz_convert,
                          missing_index=missing_index,
                          missing_columns=missing_columns,
                          download_kwargs=download_kwargs,
                          **kwargs)

        checks.assert_type(data, dict)
        for k, v in data.items():
            checks.assert_meta_equal(v, data[list(data.keys())[0]])
        self._data = data
        self._tz_localize = tz_localize
        self._tz_convert = tz_convert
        self._missing_index = missing_index
        self._missing_columns = missing_columns
        self._download_kwargs = download_kwargs
Example #15
0
    def plot_pnl(self,
                 profit_trace_kwargs={},
                 loss_trace_kwargs={},
                 fig=None,
                 **layout_kwargs):
        """Plot position P/L as markers.

        Args:
            profit_trace_kwargs (dict): Keyword arguments passed to [`plotly.graph_objects.Scatter`](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Scatter.html) for "Profit" markers.
            loss_trace_kwargs (dict): Keyword arguments passed to [`plotly.graph_objects.Scatter`](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Scatter.html) for "Loss" markers.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.
        Example:
            ```py
            portfolio = vbt.Portfolio.from_orders(price, price.diff(), init_capital=100)
            portfolio.positions.plot_pnl()
            ```

            ![](/vectorbt/docs/img/positions_plot_pnl.png)"""
        checks.assert_type(self.pnl, pd.Series)

        above_trace_kwargs = {**dict(name='Profit'), **profit_trace_kwargs}
        below_trace_kwargs = {**dict(name='Loss'), **loss_trace_kwargs}
        return self.pnl.vbt.timeseries.plot_against(
            0,
            above_trace_kwargs=above_trace_kwargs,
            below_trace_kwargs=below_trace_kwargs)
Example #16
0
    def from_order_func(cls,
                        ts,
                        order_func_np,
                        *args,
                        investment=None,
                        slippage=None,
                        commission=None):
        """Build portfolio based on order function."""
        if investment is None:
            investment = defaults.portfolio['investment']
        if slippage is None:
            slippage = defaults.portfolio['slippage']
        if commission is None:
            commission = defaults.portfolio['commission']

        checks.assert_type(ts, (pd.Series, pd.DataFrame))
        ts.vbt.timeseries.validate()

        investment = float(investment)
        slippage = float(slippage)
        commission = float(commission)

        cash, shares = nb.portfolio_np(ts.vbt.to_2d_array(), investment,
                                       slippage, commission, order_func_np,
                                       *args)

        cash = ts.vbt.wrap_array(cash)
        shares = ts.vbt.wrap_array(shares)

        return cls(ts, cash, shares, investment, slippage, commission)
Example #17
0
    def __init__(self, wrapper, mapped_arr, col_arr, idx_arr=None):
        Configured.__init__(
            self,
            wrapper=wrapper,
            mapped_arr=mapped_arr,
            col_arr=col_arr,
            idx_arr=idx_arr
        )
        checks.assert_type(wrapper, ArrayWrapper)
        if not isinstance(mapped_arr, np.ndarray):
            mapped_arr = np.asarray(mapped_arr)
        if not isinstance(col_arr, np.ndarray):
            col_arr = np.asarray(col_arr)
        checks.assert_shape_equal(mapped_arr, col_arr, axis=0)
        if idx_arr is not None:
            if not isinstance(idx_arr, np.ndarray):
                idx_arr = np.asarray(idx_arr)
            checks.assert_shape_equal(mapped_arr, idx_arr, axis=0)

        self._wrapper = wrapper
        self._mapped_arr = mapped_arr
        self._col_arr = col_arr
        self._idx_arr = idx_arr

        PandasIndexer.__init__(self, _mapped_array_indexing_func)
Example #18
0
def traverse_attr_kwargs(cls, key=None, value=None):
    """Traverse `cls` and its children for properties/methods with `kwargs`,
    and optionally a specific `key` and `value`.

    Class attributes acting as children should have a key `child_cls`.

    Returns a nested dict of attributes."""
    checks.assert_type(cls, type)

    if value is not None and not isinstance(value, tuple):
        value = (value, )
    attrs = {}
    for attr in dir(cls):
        prop = getattr(cls, attr)
        if hasattr(prop, 'kwargs'):
            kwargs = getattr(prop, 'kwargs')
            if key is None:
                attrs[attr] = kwargs
            else:
                if key in kwargs:
                    if value is None:
                        attrs[attr] = kwargs
                    else:
                        _value = kwargs[key]
                        if _value in value:
                            attrs[attr] = kwargs
            if 'child_cls' in kwargs:
                child_cls = kwargs['child_cls']
                checks.assert_type(child_cls, type)
                attrs[attr] = kwargs
                attrs[attr]['child_attrs'] = traverse_attr_kwargs(
                    child_cls, key, value)
    return attrs
Example #19
0
    def daily(self):
        """Daily returns."""
        checks.assert_type(self.index, DatetimeTypes)

        if self.freq == pd.Timedelta('1D'):
            return self._obj
        return self.resample_apply('1D', nb.total_return_apply_nb)
Example #20
0
    def update_data(self, value):
        """Update the data of the plot efficiently.

        Args:
            value (int or float): The value to be displayed.
        """
        # NOTE: If called by Plotly event handler and in case of error, this won't visible in a notebook cell, but in logs!
        checks.assert_type(value, (int, float))

        # Update value range
        if self._value_range is None:
            self._value_range = value, value
        else:
            self._value_range = min(self._value_range[0],
                                    value), max(self._value_range[1], value)

        # Update traces
        with self.batch_update():
            indicator = self.data[0]
            if self._value_range is not None:
                indicator.gauge.axis.range = self._value_range
                if self._cmap_name is not None:
                    indicator.gauge.bar.color = rgb_from_cmap(
                        self._cmap_name, value, self._value_range)
            indicator.delta.reference = indicator.value
            indicator.value = value
Example #21
0
    def plot(self,
             ts_trace_kwargs={},
             ma_trace_kwargs={},
             fig=None,
             **layout_kwargs):
        """Plot `MA.ma` against `MA.ts`.

        Args:
            ts_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `MA.ts`.
            ma_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `MA.ma`.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.
        Returns:
            vectorbt.widgets.common.DefaultFigureWidget
        Example:
            ```py
            ma[(10, False)].plot()
            ```

            ![](/vectorbt/docs/img/MA.png)"""
        checks.assert_type(self.ts, pd.Series)
        checks.assert_type(self.ma, pd.Series)

        ts_trace_kwargs = {**dict(
            name=f'Price ({self.name})'
        ), **ts_trace_kwargs}
        ma_trace_kwargs = {**dict(
            name=f'MA ({self.name})'
        ), **ma_trace_kwargs}

        fig = self.ts.vbt.timeseries.plot(trace_kwargs=ts_trace_kwargs, fig=fig, **layout_kwargs)
        fig = self.ma.vbt.timeseries.plot(trace_kwargs=ma_trace_kwargs, fig=fig, **layout_kwargs)

        return fig
Example #22
0
def unstack_to_df(arg,
                  index_levels=None,
                  column_levels=None,
                  symmetric=False,
                  sort=True):
    """Reshape `arg` based on its multi-index into a DataFrame.

    Use `index_levels` to specify what index levels will form new index, and `column_levels` 
    for new columns. Set `symmetric` to True to make DataFrame symmetric.

    ## Example

    ```python-repl
    >>> import pandas as pd
    >>> from vectorbt.base.reshape_fns import unstack_to_df

    >>> index = pd.MultiIndex.from_arrays(
    ...     [[1, 1, 2, 2], [3, 4, 3, 4], ['a', 'b', 'c', 'd']],
    ...     names=['x', 'y', 'z'])
    >>> sr = pd.Series([1, 2, 3, 4], index=index)

    >>> unstack_to_df(sr, index_levels=(0, 1), column_levels=2)
    z      a    b    c    d
    x y
    1 3  1.0  NaN  NaN  NaN
    1 4  NaN  2.0  NaN  NaN
    2 3  NaN  NaN  3.0  NaN
    2 4  NaN  NaN  NaN  4.0
    ```
    """
    # Perform checks
    checks.assert_type(arg, (pd.Series, pd.DataFrame))
    if checks.is_frame(arg):
        if arg.shape[0] == 1:
            arg = arg.iloc[0, :]
        elif arg.shape[1] == 1:
            arg = arg.iloc[:, 0]
    checks.assert_type(arg.index, pd.MultiIndex)
    sr = to_1d(arg)

    if len(sr.index.levels) > 2:
        if index_levels is None:
            raise ValueError("index_levels must be specified")
        if column_levels is None:
            raise ValueError("column_levels must be specified")
    else:
        index_levels = 0
        column_levels = 1

    # Build new index and column hierarchies
    new_index = index_fns.select_levels(arg.index, index_levels).unique()
    new_columns = index_fns.select_levels(arg.index, column_levels).unique()

    # Unstack and post-process
    unstacked = unstack_to_array(sr, levels=(index_levels, column_levels))
    df = pd.DataFrame(unstacked, index=new_index, columns=new_columns)
    if symmetric:
        return make_symmetric(df, sort=sort)
    return df
Example #23
0
    def generate_stop_loss_exits(self,
                                 ts,
                                 stops,
                                 trailing=False,
                                 first=True,
                                 keys=None,
                                 broadcast_kwargs={}):
        """See `vectorbt.signals.nb.generate_stop_loss_exits_nb`.

        Arguments will be broadcasted using `vectorbt.base.reshape_fns.broadcast`
        with `broadcast_kwargs`. Argument `stops` can be either a single number, an array of 
        numbers, or a 3D array, where each matrix corresponds to a single configuration. 
        Use `keys` as the outermost level.

        Example:
            For each entry in `sig`, set stop loss for 10% and 20% below the entry price:

            ```python-repl
            >>> ts = pd.Series([1, 2, 3, 2, 1])
            >>> print(sig.vbt.signals.generate_stop_loss_exits(ts, [0.1, 0.5]))
            stop_loss                   0.1                  0.5
                            a      b      c      a      b      c
            2020-01-01  False  False  False  False  False  False
            2020-01-02  False  False  False  False  False  False
            2020-01-03  False  False  False  False  False  False
            2020-01-04  False   True   True  False  False  False
            2020-01-05  False  False  False  False  False   True
            >>> print(sig.vbt.signals.generate_stop_loss_exits(ts, [0.1, 0.5], trailing=True))
            trail_stop                  0.1                  0.5
                            a      b      c      a      b      c
            2020-01-01  False  False  False  False  False  False
            2020-01-02  False  False  False  False  False  False
            2020-01-03  False  False  False  False  False  False
            2020-01-04   True   True   True  False  False  False
            2020-01-05  False  False  False   True  False   True
            ```"""
        entries = self._obj
        checks.assert_type(ts, (pd.Series, pd.DataFrame))

        entries, ts = reshape_fns.broadcast(entries,
                                            ts,
                                            **broadcast_kwargs,
                                            writeable=True)
        stops = reshape_fns.broadcast_to_array_of(stops,
                                                  entries.vbt.to_2d_array())
        exits = nb.generate_stop_loss_exits_nb(entries.vbt.to_2d_array(),
                                               ts.vbt.to_2d_array(),
                                               stops,
                                               trailing=trailing,
                                               first=first)

        # Build column hierarchy
        if keys is not None:
            param_columns = keys
        else:
            name = 'trail_stop' if trailing else 'stop_loss'
            param_columns = index_fns.index_from_values(stops, name=name)
        columns = index_fns.combine_indexes(param_columns, entries.vbt.columns)
        return entries.vbt.wrap(exits, columns=columns)
Example #24
0
 def test_assert_same_type(self):
     checks.assert_same_type(0, 1)
     checks.assert_same_type(np.zeros(1), np.empty(1))
     try:
         checks.assert_type(0, np.zeros(1))
         raise Exception
     except:
         pass
Example #25
0
    def annual(self, **kwargs) -> tp.SeriesFrame:
        """Annual returns."""
        checks.assert_type(self._obj.index, DatetimeIndexes)

        if self.wrapper.freq == self.year_freq:
            return self._obj
        return self.resample_apply(self.year_freq, nb.total_return_apply_nb,
                                   **kwargs)
Example #26
0
def select_levels(index, level_names):
    """Build a new index by selecting one or multiple `level_names` from `index`."""
    checks.assert_type(index, pd.MultiIndex)

    if isinstance(level_names, (list, tuple)):
        levels = [index.get_level_values(level_name) for level_name in level_names]
        return pd.MultiIndex.from_arrays(levels)
    return index.get_level_values(level_names)
Example #27
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)
Example #28
0
    def plot_position_profits(self,
                              profit_trace_kwargs={},
                              loss_trace_kwargs={},
                              fig=None,
                              **layout_kwargs):
        checks.assert_type(self.position_profits, pd.Series)
        profits = self.position_profits.copy()
        profits[self.position_profits <= 0] = np.nan
        losses = self.position_profits.copy()
        losses[self.position_profits >= 0] = np.nan

        # Set up figure
        if fig is None:
            fig = FigureWidget()
            fig.update_layout(showlegend=True)
            fig.update_layout(**layout_kwargs)

        # Plot markets
        profit_scatter = go.Scatter(x=self.position_profits.index,
                                    y=profits,
                                    mode='markers',
                                    marker=dict(symbol='circle',
                                                color='green',
                                                size=10),
                                    name='Profit')
        profit_scatter.update(**profit_trace_kwargs)
        fig.add_trace(profit_scatter)
        loss_scatter = go.Scatter(x=self.position_profits.index,
                                  y=losses,
                                  mode='markers',
                                  marker=dict(symbol='circle',
                                              color='red',
                                              size=10),
                                  name='Loss')
        loss_scatter.update(**loss_trace_kwargs)
        fig.add_trace(loss_scatter)

        # Set up axes
        maxval = np.nanmax(np.abs(self.position_profits.vbt.to_2d_array()))
        space = 0.1 * 2 * maxval
        fig.update_layout(yaxis=dict(range=[-(maxval + space), maxval +
                                            space]),
                          shapes=[
                              dict(type="line",
                                   xref="paper",
                                   yref='y',
                                   x0=0,
                                   x1=1,
                                   y0=0,
                                   y1=0,
                                   line=dict(
                                       color="grey",
                                       width=2,
                                       dash="dot",
                                   ))
                          ])

        return fig
Example #29
0
    def __add__(self, other):
        checks.assert_type(other, self.__class__)
        checks.assert_same(self.price, other.price)

        return self.__class__(self.price, self.cash + other.cash,
                              self.shares + other.shares,
                              self.init_capital + other.init_capital,
                              self.paid_fees + other.paid_fees,
                              self.paid_slippage + other.paid_slippage)
Example #30
0
                    def __init__(self, obj, mapper):
                        checks.assert_type(mapper, pd.Series)

                        self.obj = obj
                        if mapper.dtype == 'O':
                            # If params are objects, we must cast them to string first
                            # The original mapper isn't touched
                            mapper = mapper.astype(str)
                        self.mapper = mapper