Exemple #1
0
    def fetch_market(self, md_request=None):
        """Fetches market data for specific tickers

        The user does not need to know to the low level API for each data provider works. The MarketDataRequest
        needs to supply parameters that define each data request. It has details which include:
            ticker eg. EURUSD
            field eg. close
            category eg. fx
            data_source eg. bloomberg
            start_date eg. 01 Jan 2015
            finish_date eg. 01 Jan 2017

        It can also have many optional attributes, such as
            vendor_ticker eg. EURUSD Curncy
            vendor_field eg. PX_LAST

        Parameters
        ----------
        md_request : MarketDataRequest
            Describing what market data to fetch

        Returns
        -------
        pd.DataFrame
            Contains the requested market data

        """
        if self.md_request is not None:
            md_request = self.md_request

        key = md_request.generate_key()

        data_frame = None

        # If internet_load has been specified don't bother going to cache (might end up calling lower level cache though
        # through MarketDataGenerator)
        if 'cache_algo' in md_request.cache_algo:
            data_frame = self.speed_cache.get_dataframe(key)

        if data_frame is not None:
            return data_frame

        # Special cases when a predefined category has been asked
        if md_request.category is not None:

            if (md_request.category == 'fx-spot-volume'
                    and md_request.data_source == 'quandl'):
                # NOT CURRENTLY IMPLEMENTED FOR FUTURE USE
                from findatapy.market.fxclsvolume import FXCLSVolume
                fxcls = FXCLSVolume(
                    market_data_generator=self._market_data_generator)

                data_frame = fxcls.get_fx_volume(
                    md_request.start_date,
                    md_request.finish_date,
                    md_request.tickers,
                    cut="LOC",
                    data_source="quandl",
                    cache_algo=md_request.cache_algo)

            # For FX we have special methods for returning cross rates or total returns
            if (md_request.category in ['fx', 'fx-tot', 'fx-tot-forwards']) and md_request.tickers is not None and \
                    md_request.abstract_curve is None:
                fxcf = FXCrossFactory(
                    market_data_generator=self._market_data_generator)

                if md_request.category == 'fx':
                    type = 'spot'
                elif md_request.category == 'fx-tot':
                    type = 'tot'

                elif md_request.category == 'fx-tot-forwards':
                    type = 'tot-forwards'

                if (md_request.freq != 'tick' and md_request.fields == ['close']) or \
                        (md_request.freq == 'tick' and md_request.data_source in ['dukascopy', 'fxcm']):
                    data_frame = fxcf.get_fx_cross(
                        md_request.start_date,
                        md_request.finish_date,
                        md_request.tickers,
                        cut=md_request.cut,
                        data_source=md_request.data_source,
                        freq=md_request.freq,
                        cache_algo=md_request.cache_algo,
                        type=type,
                        environment=md_request.environment,
                        fields=md_request.fields)

            # For FX implied volatility we can return the full surface
            if (md_request.category == 'fx-implied-vol'):
                if md_request.tickers is not None and md_request.freq == 'daily':
                    df = []

                    fxvf = FXVolFactory(
                        market_data_generator=self._market_data_generator)

                    for t in md_request.tickers:
                        if len(t) == 6:
                            df.append(
                                fxvf.get_fx_implied_vol(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    md_request.fx_vol_tenor,
                                    cut=md_request.cut,
                                    data_source=md_request.data_source,
                                    part=md_request.fx_vol_part,
                                    cache_algo=md_request.cache_algo))

                    if df != []:
                        data_frame = Calculations().pandas_outer_join(df)

            # For FX vol market return all the market data necessary for pricing options
            # which includes FX spot, volatility surface, forward points, deposit rates
            if (md_request.category == 'fx-vol-market'):
                if md_request.tickers is not None:
                    df = []

                    fxcf = FXCrossFactory(
                        market_data_generator=self._market_data_generator)
                    fxvf = FXVolFactory(
                        market_data_generator=self._market_data_generator)
                    rates = RatesFactory(
                        market_data_generator=self._market_data_generator)

                    # For each FX cross fetch the spot, vol and forward points
                    for t in md_request.tickers:
                        if len(t) == 6:
                            # Spot
                            df.append(
                                fxcf.get_fx_cross(
                                    start=md_request.start_date,
                                    end=md_request.finish_date,
                                    cross=t,
                                    cut=md_request.cut,
                                    data_source=md_request.data_source,
                                    freq=md_request.freq,
                                    cache_algo=md_request.cache_algo,
                                    type='spot',
                                    environment=md_request.environment,
                                    fields=['close']))

                            # Entire FX vol surface
                            df.append(
                                fxvf.get_fx_implied_vol(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    md_request.fx_vol_tenor,
                                    cut=md_request.cut,
                                    data_source=md_request.data_source,
                                    part=md_request.fx_vol_part,
                                    cache_algo=md_request.cache_algo))

                            # FX forward points for every point on curve
                            df.append(
                                rates.get_fx_forward_points(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    md_request.fx_forwards_tenor,
                                    cut=md_request.cut,
                                    data_source=md_request.data_source,
                                    cache_algo=md_request.cache_algo))

                    # Lastly fetch the base depos
                    df.append(
                        rates.get_base_depos(
                            md_request.start_date,
                            md_request.finish_date,
                            self._get_base_depo_currencies(md_request.tickers),
                            md_request.base_depos_tenor,
                            cut=md_request.cut,
                            data_source=md_request.data_source,
                            cache_algo=md_request.cache_algo))

                    if df != []:
                        data_frame = Calculations().pandas_outer_join(df)

            if (md_request.category == 'fx-forwards-market'):
                if md_request.tickers is not None:
                    df = []

                    fxcf = FXCrossFactory(
                        market_data_generator=self._market_data_generator)
                    rates = RatesFactory(
                        market_data_generator=self._market_data_generator)

                    # For each FX cross fetch the spot and forward points
                    for t in md_request.tickers:
                        if len(t) == 6:
                            # Spot
                            df.append(
                                fxcf.get_fx_cross(
                                    start=md_request.start_date,
                                    end=md_request.finish_date,
                                    cross=t,
                                    cut=md_request.cut,
                                    data_source=md_request.data_source,
                                    freq=md_request.freq,
                                    cache_algo=md_request.cache_algo,
                                    type='spot',
                                    environment=md_request.environment,
                                    fields=['close']))

                            # FX forward points for every point on curve
                            df.append(
                                rates.get_fx_forward_points(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    md_request.fx_forwards_tenor,
                                    cut=md_request.cut,
                                    data_source=md_request.data_source,
                                    cache_algo=md_request.cache_algo))

                    # Lastly fetch the base depos
                    df.append(
                        rates.get_base_depos(
                            md_request.start_date,
                            md_request.finish_date,
                            self._get_base_depo_currencies(md_request.tickers),
                            md_request.base_depos_tenor,
                            cut=md_request.cut,
                            data_source=md_request.data_source,
                            cache_algo=md_request.cache_algo))

                    if df != []:
                        data_frame = Calculations().pandas_outer_join(df)

            # eg. for calculating total return indices from first principles (rather than downloading them
            # from a data vendor
            if md_request.abstract_curve is not None:
                data_frame = md_request.abstract_curve.fetch_continuous_time_series \
                    (md_request, self._market_data_generator)

            if (md_request.category == 'crypto'):
                # Add more features later
                data_frame = self._market_data_generator.fetch_market_data(
                    md_request)

            # TODO add more special examples here for different asset classes
            # the idea is that we do all the market data downloading here, rather than elsewhere

        # By default: pass the market data request to MarketDataGenerator
        if data_frame is None:
            data_frame = self._market_data_generator.fetch_market_data(
                md_request)

        # Special case where we can sometimes have duplicated data times
        if md_request.freq == 'intraday' and md_request.cut == 'BSTP':
            data_frame = self._filter.remove_duplicate_indices(data_frame)

        # Push into cache
        if md_request.push_to_cache:
            self.speed_cache.put_dataframe(key, data_frame)

        return data_frame
Exemple #2
0
    def fetch_market(self, md_request=None):
        if self.md_request is not None:
            md_request = self.md_request

        # special cases when a predefined category has been asked
        if md_request.category is not None:

            if (md_request.category == 'fx-spot-volume'
                    and md_request.data_source == 'quandl'):
                # NOT CURRENTLY IMPLEMENTED FOR FUTURE USE
                from findatapy.market.fxclsvolume import FXCLSVolume
                fxcls = FXCLSVolume(
                    market_data_generator=self.market_data_generator)

                return fxcls.get_fx_volume(md_request.start_date,
                                           md_request.finish_date,
                                           md_request.tickers,
                                           cut="LOC",
                                           source="quandl",
                                           cache_algo=md_request.cache_algo)

            if (md_request.category == 'fx' or md_request.category
                    == 'fx-tot') and md_request.tickers is not None:
                fxcf = FXCrossFactory(
                    market_data_generator=self.market_data_generator)

                if md_request.category == 'fx':
                    type = 'spot'
                elif md_request.category == 'fx-tot':
                    type = 'tot'

                if (md_request.freq != 'tick'
                        and md_request.fields == ['close']) or (
                            md_request.freq == 'tick'
                            and md_request.data_source == 'dukascopy'):
                    return fxcf.get_fx_cross(
                        md_request.start_date,
                        md_request.finish_date,
                        md_request.tickers,
                        cut=md_request.cut,
                        source=md_request.data_source,
                        freq=md_request.freq,
                        cache_algo=md_request.cache_algo,
                        type=type,
                        environment=md_request.environment)

            if (md_request.category == 'fx-implied-vol'):
                if md_request.tickers is not None and md_request.freq == 'daily':
                    df = []

                    fxvf = FXVolFactory(
                        market_data_generator=self.market_data_generator)

                    for t in md_request.tickers:
                        if len(t) == 6:
                            df.append(
                                fxvf.get_fx_implied_vol(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    fxvf.tenor,
                                    cut=md_request.cut,
                                    source=md_request.data_source,
                                    part=fxvf.part,
                                    cache_algo_return=md_request.cache_algo))

                    if df != []:
                        return Calculations().pandas_outer_join(df)

            if (md_request.category == 'fx-vol-market'):
                if md_request.tickers is not None:
                    df = []

                    fxcf = FXCrossFactory(
                        market_data_generator=self.market_data_generator)
                    fxvf = FXVolFactory(
                        market_data_generator=self.market_data_generator)
                    rates = RatesFactory(
                        market_data_generator=self.market_data_generator)

                    for t in md_request.tickers:
                        if len(t) == 6:
                            df.append(
                                fxcf.get_fx_cross(
                                    start=md_request.start_date,
                                    end=md_request.finish_date,
                                    cross=t,
                                    cut=md_request.cut,
                                    source=md_request.data_source,
                                    freq=md_request.freq,
                                    cache_algo=md_request.cache_algo,
                                    type='spot',
                                    environment=md_request.environment,
                                    fields=['close']))

                            df.append(
                                fxvf.get_fx_implied_vol(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    fxvf.tenor,
                                    cut=md_request.cut,
                                    source=md_request.data_source,
                                    part=fxvf.part,
                                    cache_algo=md_request.cache_algo))

                            df.append(
                                rates.get_fx_forward_points(
                                    md_request.start_date,
                                    md_request.finish_date,
                                    t,
                                    fxvf.tenor,
                                    cut=md_request.cut,
                                    source=md_request.data_source,
                                    cache_algo=md_request.cache_algo))

                    df.append(
                        rates.get_base_depos(md_request.start_date,
                                             md_request.finish_date,
                                             ["USD", "EUR", "CHF", "GBP"],
                                             fxvf.tenor,
                                             cut=md_request.cut,
                                             source=md_request.data_source,
                                             cache_algo=md_request.cache_algo))

                    if df != []:
                        return Calculations().pandas_outer_join(df)

            # TODO add more special examples here for different asset classes
            # the idea is that we do all the market data downloading here, rather than elsewhere

        # by default: pass the market data request to MarketDataGenerator
        return self.market_data_generator.fetch_market_data(md_request)