ivserial — user guide

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

1. What the package does

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

2. Two ways to use it

Without programming: the window (GUI)
Open a CSV or Excel file, pick a column, press Run test. Sample-size planning and the null distribution are in their own tabs.
With code: Python or the command line
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.

TaskWindow (GUI)PythonCommand line
Test one seriesTest tab, choose column, Run testserial_test(x)ivserial file.csv -c NAME
Screen many seriestick test all columnsloop over columnsivserial file.csv
Prices to log returnsTransform: log returnstransform="logdiff"-t logdiff
Options (B, seed, m, d, level, lags, patterns)Options and Portmanteau rowsarguments of serial_test--B --seed --m --d --alpha --lags --d2 --cells
Save resultsSave report... (.txt or .json)res.to_dict(), str(res)--out report.txt --json res.json
Sample size / powerSample size & power tabrequired_sample_size, approximate_powerivserial plan --gamma ...
Default resolution for nResolution for nchoose_resolution(n)ivserial plan ... --n N
Null distribution, critical valuesNull distribution tabnull_limit_summary, null_limit_sfivserial null --m 3 --d 4 --q 80

3. Installation

Step 1: Python (once)

Step 2: the package, like any other Python module

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

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.

Without installing

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.

4. Preparing your data

The folder examples contains exchange_rates.csv, the 20 daily exchange rates analysed in the paper (prices; use the log-return transform).

5. The window (GUI)

Start it with ivserial-gui, python -m ivserial, or by double-clicking as described above. It has three tabs.

Test tab

  1. Open data file... and choose your file.
  2. Choose the series (column), or tick test all columns to screen every column at once.
  3. Choose the transform: none, differences, or log returns (prices).
  4. Press Run test. Save report... writes the output as text (.txt) or as structured results (.json).

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.

TestSample size & powerNull distribution
Open data file... exchange_rates.csv (20 numeric columns)
Series (column):China ▾ ☐ test all columns (screening)
Transform:○ none   ○ differences   ● log returns (prices)
Options:Permutations B 9999 Seed 1 Block length m auto Classes d auto Level 0.05
Portmanteau:Lags 2 Classes auto Patterns shown 8
Run test Save report... Help User guide

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)

Sample size & power tab

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

TestSample size & powerNull distribution
Gamma 0.2864 tau 2.9425 m 3 d 5 Level 0.05
Target power 0.8   or: number of observations n 500 V (optional, instead of Gamma)
Use last test Required sample size Power for n Resolution for n
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

Null distribution tab

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.

TestSample size & powerNull distribution
m 3 d 4 Value of Q (optional) 75 Compute
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

6. Python

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))
FunctionPurpose
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

7. Command line

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

8. Reading the output

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
ItemMeaning
CThe test to use. A P-value below the level (e.g. 0.05) rejects serial independence.
Q, P2Blocks of m consecutive values, and pairs at lags 1 and 2. C combines them exactly.
permutation / asymptoticPermutation P-values are exact; asymptotic ones use the explicit limits and are accurate for n ≥ 350.
V-hatStrength 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-hatEfficiency: the normalized information variance, the approximate Bahadur slope of the test; Gamma = (dm−1 − 1)·V². It drives the sample-size calculation.
PatternsEach 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.

A rejection means that the values are not i.i.d. The patterns indicate the kind of dependence, not a particular model.

9. Sample size and power

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.

10. Residuals of fitted models

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).

11. Troubleshooting

MessageSolution
'python' is not recognized (Windows)Reinstall Python and tick Add python.exe to PATH, or use py instead of python.
'pip' is not recognizedUse python -m pip install ....
No module named numpy (or scipy)pip install numpy scipy
Excel file cannot be readpip 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.

12. Reference and citation

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.