def wrap_array(arg, index=None, columns=None, dtype=None, default_index=None, default_columns=None, to_ndim=None): """Wrap array into a series/dataframe.""" if not checks.is_array(arg): arg = np.asarray(arg) if to_ndim is not None: arg = soft_broadcast_to_ndim(arg, to_ndim) if index is None: index = default_index if columns is None: columns = default_columns if columns is not None and len(columns) == 1: name = columns[0] else: name = None # Perform checks if index is not None: checks.assert_same_shape(arg, index, along_axis=(0, 0)) if arg.ndim == 2 and columns is not None: checks.assert_same_shape(arg, columns, along_axis=(1, 0)) if arg.ndim == 1: return pd.Series(arg, index=index, name=name, dtype=dtype) return pd.DataFrame(arg, index=index, columns=columns, dtype=dtype)
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)
def wrap(self, arg, index=None, columns=None, ndim=None, dtype=None): """Wrap a NumPy array using the stored metadata.""" arg = np.asarray(arg) if ndim is None: ndim = self.ndim if ndim is not None: arg = soft_broadcast_to_ndim(arg, 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] else: name = None # Perform checks if index is not None: checks.assert_same_shape(arg, index, axis=(0, 0)) if arg.ndim == 2 and columns is not None: checks.assert_same_shape(arg, columns, axis=(1, 0)) if arg.ndim == 1: return pd.Series(arg, index=index, name=name, dtype=dtype) return pd.DataFrame(arg, index=index, columns=columns, dtype=dtype)
def update_data(self, data): """Update the data of the plot efficiently. Args: data (array_like): Data in any format that can be converted to NumPy. Must be of shape (`x_labels`, `trace_names`). Example: ```py fig = pd.Series([1, 2], index=['x', 'y'], name='a').vbt.Bar() fig.update_data([2, 1]) fig.show() ``` ![](/vectorbt/docs/img/Bar_updated.png) """ data = reshape_fns.to_2d(np.asarray(data)) checks.assert_same_shape(data, self._x_labels, axis=(0, 0)) checks.assert_same_shape(data, self._trace_names, axis=(1, 0)) # Update traces with self.batch_update(): for i, bar in enumerate(self.data): bar.y = data[:, i] if bar.marker.colorscale is not None: bar.marker.color = data[:, i]
def generate_random(cls, shape, n_range, n_prob=None, min_space=None, seed=None, **kwargs): """See `vectorbt.signals.nb.generate_random_nb`. `**kwargs` will be passed to pandas constructor. Example: For each column, generate either 1 (with 30% probability) or 2 (with 70% probability) signals randomly. Leave one position free between signals: ```python-repl >>> print(pd.DataFrame.vbt.signals.generate_random((5, 3), [1, 2], ... n_prob=[0.3, 0.7], min_space=1, seed=42, index=index, columns=columns)) a b c 2018-01-01 True False False 2018-01-02 False True False 2018-01-03 True False False 2018-01-04 False True True 2018-01-05 False False False ```""" if not isinstance(shape, tuple): shape = (shape, 1) elif isinstance(shape, tuple) and len(shape) == 1: shape = (shape[0], 1) n_range = reshape_fns.to_1d(n_range) if n_prob is not None: n_prob = reshape_fns.to_1d(n_prob) checks.assert_same_shape(n_range, n_prob) result = nb.generate_random_nb(shape, n_range, n_prob=n_prob, min_space=min_space, seed=seed) if cls.is_series(): return pd.Series(result[:, 0], **kwargs) return pd.DataFrame(result, **kwargs)
def wrap_array(arg, index=None, columns=None, dtype=None, default_index=None, default_columns=None, to_ndim=None): """Wrap array `arg` into a Series/DataFrame with `index` (or `default_index` if None), `columns` (or `default_columns` if None) and `dtype`. Also tries to bring the array to `to_ndim` dimensions softly.""" arg = np.asarray(arg) if to_ndim is not None: arg = soft_broadcast_to_ndim(arg, to_ndim) if index is None: index = default_index if columns is None: columns = default_columns if columns is not None and len(columns) == 1: name = columns[0] else: name = None # Perform checks if index is not None: checks.assert_same_shape(arg, index, axis=(0, 0)) if arg.ndim == 2 and columns is not None: checks.assert_same_shape(arg, columns, axis=(1, 0)) if arg.ndim == 1: return pd.Series(arg, index=index, name=name, dtype=dtype) return pd.DataFrame(arg, index=index, columns=columns, dtype=dtype)
def generate_random_after(self, n_range, n_prob=None, min_space=None, seed=None): """See `vectorbt.signals.nb.generate_random_after_nb`. Example: Generate exactly one random signal after each signal in `signals`: ```python-repl >>> print(signals.vbt.signals.generate_random_after(1, seed=42)) a b c 2018-01-01 False False False 2018-01-02 False False False 2018-01-03 True True False 2018-01-04 False False False 2018-01-05 True False True ```""" n_range = reshape_fns.to_1d(n_range) if n_prob is not None: n_prob = reshape_fns.to_1d(n_prob) checks.assert_same_shape(n_range, n_prob) return self.wrap_array( nb.generate_random_after_nb(self.to_2d_array(), n_range, n_prob=n_prob, min_space=min_space, seed=seed))
def __init__(self, wrapper, records, layout, col_field, row_field): checks.assert_type(records, np.ndarray) checks.assert_same_shape(records, layout, axis=(1, 0)) self.wrapper = wrapper self._records = records self.layout = layout self.col_field = col_field self.row_field = row_field
def perform_init_checks(ts_list, output_list, param_list, mapper_list, name): """Perform checks on objects created by running or slicing an indicator.""" checks.assert_type(ts_list[0], (pd.Series, pd.DataFrame)) for ts in ts_list + output_list: checks.assert_same_meta(ts_list[0], ts) for params in param_list: checks.assert_same_shape(param_list[0], params) for mapper in mapper_list: checks.assert_type(mapper, pd.Series) checks.assert_same_index( reshape_fns.to_2d(ts_list[0]).iloc[0, :], mapper) checks.assert_type(name, str)
def from_values(values, name=None, value_names=None): """Create index using array of values.""" if value_names is not None: checks.assert_same_shape(values, value_names, along_axis=0) return pd.Index(value_names, name=name) # just return the names value_names = [] for i, v in enumerate(values): if not checks.is_array(v): v = np.asarray(v) if np.all(v == v.item(0)): value_names.append(v.item(0)) else: value_names.append('mix_%d' % i) return pd.Index(value_names, name=name)
def build_column_hierarchy(param_list, level_names, ts_columns): """For each parameter in `param_list`, create a new column level with parameter values. Combine this level with columns `ts_columns` using Cartesian product.""" checks.assert_same_shape(param_list, level_names, axis=0) param_indexes = [index_fns.from_values(param_list[i], name=level_names[i]) for i in range(len(param_list))] param_columns = None for param_index in param_indexes: if param_columns is None: param_columns = param_index else: param_columns = index_fns.stack(param_columns, param_index) if param_columns is not None: return index_fns.combine(param_columns, ts_columns) return ts_columns
def __init__(self, price, init_capital, order_records, cash, shares, data_freq=None, year_freq=None, risk_free=None, required_return=None, cutoff=None, factor_returns=None): # Perform checks checks.assert_type(price, (pd.Series, pd.DataFrame)) checks.assert_type(order_records, np.ndarray) checks.assert_same_shape(order_records, OrderRecord, axis=(1, 0)) checks.assert_same_meta(price, cash) checks.assert_same_meta(price, shares) # Main parameters self._price = price self._init_capital = init_capital self._order_records = order_records self._cash = cash self._shares = shares # Other parameters if data_freq is None: data_freq = price.vbt.timeseries.timedelta else: data_freq = pd.to_timedelta(data_freq) self._data_freq = data_freq year_freq = defaults.portfolio[ 'year_freq'] if year_freq is None else year_freq year_freq = pd.to_timedelta(year_freq) self._year_freq = year_freq self._ann_factor = year_freq / data_freq 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 if factor_returns is not None: factor_returns = reshape_fns.broadcast_to(factor_returns, price) self._factor_returns = factor_returns # Supercharge self.wrapper = TSRArrayWrapper.from_obj(price)
def perform_init_checks(ts_list, output_list, param_list, mapper_list, name): """Perform checks on objects created by running or slicing an indicator.""" for ts in ts_list: checks.assert_type(ts, (pd.Series, pd.DataFrame)) ts.vbt.timeseries.validate() for i in range(1, len(ts_list) + len(output_list)): checks.assert_same_meta((ts_list + output_list)[i - 1], (ts_list + output_list)[i]) for i in range(1, len(param_list)): checks.assert_same_shape(param_list[i - 1], param_list[i]) for mapper in mapper_list: checks.assert_type(mapper, pd.Series) checks.assert_same_index( reshape_fns.to_2d(ts_list[0]).iloc[0, :], mapper) checks.assert_type(name, str)
def update_data(self, data): """Update the data of the plot efficiently. Args: data (array_like): Data in any format that can be converted to NumPy. Must be of shape (`x_labels`, `trace_names`). """ data = reshape_fns.to_2d(np.asarray(data)) checks.assert_same_shape(data, self._x_labels, axis=(0, 0)) checks.assert_same_shape(data, self._trace_names, axis=(1, 0)) # Update traces with self.batch_update(): for i, scatter in enumerate(self.data): scatter.y = data[:, i]
def map_array(self, a, idx_arr=None): """Convert array to `MappedArray`. The length of the array should match that of the records.""" if not isinstance(a, np.ndarray): a = np.asarray(a) checks.assert_same_shape(a, self.records_arr) if idx_arr is None: if self.idx_field is not None: idx_arr = self.records_arr[self.idx_field] else: idx_arr = None return MappedArray(a, self.records_arr['col'], self.wrapper, idx_arr=idx_arr)
def __init__(self, mapped_arr, col_arr, wrapper, idx_arr=None): 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_same_shape(mapped_arr, col_arr, axis=0) checks.assert_type(wrapper, ArrayWrapper) if idx_arr is not None: if not isinstance(idx_arr, np.ndarray): idx_arr = np.asarray(idx_arr) checks.assert_same_shape(mapped_arr, idx_arr, axis=0) self.mapped_arr = mapped_arr self.col_arr = col_arr self.wrapper = wrapper self.idx_arr = idx_arr PandasIndexer.__init__(self, _mapped_indexing_func)
def update_data(self, data): """Update the data of the plot efficiently. Args: data (array_like): Data in any format that can be converted to NumPy. Must be of shape (`y_labels`, `x_labels`). """ data = reshape_fns.to_2d(np.asarray(data)) checks.assert_same_shape(data, self._x_labels, axis=(1, 0)) checks.assert_same_shape(data, self._y_labels, axis=(0, 0)) # Update traces with self.batch_update(): heatmap = self.data[0] if self._horizontal: heatmap.z = data.transpose() else: heatmap.z = data
def stack(*indexes): """Stack each index in `indexes` on top of each other.""" new_index = indexes[0] for i in range(1, len(indexes)): index1, index2 = new_index, indexes[i] checks.assert_same_shape(index1, index2) if not isinstance(index1, pd.MultiIndex): index1 = pd.MultiIndex.from_arrays([index1]) if not isinstance(index2, pd.MultiIndex): index2 = pd.MultiIndex.from_arrays([index2]) levels = [] for i in range(len(index1.names)): levels.append(index1.get_level_values(i)) for i in range(len(index2.names)): levels.append(index2.get_level_values(i)) new_index = pd.MultiIndex.from_arrays(levels) return new_index
def update_data(self, data): """Update the data of the plot efficiently. Args: data (array_like): Data in any format that can be converted to NumPy. Must be of shape (any, `trace_names`). """ data = reshape_fns.to_2d(np.asarray(data)) checks.assert_same_shape(data, self._trace_names, axis=(1, 0)) # Update traces with self.batch_update(): for i, histogram in enumerate(self.data): if self._horizontal: histogram.x = None histogram.y = data[:, i] else: histogram.x = data[:, i] histogram.y = None
def build_column_hierarchy(param_list, level_names, ts_columns): """For each parameter in `param_list`, create a new column level with parameter values. Combine this level with columns `ts_columns` using Cartesian product. Excludes level names that are `None`.""" checks.assert_same_shape(param_list, level_names, axis=0) param_indexes = [] for i in range(len(param_list)): if level_names[i] is not None: param_index = index_fns.index_from_values(param_list[i], name=level_names[i]) param_indexes.append(param_index) if len(param_indexes) > 1: param_columns = index_fns.stack_indexes(*param_indexes) elif len(param_indexes) == 1: param_columns = param_indexes[0] else: param_columns = None if param_columns is not None: return index_fns.combine_indexes(param_columns, ts_columns) return ts_columns
def test_assert_same_shape(self): checks.assert_same_shape(0, 1) checks.assert_same_shape([1, 2, 3], np.asarray([1, 2, 3])) checks.assert_same_shape([1, 2, 3], pd.Series([1, 2, 3])) checks.assert_same_shape(np.zeros((3, 3)), pd.Series([1, 2, 3]), axis=0) checks.assert_same_shape(np.zeros((2, 3)), pd.Series([1, 2, 3]), axis=(1, 0)) with pytest.raises(Exception) as e_info: checks.assert_same_shape(np.zeros((2, 3)), pd.Series([1, 2, 3]), axis=(0, 1))
def test_assert_same_shape(self): checks.assert_same_shape(0, 1) checks.assert_same_shape([1, 2, 3], np.asarray([1, 2, 3])) checks.assert_same_shape([1, 2, 3], pd.Series([1, 2, 3])) checks.assert_same_shape(np.zeros((3, 3)), pd.Series([1, 2, 3]), axis=0) checks.assert_same_shape(np.zeros((2, 3)), pd.Series([1, 2, 3]), axis=(1, 0)) try: checks.assert_same_shape(np.zeros((2, 3)), pd.Series([1, 2, 3]), axis=(0, 1)) raise Exception except: pass