Exact symbolic tests of serial independence, version 1.0.1. Companion software to
E. Ashtari Nezhad, Information Variance and Exact Symbolic Tests of Serial Independence.
Install: pip install ivserial · PyPI: pypi.org/project/ivserial · Source: github.com/emaad7/ivserial
ivserial tests whether a time series is a sequence of independent and identically distributed (i.i.d.) values. The test is rank based and exact: under independence its P-value is valid for every sample size and every continuous distribution, with no model, bandwidth or tuning parameter to choose. It reports
serial_test(x) in a Python script or notebook, or ivserial data.csv in a terminal. Suited to many series and to reproducible work.Both use the same functions and give the same results: everything that can be done in code can also be done in the window, and the other way round. The table lists the correspondence.
| Task | Window (GUI) | Python | Command line |
|---|---|---|---|
| Test one series | Test tab, choose column, Run test | serial_test(x) | ivserial file.csv -c NAME |
| Screen many series | tick test all columns | loop over columns | ivserial file.csv |
| Prices to log returns | Transform: log returns | transform="logdiff" | -t logdiff |
| Options (B, seed, m, d, level, lags, patterns) | Options and Portmanteau rows | arguments of serial_test | --B --seed --m --d --alpha --lags --d2 --cells |
| Save results | Save report... (.txt or .json) | res.to_dict(), str(res) | --out report.txt --json res.json |
| Sample size / power | Sample size & power tab | required_sample_size, approximate_power | ivserial plan --gamma ... |
| Default resolution for n | Resolution for n | choose_resolution(n) | ivserial plan ... --n N |
| Null distribution, critical values | Null distribution tab | null_limit_summary, null_limit_sf | ivserial null --m 3 --d 4 --q 80 |
https://www.python.org/downloads/. In the first screen of the installer tick "Add python.exe to PATH", then Install Now. Check in Command Prompt: python --version.python3 and pip3 instead of python and pip.sudo apt install python3-tk.Open a terminal (Command Prompt on Windows) and run one of
pip install ivserial # from the Python Package Index (recommended) pip install git+https://github.com/emaad7/ivserial # latest version from GitHub (needs Git)
The package page on the Python Package Index is pypi.org/project/ivserial; the source code, examples and this guide are at github.com/emaad7/ivserial. To update to a newer version later, run pip install --upgrade ivserial.
Without internet access, download the wheel file ivserial-1.0.1-py3-none-any.whl (from the Releases page on GitHub or the Download files page on PyPI), open a terminal in the folder where you saved it, and run pip install ivserial-1.0.1-py3-none-any.whl.
The required libraries numpy and scipy are installed automatically. For Excel files also run pip install pandas openpyxl (or pip install "ivserial[excel]"). If pip is not found, use python -m pip install ....
After installation you have
import ivserial;ivserial in any terminal;ivserial-gui, which opens the window (also python -m ivserial).Check: ivserial --version prints ivserial 1.0.1. This guide is installed with the package: ivserial guide opens it, as does the User guide button in the window.
On GitHub press Code → Download ZIP and unzip the file, run pip install numpy scipy once, and double-click run_gui_windows.bat (Windows), run_gui_mac_linux.command (macOS, Linux) or ivserial_gui.pyw.
The folder examples contains exchange_rates.csv, the 20 daily exchange rates analysed in the paper (prices; use the log-return transform).
Start it with ivserial-gui, python -m ivserial, or by double-clicking as described above. It has three tabs.
The options can be left at their defaults: B = 9999 random permutations, block length m and classes d chosen automatically, level 0.05, portmanteau with lags 1 and 2. Keep the seed fixed to make the P-values reproducible.
After Run test the report appears below the buttons (here for the yuan):
Exact symbolic test of serial independence [China] =================================================== Observations n = 939 Block statistic: m = 3 consecutive values, d = 5 quantile classes (125 patterns) Portmanteau: lags 1..2, d = 5 classes Random permutations B = 9999 Test Statistic P-value C = min(p_Q, p_P2) [proposed] 0.0001 Q (blocks, permutation) 380.369 0.0001 Q (blocks, asymptotic) < 0.0001 P2 (lags, permutation) 170.349 0.0001 P2 (lags, asymptotic) < 0.0001 Serial independence is REJECTED at the 0.05 level (combined test C). Strength of dependence: V-hat = 0.109 (serial Cramer coefficient, 0 to 1: 0 = independent blocks, 1 = each value determines its block) Efficiency: Gamma-hat = 0.2864 (bias-corrected normalized information variance = approximate Bahadur slope; about 0 under independence) Planning: power 0.8 against dependence of this strength needs about 250 observations (tau-hat = 2.943; Corollary 4.8 of the paper). Most over- and under-represented patterns (classes 1 = lowest ... 5 = highest): pattern observed expected residual 3-3-3 41 7.5 12.24 1-5-5 20 7.5 4.57 1-1-5 19 7.5 4.20 5-5-5 17 7.5 3.47 Residual = (observed - expected)/sqrt(expected); |residual| > 3 is notable.
With test all columns, a screening table comes first, with P-values adjusted for multiple testing (Benjamini–Hochberg), followed by the full report for each series:
Screening summary (Benjamini-Hochberg adjustment) series n p_C adj. p V-hat Gamma-hat decision Australia 939 0.6368 0.7076 0.000 -0.0151 - Brazil 939 0.2840 0.4327 0.025 0.0145 - China 939 0.0001 0.0010 0.109 0.2864 reject India 939 0.0001 0.0010 0.072 0.1247 reject Japan 939 0.0030 0.0200 0.047 0.0535 reject Mexico 939 0.0053 0.0265 0.038 0.0353 reject Taiwan 939 0.0096 0.0384 0.046 0.0518 reject ... (20 series in total)
Enter the strength of dependence Gamma, or instead the coefficient V between 0 and 1 (and, if known, tau), at resolution (m, d), or press Use last test to take Gamma-hat, tau-hat, m and d from the test just run, for example on a pilot sample or a comparable series. Then
Required number of observations (Gamma = 0.2864, V = 0.109, tau = 2.9425, (m, d) = (3, 5), level 0.05)
power n
0.50 105
0.80 250 <- target
0.90 368
0.95 491
Shows the explicit limit Lm,d of the block statistic under independence, its mean and variance, the critical values at the 10%, 5% and 1% levels, and the P-value of any value of Q.
Null limit for m = 3, d = 4 (64 patterns): L = 2 x chi2(9) + 1 x chi2(36)
mean = 54.00, variance = 144.00
level critical value
0.10 69.832
0.05 75.257
0.01 86.294
P(L > 75) = 0.05175
import numpy as np
from ivserial import serial_test, required_sample_size, approximate_power
x = np.loadtxt("returns.txt") # any 1-d array, in time order
res = serial_test(x, seed=1) # B = 9999 permutations by default
print(res) # full report, as in the window
res.p_C, res.reject # P-value of C and decision at level 0.05
res.p_Q, res.p_P2, res.p_Q_asymptotic # components and asymptotic P-value
res.cramer_v # strength of dependence, between 0 and 1
res.gamma_hat, res.tau_hat # efficiency and its standard deviation
res.cells[:5] # most over- and under-represented patterns
res.to_dict() # all results, e.g. for a pandas DataFrame
serial_test(prices, transform="logdiff", label="WTI") # prices -> log returns
serial_test(x, m=3, d=4, lags=3, B=99999, alpha=0.01) # options
Reading a data file as in the window:
from ivserial import read_table
cols = read_table("examples/exchange_rates.csv") # {column name: array}
for name, v in cols.items():
r = serial_test(v, transform="logdiff", seed=1, label=name)
print(name, round(r.p_C, 4), round(r.cramer_v, 3))
| Function | Purpose |
|---|---|
serial_test(x, m, d, d_portmanteau, lags, B, seed, alpha, transform, label, n_cells) | the test; returns a result object with the attributes above |
required_sample_size(gamma, m, d, alpha, power, tau) | observations needed for a given power |
approximate_power(gamma, n, m, d, alpha, tau) | power for n observations |
sample_size_table(gamma, m, d, alpha, tau, powers) | sample sizes for several powers |
serial_cramer_v(gamma, m, d), gamma_from_cramer_v(v, m, d) | convert between Gamma and V |
choose_resolution(n) | default (m, d) |
null_limit_summary(m, d), null_limit_sf(q, m, d), null_limit_quantile(alpha, m, d) | null limit Lm,d: moments, critical values, P-values |
read_table(path) | numeric columns of a CSV, TXT or Excel file |
ivserial data.csv # every numeric column ivserial prices.csv -c Close -t logdiff --seed 1 # one column, log returns ivserial examples/exchange_rates.csv -t logdiff --seed 1 --out report.txt --json results.json ivserial plan --gamma 0.13 --tau 1.13 --m 3 --d 4 --n 350 # sample size and power ivserial plan --v 0.093 --tau 1.13 --m 3 --d 4 # the same, starting from V ivserial null --m 3 --d 4 --q 80 # null limit and P-value of Q = 80 ivserial gui # open the window ivserial guide # open this guide ivserial --help # all options
Test Statistic P-value C = min(p_Q, p_P2) [proposed] 0.0001 Q (blocks, permutation) 380.369 0.0001 Q (blocks, asymptotic) < 0.0001 P2 (lags, permutation) 170.349 0.0001 P2 (lags, asymptotic) < 0.0001 Serial independence is REJECTED at the 0.05 level (combined test C). Strength of dependence: V-hat = 0.109 Efficiency: Gamma-hat = 0.2864 Planning: power 0.8 against dependence of this strength needs about 250 observations
| Item | Meaning |
|---|---|
| C | The test to use. A P-value below the level (e.g. 0.05) rejects serial independence. |
| Q, P2 | Blocks of m consecutive values, and pairs at lags 1 and 2. C combines them exactly. |
| permutation / asymptotic | Permutation P-values are exact; asymptotic ones use the explicit limits and are accurate for n ≥ 350. |
| V-hat | Strength of dependence, between 0 and 1 (serial Cramér coefficient): 0 means that blocks of m consecutive classes are independent, 1 that the class of any one value determines its whole block. For m = 2 it is Cramér’s V of consecutive classes. Compare values at the same (m, d). |
| Gamma-hat | Efficiency: the normalized information variance, the approximate Bahadur slope of the test; Gamma = (dm−1 − 1)·V². It drives the sample-size calculation. |
| Patterns | Each value is assigned to one of d classes by its rank (1 = lowest, d = highest). Residual = (observed − expected)/√expected; |residual| > 3 is notable. |
Example (Chinese yuan, from the paper). The pattern 3-3-3 occurs 41 times against 7.5 expected (residual 12.2): runs of near-zero changes around the official reference rate. The patterns 1-5-5, 1-1-5 and 5-5-5, made of large moves of either sign, reflect volatility clustering.
The normalized information variance Gamma is the efficiency of the test (its approximate Bahadur slope), so it converts directly into a sample size (Corollary 4.8 of the paper):
power ≈ Φ( (K·Gamma + μ0 − qα) / √(K·tau² + V0) ), K = n − m + 1,
where μ0, V0 and qα are the mean, variance and upper α point of Lm,d. serial_test estimates both Gamma and tau from the data, so a pilot sample or a comparable series gives a realistic plan. With tau = 0 the formula is accurate for weak dependence and otherwise optimistic. For example, for an ARCH(1) process at (m, d) = (3, 4), with Gamma = 0.13 and tau = 1.13 estimated from data, the predicted power at n = 350 is 0.85, against 0.82 in simulations; with tau = 0 it would be 0.98.
The test can be applied to residuals, for example standardized GARCH residuals, to check whether dependence remains. The P-values are then only approximately exact. When the model is estimated efficiently (maximum likelihood with the correct innovation distribution), they remain valid and are slightly conservative (Theorem 4.11 of the paper). After Gaussian quasi-maximum likelihood with non-normal innovations they can be misleading, especially for squared residuals; then use a model-based bootstrap: simulate from the fitted model, re-estimate, and recompute the statistic (Section 4.5 of the paper).
| Message | Solution |
|---|---|
'python' is not recognized (Windows) | Reinstall Python and tick Add python.exe to PATH, or use py instead of python. |
'pip' is not recognized | Use python -m pip install .... |
No module named numpy (or scipy) | pip install numpy scipy |
| Excel file cannot be read | pip install pandas openpyxl |
No module named tkinter (Linux) | sudo apt install python3-tk |
| Double-click does nothing (Windows) | Right-click the file, Open with, Python; or run python ivserial_gui.pyw in Command Prompt. |
| "only ... blocks per pattern" | The series is short for the chosen (m, d); use the automatic choice or smaller values. |
Default resolution: (m, d) = (3, 3) for n < 300, (3, ⌊(n−300)/400⌋+4) for 300 ≤ n < 1500, and m = ⌊log n/(2 log 3)⌋, d = 3 beyond; portmanteau classes 3, 4 or 5. Ties are broken at random, which keeps the test exact. P-value = (1 + #{permuted statistics ≥ observed})/(B + 1). Computing time: about 1 second for n = 1000 with B = 9999, and about 15 seconds for n = 100,000 with B = 999.
If you use the package, please cite: E. Ashtari Nezhad, Information Variance and Exact Symbolic Tests of Serial Independence. License: MIT.
Questions, bug reports and suggestions: open an issue at github.com/emaad7/ivserial/issues.