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]))
Example #2
0
 def test_robust_vol_calc_min_period(self):
     prices = pd_readcsv_frompackage(
         "syscore", "pricetestdata_min_period.csv", ["tests"])
     returns = prices.diff()
     vol = robust_vol_calc(returns, min_periods=9)
     self.assertAlmostEqual(vol.iloc[-1, 0], 0.45829858614978286)
     vol = robust_vol_calc(returns, min_periods=10)
     self.assertTrue(np.isnan(vol.iloc[-1][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)
Example #4
0
    def test_robust_vol_calc(self):
        prices = pd_readcsv_frompackage(
            "syscore", "pricetestdata.csv", ["tests"])
        returns = prices.diff()
        vol = robust_vol_calc(returns, days=35)
        self.assertAlmostEqual(vol.iloc[-1, 0], 0.41905275480464305)

        vol = robust_vol_calc(returns, days=100)
        self.assertAlmostEqual(vol.iloc[-1, 0], 0.43906619578902956)
Example #5
0
 def test_robust_vol_calc_floor(self):
     prices = pd_readcsv_frompackage(
         "syscore.tests.pricetestdata_vol_floor.csv")
     returns = prices.diff()
     vol = robust_vol_calc(returns)
     self.assertAlmostEqual(vol.iloc[-1, 0], 0.54492982003602064)
     vol = robust_vol_calc(returns, vol_floor=False)
     self.assertAlmostEqual(vol.iloc[-1, 0], 0.42134038479240132)
     vol = robust_vol_calc(returns, floor_min_quant=.5)
     self.assertAlmostEqual(vol.iloc[-1, 0], 1.6582199589924964)
     vol = robust_vol_calc(returns, floor_min_periods=500)
     self.assertAlmostEqual(vol.iloc[-1, 0], 0.42134038479240132)
     vol = robust_vol_calc(returns, floor_days=10, floor_min_periods=5)
     self.assertAlmostEqual(vol.iloc[-1, 0], 0.42134038479240132)
Example #6
0
def calc_ewmac_forecast(price, Lfast, Lslow):
    price=price.resample("1B", how="last")
    fast_ewma = pd.ewma(price, span=Lfast)
    slow_ewma = pd.ewma(price, span=Lslow)
    raw_ewmac = fast_ewma - slow_ewma
    vol = robust_vol_calc(price.diff())
    return raw_ewmac /  vol
def get_scatter_data_for_code_vol(
        system, instrument_code, rule_name, return_period=5, days=64):

    denom_price = system.rawdata.daily_denominator_price(instrument_code)
    x = system.rawdata.daily_returns(instrument_code)
    vol = robust_vol_calc(x, days)
    perc_vol = 100.0 * divide_df_single_column(vol, denom_price.shift(1))

    volavg = pd.rolling_median(perc_vol, 1250, min_periods=10)
    vol_qq = (perc_vol - volavg) / volavg

    # work out return for the N days after the forecast

    norm_data = system.accounts.pandl_for_instrument_forecast(
        instrument_code, rule_name)

    (vol_qq, norm_data) = align_to_joint(
        vol_qq, norm_data, ffill=(True, False))

    period_returns = pd.rolling_sum(norm_data, return_period, min_periods=1)

    ex_post_returns = period_returns.shift(-return_period)
    lagged_vol = vol_qq.shift(1)

    return (list(ex_post_returns.iloc[:, 0].values), list(
        lagged_vol.iloc[:, 0].values))
Example #8
0
def sharpe(price, forecast):
    """
    Herein the proof why this position calculation is correct (see chapters
    5-11 of 'systematic trading' book)
    Position = forecast x instrument weight x instrument_div_mult x vol_scalar / 10.0
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x instr value volatility)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x instr ccy volatility x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x block value x % price volatility x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x underlying price x 0.01 x value of price move x 100 x price change volatility/(underlying price) x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x value of price move x price change volatility x fx rate)
    Making some arbitrary assumptions (one instrument, 100% of capital, daily target DAILY_CAPITAL):
             = forecast x 1.0 x 1.0 x DAILY_CAPITAL / (10.0 x value of price move x price diff volatility x fx rate)
             = forecast x  multiplier / (value of price move x price change volatility x fx rate)
    """        
    base_capital = DEFAULT_CAPITAL
    daily_risk_capital = DEFAULT_CAPITAL * DEFAULT_ANN_RISK_TARGET / ROOT_BDAYS_INYEAR        
    ts_capital=pd.Series(np.ones(len(price)) * DEFAULT_CAPITAL, index=price.index)
    ann_risk = ts_capital * DEFAULT_ANN_RISK_TARGET
    daily_returns_volatility = robust_vol_calc(price.diff())
    multiplier = daily_risk_capital * 1.0 * 1.0 / 10.0
    numerator = forecast *  multiplier
    positions = numerator.ffill() /  daily_returns_volatility.ffill()
    cum_trades = positions.shift(1).ffill()
    price_returns = price.diff()
    instr_ccy_returns = cum_trades.shift(1)*price_returns 
    instr_ccy_returns=instr_ccy_returns.cumsum().ffill().reindex(price.index).diff()
    mean_return = instr_ccy_returns.mean() * BUSINESS_DAYS_IN_YEAR
    vol = instr_ccy_returns.std() * ROOT_BDAYS_INYEAR
    return mean_return / vol
Example #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.DataFrame
    :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
    # http://qoppac.blogspot.co.uk/2015/05/systems-building-futures-rolling.html

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

    fast_ewma = pd.ewma(price, span=Lfast)
    slow_ewma = pd.ewma(price, span=Lslow)
    raw_ewmac = fast_ewma - slow_ewma

    vol = robust_vol_calc(price.diff())

    return divide_df_single_column(raw_ewmac, vol, ffill=(False, True))
Example #10
0
def calc_ewmac_forecast(price, Lfast, Lslow=None):
    """
    Calculate the ewmac trading fule 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
    # http://qoppac.blogspot.co.uk/2015/05/systems-building-futures-rolling.html

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

    if Lslow is None:
        Lslow = 4 * Lfast

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

    fast_ewma = pd.ewma(price, span=Lfast)
    slow_ewma = pd.ewma(price, span=Lslow)
    raw_ewmac = fast_ewma - slow_ewma

    vol = robust_vol_calc(price.diff())

    return divide_df_single_column(raw_ewmac, vol)
Example #11
0
     def _get_daily_returns_volatility(system, instrument_code):
         if hasattr(system, "rawdata"):
             returns_vol=system.rawdata.daily_returns_volatility(instrument_code)
         else:
             price = system.data.get_instrument_price(instrument_code)
             price = price.resample("1B", how="last")
             returns_vol = robust_vol_calc(price.diff())
 
         return returns_vol
Example #12
0
        def _get_daily_returns_volatility(system, instrument_code):
            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
Example #13
0
        def _get_price_volatility(system, instrument_code, this_stage_notused):
            if hasattr(system, "rawdata"):
                daily_perc_vol = system.rawdata.get_daily_percentage_volatility(
                    instrument_code)
            else:
                price = system.data.daily_prices(instrument_code)
                return_vol = robust_vol_calc(price.diff())
                daily_perc_vol = 100.0 * return_vol / price

            return daily_perc_vol
Example #14
0
     def _get_price_volatility(system, instrument_code):
         if hasattr(system, "rawdata"):
             daily_perc_vol = system.rawdata.get_daily_percentage_volatility(
                 instrument_code)
         else:
             price = system.data.get_instrument_price(instrument_code)
             price = price.resample("1B", how="last")
             return_vol = robust_vol_calc(price.diff())
             daily_perc_vol = 100.0 * divide_df_single_column(return_vol, price)
 
         return daily_perc_vol
Example #15
0
        def _get_price_volatility(system, instrument_code):
            if hasattr(system, "rawdata"):
                daily_perc_vol = system.rawdata.get_daily_percentage_volatility(
                    instrument_code)
            else:
                price = system.data.daily_prices(instrument_code)
                return_vol = robust_vol_calc(price.diff())
                daily_perc_vol = 100.0 * \
                    divide_df_single_column(return_vol, price)

            return daily_perc_vol
Example #16
0
    def test_robust_vol_calc_floor(self):
        prices = pd_readcsv_frompackage(
            "syscore.tests.pricetestdata_vol_floor.csv")
        returns = prices.diff()
        vol = robust_vol_calc(returns)

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

        vol = robust_vol_calc(returns, vol_floor=False)

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

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

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

        vol = robust_vol_calc(returns, floor_days=10, floor_min_periods=5)
        self.assertAlmostEqual(vol.iloc[-1][0], 0.42134038479240132)
Example #17
0
def skew(price, forecast): 
    base_capital = DEFAULT_CAPITAL
    daily_risk_capital = DEFAULT_CAPITAL * DEFAULT_ANN_RISK_TARGET / ROOT_BDAYS_INYEAR
    use_fx = pd.Series([1.0] * len(price.index),index=price.index)
    get_daily_returns_volatility = robust_vol_calc(price.diff())
    multiplier = daily_risk_capital * 1.0 * 1.0 / 10.0
    denominator = get_daily_returns_volatility* use_fx
    numerator = forecast *  multiplier
    positions = numerator.ffill() /  denominator.ffill()
    cum_trades = positions.shift(1).ffill()
    trades_to_use=cum_trades.diff()        
    price_returns = price.diff()
    instr_ccy_returns = cum_trades.shift(1)* price_returns 
    instr_ccy_returns=instr_ccy_returns.cumsum().ffill().reindex(price.index).diff()
    pct = 100.0 * instr_ccy_returns / base_capital
    return scipy.stats.skew(pct[pd.isnull(pct) == False])
Example #18
0
def ewmac_calc_vol(price, Lfast, Lslow, vol_days=35):
    """
    Calculate the ewmac trading fule forecast, given a price and EWMA speeds Lfast, Lslow and vol_lookback

    Assumes that 'price' and vol 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


    >>> 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
    # http://qoppac.blogspot.co.uk/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()
    def get_price_volatility(self, instrument_code):
        """
        Get the daily % volatility; If a rawdata stage exists from there; otherwise work it out

        :param instrument_code: instrument to get values for
        :type instrument_code: str

        :returns: Tx1 pd.DataFrame

        KEY INPUT

        Note as an exception to the normal rule we cache this, as it sometimes comes from data

        >>> from systems.tests.testdata import get_test_object_futures_with_comb_forecasts
        >>> from systems.basesystem import System
        >>> (comb, fcs, rules, rawdata, data, config)=get_test_object_futures_with_comb_forecasts()
        >>> system=System([rawdata, rules, fcs, comb, PositionSizing()], data, config)
        >>>
        >>> system.positionSize.get_price_volatility("EDOLLAR").tail(2)
                         vol
        2015-12-10  0.055281
        2015-12-11  0.059789
        >>>
        >>> system2=System([ rules, fcs, comb, PositionSizing()], data, config)
        >>>
        >>> system2.positionSize.get_price_volatility("EDOLLAR").tail(2)
                         vol
        2015-12-10  0.055318
        2015-12-11  0.059724
        """
        system = self.parent
        if hasattr(system, "rawdata"):
            daily_perc_vol = system.rawdata.get_daily_percentage_volatility(
                instrument_code)
        else:
            price = system.data.daily_prices(instrument_code)
            return_vol = robust_vol_calc(price.diff())
            daily_perc_vol = 100.0 * return_vol / price

        return daily_perc_vol
Example #20
0
    def get_price_volatility(self, instrument_code):
        """
        Get the daily % volatility; If a rawdata stage exists from there; otherwise work it out

        :param instrument_code: instrument to get values for
        :type instrument_code: str

        :returns: Tx1 pd.DataFrame

        KEY INPUT

        Note as an exception to the normal rule we cache this, as it sometimes comes from data

        >>> from systems.tests.testdata import get_test_object_futures_with_comb_forecasts
        >>> from systems.basesystem import System
        >>> (comb, fcs, rules, rawdata, data, config)=get_test_object_futures_with_comb_forecasts()
        >>> system=System([rawdata, rules, fcs, comb, PositionSizing()], data, config)
        >>>
        >>> system.positionSize.get_price_volatility("EDOLLAR").tail(2)
                         vol
        2015-12-10  0.055281
        2015-12-11  0.059789
        >>>
        >>> system2=System([ rules, fcs, comb, PositionSizing()], data, config)
        >>>
        >>> system2.positionSize.get_price_volatility("EDOLLAR").tail(2)
                         vol
        2015-12-10  0.055318
        2015-12-11  0.059724
        """
        system = self.parent
        if hasattr(system, "rawdata"):
            daily_perc_vol = system.rawdata.get_daily_percentage_volatility(
                instrument_code)
        else:
            price = system.data.daily_prices(instrument_code)
            return_vol = robust_vol_calc(price.diff())
            daily_perc_vol = 100.0 * return_vol / price

        return daily_perc_vol
    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
Example #22
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
Example #23
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
Example #24
0
    def calc_ewmac_forecast(price, Lfast, Lslow=None):
        """
        Calculate the ewmac trading fule 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
        # http://qoppac.blogspot.co.uk/2015/05/systems-building-futures-rolling.html

        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
Example #25
0
    Making some arbitrary assumptions (one instrument, 100% of capital, daily target DAILY_CAPITAL):
             = forecast x 1.0 x 1.0 x DAILY_CAPITAL / (10.0 x value of price move x price diff volatility x fx rate)
             = forecast x  multiplier / (value of price move x price change volatility x fx rate)
    """        
    base_capital = DEFAULT_CAPITAL
    daily_risk_capital = DEFAULT_CAPITAL * DEFAULT_ANN_RISK_TARGET / ROOT_BDAYS_INYEAR        
    ts_capital=pd.Series(np.ones(len(price)) * DEFAULT_CAPITAL, index=price.index)
    ann_risk = ts_capital * DEFAULT_ANN_RISK_TARGET
    daily_returns_volatility = robust_vol_calc(price.diff())
    multiplier = daily_risk_capital * 1.0 * 1.0 / 10.0
    numerator = forecast *  multiplier
    positions = numerator.ffill() /  daily_returns_volatility.ffill()
    cum_trades = positions.shift(1).ffill()
    price_returns = price.diff()
    instr_ccy_returns = cum_trades.shift(1)*price_returns 
    instr_ccy_returns=instr_ccy_returns.cumsum().ffill().reindex(price.index).diff()
    mean_return = instr_ccy_returns.mean() * BUSINESS_DAYS_IN_YEAR
    vol = instr_ccy_returns.std() * ROOT_BDAYS_INYEAR
    return mean_return / vol

if __name__ == "__main__": 
 
    f = '../sysdata/legacycsv/EDOLLAR_price.csv'
    df = pd.read_csv(f,index_col=0,parse_dates=True)
    fast_ewma = pd.ewma(df.PRICE, span=32)
    slow_ewma = pd.ewma(df.PRICE, span=128)
    raw_ewmac = fast_ewma - slow_ewma
    vol = robust_vol_calc(df['PRICE'].diff())
    forecast = raw_ewmac /  vol 
    print (sharpe(df.PRICE, forecast))
Example #26
0
 def test_robust_vol_calc_min_value(self):
     prices = pd_readcsv_frompackage(
         "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], 0.01)
Example #27
0
    """
    base_capital = DEFAULT_CAPITAL
    daily_risk_capital = DEFAULT_CAPITAL * DEFAULT_ANN_RISK_TARGET / ROOT_BDAYS_INYEAR
    ts_capital = pd.Series(np.ones(len(price)) * DEFAULT_CAPITAL,
                           index=price.index)
    ann_risk = ts_capital * DEFAULT_ANN_RISK_TARGET
    daily_returns_volatility = robust_vol_calc(price.diff())
    multiplier = daily_risk_capital * 1.0 * 1.0 / 10.0
    numerator = forecast * multiplier
    positions = numerator.ffill() / daily_returns_volatility.ffill()
    cum_trades = positions.shift(1).ffill()
    price_returns = price.diff()
    instr_ccy_returns = cum_trades.shift(1) * price_returns
    instr_ccy_returns = instr_ccy_returns.cumsum().ffill().reindex(
        price.index).diff()
    mean_return = instr_ccy_returns.mean() * BUSINESS_DAYS_IN_YEAR
    vol = instr_ccy_returns.std() * ROOT_BDAYS_INYEAR
    return mean_return / vol


if __name__ == "__main__":

    f = '../sysdata/legacycsv/EDOLLAR_price.csv'
    df = pd.read_csv(f, index_col=0, parse_dates=True)
    fast_ewma = pd.ewma(df.PRICE, span=32)
    slow_ewma = pd.ewma(df.PRICE, span=128)
    raw_ewmac = fast_ewma - slow_ewma
    vol = robust_vol_calc(df['PRICE'].diff())
    forecast = raw_ewmac / vol
    print(sharpe(df.PRICE, forecast))
Example #28
0
def get_positions_from_forecasts(price, get_daily_returns_volatility, forecast,
                                 fx, value_of_price_point, **kwargs):
    """
    Work out position using forecast, volatility, fx, value_of_price_point
    (this will be for an arbitrary daily risk target)

    If volatility is not provided, work out from price (uses a standard method
    so may differ from precise system p&l)

    :param price: price series
    :type price: Tx1 pd.DataFrame

    :param get_daily_returns_volatility: series of volatility estimates. NOT %
    volatility, price difference vol
    :type get_daily_returns_volatility: Tx1 pd.DataFrame  or None

    :param forecast: series of forecasts, needed to work out positions
    :type forecast: Tx1 pd.DataFrame

    :param fx: series of fx rates from instrument currency to base currency, to
    work out p&l in base currency
    :type fx: Tx1 pd.DataFrame

    :param value_of_price_point: value of one unit movement in price
    :type value_of_price_point: float

    **kwargs: passed to vol calculation

    :returns: Tx1 pd dataframe of positions

    """
    if forecast is None:
        raise Exception(
            "If you don't provide a series of trades or positions, I need a "
            "forecast")

    if get_daily_returns_volatility is None:
        get_daily_returns_volatility = robust_vol_calc(price.diff(), **kwargs)
    """
    Herein the proof why this position calculation is correct (see chapters
    5-11 of 'systematic trading' book)

    Position = forecast x instrument weight x instrument_div_mult x vol_scalar / 10.0
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x instr value volatility)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x instr ccy volatility x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x block value x % price volatility x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x underlying price x 0.01 x value of price move x 100 x price diff volatility/(underlying price) x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x value of price move x price change volatility x fx rate)

    Making some arbitrary assumptions (one instrument, 100% of capital, daily target DAILY_CAPITAL):

             = forecast x 1.0 x 1.0 x DAILY_CAPITAL / (10.0 x value of price move x price diff volatility x fx rate)
             = forecast x  multiplier / (value of price move x price change volatility x fx rate)
    """
    multiplier = DAILY_CAPITAL * 1.0 * 1.0 / 10.0
    fx = fx.reindex(get_daily_returns_volatility.index, method="ffill")

    denominator = (value_of_price_point * multiply_df_single_column(
        get_daily_returns_volatility, fx, ffill=(False, True)))

    position = divide_df_single_column(forecast * multiplier,
                                       denominator,
                                       ffill=(True, True))
    position.columns = ['position']
    return position
Example #29
0
def get_positions_from_forecasts(price, get_daily_returns_volatility, forecast,
                                 fx, value_of_price_point, capital,
                                 ann_risk_target, **kwargs):
    """
    Work out position using forecast, volatility, fx, value_of_price_point
    (this will be for an arbitrary daily risk target)

    If volatility is not provided, work out from price (uses a standard method
    so may differ from precise system p&l)

    :param price: price series
    :type price: Tx1 pd.DataFrame

    :param get_daily_returns_volatility: series of volatility estimates. NOT %
    volatility, price difference vol
    :type get_daily_returns_volatility: Tx1 pd.DataFrame  or None

    :param forecast: series of forecasts, needed to work out positions
    :type forecast: Tx1 pd.DataFrame

    :param fx: series of fx rates from instrument currency to base currency, to
    work out p&l in base currency
    :type fx: Tx1 pd.DataFrame

    :param value_of_price_point: value of one unit movement in price
    :type value_of_price_point: float

    **kwargs: passed to vol calculation

    :returns: Tx1 pd dataframe of positions

    """
    if forecast is None:
        raise Exception(
            "If you don't provide a series of trades or positions, I need a "
            "forecast")

    if get_daily_returns_volatility is None:
        get_daily_returns_volatility = robust_vol_calc(price.diff(), **kwargs)

    """
    Herein the proof why this position calculation is correct (see chapters
    5-11 of 'systematic trading' book)

    Position = forecast x instrument weight x instrument_div_mult x vol_scalar / 10.0
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x instr value volatility)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x instr ccy volatility x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x block value x % price volatility x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x underlying price x 0.01 x value of price move x 100 x price change volatility/(underlying price) x fx rate)
             = forecast x instrument weight x instrument_div_mult x daily cash vol target / (10.0 x value of price move x price change volatility x fx rate)

    Making some arbitrary assumptions (one instrument, 100% of capital, daily target DAILY_CAPITAL):

             = forecast x 1.0 x 1.0 x DAILY_CAPITAL / (10.0 x value of price move x price diff volatility x fx rate)
             = forecast x  multiplier / (value of price move x price change volatility x fx rate)
    """
    (Unused_capital, daily_capital) = resolve_capital(forecast, capital, ann_risk_target)
    multiplier = daily_capital * 1.0 * 1.0 / 10.0
    fx = fx.reindex(get_daily_returns_volatility.index, method="ffill")

    denominator = (value_of_price_point *
                   multiply_df_single_column(get_daily_returns_volatility,
                                             fx,
                                             ffill=(False, True)))

    numerator = multiply_df_single_column(forecast, multiplier, ffill=(False,True))

    position = divide_df_single_column(numerator,
                                       denominator,
                                       ffill=(True, True))
    position.columns = ['position']
    return position
 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)
Example #31
0
import pandas as pd, numpy as np

def carry(daily_ann_roll, vol, smooth_days=90):
    ann_stdev = vol * 256
    raw_carry = daily_ann_roll / ann_stdev
    smooth_carry = pd.ewma(raw_carry, smooth_days)
    return smooth_carry


#inst = "MXP"; carryoffset = 3 
inst = "CORN"; carryoffset = -3 # SR 0.06
#inst = "EDOLLAR"; carryoffset = -3 # SR -0.67

carry_multiplier = 20.

f = '../../sysdata/legacycsv/%s_price.csv' % inst
df = pd.read_csv(f,index_col=0,parse_dates=True)
f = '../../sysdata/legacycsv/%s_carrydata.csv' % inst
df2 = pd.read_csv(f,index_col=0,parse_dates=True)

vol = robust_vol_calc(df.PRICE.diff())

#forecast2 = np.sign(carryoffset)*(df2.CARRY-df2.PRICE)
forecast2 = df2.PRICE-df2.CARRY/(carryoffset/12.)
forecast2 = carry(forecast2, vol) * carry_multiplier
forecast2.loc[forecast2 > 20] = 20
forecast2.loc[forecast2 < -20] = -20

account = accountCurve(df.PRICE, forecast=forecast2)
print (account.sharpe())
Example #32
0
 def test_robust_vol_calc_min_value(self):
     prices = pd_readcsv_frompackage(
         "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], 0.01)