Repository: quantopian/zipline
File: zipline/pipeline/data/dataset.py (Python)

Code before:
        Parameters
        ----------
        currency : str or zipline.currency.Currency
            Currency into which to convert this column's data.

        Returns
        -------
        column : BoundColumn
            Column producing the same data as ``self``, but currency-converted
            into ``currency``.
        """
        if hasattr(self.dataset, 'extra_coords'):
            name = self.dataset.extra_coords['item']
        else:
            name = self.name

        if self.dtype != float64_dtype:
            raise TypeError(
                'The .fx method cannot be called on {} because {} does not '
                'have a float64 dtype.'.format(self, name)
            )

        conversion = self._currency_conversion
        if conversion is Disallowed:
            raise TypeError(
                'The .fx method cannot be called on {} because {} is not '
                'currency aware.'.format(self, name)
            )
        elif conversion is not None and conversion.currency == currency:
            return self

        return self._replace(
            currency_conversion=CurrencyConversion(
                currency=currency,
                field=DEFAULT_FX_RATE,
            )
        )

    @property
    def currency_conversion(self):
        """Specification for currency conversions applied for this term.
        """
        if self._currency_conversion is Disallowed:
            return None
        return self._currency_conversion

    @property
    def dataset(self):
        """
        The dataset to which this column is bound.
        """

Review comment (suggestion):
Thinking about the wording here:

- I'm not sure why we're including both `self` and a variant on `self.name` in this message. I think `self.qualname` should be sufficient to tell the reader what column they used.
- Do we want "is not currency-aware" to be the user-facing description of the problem here? That's a very mechanical description of the issue vs. something more conceptual like "does not produce currency-denominated data". cc @jmccorriston for thoughts on the language here.

Code after:
        return type(self)(**kw)

    def specialize(self, domain):
        """Specialize ``self`` to a concrete domain.
        """
        if domain == self.domain:
            return self

        return self._replace(dataset=self._dataset.specialize(domain))

    def unspecialize(self):
        """
        Unspecialize a column to its generic form.

        This is equivalent to ``column.specialize(GENERIC)``.
        """
        return self.specialize(GENERIC)

    @coerce_types(currency=(str, Currency))
    def fx(self, currency):
        """
        Construct a currency-converted version of this column.

        Parameters
        ----------
        currency : str or zipline.currency.Currency
            Currency into which to convert this column's data.

        Returns
        -------
        column : BoundColumn
            Column producing the same data as ``self``, but currency-converted
            into ``currency``.
        """
        conversion = self._currency_conversion

        if not self._currency_aware:
            raise TypeError(
                'The .fx() method cannot be called on {} because it does not '
                'produce currency-denominated data.'.format(self.qualname)
            )
        elif conversion is not None and conversion.currency == currency:
            return self

        return self._replace(
            currency_conversion=CurrencyConversion(
                currency=currency,
                field=DEFAULT_FX_RATE,
            )
        )