import numpy as np
import pytest
import scirs2
class TestQuintiles:
def test_quintiles_basic(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0])
result = scirs2.quintiles_py(data)
assert len(result) == 4
assert result[0] == pytest.approx(2.8, abs=0.01)
assert result[1] == pytest.approx(4.6, abs=0.01)
assert result[2] == pytest.approx(6.4, abs=0.01)
assert result[3] == pytest.approx(8.2, abs=0.01)
def test_quintiles_ordering(self):
data = np.random.normal(0, 1, 100)
result = scirs2.quintiles_py(data)
assert len(result) == 4
assert result[0] < result[1] < result[2] < result[3]
def test_quintiles_uniform_data(self):
data = np.linspace(0, 100, 1000)
result = scirs2.quintiles_py(data)
expected = [20.0, 40.0, 60.0, 80.0]
for i, exp in enumerate(expected):
assert result[i] == pytest.approx(exp, abs=1.0)
def test_quintiles_small_dataset(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.quintiles_py(data)
assert len(result) == 4
assert np.all(result >= data.min())
assert np.all(result <= data.max())
def test_quintiles_vs_quartiles(self):
data = np.random.normal(50, 10, 500)
quintiles = scirs2.quintiles_py(data)
quartiles = scirs2.quartiles_py(data)
assert quintiles[1] < quartiles[1] < quintiles[2]
class TestSkewnessCI:
def test_skewness_ci_basic(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0])
result = scirs2.skewness_ci_py(data, bias=False, confidence=0.95, n_bootstrap=100, seed=42)
assert 'estimate' in result
assert 'lower' in result
assert 'upper' in result
assert 'confidence' in result
assert result['estimate'] > 0
assert result['lower'] < result['estimate']
assert result['upper'] > result['estimate']
assert result['confidence'] == 0.95
def test_skewness_ci_symmetric_data(self):
np.random.seed(42)
data = np.random.normal(0, 1, 100)
result = scirs2.skewness_ci_py(data, n_bootstrap=200, seed=42)
assert abs(result['estimate']) < 0.5
assert result['lower'] < 0 < result['upper']
def test_skewness_ci_confidence_levels(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 100.0])
result_90 = scirs2.skewness_ci_py(data, confidence=0.90, n_bootstrap=200, seed=42)
result_95 = scirs2.skewness_ci_py(data, confidence=0.95, n_bootstrap=200, seed=42)
width_90 = result_90['upper'] - result_90['lower']
width_95 = result_95['upper'] - result_95['lower']
assert width_90 < width_95
def test_skewness_ci_reproducibility(self):
data = np.random.normal(0, 1, 50)
result1 = scirs2.skewness_ci_py(data, n_bootstrap=100, seed=123)
result2 = scirs2.skewness_ci_py(data, n_bootstrap=100, seed=123)
assert result1['estimate'] == pytest.approx(result2['estimate'])
assert result1['lower'] == pytest.approx(result2['lower'])
assert result1['upper'] == pytest.approx(result2['upper'])
def test_skewness_ci_bootstrap_samples(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0])
result_100 = scirs2.skewness_ci_py(data, n_bootstrap=100, seed=42)
result_500 = scirs2.skewness_ci_py(data, n_bootstrap=500, seed=42)
assert result_100['estimate'] > 0
assert result_500['estimate'] > 0
class TestKurtosisCI:
def test_kurtosis_ci_basic(self):
np.random.seed(42)
data = np.random.normal(0, 1, 100)
result = scirs2.kurtosis_ci_py(data, fisher=True, bias=False, confidence=0.95, n_bootstrap=100, seed=42)
assert 'estimate' in result
assert 'lower' in result
assert 'upper' in result
assert 'confidence' in result
assert abs(result['estimate']) < 1.0
assert result['lower'] < result['estimate']
assert result['upper'] > result['estimate']
def test_kurtosis_ci_fisher_vs_pearson(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0])
result_fisher = scirs2.kurtosis_ci_py(data, fisher=True, n_bootstrap=100, seed=42)
result_pearson = scirs2.kurtosis_ci_py(data, fisher=False, n_bootstrap=100, seed=42)
diff = result_pearson['estimate'] - result_fisher['estimate']
assert diff == pytest.approx(3.0, abs=0.1)
def test_kurtosis_ci_heavy_tails(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 50.0, -50.0])
result = scirs2.kurtosis_ci_py(data, fisher=True, n_bootstrap=100, seed=42)
assert result['estimate'] > 0
def test_kurtosis_ci_confidence_levels(self):
data = np.random.normal(0, 1, 80)
result_90 = scirs2.kurtosis_ci_py(data, confidence=0.90, n_bootstrap=200, seed=42)
result_95 = scirs2.kurtosis_ci_py(data, confidence=0.95, n_bootstrap=200, seed=42)
width_90 = result_90['upper'] - result_90['lower']
width_95 = result_95['upper'] - result_95['lower']
assert width_90 < width_95
def test_kurtosis_ci_reproducibility(self):
data = np.random.normal(0, 1, 50)
result1 = scirs2.kurtosis_ci_py(data, n_bootstrap=100, seed=456)
result2 = scirs2.kurtosis_ci_py(data, n_bootstrap=100, seed=456)
assert result1['estimate'] == pytest.approx(result2['estimate'])
assert result1['lower'] == pytest.approx(result2['lower'])
assert result1['upper'] == pytest.approx(result2['upper'])
class TestConfidenceIntervalRealWorld:
def test_income_distribution_skewness(self):
np.random.seed(42)
incomes = np.random.lognormal(mean=10, sigma=0.5, size=200)
result = scirs2.skewness_ci_py(incomes, confidence=0.95, n_bootstrap=300, seed=42)
assert result['estimate'] > 0
assert result['lower'] > -0.5
def test_returns_kurtosis(self):
np.random.seed(42)
normal_returns = np.random.normal(0, 0.01, 180)
extreme_returns = np.random.normal(0, 0.05, 20)
returns = np.concatenate([normal_returns, extreme_returns])
result = scirs2.kurtosis_ci_py(returns, fisher=True, confidence=0.95, n_bootstrap=200, seed=42)
assert result['estimate'] > 0
def test_quality_control_metrics(self):
np.random.seed(42)
measurements = np.random.normal(100, 5, 500)
quintiles = scirs2.quintiles_py(measurements)
assert quintiles[0] < 100 < quintiles[3] assert quintiles[3] - quintiles[0] > 0
class TestEdgeCases:
def test_quintiles_small_n(self):
data = np.array([1.0, 2.0, 3.0])
result = scirs2.quintiles_py(data)
assert len(result) == 4
def test_skewness_ci_minimum_data(self):
data = np.array([1.0, 2.0, 3.0])
result = scirs2.skewness_ci_py(data, n_bootstrap=50, seed=42)
assert 'estimate' in result
assert 'lower' in result
assert 'upper' in result
def test_kurtosis_ci_minimum_data(self):
data = np.array([1.0, 2.0, 3.0, 4.0])
result = scirs2.kurtosis_ci_py(data, n_bootstrap=50, seed=42)
assert 'estimate' in result
assert 'lower' in result
assert 'upper' in result
def test_quintiles_all_equal(self):
data = np.array([5.0, 5.0, 5.0, 5.0, 5.0])
result = scirs2.quintiles_py(data)
assert np.all(result == 5.0)
def test_ci_wide_range(self):
data = np.array([0.001, 0.002, 0.003, 1000.0, 2000.0, 3000.0])
sk_result = scirs2.skewness_ci_py(data, n_bootstrap=50, seed=42)
kurt_result = scirs2.kurtosis_ci_py(data, n_bootstrap=50, seed=42)
assert sk_result['estimate'] is not None
assert kurt_result['estimate'] is not None