diff --git a/README.md b/README.md index 3509976..34e7ac1 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Multifractal Detrended Fluctuation Analysis `MFDFA` is a model-independent method to uncover the self-similarity of a stochastic process or auto-regressive model. `DFA` was first developed by Peng *et al.*1 and later extended to study multifractality `MFDFA` by Kandelhardt *et al.*2. +In the latest release there is as well added a moving window system, especially useful for short timeseries, a recent extension to DFA called *extended DFA*, and the extra feature of Empirical Mode Decomposition as detrending method. + # Installation To install MFDFA you can simply use @@ -29,6 +31,8 @@ There is an added library `fgn` to generate fractional Gaussian noise. # Employing the `MFDFA` library ## An exemplary one-dimensional fractional Ornstein–Uhlenbeck process +The rationale here is simple: Numerically integrate a stochastic process in which we know exactly the fractal properties, characterised by the Hurst coefficient, and recover this with MFDFA. +We will use a fractional Ornstein–Uhlenbeck, a commonly employ stochastic process with mean-reverting properties. For a more detailed explanation on how to integrate an Ornstein–Uhlenbeck process, see the [kramersmoyal's package](https://github.com/LRydin/KramersMoyal#a-one-dimensional-stochastic-process). You can also follow the [fOU.ipynb](/examples/fOU.ipynb) @@ -70,7 +74,7 @@ To now utilise the `MFDFA`, we take this exemplary process and run the (multifra ```python # Select a band of lags, which usually ranges from # very small segments of data, to very long ones, as -lag = np.logspace(0.7, 4, 30).astype(int) +lag = np.unique(np.logspace(0.5, 3, 100).astype(int)) # Notice these must be ints, since these will segment # the data into chucks of lag size @@ -98,16 +102,14 @@ np.polyfit(np.log(lag[:15]), np.log(dfa[:15]),1)[0] # Now what you should obtain is: slope = H + 1 ``` - + ## Uncovering multifractality in stochastic processes -`MFDFA`, as an extension to `DFA`, was developed to uncover if a given process is mono or multi fractal. -Let `Xₜ` be a multi fractal stochastic process. This mean `Xₜ` scales with some function alpha(t) as `Xcₜ = |c|alpha(t) Xₜ`. -With the help of taking different powers variations of the `DFA`, one we can distinguish monofractal and multifractal processes. +You can find more about multifractality in the [documentation](https://mfdfa.readthedocs.io/en/latest/1dLevy.html). # Changelog -- Version 0.4 - EMD is now optional. Restored back compatibility: py3.3 to py3.9 +- Version 0.4 - EMD is now optional. Restored back compatibility: py3.3 to py3.9. For EMD py3.6 or larger is needed. - Version 0.3 - Adding EMD detrending. First release. PyPI code. - Version 0.2 - Removed experimental features. Added documentation - Version 0.1 - Uploaded initial working code @@ -122,7 +124,7 @@ This package abides to a [Conduct of Fairness](contributions.md). This library has been submitted for publication at [The Journal of Open Source Software](https://joss.theoj.org/) in December 2019. It was rejected. The review process can be found [here on GitHub](https://github.com/openjournals/joss-reviews/issues/1966). The plan is to extend the library and find another publisher. ### History -This project was started in 2019 at the [Faculty of Mathematics, University of Oslo](https://www.mn.uio.no/math/english/research/groups/risk-stochastics/) in the Risk and Stochastics section by Leonardo Rydin Gorjão and is supported by Dirk Witthaut and the [Institute of Energy and Climate Research Systems Analysis and Technology Evaluation](https://www.fz-juelich.de/iek/iek-ste/EN/Home/home_node.html). I'm very thankful to all the folk in Section 3 in the Faculty of Mathematics, University of Oslo, for helping me getting around the world of stochastic processes: Dennis, Anton, Michele, Fabian, Marc, Prof. Benth and Prof. di Nunno. In April 2020 Galib Hassan joined in extending `MFDFA`, particularly the implementation of EMD. +This project was started in 2019 at the [Faculty of Mathematics, University of Oslo](https://www.mn.uio.no/math/english/research/groups/risk-stochastics/) in the Risk and Stochastics section by Leonardo Rydin Gorjão and is supported by Dirk Witthaut and the [Institute of Energy and Climate Research Systems Analysis and Technology Evaluation](https://www.fz-juelich.de/iek/iek-ste/EN/Home/home_node.html). I'm very thankful to all the folk in Section 3 in the Faculty of Mathematics, University of Oslo, for helping me getting around the world of stochastic processes: Dennis, Anton, Michele, Fabian, Marc, Prof. Benth and Prof. di Nunno. In April 2020 Galib Hassan joined in extending `MFDFA`, particularly the implementation of `EMD`. ### Funding diff --git a/docs/1dLevy.rst b/docs/1dLevy.rst new file mode 100644 index 0000000..6b1f901 --- /dev/null +++ b/docs/1dLevy.rst @@ -0,0 +1,47 @@ +Multifractality in one dimensional distributions +================================================ + +To show how multifractality can be studied, let us take a sample of random numbers of a symmetric `Lévy distribution `_. + + +Univariate random numbers from a Lévy stable distribution +--------------------------------------------------------- + +To obtain a sample of random numbers of Lévy stable distributions, use `scipy`'s `levy_stable`. In particular, take an :math:`\alpha`-stable distribution, with :math:`\alpha=1.5` + +.. code:: python + + # Imports + from MFDFA import MFDFA + from scipy.stats import levy_stable + + # Generate 100000 points + alpha = 1.5 + X = levy_stable.rvs(alpha=alpha, beta = 0, size=10000) + + +For :code:`MFDFA` to detect the multifractal spectrum of the data, we need to vary the parameter :math:`q\in[-10,10]` and exclude :math:`0`. Let us also use a quadratic polynomial fitting by setting :code:`order=2` + +.. code:: python + + # Select a band of lags, which are ints + lag = np.unique(np.logspace(0.5, 3, 100).astype(int)) + + # Select a list of powers q + q_list = np.linspace(-10,10,41) + q_list = q_list[q_list!=0.0] + + # The order of the polynomial fitting + order = 2 + + # Obtain the (MF)DFA as + lag, dfa = MFDFA(y, lag = lag, q = q_list, order = order) + + +Again, we plot this in a double logarithmic scale, but now we include 6 curves, from 6 selected :math:`q={-10,-5-2,2,5,10}`. Include as well are the theoretical curves for :math:`q=-10`, with a slope of :math:`1/\alpha=1/1.5` and :math:`q=10`, with a slope of :math:`1/q=1/10` + + +.. image:: /_static/fig2.png + :height: 450 + :align: center + :alt: Plot of the MFDFA of a Lévy stable distribution for a few q values. diff --git a/docs/1dprocess.rst b/docs/1dprocess.rst index fa02843..1ea3271 100644 --- a/docs/1dprocess.rst +++ b/docs/1dprocess.rst @@ -49,7 +49,7 @@ To now utilise the :code:`MFDFA`, we take this exemplary process and run the (mu # Select a band of lags, which usually ranges from # very small segments of data, to very long ones, as - lag = np.logspace(0.7, 4, 30).astype(int) + lag = np.unique(np.logspace(0.5, 3, 100).astype(int)) # Notice these must be ints, since these will segment # the data into chucks of lag size diff --git a/docs/_static/fig1.png b/docs/_static/fig1.png index 5e0e01a..d3c6975 100644 Binary files a/docs/_static/fig1.png and b/docs/_static/fig1.png differ diff --git a/docs/_static/fig2.png b/docs/_static/fig2.png new file mode 100644 index 0000000..fbc39eb Binary files /dev/null and b/docs/_static/fig2.png differ diff --git a/docs/conf.py b/docs/conf.py index 94e21e6..e84e6a7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,12 +22,12 @@ # -- Project information ----------------------------------------------------- project = 'MFDFA' -copyright = '2019-2020 Leonardo Rydin' +copyright = '2019-2021 Leonardo Rydin' author = 'Leonardo Rydin' # The full version, including alpha/beta/rc tags -release = '0.3' -version = '0.3' +release = '0.4' +version = '0.4' # -- General configuration --------------------------------------------------- @@ -89,7 +89,7 @@ 'style_external_links': False, 'style_nav_header_background': 'black', # Toc options - 'collapse_navigation': True, + 'collapse_navigation': False, 'sticky_navigation': True, 'navigation_depth': 4, 'titles_only': False diff --git a/docs/index.rst b/docs/index.rst index 1bafb25..e80e3bb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,6 +10,8 @@ MFDFA's documentation .. include:: 1dprocess.rst +.. include:: 1dLevy.rst + .. include:: extensions.rst Literature @@ -30,9 +32,11 @@ Table of Content .. toctree:: :maxdepth: 3 + :hidden: installation 1dprocess + 1dLevy extensions functions/index license diff --git a/other/fig1.png b/other/fig1.png deleted file mode 100644 index 5e0e01a..0000000 Binary files a/other/fig1.png and /dev/null differ diff --git a/tester.py b/tester.py index b0d7e48..c205479 100644 --- a/tester.py +++ b/tester.py @@ -3,7 +3,8 @@ from numpy.polynomial.polynomial import polyfit import matplotlib.pyplot as plt -import MFDFA as MFDFA +from MFDFA import MFDFA +from MFDFA import fgn # %% Lets take a fractional Ornstein–Uhlenbeck process Xₜ with a time-dependent # diffusion or volatility σₜ, some drift of mean reverting term θ(Xₜ), and @@ -31,7 +32,7 @@ H = 0.5 # Generate the fractional Gaussian noise -dw = (t_final ** H) * MFDFA.fgn(time.size, H = H) +dw = (t_final ** H) * fgn(time.size, H = H) # Integrate the process for i in range(1,time.size): @@ -49,7 +50,7 @@ q = 2 # dfa records the fluctuation function using the EMD as a detrending mechanims. -lag, dfa, dfa_std, e_dfa = MFDFA.MFDFA(X, lag, q = q, order = 1, stat = True, extensions = {"eDFA": True}) +lag, dfa, dfa_std, e_dfa = MFDFA(X, lag, q = q, order = 1, stat = True, extensions = {"eDFA": True}) # %% Plots # Visualise the results in a log-log plot