Exemplo n.º 1
0
def small_data():
    rs = np.random.RandomState([2389280, 238901, 382908031])
    mod = ZeroMean(None,
                   volatility=GARCH(),
                   distribution=Normal(random_state=rs))
    sim = mod.simulate([1e-4, 0.05, 0.90], nobs=1000)
    return sim.data
 def getvolatility(self):
     df = volatility.getyieldrate(self)
     vol = 0.0
     for i in range(1, len(df)):
         vol = vol + df[i] * df[i] / 10000.0
     am = ConstantMean(df)
     am.volatility = GARCH(1, 0, 1)
     am.distribution = Normal()
     res = am.fit()
     print('vol =' + str(vol))
     print(res.summary)
     return 0
Exemplo n.º 3
0
def test_simulate():
    normal = Normal(random_state=np.random.RandomState(0))
    gim = ARCHInMean(SP500, volatility=GARCH(), distribution=normal)
    res = gim.fit(disp="off")
    sim = gim.simulate(res.params, 1000)
    assert sim.shape == (1000, 3)
    assert "data" in sim
    assert "volatility" in sim
    assert "errors" in sim
    mean = sim.data - sim.errors
    vol = mean - res.params.iloc[0]
    kappa = res.params.iloc[1]
    rescaled_vol = vol / kappa
    np.testing.assert_allclose(rescaled_vol, sim.volatility)
    with pytest.raises(ValueError, match="initial_value has the wrong shape"):
        gim.simulate(res.params, 1000, initial_value=np.array([0.0, 0.0]))
Exemplo n.º 4
0
def test_simulate_arx(form):
    normal = Normal(random_state=np.random.RandomState(0))
    gim = ARCHInMean(
        SP500,
        constant=False,
        lags=2,
        volatility=GARCH(),
        distribution=normal,
        x=X,
        form=form,
    )
    res = gim.fit(disp="off")
    sim = gim.simulate(res.params, 1000, x=X.iloc[:1500], initial_value=0.0)
    assert sim.shape == (1000, 3)
    assert "data" in sim
    assert "volatility" in sim
    assert "errors" in sim
    gim.simulate(res.params, 1000, x=X.iloc[:1500], initial_value=np.zeros(2))
Exemplo n.º 5
0
 def _get_ARCH_model(self, returns: LogReturnsSeries, vol_process: VolatilityProcess):
     am = ConstantMean(returns)
     am.volatility = vol_process
     am.distribution = Normal()
     return am
Exemplo n.º 6
0
def return_sampler_garch(
    N_train: int,
    mean_process: str = "Constant",
    lags_mean_process: int = None,
    vol_process: str = "GARCH",
    distr_noise: str = "normal",
    seed: int = None,
    seed_param: int = None,
    p_arg: list = None,
) -> Tuple[np.ndarray, pd.Series]:
    # https://stats.stackexchange.com/questions/61824/how-to-interpret-garch-parameters
    # https://arch.readthedocs.io/en/latest/univariate/introduction.html
    # https://arch.readthedocs.io/en/latest/univariate/volatility.html
    # https://github.com/bashtage/arch/blob/master/arch/univariate/volatility.py
    """
    Generates financial returns driven by mean-reverting factors.

    Parameters
    ----------
    N_train: int
        Length of the experiment

    mean_process: str
        Mean process for the returns. It can be 'Constant' or 'AR'

    lags_mean_process: int
        Order of autoregressive lag if mean_process is AR

    vol_process: str
        Volatility process for the returns. It can be 'GARCH', 'EGARCH', 'TGARCH',
        'ARCH', 'HARCH', 'FIGARCH' or 'Constant'. Note that different volatility
        processes requires different parameter, which are hard coded. If you want to
        pass them explicitly, use p_arg.

    distr_noise: str
        Distribution for the unpredictable component of the returns. It can be
        'normal', 'studt', 'skewstud' or 'ged'. Note that different distributions
        requires different parameter, which are hard coded. If you want to
        pass them explicitly, use p_arg.

    seed: int
        Seed for experiment reproducibility

    seed_param: int
        Seed for drawing randomly the parameters needed for the simulation. The
        ranges provided are obtained as average lower and upper bounds of several
        GARCH-type model fitting on real financial time-series.

    p_arg: pd.Series
        Pandas series of parameters that you want to pass explicitly.
        They need to be passed in the right order. Check documentation of the
        arch python package (https://arch.readthedocs.io/en/latest/index.html) for more details.
    Returns
    -------
    simulations['data'].values: np.ndarray
        Simulated series of returns
    p: pd.Series
        Series  of parameters used for simulation
    """
    names = []
    vals = []

    if seed_param is None:
        seed_param = seed

    rng = np.random.RandomState(seed_param)

    # choose mean process
    if mean_process == "Constant":
        model = ConstantMean(None)
        names.append("const")
        if seed_param:
            vals.append(rng.uniform(0.01, 0.09))
        else:
            vals.append(0.0)

    elif mean_process == "AR":
        model = ARX(None, lags=lags_mean_process)
        names.append("const")
        vals.append(0.0)
        if seed_param:
            for i in range(lags_mean_process):
                names.append("lag{}".format(i))
                vals.append(rng.uniform(-0.09, 0.09))
        else:
            for i in range(lags_mean_process):
                names.append("lag{}".format(i))
                vals.append(0.9)

    else:
        return print("This mean process doesn't exist or it's not available.")
        sys.exit()

    # choose volatility process
    if vol_process == "GARCH":
        model.volatility = GARCH(p=1, q=1)
        names.extend(["omega", "alpha", "beta"])
        if seed_param:
            om = rng.uniform(0.03, 0.1)
            alph = rng.uniform(0.05, 0.1)
            b = rng.uniform(0.86, 0.92)
            garch_p = np.array([om, alph, b]) / (np.array([om, alph, b]).sum())
        else:
            om = 0.01
            alph = 0.05
            b = 0.94
            garch_p = np.array([om, alph, b])
        vals.extend(list(garch_p))

    elif vol_process == "ARCH":
        model.volatility = GARCH(p=1, q=0)

        names.extend(["omega", "alpha"])
        if seed_param:
            om = rng.uniform(1.4, 4.0)
            alph = rng.uniform(0.1, 0.6)
        else:
            om = 0.01
            alph = 0.4
        garch_p = np.array([om, alph])
        vals.extend(list(garch_p))

    elif vol_process == "HARCH":
        model.volatility = HARCH(lags=[1, 5, 22])

        names.extend(["omega", "alpha[1]", "alpha[5]", "alpha[22]"])
        if seed_param:
            om = rng.uniform(1.2, 0.5)
            alph1 = rng.uniform(0.01, 0.1)
            alph5 = rng.uniform(0.05, 0.3)
            alph22 = rng.uniform(0.4, 0.7)
        else:
            om = 0.01
            alph1 = 0.05
            alph5 = 0.15
            alph22 = 0.5
        garch_p = np.array([om, alph1, alph5, alph22])
        vals.extend(list(garch_p))

    elif vol_process == "FIGARCH":
        model.volatility = FIGARCH(p=1, q=1)

        names.extend(["omega", "phi", "d", "beta"])
        if seed_param:
            om = rng.uniform(0.05, 0.03)
            phi = rng.uniform(0.1, 0.35)
            d = rng.uniform(0.3, 0.5)
            beta = rng.uniform(0.4, 0.7)
        else:
            om = 0.01
            phi = 0.2
            d = 0.2
            beta = 0.55
        garch_p = np.array([om, phi, d, beta])
        vals.extend(list(garch_p))

    elif vol_process == "TGARCH":
        model.volatility = GARCH(p=1, o=1, q=1)
        names.extend(["omega", "alpha", "gamma", "beta"])
        if seed_param:
            om = rng.uniform(0.02, 0.15)
            alph = rng.uniform(0.01, 0.07)
            gamma = rng.uniform(0.03, 0.1)
            b = rng.uniform(0.88, 0.94)
        else:
            om = 0.01
            alph = 0.05
            gamma = 0.04
            b = 0.90
        garch_p = np.array([om, alph, gamma, b])
        vals.extend(list(garch_p))

    elif vol_process == "EGARCH":
        model.volatility = EGARCH(p=1, o=1, q=1)
        names.extend(["omega", "alpha", "gamma", "beta"])
        if seed_param:
            om = rng.uniform(0.01, 0.03)
            alph = rng.uniform(0.06, 0.17)
            gamma = rng.uniform(-0.05, -0.02)
            b = rng.uniform(0.97, 0.99)
            garch_p = np.array([om, alph, gamma, b]) / (np.array(
                [om, alph, gamma, b]).sum())
        else:
            om = 0.01
            alph = 0.05
            gamma = -0.02
            b = 0.94
            garch_p = np.array([om, alph, gamma, b])
        vals.extend(list(garch_p))

    elif vol_process == "Constant":
        model.volatility = ConstantVariance()
        names.append("sigma_const")
        vals.append(rng.uniform(0.02, 0.05))
    else:
        print("This volatility process doesn't exist or it's not available.")
        sys.exit()

    if distr_noise == "normal":
        model.distribution = Normal(np.random.RandomState(seed))
    elif distr_noise == "studt":
        model.distribution = StudentsT(np.random.RandomState(seed))
        names.append("nu")
        if seed_param:
            vals.append(rng.randint(6.0, 10.0))
        else:
            vals.append(8.0)
    elif distr_noise == "skewstud":
        model.distribution = SkewStudent(np.random.RandomState(seed))
        names.extend(["nu", "lambda"])
        if seed_param:
            vals.extend([rng.uniform(6.0, 10.0), rng.uniform(-0.1, 0.1)])
        else:
            vals.extend([8.0, 0.05])
    elif distr_noise == "ged":
        model.distribution = GeneralizedError(np.random.RandomState(seed))
        names.append("nu")
        if seed_param:
            vals.append(rng.uniform(1.05, 3.0))
        else:
            vals.append(2.0)
    else:
        print("This noise distribution doesn't exist or it's not available.")
        sys.exit()

    p = pd.Series(data=vals, index=names)
    if p_arg:
        p = p_arg
    simulations = model.simulate(p, N_train) / 100

    return simulations["data"].values, p
Exemplo n.º 7
0
import datetime as dt

import pandas_datareader.data as web

from arch import arch_model
from arch.univariate import ConstantMean, GARCH, Normal
#from arch.univariate import ZeroMean, GARCH, Normal

start = dt.datetime(2000, 1, 1)
end = dt.datetime(2014, 1, 1)
sp500 = web.DataReader('^GSPC', 'yahoo', start=start, end=end)
returns = 100 * sp500['Adj Close'].pct_change().dropna()

am = ConstantMean(returns)
am.volatility = GARCH(1, 0, 1)
am.distribution = Normal()

res = am.fit()

res.summary()

# %%

# import the packages
import numpy as np
from scipy.optimize import minimize
import scipy.stats as stats
import time

# Set up your x values
x = np.linspace(0, 100, num=100)
Exemplo n.º 8
0
def bruteforce_ts_model(returns, start_p, start_q, max_p, max_q):
    """ This methods bruteforce each possible combination of the ARCH family models. (e.g. ARCH(3), GARCH(3,4), EGARCH(1,3))
        Records its score and save it.

        Args: 
            returns (pandas.Series) : Contains the list of all the returns.
            start_p (int) : Integer who gives the starting point of the range of p parameter
            start_q (int) : Integer who gives the starting point of the range of q parameter
            max_p (int) : Integer who gives the ending point of the range of p parameter
            max_q (int) : Integer who gives the ending point of the range of q parameter

        Output:
            df (pandas.DataFrame) : Dataframe containing all the models and Information criteria
    """

    # We define our list of models to test
    model_types = ['ARCH', 'GARCH', 'EGARCH']

    # We define our list of distribution to test
    dist_types = ['normal', 'studentst', 'skewstudent']

    # We define our list
    AIC_score = []
    BIC_score = []
    LL_score = []
    model_list = []
    mean_model_list = []
    dist_list = []
    q_list = []
    p_list = []

    # We compute the total number of models
    max_iter = max_p * max_q * len(model_types) * len(dist_types)
    current_iter = 0

    # For each model we have
    for model in model_types:

        # For each parameter p
        for each_p in range(start_p, max_p):

            # For each parameter q
            for each_q in range(start_q, max_q):

                # For each distribution type
                for dist in dist_types:

                    # We define our mean model
                    am = ConstantMean(returns)

                    # We define our constant mean
                    mean_model_list.append('ConstantMean')

                    # Our distribution
                    if dist is 'normal':
                        am.distribution = Normal()
                    elif dist is 'studentst':
                        am.distribution = StudentsT()
                    elif dist is 'skewstudent':
                        am.distribution = SkewStudent()

                    # Our volatility process
                    if model is "ARCH":
                        am.volatility = ARCH(p=each_p)
                    elif model is "GARCH":
                        am.volatility = GARCH(p=each_p, q=each_q)
                    elif model is "EGARCH":
                        am.volatility = EGARCH(p=each_p, q=each_q)

                    # We fit our model
                    res = am.fit(update_freq=5, disp='off')

                    # We record our model and distribution
                    model_list.append(model)
                    dist_list.append(dist)

                    # We record the scores
                    AIC_score.append(res.aic)
                    BIC_score.append(res.bic)
                    LL_score.append(res.loglikelihood)

                    # We record the parameters
                    q_list.append(each_q)
                    p_list.append(each_p)

                    # We log the information about each computed model
                    print(
                        f"it: {current_iter}/{max_iter}\tmodel:{model}\tdist:{dist[:6]}\tp:{each_p}\tq:{each_q}\tAIC_score:{round(res.aic,2)}\tBIC_score:{round(res.bic,2)}\tLog Likelihood:{round(res.loglikelihood,2)}"
                    )

                    # If a model has been added then we add one to the iterator
                    current_iter += 1

        # For each computed model
        print("=" * 20, f"{model} finished", "=" * 20)

    # We combine everything to a dataframe
    df = pd.DataFrame({
        'volatility_model': model_list,
        'mean_model': mean_model_list,
        'dist': dist_list,
        'p': p_list,
        'q': q_list,
        'AIC_score': AIC_score,
        'BIC_score': BIC_score,
        'LL_score': LL_score
    })
    return df
Exemplo n.º 9
0
forecast variance(10 days): 3.6425481901571626
forecast VaR: 4.439942146600405
forecast ES: 5.086684187983292
'''

# NGARCH(1,1)

omega = 1.5E-6 * scale**2
alpha = 0.05
beta = 0.8
theta = 1.25

ngarch = ZeroMean(returns['Close'])
ngarch11 = NGARCH11(np.array([omega, alpha, beta, theta]))
ngarch.volatility = ngarch11
ngarch.distribution = Normal()
rst = ngarch.fit()

print(rst)

rst.plot(annualize='D')

print(
    ngarch11.is_valid(rst.params['alpha'], rst.params['beta'],
                      rst.params['theta']))

rs = np.random.RandomState(1234)
forecast_variance_10days = rst.forecast(horizon=10,
                                        method='simulation',
                                        rng=lambda x: rs.normal(size=x),
                                        simulations=1000).variance.iloc[-1, :]