Пример #1
0
    def test_robust_vol_calc_min_period(self):
        prices = get_data("syscore.tests.pricetestdata_min_period.csv")

        returns = prices.diff()
        vol = robust_vol_calc(returns, min_periods=9)
        self.assertAlmostEqual(vol.iloc[-1], 0.45829858614978286)
        vol = robust_vol_calc(returns, min_periods=10)
        self.assertTrue(np.isnan(vol.iloc[-1]))
Пример #2
0
    def test_robust_vol_calc(self):
        prices = get_data("syscore.tests.pricetestdata.csv")
        returns = prices.diff()
        vol = robust_vol_calc(returns, days=35)

        self.assertAlmostEqual(vol.iloc[-1], 0.41905275480464305)

        vol = robust_vol_calc(returns, days=100)
        self.assertAlmostEqual(vol.iloc[-1], 0.43906619578902956)
Пример #3
0
def calc_ewmac_forecast(price, Lfast, Lslow=None):
    """
    Calculate the ewmac trading rule forecast, given a price and EWMA speeds
    Lfast, Lslow and vol_lookback

    """
    # price: This is the stitched price series
    # We can't use the price of the contract we're trading, or the volatility
    # will be jumpy
    # And we'll miss out on the rolldown. See
    # https://qoppac.blogspot.com/2015/05/systems-building-futures-rolling.html

    price = price.resample("1B").last()

    if Lslow is None:
        Lslow = 4 * Lfast

    # We don't need to calculate the decay parameter, just use the span
    # directly
    fast_ewma = price.ewm(span=Lfast).mean()
    slow_ewma = price.ewm(span=Lslow).mean()
    raw_ewmac = fast_ewma - slow_ewma

    vol = robust_vol_calc(price.diff())
    return raw_ewmac / vol
Пример #4
0
    def test_robust_vol_calc_floor(self):
        prices = get_data("syscore.tests.pricetestdata_vol_floor.csv")
        returns = prices.diff()

        vol = robust_vol_calc(returns)
        self.assertAlmostEqual(vol.iloc[-1], 0.54492982003602064)

        vol = robust_vol_calc(returns, vol_floor=False)
        self.assertAlmostEqual(vol.iloc[-1], 0.42134038479240132)

        vol = robust_vol_calc(returns, floor_min_quant=0.5)
        self.assertAlmostEqual(vol.iloc[-1], 1.6582199589924964)

        vol = robust_vol_calc(returns, floor_min_periods=500)
        self.assertAlmostEqual(vol.iloc[-1], 0.42134038479240132)

        vol = robust_vol_calc(returns, floor_days=10, floor_min_periods=5)
        self.assertAlmostEqual(vol.iloc[-1], 0.42134038479240132)
Пример #5
0
    def _get_daily_vol_from_sim_data(self, instrument_code: str) -> pd.Series:
        price = self.data.daily_prices(instrument_code)

        # backadjusted prices can be negative
        abs_price = abs(price)
        return_vol = robust_vol_calc(price.diff())
        daily_vol_as_ratio = return_vol / abs_price
        daily_perc_vol = 100.0 * daily_vol_as_ratio

        return daily_perc_vol
Пример #6
0
def ewmac_calc_vol(price, Lfast, Lslow, vol_days=35):
    """
    Calculate the ewmac trading rule forecast, given a price and EWMA speeds Lfast, Lslow and number of days to
    lookback for volatility

    Assumes that 'price' is daily data

    This version recalculates the price volatility, and does not do capping or scaling

    :param price: The price or other series to use (assumed Tx1)
    :type price: pd.Series

    :param Lfast: Lookback for fast in days
    :type Lfast: int

    :param Lslow: Lookback for slow in days
    :type Lslow: int

    :param vol_days: Lookback for volatility in days
    :type vol_days: int

    :returns: pd.Series -- unscaled, uncapped forecast


    >>> from systems.tests.testdata import get_test_object_futures
    >>> from systems.basesystem import System
    >>> (rawdata, data, config)=get_test_object_futures()
    >>> system=System( [rawdata], data, config)
    >>>
    >>> ewmac(rawdata.get_daily_prices("EDOLLAR"), rawdata.daily_returns_volatility("EDOLLAR"), 64, 256).tail(2)
    2015-12-10    5.327019
    2015-12-11    4.927339
    Freq: B, dtype: float64
    """
    # price: This is the stitched price series
    # We can't use the price of the contract we're trading, or the volatility will be jumpy
    # And we'll miss out on the rolldown. See
    # https://qoppac.blogspot.com/2015/05/systems-building-futures-rolling.html

    # We don't need to calculate the decay parameter, just use the span
    # directly

    fast_ewma = price.ewm(span=Lfast).mean()
    slow_ewma = price.ewm(span=Lslow).mean()
    raw_ewmac = fast_ewma - slow_ewma

    vol = robust_vol_calc(price, vol_days)

    return raw_ewmac / vol.ffill()
Пример #7
0
def conditioned_factor_trading_rule(
    demean_factor_value, condition_demean_factor_value, smooth=90
):
    vol = robust_vol_calc(demean_factor_value)
    normalised_factor_value = demean_factor_value / vol

    sign_condition = condition_demean_factor_value.apply(np.sign)
    sign_condition_resample = sign_condition.reindex(
        normalised_factor_value.index
    ).ffill()

    conditioned_factor = normalised_factor_value * sign_condition_resample
    smoothed_conditioned_factor = conditioned_factor.ewm(span=smooth).mean()

    return smoothed_conditioned_factor
Пример #8
0
    def get_daily_returns_volatility(self, instrument_code):
        """
        Get the daily return (not %) volatility from previous stage, or calculate

        KEY INPUT

        :param instrument_code:
        :type str:

        :returns: Tx1 pd.DataFrames

        """

        system = self.parent
        if hasattr(system, "rawdata"):
            returns_vol = system.rawdata.daily_returns_volatility(
                instrument_code)
        else:
            price = self.get_daily_price(instrument_code)
            returns_vol = robust_vol_calc(price.diff())

        return returns_vol
Пример #9
0
def ewmac_forecast_with_defaults(price, Lfast=32, Lslow=128):
    """
    Calculate the ewmac trading fule forecast, given a price and EWMA speeds
      Lfast, Lslow and vol_lookback

    Assumes that 'price' is daily data

    This version recalculates the price volatility, and does not do capping or
      scaling

    :param price: The price or other series to use (assumed Tx1)
    :type price: pd.Series

    :param Lfast: Lookback for fast in days
    :type Lfast: int

    :param Lslow: Lookback for slow in days
    :type Lslow: int

    :returns: pd.DataFrame -- unscaled, uncapped forecast


    """
    # price: This is the stitched price series
    # We can't use the price of the contract we're trading, or the volatility
    # will be jumpy
    # And we'll miss out on the rolldown. See
    # https://qoppac.blogspot.com/2015/05/systems-building-futures-rolling.html

    # We don't need to calculate the decay parameter, just use the span
    # directly

    fast_ewma = price.ewm(span=Lfast).mean()
    slow_ewma = price.ewm(span=Lslow).mean()
    raw_ewmac = fast_ewma - slow_ewma

    vol = robust_vol_calc(price.diff())

    return raw_ewmac / vol
Пример #10
0
def factor_trading_rule(demean_factor_value, smooth=90):
    vol = robust_vol_calc(demean_factor_value)
    normalised_factor_value = demean_factor_value / vol
    smoothed_normalised_factor_value = normalised_factor_value.ewm(span=smooth).mean()

    return smoothed_normalised_factor_value
Пример #11
0
 def test_robust_vol_calc_min_value(self):
     prices = get_data("syscore.tests.pricetestdata_zero_vol.csv")
     returns = prices.diff()
     vol = robust_vol_calc(returns, vol_abs_min=0.01)
     self.assertEqual(vol.iloc[-1], 0.01)
Пример #12
0
    def calculate_daily_returns_vol(self, instrument_code: str) -> pd.Series:
        price = self._daily_prices_direct_from_data(instrument_code)
        returns_vol = robust_vol_calc(price.diff())

        return returns_vol