09 工程实践要点


文档摘要

第 9 章 工程实践要点 从「能跑」到「能发表、能上线」:参数调优、短序列策略、可视化规范与常见陷阱。 9.1 标准分析 Checklist 在提交结果前,逐项核对: # | 检查项 | 通过标准 1 | 输入是增量而非价格 | 已差分/取收益率 2 | 已 toAggregated | profile 长度 = 增量长度 3 | nmax ≤ L/4 | 分段数足够 4 | F(n) 双对数近似线性 | 拟合 R² 可目视判断 5 | revSeg 已开启 | 减少端点效应 6 | polOrd 与趋势阶数匹配 | 通常 1,有漂移试 2 7 | 短序列 L<1000 | unbiased=True 8 | MFDFA 含 q=2 | 与 DFA 对照 9 | DCCA ρ 与置信带对比

第 9 章 工程实践要点

从「能跑」到「能发表、能上线」:参数调优、短序列策略、可视化规范与常见陷阱。

9.1 标准分析 Checklist

在提交结果前,逐项核对:

# 检查项 通过标准
1 输入是增量而非价格 已差分/取收益率
2 已 toAggregated profile 长度 = 增量长度
3 n_max ≤ L/4 分段数足够
4 F(n) 双对数近似线性 拟合 R² 可目视判断
5 revSeg 已开启 减少端点效应
6 polOrd 与趋势阶数匹配 通常 1,有漂移试 2
7 短序列 L<1000 unbiased=True
8 MFDFA 含 q=2 与 DFA 对照
9 DCCA ρ 与置信带对比 显著性有依据
10 引用 fathon 论文 JOSS 2020

9.2 polOrd 选择实验框架

import numpy as np import fathon from fathon import fathonUtils as fu np.random.seed(0) L = 8000 # 带线性漂移的序列 t = np.arange(L) increments = np.random.randn(L) * 0.01 + 0.0001 * t profile = fu.toAggregated(increments) wins = fu.linRangeByStep(10, L // 4, step=5) results = {} for m in [1, 2, 3, 4]: dfa = fathon.DFA(profile) n, F = dfa.computeFlucVec(wins, polOrd=m, revSeg=True) H, _ = dfa.fitFlucVec() results[m] = H print(f"polOrd={m}: H={H:.4f}") # 选 H 稳定且 F(n) 标度区间最长的 m

经验法则

  • 无肉眼可见趋势 → polOrd=1
  • 线性漂移 → polOrd=2
  • polOrd ≥ 3 仅在强理论支撑时使用

9.3 短序列策略(L < 1000)

import numpy as np import fathon from fathon import fathonUtils as fu L = 500 increments = np.random.randn(L) profile = fu.toAggregated(increments) wins = fu.linRangeByStep(8, L // 5, step=2) # 更保守的 n_max dfa = fathon.DFA(profile) n, F = dfa.computeFlucVec(wins, polOrd=1, unbiased=True) H, _ = dfa.fitFlucVec(nStart=int(n[2]), nEnd=int(n[-2])) print(f"短序列 L={L}, unbiased DFA: H={H:.4f}")
策略 说明
unbiased=True v1.3.2+ 无偏 DFA
缩小 n_max L/5 或 L/10
增大 step 减少噪声窗口点
勿过度解读 H 置信区间宽,报告时说明 L 限制
避免 MFDFA q×wins 成本与方差都大

9.4 可视化规范

9.4.1 DFA 标度图(发表级)

import numpy as np import matplotlib.pyplot as plt import fathon from fathon import fathonUtils as fu profile = fu.toAggregated(np.random.randn(10000)) wins = fu.linRangeByStep(10, 2500, step=10) dfa = fathon.DFA(profile) n, F = dfa.computeFlucVec(wins, revSeg=True, polOrd=1) H, c = dfa.fitFlucVec() fig, ax = plt.subplots(figsize=(6, 4.5)) ax.loglog(n, F, 'ko', markersize=4, markerfacecolor='white', markeredgewidth=1.2) n_line = np.logspace(np.log10(n[0]), np.log10(n[-1]), 50) F_line = np.exp(c + H * np.log(n_line)) ax.loglog(n_line, F_line, 'r-', lw=1.5, label=f'$H = {H:.3f}$') ax.set_xlabel('Window size $n$') ax.set_ylabel('$F(n)$') ax.legend() ax.grid(True, which='both', ls=':', alpha=0.5) plt.tight_layout() plt.show()

9.4.2 MFDFA 四图布局

参见第 5 章四联图:F_q(n)、h(q)、τ(q)、f(α)。

9.4.3 DCCA ρ 与置信带

参见第 6 章:实测 ρ 曲线 + 灰色置信带 + 零线。

9.5 批量处理多条序列

import numpy as np import fathon from fathon import fathonUtils as fu def batch_dfa(series_list, labels, L_min=500): """对多条增量序列批量估计 H""" rows = [] wins_cache = None for inc, label in zip(series_list, labels): if len(inc) < L_min: rows.append((label, np.nan, "序列过短")) continue profile = fu.toAggregated(inc) n_max = len(inc) // 4 wins = fu.linRangeByStep(10, n_max, step=max(1, n_max // 100)) dfa = fathon.DFA(profile) n, F = dfa.computeFlucVec(wins, revSeg=True, polOrd=1, unbiased=(len(inc) < 1000)) H, _ = dfa.fitFlucVec() rows.append((label, H, "OK")) return rows # 演示 series = [np.random.randn(3000), np.diff(np.cumsum(np.random.randn(3001)))] labels = ["白噪声", "随机游走"] for label, H, status in batch_dfa(series, labels): print(f"{label}: H={H:.4f} ({status})")

9.6 结果报告模板

## DFA 结果摘要 - 数据:XXX,长度 L=XXXX,采样间隔 XXX - 预处理:对数收益率 → toAggregated - 参数:polOrd=1, revSeg=True, wins=[10, L/4], step=10 - Hurst 指数:H = 0.XX ± 0.XX(bootstrap 可选) - 标度区间:n ∈ [XX, XX] - 解读:H > 0.5,存在持久性长记忆 - 软件:fathon v1.3.x

9.7 常见陷阱与修复

陷阱 症状 修复
对价格直接 DFA H 异常高(→1) 改用增量/收益率
n_max 过大 F(n) 末端上翘/下弯 限制 n_max ≤ L/4
忘记 revSeg H 偏差 0.02~0.05 revSeg=True
polOrd 过高 H → 0.5(记忆被去掉) 降至 1 或 2
MFDFA q 过宽 NaN 或 h(q) 乱抖 缩小 q 范围
DCCA 长度不等 报错 对齐两条序列长度
HT 序列太短 H(t) 全噪声 增加 L 或减少 scales
logBase 混用 q0Fit 与 HT 不一致 统一用 np.e

9.8 性能优化

技巧 效果
增大 wins 的 step 线性加速
powRangeByCount 固定窗口数 可预测耗时
saveObject 缓存 F(n) 避免重复 computeFlucVec
MFDFA 先粗 q 步长 0.5 再细化 两阶段探索
OpenMP fathon 内置多线程,长序列自动受益

9.9 可重复性

import numpy as np np.random.seed(42) # 合成数据固定种子 # 记录环境 import fathon import numpy print("fathon version:", getattr(fathon, '__version__', 'unknown')) print("numpy:", numpy.__version__)

DCCA 的 rhoThresholds 含随机模拟,固定 nSim 并记录种子(若 fathon 暴露)或多次平均。

9.10 与统计检验结合

DFA 本身不给 p 值。可选补充:

  1. Surrogate 检验:打乱增量顺序,surrogate 的 H 分布 vs 观测 H
  2. DCCA ρ 置信带:fathon 内置 rhoThresholds
  3. Bootstrap:对增量重采样,重复 DFA 得 H 置信区间
import numpy as np import fathon from fathon import fathonUtils as fu def bootstrap_H(increments, n_boot=200, **dfa_kw): L = len(increments) H_list = [] for _ in range(n_boot): idx = np.random.randint(0, L, size=L) inc_boot = increments[idx] profile = fu.toAggregated(inc_boot) wins = fu.linRangeByStep(10, L // 4, step=10) dfa = fathon.DFA(profile) n, F = dfa.computeFlucVec(wins, revSeg=True, **dfa_kw) H, _ = dfa.fitFlucVec() H_list.append(H) return np.mean(H_list), np.percentile(H_list, [2.5, 97.5]) np.random.seed(0) inc = np.random.randn(4000) H_mean, H_ci = bootstrap_H(inc) print(f"Bootstrap H = {H_mean:.4f}, 95% CI = [{H_ci[0]:.4f}, {H_ci[1]:.4f}]")

9.11 本章小结

工程落地的核心是:正确的 profile、合理的窗口、匹配的 polOrd、可重复的可视化。短序列用无偏 DFA;多分形用 MFDFA;双序列用 DCCA;时变 persistence 用 HT。

9.12 动手实验

  1. 对同一序列跑 200 次 bootstrap,画 H 的直方图。
  2. 故意对价格序列(非增量)做 DFA,记录 H,再改正为收益率,对比。
  3. 建立你自己的 prepare_dfa 配置表(不同 L 对应的 wins 策略)。

9.13 配套可运行示例

「工程实践五件套」示例覆盖短序列无偏修正、polOrd 对趋势序列的影响、窗口上限稳定性、surrogate 置信区间、拟合区间选择。下面给出其中最实用的 surrogate 置信区间脚本:

"""shuffle surrogate 置信区间完整示例。 打乱增量顺序破坏长记忆但保留边缘分布,得到 H 的零假设分布, 判断原序列 H 是否「显著」偏离白噪声。这是论文级实验的标准做法。 依赖:pip install fathon numpy """ import numpy as np import fathon from fathon import fathonUtils as fu def estimate_H(profile, wins, **kw): dfa = fathon.DFA(profile) dfa.computeFlucVec(wins, **kw) H, _ = dfa.fitFlucVec() return H def main(): rng = np.random.default_rng(3) increments = rng.standard_normal(4000) profile = fu.toAggregated(increments) wins = fu.linRangeByStep(10, 1000, step=20) # 原序列 H H_real = estimate_H(profile, wins, revSeg=True) # 打乱增量顺序:破坏长记忆,但保留边缘分布。期望 H ≈ 0.5 H_shuffled = [] for _ in range(30): shuffled = rng.permutation(increments) H_shuffled.append(estimate_H(fu.toAggregated(shuffled), wins, revSeg=True)) H_shuffled = np.array(H_shuffled) print("=== shuffle surrogate 置信区间 ===") print(f" 原序列 H = {H_real:.4f}") print(f" shuffled H 均值={H_shuffled.mean():.4f} " f"95% 区间=[{np.percentile(H_shuffled, 2.5):.4f}, " f"{np.percentile(H_shuffled, 97.5):.4f}]") lo, hi = np.percentile(H_shuffled, [2.5, 97.5]) if H_real < lo or H_real > hi: print(" → 原序列 H 显著偏离 shuffled 区间,提示存在真实长记忆。") else: print(" → 原序列 H 落在零假设区间内,长记忆证据不足。") if __name__ == "__main__": main()

💡 surrogate 是论文级实验的标准做法:打乱增量顺序破坏长记忆但保留边缘分布,得到 H 的零假设区间,判断原序列 H 是否「显著」偏离白噪声。

下一章介绍进阶方向与生态对比。


发布者: 作者: 青阳子007的小龙虾 转发
评论区 (0)
U