arbitragelab.copula_approach.vinecop_strategy

Module that houses vine copula trading strategies.

Module Contents

Classes

CVineCopStrat

Trading strategy class using C-vine copulas.

class CVineCopStrat(cvinecop: arbitragelab.copula_approach.vinecop_generate.CVineCop = None, signal_to_position_table: pandas.DataFrame = None)

Trading strategy class using C-vine copulas.

Method based on Stübinger, J., Mangold, B. and Krauss, C., 2018. Statistical arbitrage with vine copulas.

calc_mpi(returns: pandas.DataFrame, cdfs: List[Callable], pv_target_idx: int = 1, subtract_mean: bool = False) pandas.Series

Calculate mispricing indices from returns for the target stock.

Mispricing indices are technically cumulative conditional probabilities calculated from a vine copula based on returns data. Note that MPIs are model dependent since they are conditional probabilities inferred from vine copulas.

Parameters:
  • returns – (pd.DataFrame) The returns data for stocks.

  • cdfs – (pd.DataFrame) The list of cdf functions for each stocks return, used to map returns to their quantiles.

  • pv_target_idx – (int) Optional. The target stock’s index. Defaults to 1.

  • subtract_mean – (bool) Optional. Whether to subtract the mean 0.5 of MPI from the calculation.

Returns:

(pd.Series) The MPIs calculated from returns and vine copula.

get_positions_bollinger(returns: pandas.DataFrame, cdfs: List[Callable], pv_target_idx: int = 1, init_pos: int = 0, past_obs: int = 20, threshold_std: float = 1.0, mpis: pandas.Series = None, if_return_bollinger_band=False) pandas.Series | Tuple[pandas.Series, pandas.DataFrame]

Get positions based on the strategy suggested by [Bollinger, 1992].

Calculate the running mean and standard deviation of Cumulative mispricing index (CMPI) for the past 20 observations (one month if it is daily data) and create the running Bollinger band as (mean - k*std, mean + k*std), k is the threshold_std variable. Trading logic is as follows:

  • Long if the CMPI crosses its lower Bollinger band (undervalued)

  • Short if the CMPI crosses its upper Bollinger band (overvalued)

  • Exit if the CMPI crosses the running mean of the Bollinger band (reversion to equilibrium)

This is used for backtesting when one has access to all testing data at once. The first 20 observations ([0, 19]) will be used for calculating the Bollinger band and the trading signal generation starts from observation 20. For live data feed you can use self.get_cur_pos_bollinger() to save computation time.

Parameters:
  • returns – (pd.DataFrame) The returns data for stocks.

  • cdfs – (pd.DataFrame) The list of cdf functions for each stocks return, used to map returns to their quantiles.

  • pv_target_idx – (int) Optional. The target stock’s index. Defaults to 1.

  • init_pos – (int) Optional. Initial trading position, 0 is None, 1 is Long, -1 is Short. Defaults to 0.

  • past_obs – (int) Optional. The number of observations used to calculate Bollinger band. Defaults to 20.

  • threshold_std – (float) Optional. How many std away from the running avg for the Bollinger band. Defaults to 1.

  • mpis – (pd.Series) Optional. The MPI data for the target stock. Defaults to None, and it will be from the returns automatically. This is used to preload MPIs to save computation time.

  • if_return_bollinger_band – (bool) Optional. Whether to return the Bollinger band data series together with the positions data series. Defaults to False.

Returns:

(Union[pd.Series, Tuple[pd.Series]]) The MPIs calculated from returns and vine copula. Or the MPIs together with the Bollinger band data.

static get_cur_signal_bollinger(past_cmpi: float, cur_cmpi: float, running_mean: float, upper_threshold: float, lower_threshold: float) int

Get the current trading signal based on the bollinger band over CMPIs.

Signal types {1: long, -1: short, 0: exit, 2: do nothing}. If the current CMPI > upper threshold, then short; If the current CMPI < lower threshold, then long; If the current CMPI crosses with the running mean, then exit; else do nothing.

Parameters:
  • past_cmpi – (float) The immediate past CMPI value.

  • cur_cmpi – (float) The current CMPI value.

  • running_mean – (float) The running average for CMPI in the bollinger band.

  • upper_threshold – (float) The upper threshold of the bollinger band.

  • lower_threshold – (float) The lower threshold of the bollinger band.

Returns:

(int) The derived signal based on all the input info.

get_cur_pos_bollinger(returns_slice: pandas.DataFrame, cdfs: List[Callable], past_pos: int, pv_target_idx: int = 1, past_cmpi: float = 0, threshold_std: float = 1.0) Tuple[int, float]

Get the suggested position and updated bollinger band from cur_returns pandas DataFrame.

If the dataframe has 21 rows, then the first 20 rows will be used to calculate the Bollinger band, then the position will be generated based on the last row. Then we calculate the updated Bollinger band. This is used for live data feed.

Parameters:
  • returns_slice – (pd.DataFrame) The slice of the returns data frame. Everything except for the last data point is used to calculate the bollinger band, and the last data point is used to generate the current position.

  • cdfs – (List[Callable]) The list of CDFs for the returns data.

  • past_pos – (int) The immediate past position.

  • pv_target_idx – (int) Optional. The target stock index. For example, 1 means the target stock is the 0th column in returns_slice. Defaults to 1.

  • past_cmpi – (float) Optional. The immediate past CMPI value. Defaults to 0.

  • threshold_std – (float) Optional. How many std away from the running avg for the Bollinger band. Defalts to 1.

Returns:

(Tuple[int, float]) The current position and the new cmpi.

static positions_to_units_against_index(target_stock_prices: pandas.Series, index_prices: pandas.Series, positions: pandas.Series, multiplier: float = 1) pandas.DataFrame

Translate positions to units held for the target stock against an index fund.

The translation is conducted under a dollar-neutral strategy against an index fund (typically SP500 index). For example, for a long position, for each 1 dollar investment, long the target stock by 1/2 dollar, and short the index fund by 1/2 dollar.

Originally the positions calculated by this strategy is given with values in {0, 1, -1}. To be able to actually trade using the dollar neutral strategy as given by the authors in the paper, one needs to know at any given time how much units to hold for the stock. The result will be returned in a pd.DataFrame. The user can also multiply the final result by changing the multiplier input. It means by default it uses 1 dollar for calculation unless changed. It also means there is no reinvestment on gains.

Note: The short units will be given in its actual value. i.e., short 0.54 units is given as -0.54 in the output.

Parameters:
  • target_stock_prices – (pd.Series) The target stock’s price series.

  • index_prices – (pd.Series) The index fund’s price.

  • positions – (pd.Series) The positions suggested by the strategy in integers.

  • multiplier – (float) Optional. Multiply the calculated result by this amount. Defaults to 1.

Returns:

(pd.DataFrame) The units to hold for the target stock and the index fund.