lppls
is a Python module for fitting the LPPLS model to data.
The LPPLS model provides a flexible framework to detect bubbles and predict regime changes of a financial asset. A bubble is defined as a faster-than-exponential increase in asset price, that reflects positive feedback loop of higher return anticipations competing with negative feedback spirals of crash expectations. It models a bubble price as a power law with a finite-time singularity decorated by oscillations with a frequency increasing with time.
Here is the model:
where:
- expected log price at the date of the termination of the bubble
- critical time (date of termination of the bubble and transition in a new regime)
- expected log price at the peak when the end of the bubble is reached at
- amplitude of the power law acceleration
- amplitude of the log-periodic oscillations
- degree of the super exponential growth
- scaling ratio of the temporal hierarchy of oscillations
- time scale of the oscillations
The model has three components representing a bubble. The first, , handles the hyperbolic power law. For < 1 when the price growth becomes unsustainable, and at the growth rate becomes infinite. The second term, , controls the amplitude of the oscillations. It drops to zero at the critical time . The third term, , models the frequency of the osciallations. They become infinite at .
- Official source code repo: https://github.com/Boulder-Investment-Technologies/lppls
- Download releases: https://pypi.org/project/lppls/
- Issue tracker: https://github.com/Boulder-Investment-Technologies/lppls/issues
Dependencies
lppls
requires:
- Python (>= 3.7)
- Matplotlib (>= 3.1.1)
- Numba (>= 0.51.2)
- NumPy (>= 1.17.0)
- Pandas (>= 0.25.0)
- SciPy (>= 1.3.0)
- Pytest (>= 6.2.1)
User installation
pip install -U lppls
from lppls import lppls, data_loader
import numpy as np
import pandas as pd
%matplotlib inline
# read example dataset into df
data = data_loader.sp500()
# convert index col to evenly spaced numbers over a specified interval
time = np.linspace(0, len(data)-1, len(data))
# create list of observation data, in this case,
# daily adjusted close prices of the S&P 500
# use log price
price = np.log(data['Adj Close'].values)
# create Mx2 matrix (expected format for LPPLS observations)
observations = np.array([time, price])
# set the max number for searches to perform before giving-up
# the literature suggests 25
MAX_SEARCHES = 25
# instantiate a new LPPLS model with the S&P 500 dataset
lppls_model = lppls.LPPLS(observations=observations)
# fit the model to the data and get back the params
tc, m, w, a, b, c, c1, c2 = lppls_model.fit(observations, MAX_SEARCHES, minimizer='Nelder-Mead')
# visualize the fit
lppls_model.plot_fit()
# should give a plot like the following...
# define custom filter condition
filter_conditions_config = [
{'condition_1':[
(0.0, 0.1), # tc_range
(0,1), # m_range
(4,25), # w_range
2.5, # O_min
0.5, # D_min
]},
]
# compute the confidence indicator
res = lppls_model.mp_compute_indicator(
workers=4,
window_size=120,
smallest_window_size=30,
increment=5,
max_searches=25,
filter_conditions_config=filter_conditions_config
)
lppls_model.plot_confidence_indicators(res, condition_name='condition_1', title='Short Term Indicator 120-30')
# should give a plot like the following...
If you wish to store res
as a pd.DataFrame, use res_to_df
.
Example
res_df = lppls_model.res_to_df(res, condition_name='condition_1')
res_df.tail()
# gives the following...
- Filimonov, V. and Sornette, D. A Stable and Robust Calibration Scheme of the Log-Periodic Power Law Model. Physica A: Statistical Mechanics and its Applications. 2013
- Sornette, D. Why Stock Markets Crash: Critical Events in Complex Financial Systems. Princeton University Press. 2002.
- Sornette, D. and Demos, G. and Zhang, Q. and Cauwels, P. and Filimonov, V. and Zhang, Q., Real-Time Prediction and Post-Mortem Analysis of the Shanghai 2015 Stock Market Bubble and Crash (August 6, 2015). Swiss Finance Institute Research Paper No. 15-31.