Beispiel #1
0
    def update(self, **kwargs):
        """Update the data using `Data.update_symbol`.

        Args:
            **kwargs: Passed to `Data.update_symbol`.

                If two symbols require different keyword arguments, pass `symbol_dict` for each argument.

        !!! note
            Returns a new `Data` instance."""
        new_data = dict()
        for k, v in self.data.items():
            # Select keyword arguments for this symbol
            _kwargs = self.select_symbol_kwargs(k, kwargs)

            # Download new data for this symbol
            new_obj = self.update_symbol(k, **_kwargs)

            # Convert array to pandas
            if not isinstance(new_obj, (pd.Series, pd.DataFrame)):
                new_obj = np.asarray(new_obj)
                index = pd.RangeIndex(start=v.index[-1],
                                      stop=v.index[-1] + new_obj.shape[0],
                                      step=1)
                if new_obj.ndim == 1:
                    new_obj = pd.Series(new_obj, index=index)
                else:
                    new_obj = pd.DataFrame(new_obj, index=index)

            # Perform operations with datetime-like index
            if isinstance(new_obj.index, pd.DatetimeIndex):
                if self.tz_localize is not None:
                    if not is_tz_aware(new_obj.index):
                        new_obj = new_obj.tz_localize(
                            to_timezone(self.tz_localize))
                if self.tz_convert is not None:
                    new_obj = new_obj.tz_convert(to_timezone(self.tz_convert))

            new_data[k] = new_obj

        # Align index and columns
        new_data = self.align_index(new_data, missing=self.missing_index)
        new_data = self.align_columns(new_data, missing=self.missing_columns)

        # Concatenate old and new data
        for k, v in new_data.items():
            if isinstance(self.data[k], pd.Series):
                if isinstance(v, pd.DataFrame):
                    v = v[self.data[k].name]
            else:
                v = v[self.data[k].columns]
            v = pd.concat((self.data[k], v), axis=0)
            v = v[~v.index.duplicated(keep='last')]
            if isinstance(v.index, pd.DatetimeIndex):
                v.index.freq = v.index.inferred_freq
            new_data[k] = v

        # Create new instance
        new_index = new_data[self.symbols[0]].index
        return self.copy(wrapper=self.wrapper.copy(index=new_index),
                         data=new_data)
Beispiel #2
0
    def from_data(cls,
                  data,
                  tz_localize=None,
                  tz_convert=None,
                  missing_index=None,
                  missing_columns=None,
                  wrapper_kwargs=None,
                  **kwargs):
        """Create a new `Data` instance from (aligned) data.

        Args:
            data (dict): Dictionary of array-like objects keyed by symbol.
            tz_localize (any): If the index is tz-naive, convert to a timezone.

                See `vectorbt.utils.datetime.to_timezone`.
            tz_convert (any): Convert the index from one timezone to another.

                See `vectorbt.utils.datetime.to_timezone`.

                Defaults to `tz_convert` in `vectorbt.settings.data`.
            missing_index (str): See `Data.align_index`.

                Defaults to `missing_index` in `vectorbt.settings.data`.
            missing_columns (str): See `Data.align_columns`.

                Defaults to `missing_columns` in `vectorbt.settings.data`.
            wrapper_kwargs (dict): Keyword arguments passed to `vectorbt.base.array_wrapper.ArrayWrapper`.
            **kwargs: Keyword arguments passed to the `__init__` method."""
        from vectorbt import settings

        # Get global defaults
        if tz_localize is None:
            tz_localize = settings.data['tz_localize']
        if tz_convert is None:
            tz_convert = settings.data['tz_convert']
        if missing_index is None:
            missing_index = settings.data['missing_index']
        if missing_columns is None:
            missing_columns = settings.data['missing_columns']
        if wrapper_kwargs is None:
            wrapper_kwargs = {}

        data = data.copy()
        for k, v in data.items():
            # Convert array to pandas
            if not isinstance(v, (pd.Series, pd.DataFrame)):
                v = np.asarray(v)
                if v.ndim == 1:
                    v = pd.Series(v)
                else:
                    v = pd.DataFrame(v)

            # Perform operations with datetime-like index
            if isinstance(v.index, pd.DatetimeIndex):
                if tz_localize is not None:
                    if not is_tz_aware(v.index):
                        v = v.tz_localize(to_timezone(tz_localize))
                if tz_convert is not None:
                    v = v.tz_convert(to_timezone(tz_convert))
                v.index.freq = v.index.inferred_freq
            data[k] = v

        # Align index and columns
        data = cls.align_index(data, missing=missing_index)
        data = cls.align_columns(data, missing=missing_columns)

        # Create new instance
        symbols = list(data.keys())
        wrapper = ArrayWrapper.from_obj(data[symbols[0]], **wrapper_kwargs)
        return cls(wrapper,
                   data,
                   tz_localize=tz_localize,
                   tz_convert=tz_convert,
                   missing_index=missing_index,
                   missing_columns=missing_columns,
                   **kwargs)