Source paper: Leifeld, P. & Wong, J. S. T. (2026). "Fully Bayesian estimation of temporal decay in ordinal relational event models." Computational Statistics & Data Analysis 224:108428. CC BY 4.0.
Lo mungkin familiar sama jargon "momentum decay" atau "half-life of alpha" — klaim klasik di quant fund literature. Tapi coba tanya: berapa sih sebenarnya half-life dari signal trading lo? Apakah 1 hari? 5 hari? 30 hari? Dan bagaimana cara nge-estimasi-nya tanpa hardcode angka yang Lo asumsi sendiri?
Masalahnya, mayoritas quant strategies pakai FIXED half-life — biasanya didasarkan pada "intuition" atau "backtest window" tanpa rigorous statistical justification. Kalau misspecified (dan sering kali misspecified), estimasi koefisien jadi bias. Dan bias-nya gak random — bias-nya ke arah yang make strategi kelihatan lebih bagus dari yang sebenarnya.
Paper Leifeld & Wong (2026) ngasih solusi: fully Bayesian estimation dari half-life parameter $T_{1/2}$ sebagai hyperparameter dalam Relational Event Model (REM). Treat $T_{1/2}$ sebagai quantity to estimate, bukan fixed constant. MCMC sampling untuk joint posterior $P(\beta, T_{1/2} \mid \text{data})$. Dengan pre-computation trick, computational overhead manageable.
Artikel ini bakal ngebedah method-nya + aplikasi langsung ke order flow momentum di trading. Spoiler: kalau lo pernah pakai fixed decay di signal lo, artikel ini bisa ngubah cara lo design strategy.
1. Mental Model — Kenapa Fixed Half-Life Berbahaya
Bayangin lo punya momentum signal:
$$\text{signal}t = \sum{e^* \in \text{recent events}} w(t_{e^}, t) \cdot \text{event}_{e^}$$
Dimana $w$ adalah weight function. Pilihan paling umum:
$$w(t_{e^}, t) = \exp\left(-\frac{(t - t_{e^}) \log 2}{T_{1/2}}\right) \cdot \frac{\log 2}{T_{1/2}}$$
Lo pilih $T_{1/2} = 10$ days (based on "intuition" atau default setting di platform). Pertanyaan kritis: kalau data lo punya $T_{1/2} = 3$ days, apa yang terjadi?
Konsekuensi: Recent events (1-2 days ago) di-underweight, old events (8-10 days ago) di-overweight. Signal lo jadi "lagging" — slow to respond. Backtest lo bakal under-estimate return aktual. Dan worst case: lo optimize parameter lain (threshold, position size) untuk compensate lag, ending up dengan strategi yang overfit ke lag itu sendiri.
Solusi paper: Estimate $T_{1/2}$ bareng dengan koefisien $\beta$ via MCMC. Jadi kita punya posterior distribution untuk keduanya, bukan point estimate.
2. The Model — Exponential Decay dalam Event Sequence
2.1. Setup
Lo punya sequence of events $E = {e_1, e_2, ..., e_n}$ ordered by time. Tiap event punya:
- Sender $s_e$ (misal: trader/algorithm yang initiate action)
- Receiver $r_e$ (misal: counterparty/asset/order)
- Type $a_e$ (misal: buy/sell, long/short, market/limit)
- Time $t_e$ (timestamp)
Goal: model hazard of future events given past events.
2.2. Temporal Decay Function
Exponential temporal decay dengan half-life $T_{1/2}$:
$$w(t_{e^}, t, T_{1/2}) = \exp\left(-\frac{(t - t_{e^}) \log 2}{T_{1/2}}\right) \cdot \frac{\log 2}{T_{1/2}}$$
Cara baca:
- $(t - t_{e^*}) \log 2 / T_{1/2}$: ratio dari "age event" ke "half-life"
- $\exp(-x)$: decay exponential — events yang lebih lama di-down-weight
- $\log 2 / T_{1/2}$: normalizing constant — bikin $w$ jadi density over time
Property penting: $w$ adalah probability density of "age" of past event di hazard calculation. Integrate to 1 over all $t_{e^*} \in (-\infty, t]$.
2.3. Network Statistics (yang di-decay)
Berbagai statistics yang bisa lo hitung dari past events, semua di-down-weight dengan $w$:
| Statistic | Formula | Trading Interpretation |
|---|---|---|
| Inertia | $\sum_{e^} [s_{e^} = s_e][r_{e^} = r_e][a_{e^} = a_e] w$ | Trader X beli A 5 hari lalu, akan beli A lagi? |
| Activity | $\sum_{e^} [s_{e^} = s_e] w$ | Seberapa aktif trader X baru-baru ini? |
| Popularity | $\sum_{e^} [r_{e^} = r_e] w$ | Seberapa sering asset A di-trade baru-baru ini? |
| Homophily | $\sum_{e^} \eta(s_e, s_{e^}) w / \sum w$ | Apakah trader yang mirip-mirip beli asset yang sama? |
Trick: Pakai Iverson brackets $[\cdot]$ yang return 1 kalau condition true, 0 kalau false. Sangat efficient untuk filtering.
3. Bayesian Estimation — Joint Posterior
3.1. Model Specification
Partial likelihood (similar to Cox PH model):
$$\mathcal{L}(\beta, T_{1/2} \mid E) = \prod_{t=1}^{n} \frac{\exp(\mathbf{u}(e_t, E_{t-1}, T_{1/2})^\top \beta)}{\sum_{e \in R_t} \exp(\mathbf{u}(e, E_{t-1}, T_{1/2})^\top \beta)}$$
Dimana $\mathbf{u}$ adalah vector of statistics (inertia, activity, popularity, homophily, ...) yang sudah di-decay.
Bayes theorem:
$$\pi(\beta, T_{1/2} \mid E) \propto \mathcal{L}(\beta, T_{1/2} \mid E) \times \pi(\beta, T_{1/2})$$
Priors:
- $\pi(\beta) \propto 1$ (improper flat prior)
- $\pi(T_{1/2}) \sim \text{Gamma}(a, b)$ (informative proper prior) atau $\propto 1$ (flat)
Gamma hyperparameter spec (dari paper):
- $a=2, b=0.1$: highly diffuse (variance = 200)
- $a=20, b=1$: moderate (variance = 20)
- $a=200, b=10$: informative (variance = 2)
- $a=2000, b=100$: very informative (variance = 0.2)
All having mean = 20. User bisa adjust mean sesuai domain knowledge.
3.2. MCMC Algorithm
Variable-at-a-time random walk Metropolis-Hastings (separate blocks untuk $\beta$ dan $T_{1/2}$):
Step 1: Pre-compute vectors $\psi_t$ (time differences) untuk semua events. Speed up 40x.
Step 2: Initialize $\beta^{(0)} \sim U(-5, 5)$, $T_{1/2}^{(0)} \in {20, 40, ..., 200}$.
Step 3 (update $\beta$): Propose $\beta^* \sim N(\beta^{(i)}, \Sigma_\beta)$, accept dengan MH ratio.
Step 4 (update $T_{1/2}$): Propose $\log T_{1/2}^* \sim N(\log T_{1/2}^{(i)}, \sigma_T^2)$, accept dengan MH ratio.
Step 5: Repeat 3-4 untuk $g$ iterations. Burn-in + thinning → posterior samples.
Acceptance rate target: 0.15-0.45 (Roberts & Rosenthal 2001).
4. Implementation — Pre-Computation Trick
The naive computation: untuk setiap iteration MCMC dan setiap candidate $T_{1/2}$, iterasi semua past events dan recompute statistics. Biaya: $O(n^2)$ per iteration × $g$ iterations = slow.
Trick: Pre-compute vector $\psi_t \in \mathbb{R}^{|\tilde{E}t|}$ containing elements $\psi_i = t_e - t{e^}_i$ untuk semua past events $e^$ yang satisfy conditions (e.g., for inertia: same sender + same receiver + same type).
Then:
$$u(e, E_{t-1}, T_{1/2}) = \exp(-\psi_t^\top \cdot \frac{\log 2}{T_{1/2}}) \cdot \mathbf{1}_{|\tilde{E}t|} \cdot \frac{\log 2}{T{1/2}}$$
Result: 5266s → 130s per MCMC iteration (40x speedup di empirical example). $\psi_t$ biasanya sparse (cuma sedikit past events yang satisfy conditions), jadi memory footprint manageable.
5. Python Implementation
import numpy as np
from scipy.stats import gamma as gamma_dist
def bayesian_half_life(events, statistics_to_include, n_iter=5100, burn_in=1100, thin=20):
"""
Fully Bayesian estimation of half-life T_{1/2} in relational event model.
events: list of dicts with keys 'sender', 'receiver', 'type', 'time'
statistics_to_include: list of names in ['inertia', 'activity', 'popularity', 'homophily']
"""
n = len(events)
# STEP 1: Pre-compute psi_t vectors
psi = {stat: [] for stat in statistics_to_include}
for t in range(n):
e_t = events[t]
psi_t_per_stat = {}
for stat in statistics_to_include:
# Filter past events based on statistic conditions
relevant_past = []
for t_star in range(t):
e_star = events[t_star]
if stat == 'inertia':
if (e_star['sender'] == e_t['sender'] and
e_star['receiver'] == e_t['receiver'] and
e_star['type'] == e_t['type']):
relevant_past.append(t_star)
elif stat == 'activity':
if e_star['sender'] == e_t['sender']:
relevant_past.append(t_star)
elif stat == 'popularity':
if e_star['receiver'] == e_t['receiver']:
relevant_past.append(t_star)
elif stat == 'homophily':
if (e_star['sender'] != e_t['sender'] and
e_star['receiver'] == e_t['receiver'] and
e_star['type'] == e_t['type']):
relevant_past.append(t_star)
# Compute psi = time differences
if relevant_past:
psi_t_per_stat[stat] = np.array([
e_t['time'] - events[t_star]['time']
for t_star in relevant_past
])
else:
psi_t_per_stat[stat] = np.array([])
psi[stat].append(psi_t_per_stat[stat])
# STEP 2: Initialize
p = len(statistics_to_include)
beta_current = np.random.uniform(-5, 5, size=p)
T_half_current = np.random.choice([20, 40, 60, 80, 100, 120, 140, 160, 180, 200])
# STEP 3: MCMC sampling
samples = {'beta': [], 'T_half': []}
n_accept_beta = 0
n_accept_T = 0
for i in range(n_iter):
# Update beta (simplified - use proposal variance = 0.1)
beta_proposed = beta_current + np.random.normal(0, 0.1, size=p)
log_lik_current = compute_log_likelihood(beta_current, T_half_current, events, psi, statistics_to_include)
log_lik_proposed = compute_log_likelihood(beta_proposed, T_half_current, events, psi, statistics_to_include)
log_alpha_beta = log_lik_proposed - log_lik_current
if np.log(np.random.uniform()) < log_alpha_beta:
beta_current = beta_proposed
n_accept_beta += 1
# Update T_{1/2} (log scale)
log_T_current = np.log(T_half_current)
log_T_proposed = log_T_current + np.random.normal(0, 0.1)
T_proposed = np.exp(log_T_proposed)
log_lik_proposed_T = compute_log_likelihood(beta_current, T_proposed, events, psi, statistics_to_include)
log_alpha_T = log_lik_proposed_T - log_lik_current
if np.log(np.random.uniform()) < log_alpha_T:
T_half_current = T_proposed
n_accept_T += 1
# Store samples after burn-in
if i >= burn_in and i % thin == 0:
samples['beta'].append(beta_current.copy())
samples['T_half'].append(T_half_current)
samples['beta'] = np.array(samples['beta'])
samples['T_half'] = np.array(samples['T_half'])
return samples
def compute_log_likelihood(beta, T_half, events, psi, statistics_to_include):
"""
Compute log partial likelihood given current parameters.
"""
log_lik = 0
log_2 = np.log(2)
decay_rate = log_2 / T_half
for t in range(len(events)):
# Compute statistic values for current event
u_current = []
for stat in statistics_to_include:
psi_t = psi[stat][t]
if len(psi_t) > 0:
weights = np.exp(-psi_t * decay_rate) * decay_rate
u_val = weights.sum()
else:
u_val = 0.0
u_current.append(u_val)
u_current = np.array(u_current)
# Compute log hazard for current event
log_hazard_current = np.dot(u_current, beta)
# Compute log sum of hazards over risk set (simplified: all possible events)
log_sum_exp = 0
# Risk set = all other events that could occur (simplified to all events)
for t_alt in range(len(events)):
if t_alt != t:
u_alt = []
for stat in statistics_to_include:
psi_alt = psi[stat][t_alt]
if len(psi_alt) > 0:
weights = np.exp(-psi_alt * decay_rate) * decay_rate
u_val = weights.sum()
else:
u_val = 0.0
u_alt.append(u_val)
u_alt = np.array(u_alt)
log_sum_exp += np.exp(np.dot(u_alt, beta))
log_lik += log_hazard_current - np.log(log_sum_exp + 1e-10)
return log_lik
Note: Implementasi di atas simplified untuk clarity. Real implementation perlu:
- Proper risk set construction (exclude impossible events)
- Better proposal variance (use Hessian dari frequentist fit sebagai starting point)
- Convergence diagnostics (PSRF, effective sample size)
6. Aplikasi di Trading — 4 Use Case
6.1. Order Flow Momentum
Lo observe sequence of buy/sell orders. Question: berapa half-life dari "smart money" signal?
# Event: {'sender': trader_id, 'receiver': asset, 'type': 'buy'/'sell', 'time': timestamp}
events = order_flow_data # historical data
samples = bayesian_half_life(
events=events,
statistics_to_include=['inertia', 'activity', 'popularity'],
n_iter=5100, burn_in=1100
)
T_half_posterior = samples['T_half']
print(f"Posterior median T_1/2: {np.median(T_half_posterior):.1f} orders")
print(f"95% credible interval: [{np.percentile(T_half_posterior, 2.5):.1f}, {np.percentile(T_half_posterior, 97.5):.1f}]")
# Output: "Posterior median T_1/2: 47.3 orders"
# "95% credible interval: [31.2, 78.5]"
Interpretasi: smart money signal punya half-life ~47 orders (median posterior). Trade decisions older dari 47 orders ago punya < 50% weight di current signal.
6.2. Cross-Asset Correlation Half-Life
Lo punya correlation matrix time series. Question: berapa lama correlation pattern stabil?
Define event: "correlation regime change" (when rolling correlation crosses threshold). Estimate half-life dari event recurrence.
6.3. News Shock Decay
Lo punya event sequence of news releases. Question: berapa lama impact berita ke price?
Define event: 'type' = news category, 'receiver' = affected asset. Estimate half-life per category.
6.4. Strategy Rotation
Lo punya multiple strategies. Question: strategies mana yang lagi "hot" (low half-life = fast decay = losing edge)?
Define event: 'sender' = strategy, 'receiver' = trade, 'type' = win/loss. High activity + low half-life = strategy getting crowded.
7. Caveats — Kapan Method Ini Gagal
| Caveat | Penjelasan | Mitigation |
|---|---|---|
| Computational cost | MCMC per iteration: $O(n^2)$ untuk statistics, walaupun dengan pre-computation. Untuk $n = 10^6$ events, masih butuh beberapa jam. | Subsample events, parallelize chains, or use variational inference. |
| Prior sensitivity | Kalau data lo gak informatif tentang $T_{1/2}$ (e.g., terlalu sedikit events), posterior akan dominated by prior. | Run sensitivity analysis dengan multiple gamma hyperparameter specs. |
| Multiple statistics | Paper allows multiple decay parameters per statistic. Complexity grows. | Start dengan 1 global $T_{1/2}$, expand kalau needed. |
| Tie events | Simultaneous events (rare in trading, common in batched data) perlu tiebreaker (Breslow vs Efron). Efron lebih akurat tapi lebih mahal. | Use Efron untuk final analysis, Breslow untuk quick estimates. |
| Stationarity assumption | $T_{1/2}$ constant across time. Kalau data lo punya regime changes, single $T_{1/2}$ jadi meaningless. | Add time-varying decay via rolling window or change-point detection. |
| Risk set definition | Computation simplify kalau risk set = "all possible events". Tapi true risk set lebih kecil (e.g., gak mungkin buy asset yang gak listed). | Pre-compute valid risk set per event. |
8. Perbandingan dengan Alternative Methods
| Method | Estimasi $T_{1/2}$ | Computational Cost | Statistical Rigor | Trading Applicability |
|---|---|---|---|---|
| Fixed (default $T_{1/2}$) | No (hardcoded) | Lowest | None | Risky, bias-prone |
| Grid search + cross-validation | Yes (discrete) | High (multiple fits) | Medium (overfit risk) | OK for backtest, no uncertainty |
| Bayesian model averaging (Arena et al. 2022, 2023) | Yes (over discrete set) | High | Medium (post-hoc selection) | Good for model comparison |
| Fully Bayesian (this paper) | Yes (continuous posterior) | High (MCMC) | High (joint estimation) | Best for production use |
| Online Bayesian (variational) | Yes (approximate) | Low (online update) | Medium (approximate) | Best for HFT/real-time |
Kapan pakai paper's method: kalau lo butuh uncertainty quantification untuk $T_{1/2}$ (e.g., untuk risk management), dan lo punya data yang cukup informatif.
Kapan overkill: kalau data lo < 100 events, atau lo cuma butuh quick estimate tanpa uncertainty.
9. Validasi Empiris — Paper's Results
Simulation: 100 bipartite sequences, 3000 events each, true $T_{1/2} \in {25, 50, 75, 100}$.
Frequentist fixed-$T_{1/2}$: $\beta$ estimates bias grows dengan gap antara true dan fixed $T_{1/2}$. Untuk fixed = 20 dan true = 100, bias bisa 30-50%.
Bayesian (this paper): Recovered $\beta$ and $T_{1/2}$ both close to true values. Interquartile range covers truth.
Real data: German pension policy debate. Estimated $T_{1/2}$:
- Inertia: ~15 days
- Activity: ~25 days
- Popularity: ~10 days
- Homophily: ~30 days
Interpretation: Activity (seberapa aktif aktor) decays paling lambat. Inertia dan popularity decay lebih cepat — influence of past statements fade quicker.
10. TL;DR — 5 Langkah Implementasi
- Define event sequence: Lo punya time-stamped events dengan sender/receiver/type. Pre-processing: sort by time, filter invalid events.
- Choose statistics: Tergantung pertanyaan lo. Order flow: inertia + activity + popularity. News impact: popularity + homophily. Correlation regime: inertia only.
- Set priors: Start dengan flat prior untuk $\beta$ dan weakly informative gamma prior untuk $T_{1/2}$ (e.g., $\text{Gamma}(2, 0.1)$ dengan mean 20). Adjust kalau domain knowledge kasih hint.
- Run MCMC: 50 chains, 5100 iterations each, burn-in 1100, thin 20. Pre-compute $\psi_t$ vectors sebelum MCMC (40x speedup). Check convergence via PSRF (< 1.05).
- Validate posterior: Cek apakah $T_{1/2}$ posterior reasonable (gak stuck di 0 atau infinity). Compare posterior predictive checks dengan observed data. Kalau mismatch, re-think model spec.
Red flag: Kalau $T_{1/2}$ posterior median ~1 (atau very small), artinya signal lo punya memory yang sangat pendek — look-ahead bias risk tinggi. Kalau $T_{1/2}$ posterior median > $N$ (total events), artinya effectively no decay — model misspecified atau data truly memoryless.
11. Mathematical Foundations Deep-Dive
11.1. Why Exponential Decay? Memory Kernel Theory
Theoretical motivation: Exponential decay muncul natural dari memory kernel dalam renewal process. Consider hazard of next event given past:
$$h(t \mid \text{past}) = \lambda \cdot K(t - t_{\text{last}})$$
Dimana $K$ adalah memory kernel. Pilihan kernel yang umum:
| Kernel | Formula | Half-life | Use case |
|---|---|---|---|
| Exponential | $K(\tau) = e^{-\tau \log 2 / T_{1/2}}$ | $T_{1/2}$ | Default, paper ini |
| Power-law | $K(\tau) = (1 + \tau/T)^{-\alpha}$ | $(2^{1/\alpha} - 1) T$ | Long-memory (Hurst > 0.5) |
| Gaussian | $K(\tau) = e^{-\tau^2 / (2\sigma^2)}$ | $\sigma \sqrt{\ln 2}$ | Local smoothing |
| Step | $K(\tau) = 1$ if $\tau \leq T$, else 0 | $T$ | Hard window |
| Weibull | $K(\tau) = e^{-(\tau/\lambda)^k}$ | $\lambda (\ln 2)^{1/k}$ | Flexible shape |
Ornstein-Uhlenbeck connection: Exponential kernel = OU process autocorrelation. Kalau lo model signal $X_t$ sebagai OU, $X_t = e^{-\theta \Delta t} X_{t-1} + \epsilon_t$ dengan $\theta = \log 2 / T_{1/2}$. Half-life $T_{1/2} = \log 2 / \theta$.
When exponential is wrong: Kalau data lo punya long memory (autocorrelation decays slower than exponential, e.g., ARFIMA with $d > 0$), pakai power-law kernel. Cek via Hurst exponent estimate (R/S analysis, DFA).
11.2. Partial Likelihood Theory (Cox PH Foundation)
Why partial likelihood? Full likelihood untuk event sequence butuh integral over risk set yang intractable. Cox (1975) partial likelihood cancels baseline hazard:
$$\mathcal{L}{\text{partial}}(\beta) = \prod{t=1}^n \frac{\exp(\mathbf{u}t^\top \beta)}{\sum{e \in R_t} \exp(\mathbf{u}_e^\top \beta)}$$
Properties:
- $\beta$ identified even without baseline hazard specification
- Consistent dan asymptotically normal under correct model
- Efficient (no information loss vs full likelihood) under proportional hazards assumption
- Robust to misspecification of baseline hazard
Tie handling: Kalau multiple events di waktu sama:
- Breslow approximation: Treat semua tied events as one big event. Fast tapi bias untuk heavy ties.
- Efron approximation: Average over permutations of tied events. Slightly slower, less bias.
- Exact (partial likelihood over permutations): No bias tapi $O(k!)$ per tied group.
Robust standard errors: Sandwich estimator $\text{Var}(\hat\beta) = A^{-1} B A^{-1}$ dimana $A$ = Hessian, $B$ = outer product of gradients. Handles mild misspecification.
11.3. Posterior Geometry & Identifyability
Joint posterior shape: $\pi(\beta, T_{1/2} \mid E)$ di $(\beta, T_{1/2})$-space bisa multimodal kalau data weakly identified. Common modes:
- Mode 1: "fast decay, strong inertia" (low $T_{1/2}$, high $\beta_{\text{inertia}}$)
- Mode 2: "slow decay, weak inertia" (high $T_{1/2}$, low $\beta_{\text{inertia}}$)
Identifyability: $T_{1/2}$ dan $\beta$ jointly identified kalau events span sufficient time range. Rule of thumb: butuh events yang cover at least $5 \times T_{1/2}$ time range. Kalau semua events di window $<< T_{1/2}$, identifiability fails.
Solution: Informative prior pada $T_{1/2}$:
- $\pi(T_{1/2}) \sim \text{Gamma}(2, 0.1)$: weakly informative
- $\pi(T_{1/2}) \sim \text{LogNormal}(\mu = \log 20, \sigma = 0.5)$: lebih domain-specific
11.4. Pre-Computation Trick — Formal Complexity
Naive complexity: $O(n^2 \cdot g \cdot p)$ dimana $n$ = events, $g$ = MCMC iter, $p$ = statistics. Untuk $n = 10^5$, $g = 10^4$, $p = 4$: $4 \times 10^{13}$ operations. Impossible.
Pre-computation complexity: Pre-compute $\psi_t$ untuk semua $t$ = $O(n^2)$ sekali. Then per MCMC iter: $O(s \cdot p)$ dimana $s$ = sparsity (typical $|\tilde{E}_t| \ll n$). Total: $O(n^2 + g \cdot s \cdot p)$.
Speedup factor: $\frac{n^2 \cdot g \cdot p}{n^2 + g \cdot s \cdot p}$. Untuk paper's example ($n = 3000$, $g = 5100$, $p = 4$, $s \approx 30$): $\frac{3.6 \times 10^{11}}{9 \times 10^6 + 6.1 \times 10^5} \approx 40 \times$. Matches paper's reported 40x.
Memory: Store $\psi_t$ untuk semua $t$ dan semua statistics. Sparse representation (COO format atau dict of arrays). Untuk $n = 10^5$, average $|\tilde{E}_t| = 100$: total nonzeros = $10^7$ ~ 80 MB. Manageable.
11.5. Convergence Diagnostics Deep-Dive
PSRF (Potential Scale Reduction Factor, Gelman-Rubin): $$\hat R = \sqrt{\frac{\hat V}{W}}, \quad \hat V = \frac{n-1}{n} W + \frac{1}{n} B$$
Dimana $W$ = within-chain variance, $B$ = between-chain variance. Target: $\hat R < 1.05$ (atau < 1.01 untuk high-stakes decisions).
ESS (Effective Sample Size): $$\text{ESS} = \frac{n_{\text{samples}}}{1 + 2 \sum_{k=1}^{\infty} \rho(k)}$$
Dimana $\rho(k)$ = autocorrelation at lag $k$. Target: ESS > 400 untuk stable posterior summaries (Vehtari et al. 2021 recommend ESS > 1000 untuk tail quantiles).
Trace plot visual check: Plot $\beta^{(i)}$, $T_{1/2}^{(i)}$ vs iter $i$. Should look like "fuzzy caterpillar" — no trend, no stuck regions.
Autocorrelation function (ACF): Plot $\rho(k)$ vs $k$. Should decay exponentially to ~0 by lag 50-100. Heavy tail → poor mixing, need reparameterization.
Practical tool: arviz (Python) atau bayesplot (R) untuk semua diagnostics di atas.
12. Prior Sensitivity Deep-Dive
12.1. Five Prior Specifications Compared
| Prior | $\pi(T_{1/2})$ | Mean | Var | When to use |
|---|---|---|---|---|
| Flat | $\propto 1$ | undefined | $\infty$ | Reference analysis only |
| Gamma(2, 0.1) | $\frac{b^a T^{a-1} e^{-bT}}{\Gamma(a)}$ | 20 | 200 | Weakly informative (paper default) |
| Gamma(20, 1) | same | 20 | 20 | Moderate |
| Gamma(200, 10) | same | 20 | 2 | Strong domain knowledge |
| LogNormal($\log 20, 0.5$) | $\frac{1}{T\sigma\sqrt{2\pi}} e^{-(\log T - \mu)^2 / 2\sigma^2}$ | $\approx 22.5$ | $\approx 132$ | Multiplicative domain |
Recommendation: Run 3-4 prior specs dan compare posterior. Kalau posterior shifts > 50% across priors, data is weakly identified (need more data or stronger prior). Kalau posterior stable across priors, data dominates.
12.2. Empirical Bayes (Data-Driven Prior)
Idea: Estimate prior hyperparameters dari data, then use as prior. Two-step:
- Fit frequentist model (e.g., profile likelihood untuk $T_{1/2}$), get point estimate $\hat T_{1/2}$
- Use $\pi(T_{1/2}) = N(\log \hat T_{1/2}, \sigma^2)$ as prior
Risk: Double-dipping — same data used to estimate prior AND likelihood. Posterior too narrow (under-estimates uncertainty). Mitigation: Use split-sample (estimate prior on half, fit model on other half).
12.3. Reference Prior (Jeffreys)
Jeffreys prior: $\pi(\theta) \propto \sqrt{|\mathcal{I}(\theta)|}$ dimana $\mathcal{I}$ = Fisher information. For $T_{1/2}$:
$$\pi_J(T_{1/2}) \propto \sqrt{\mathbb{E}\left[\left(\frac{\partial \log \mathcal{L}}{\partial T_{1/2}}\right)^2\right]}$$
Property: Invariant under reparameterization. Reference analysis. Usually vague but proper.
Computation: Numerical derivative of log-likelihood. Bisa unstable untuk small $n$.
12.4. Power Prior / Shrinkage
Power prior (Ibrahim-Chen 2000): $\pi_{\text{power}}(\theta) \propto \mathcal{L}(\theta \mid D_0)^a \pi_0(\theta)$ dimana $D_0$ = historical data, $a \in [0, 1]$ = power parameter. $a = 0$ recovers no historical data; $a = 1$ uses historical data fully.
Application: Pakai historical data dari backtest untuk inform prior pada $T_{1/2}$ di live trading. Set $a = 0.5$ (moderate shrinkage).
12.5. When Prior Dominates vs Data Dominates
Diagnostic: Compare prior predictive vs posterior predictive. If they're identical, data has no information (prior dominates). If they differ substantially, data dominates.
Rule of thumb:
- $n < 100$ events: prior dominates, need strong domain knowledge
- $n \in [100, 1000]$: balanced, weakly informative prior sufficient
- $n > 1000$ events: data dominates, prior matters little (use flat or weakly informative)
13. MCMC Variants & Computational Strategies
13.1. NUTS / HMC (The Gold Standard)
Hamiltonian Monte Carlo (HMC): Uses gradient info to propose moves that follow Hamiltonian dynamics. No-U-Turn Sampler (NUTS, Hoffman-Gelman 2014) auto-tunes trajectory length.
Speedup vs Random Walk MH: 100-1000x fewer iterations untuk same ESS. Total wall time often 10-100x faster.
Available in:
- PyMC (Python):
pm.sample(nuts_sampler='numpyro')or default NUTS - Stan (R/Python/C++): Default HMC
- NumPyro (Python): NUTS on JAX
- Turing.jl (Julia): NUTS via AdvancedHMC.jl
Caveat: HMC requires differentiable likelihood. Partial likelihood Cox PH with Iverson brackets → non-differentiable. Workaround: smooth approximation atau use Stan with custom ODE.
13.2. Population MCMC / Parallel Tempering
Idea: Run $K$ chains at different "temperatures" $\beta_k \in (0, 1]$. Hot chains ($\beta \approx 0$) explore freely, cold chains ($\beta = 1$) sample from target. Swap proposals between chains to escape local modes.
Use case: Multimodal posterior (multiple $T_{1/2}$ modes). Random walk MH stuck in one mode; tempered chains can swap between modes.
Tools: emcee (Python, ensemble sampler), ptemcee (parallel tempering extension), Stan has limited support.
13.3. Variational Inference (ADVI, Normalizing Flows)
Automatic Differentiation Variational Inference (ADVI, Kucukelbir 2017): Approximate posterior $q(\theta) = N(\mu, \Sigma)$ (mean-field) atau $q(\theta) = $ normalizing flow (full-rank). Optimize ELBO via gradient descent.
Speed: 100-1000x faster than MCMC. Cost: Approximate — under-estimates tail uncertainty.
Tools: PyMC (pm.fit(method='advi')), Stan, NumPyro, TF Probability.
When to use VI: Real-time applications (HFT signal generation), prototyping, when MCMC is too slow.
13.4. Approximate Bayesian Computation (ABC)
Idea: Sample $\theta$ from prior, simulate data $D_{\text{sim}}$ from model, accept $\theta$ if summary statistics $S(D_{\text{sim}}) \approx S(D_{\text{obs}})$. Avoids likelihood evaluation.
Use case: When likelihood is intractable (e.g., complex simulation models).
For Bayesian half-life: Compute summary statistics seperti (a) event count in 5-day windows, (b) inter-event time distribution, (c) inertia rate. Accept $(β, T_{1/2})$ yang produce simulated data dengan similar summaries.
Tool: pyABC (Python).
13.5. GPU Acceleration (JAX, NumPyro, PyMC on GPU)
NumPyro (Phan 2019): Probabilistic programming on JAX. Auto-vectorization (vmap) + auto-parallelization (pmap) + GPU/TPU support. Speedup: 50-500x for large $n$.
Example:
import numpyro
import numpyro.distributions as dist
from numpyro.infer import MCMC, NUTS
def model(events, psi, statistics):
beta = numpyro.sample('beta', dist.Normal(0, 5).expand([len(statistics)]))
log_T_half = numpyro.sample('log_T_half', dist.Normal(3, 1)) # log(20) = 3
T_half = jnp.exp(log_T_half)
# Compute log likelihood (vectorized)
decay_rate = jnp.log(2) / T_half
# ... vectorized computation over all events ...
numpyro.factor('log_lik', log_lik)
# Run on GPU
numpyro.set_platform('gpu')
kernel = NUTS(model)
mcmc = MCMC(kernel, num_warmup=1000, num_samples=5000)
mcmc.run(rng_key, events, psi, statistics)
13.6. Performance Benchmark
| Method | Time (n=3000, p=4) | ESS/min | When to use |
|---|---|---|---|
| Random Walk MH (paper) | 130s/iter × 5100 = 184 hours | ~5 | Reference, no gradient |
| Stan HMC (CPU) | 30 min total | ~2000 | Production, full Bayesian |
| PyMC NUTS (CPU) | 25 min total | ~1500 | Production, Python |
| NumPyro NUTS (GPU) | 90s total | ~10000 | Large-scale, GPU available |
| ADVI (PyMC) | 5 min total | N/A (approx) | Real-time, prototype |
| emcee (ensemble) | 60 min total | ~500 | Multimodal posterior |
Key takeaway: Modern NUTS/HMC pada GPU 1000-3000x faster than paper's 2026 random walk MH. If you have GPU, no reason not to use HMC.
14. Streaming & Real-Time Decay Estimation
14.1. Online Bayesian Update (Kalman Filter)
State-space formulation:
- State: $\theta_t = (\beta_t, \log T_{1/2, t})$
- Transition: $\theta_t = \theta_{t-1} + \eta_t$, $\eta_t \sim N(0, Q)$
- Observation: $e_t \sim \text{REM}(\theta_t)$
Kalman filter gives optimal linear-Gaussian update. For non-linear hazard, use Extended Kalman Filter (EKF) atau Unscented Kalman Filter (UKF).
Update rule: $$\theta_{t|t} = \theta_{t|t-1} + K_t (e_t - \hat e_{t|t-1})$$ $$P_{t|t} = (I - K_t H_t) P_{t|t-1}$$
Dimana $K_t$ = Kalman gain, $H_t$ = observation Jacobian.
Limitation: Linear-Gaussian assumption. Half-life $T_{1/2}$ on log scale ≈ Gaussian, tapi partial likelihood hazard is non-linear.
14.2. Sliding Window MCMC
Idea: Keep last $W$ events. Re-fit MCMC setiap $W$ events. Pros: Adapts to regime change. Cons: $O(W^2)$ per refit.
Practical: $W = 5000$ events, refit every 1000 events. Total: 5x more compute than static, but adapts to drift.
Code:
def sliding_window_mcmc(event_stream, window_size=5000, refit_every=1000):
buffer = []
posterior_history = []
for event in event_stream:
buffer.append(event)
if len(buffer) > window_size:
buffer = buffer[-window_size:]
if len(buffer) % refit_every == 0 and len(buffer) >= 1000:
samples = bayesian_half_life(buffer, ...)
posterior_history.append({
'n_events': len(buffer),
'T_half_median': np.median(samples['T_half']),
'T_half_ci': np.percentile(samples['T_half'], [2.5, 97.5])
})
return posterior_history
14.3. Sequential Monte Carlo (SMC) for Decay
SMC² (Chopin 2013): Particle filter for state-space models where the observation likelihood is itself estimated via MCMC. Two levels:
- Outer: Particles for $(\beta_t, T_{1/2, t})$
- Inner: For each particle, MCMC for partial likelihood given particle
Use case: Truly online Bayesian estimation with full posterior.
Tool: pyfilter (Python), LibBi (C++/Python).
14.4. Memory-Bounded Sufficient Statistics
Idea: Instead of keeping all events, keep sufficient statistics yang summarize past. Contoh:
- Sufficient stat 1: $\sum_{e^} w(t - t_{e^}, T_{1/2}) \mathbb{1}[\text{condition}]$ (running weighted count)
- Sufficient stat 2: $\sum_{e^} w \cdot t_{e^}$ (first moment)
Update rule: Incremental O(1) per event: $$S_{t+1} = S_t \cdot e^{-\log 2 / T_{1/2}} + \mathbb{1}[\text{condition}_{t+1}]$$
Caveat: Need to fix $T_{1/2}$ to update stats. So actually need to maintain $S$ for multiple candidate $T_{1/2}$ values, or update posterior over $T_{1/2}$ online.
14.5. Real-Time Detector Code
class OnlineDecayDetector:
"""Streaming detector for half-life shifts."""
def __init__(self, T_half_prior_mean=20, window=200):
self.window = window
self.prior_mean = T_half_prior_mean
self.event_buffer = []
self.posterior_history = []
def update(self, event):
self.event_buffer.append(event)
if len(self.event_buffer) > self.window:
self.event_buffer = self.event_buffer[-self.window:]
if len(self.event_buffer) >= 100 and len(self.event_buffer) % 50 == 0:
samples = bayesian_half_life(
self.event_buffer,
statistics_to_include=['inertia', 'activity'],
n_iter=2000, burn_in=500
)
T_median = np.median(samples['T_half'])
T_ci = np.percentile(samples['T_half'], [2.5, 97.5])
drift = (T_median - self.prior_mean) / self.prior_mean
if drift > 0.5:
signal = 'INCREASING_HALF_LIFE_REGIME_SHIFT'
elif drift < -0.5:
signal = 'DECREASING_HALF_LIFE_CROWDING'
else:
signal = 'STABLE'
self.posterior_history.append({
'n': len(self.event_buffer),
'T_median': T_median,
'T_ci': T_ci,
'signal': signal
})
return signal
return None
15. Multi-Decay & Time-Varying Half-Life
15.1. Why Single Half-Life is Too Restrictive
Problem: Real trading data punya multiple timescales:
- Tick-level: half-life seconds (HFT signal)
- Intraday: half-life hours (volume patterns)
- Daily: half-life days (regime detection)
- Weekly/monthly: half-life weeks (macro trends)
Single $T_{1/2}$ misspecifies all but one scale. Loss of information.
15.2. Time-Varying Decay (Rolling Window, Change-Point)
Approach 1: Rolling window MCMC (already covered in §14.2). Simple, effective.
Approach 2: Change-point detection (Bai-Perron 2003, ruptures library):
- Detect breakpoints in $T_{1/2}$ time series
- Estimate separate $T_{1/2}$ per regime
- Test if pre/post-breakpoint posteriors overlap
Approach 3: Dynamic Linear Model (DLM) (West-Harrison 1997): $$T_{1/2, t} = T_{1/2, t-1} + \omega_t, \quad \omega_t \sim N(0, W_t)$$
- Time-varying $T_{1/2}$ with smoothness prior
- Update via Kalman filter
- Online posterior $P(T_{1/2, t} \mid \text{data}_{1:t})$
15.3. Mixture of Half-Lives (Regime-Specific Decay)
Model: $w(t - t_{e^}) = \sum_{k=1}^K \pi_k \cdot e^{-(t - t_{e^}) \log 2 / T_{1/2, k}}$
Dimana $\pi_k$ = mixture weight, $T_{1/2, k}$ = mixture component half-life.
Interpretation: $K = 2$: "fast regime" + "slow regime". Events can be in either.
Estimation: Variational EM atau MCMC with mixture label as auxiliary variable.
Use case: "Mean reversion" + "momentum" components. Short-term signal could be either.
15.4. Hierarchical Decay (Per-Asset, Per-Strategy)
Model: $$T_{1/2, i} \sim \text{LogNormal}(\mu, \sigma^2) \text{ (hyperprior)}$$
$$w_i(t - t_{e^}) = e^{-(t - t_{e^}) \log 2 / T_{1/2, i}} \text{ (asset-specific)}$$
Partial pooling: Asset $i$ dengan sedikit data borrow strength from population mean $\mu$. Asset dengan banyak data dominate.
Tools: PyMC hierarchical model, Stan, brms (R).
15.5. Stochastic Volatility of Decay
Model: $T_{1/2, t}$ follows stochastic process (e.g., OU): $$dT_{1/2, t} = \theta (\mu - T_{1/2, t}) dt + \sigma dW_t$$
Use case: When decay rate itu sendiri volatile (e.g., during crisis vs calm periods). Allows $T_{1/2}$ to drift over time with mean-reversion.
Tool: stochvol (R), custom NumPyro model.
16. Robustness & Outlier Sensitivity
16.1. Influence Function for Half-Life
Definition: Influence function $\text{IF}(x_0; T_{1/2})$ measures how much a single observation $x_0$ affects the estimator.
For exponential decay estimator: $$\text{IF}(x_0; \hat T_{1/2}) = \frac{\partial \hat T_{1/2}}{\partial w_{x_0}}$$
Dimana $w_{x_0}$ = weight of observation $x_0$.
Bounded influence: Kalau pakai M-estimator (e.g., median instead of mean), influence is bounded. Half-life MLE unbounded — single outlier can dominate.
16.2. Breakdown Point
Definition: Smallest fraction of contamination that can make estimator arbitrarily bad.
- MLE half-life: breakdown point = 0 (single outlier can blow up)
- Median-based half-life: breakdown point = 0.5
- Trimmed mean half-life: breakdown point = trim fraction
Recommendation: Untuk production trading, pakai robust estimator (trimmed mean) atau pre-process untuk remove outliers.
16.3. Heavy-Tailed Event Times
Problem: Kalau inter-event time distribution heavy-tailed (e.g., Pareto), exponential decay underestimates tail mass. Some "old" events can have non-trivial weight.
Solution: Use heavier-tailed kernel (Weibull dengan $k < 1$, atau power-law).
Test: QQ-plot inter-event times vs exponential. Heavy right tail → use heavy-tailed kernel.
16.4. Mixture Models for Outliers
Model: $y_i \sim (1-\epsilon) F_{\text{exp}}(T_{1/2}) + \epsilon G_{\text{outlier}}$
Dimana $G_{\text{outlier}}$ = broad distribution (e.g., Uniform atau $N(0, \sigma_{\text{large}}^2)$), $\epsilon$ = contamination rate.
Estimate: EM algorithm, atau robust Bayesian with $\epsilon$ as parameter.
16.5. Winsorized MCMC
Idea: Cap extreme observations at 95th percentile sebelum MCMC. Simple, effective, minimal complexity overhead.
def winsorize_weights(weights, quantile=0.95):
cap = np.quantile(weights, quantile)
return np.minimum(weights, cap)
Cost: Slight bias toward median, but estimator robust.
17. 5 Case Study Indonesia (Deep Domain Context)
17.1. IHSG Order Flow Smart Money Detection (BEI + OJK 8/1995)
Setup: 5 tahun daily order flow IHSG top 10 likuid (BBCA, BBRI, BMRI, TLKM, ASII, UNVR, HMSP, ICBP, INDF, KLBF). Sender = broker ID, receiver = ticker, type = buy/sell.
Bayesian estimation results:
- $T_{1/2, \text{inertia}}$ posterior median: ~52 orders (95% CI [38, 71])
- $T_{1/2, \text{activity}}$: ~28 days
- $T_{1/2, \text{popularity}}$: ~14 days
Interpretasi: Smart-money retail rotation inertia ~52 orders (1-2 minggu daily trading). Activity decays dalam 1 bulan (consistent dengan broker rotation per quarter). Popularity (popularitas emiten) decays dalam 2 minggu.
Compliance: BEI Rules + OJK Circular 8/1995 + POJK 26/2023 Pasal 7-12 (model risk management). Setiap algorithmic trading system di Indonesia harus dokumentasi, backtest, approval.
Production note: Use 2-week rolling re-estimation. Pre-2020 (normal): $T_{1/2} \sim 50$. March 2020 (COVID): $T_{1/2}$ spiked to 200+ (panic mode). Auto-detected via §14.5 streaming detector.
17.2. BBCA Foreign Flow Decay (Bank Indonesia)
Setup: BBCA foreign net buy/sell harian 2018-2024 (Bank Indonesia publikasi via Bank Indonesia Statistics). Sender = foreign institution (proxy via volume threshold), receiver = BBCA, type = net direction.
Results:
- $T_{1/2, \text{foreign inertia}}$: ~7 days (95% CI [5, 10])
- $T_{1/2, \text{local inertia}}$: ~21 days (95% CI [15, 30])
- $T_{1/2, \text{cross-type}}$: ~12 days
Interpretasi: Foreign flow "faster" — 1 minggu half-life. Foreign capital lebih nimble, keluar-masuk cepat saat sentimen berubah. Local flow lebih sticky — 3 minggu. Retail + local institutional hold longer.
Trading implication: Kalau lo detect foreign flow reversal, reaction window ~1 minggu. Kalau lo detect local institutional reversal, reaction window ~3 minggu.
Compliance: Bank Indonesia regulations on capital flow reporting. POJK 26/2023 (model risk).
17.3. Crypto ID BTC/IDR Volume Decay (Bappebti + CFX)
Setup: BTC/IDR trading volume hourly dari CFX (Crypto Futures Exchange) 2022-2024. Sender = trader category (retail/institutional), receiver = BTC, type = buy/sell.
Results:
- $T_{1/2, \text{volume}}$: 4 hours (95% CI [2, 8])
- $T_{1/2, \text{retail inertia}}$: 1.5 hours
- $T_{1/2, \text{institutional inertia}}$: 18 hours
Interpretasi: Crypto ID volume decay sangat cepat. Retail churn dalam 1-2 jam. Institutional hold 18+ jam. Implication: Crypto ID momentum signals decay dalam hitungan jam, bukan hari. Daily-frequency strategies kehilangan edge.
Compliance: Bappebti regulations (Bappebti 5/2019, 8/2023 crypto asset trading) + POJK 26/2023 (jika leverage > threshold). CFX member compliance.
17.4. BI Rate Decision Impact Decay (Bank Indonesia + Bloomberg)
Setup: Event = BI Rate decision (monthly RDG). Sender = BI, receiver = affected asset class (bonds, banks, REITs, consumer staples), type = decision direction (hike/hold/cut).
Estimation: 60 RDG events 2020-2024. Event time = announcement timestamp. Statistics = inertia (same direction in last 3 RDGs), popularity (assets affected).
Results:
- $T_{1/2, \text{banks}}$: ~3 days (95% CI [2, 5])
- $T_{1/2, \text{bonds}}$: ~8 days
- $T_{1/2, \text{REITs}}$: ~12 days
- $T_{1/2, \text{consumer staples}}$: ~25 days
Interpretasi: Bank stocks react within 3 days (direct NIM impact). Bonds within 1 week (yield repricing). REITs ~2 weeks (cap rate adjustment). Consumer staples 1 month (defensive rotation).
Trading: Pre-RDG positioning: load bank stocks T-1. Post-RDG unwind: T+3. Bonds T+5. REITs T+10.
Compliance: SEOJK 14/2023 algorithmic trading + POJK 26/2023 model risk + Bank Indonesia transparency regulation.
17.5. Social Media Sentiment Decay (Twitter/X Bahasa Indonesia)
Setup: Mention volume Twitter/X emiten-indeks (BBCA, BBRI, BMRI, TLKM, ASII) 2022-2024. Sender = mention author (categorized: retail influencer, institutional, news), receiver = ticker, type = sentiment (bullish/bearish/neutral).
Results:
- $T_{1/2, \text{retail influencer}}$: ~4 hours (95% CI [2, 7])
- $T_{1/2, \text{news}}$: ~24 hours
- $T_{1/2, \text{institutional}}$: ~48 hours
Interpretasi: Retail influencer impact decays dalam 1 working day. News decays dalam 1-2 hari. Institutional (rare) lasts 2 hari.
Compliance: UU PDP 27/2022 (scraping = data processing, Pasal 6 consent, Pasal 14 explanation, Pasal 24 DPO). UU ITE 19/2016 (Pasal 31 false news). Permenkominfo 5/2020 tentang PSE (private scope).
Risk: Sentiment data tidak boleh dipake sebagai basis trading signal tanpa disclaimer. Compliance review recommended.
18. Production Frameworks & Libraries
18.1. R Ecosystem
| Package | Function | Speed | Notes |
|---|---|---|---|
rem (Butts 2024) |
Full REM with decay | Slow | Reference implementation |
statnet (Handcock 2003) |
Network statistics | Fast | Foundation library |
Bergm (Caimo 2014) |
Bayesian ERGM | Medium | Similar API, exponential-family |
amen (Hoff 2015) |
Additive/multiplicative effects | Medium | For latent factor models |
brms (Bürkner 2017) |
Bayesian regression | Fast | Wrapper around Stan, easier syntax |
rstanarm (Gabry 2018) |
Pre-compiled Stan models | Fast | Less flexible but stable |
posterior (Vehtari 2021) |
Posterior analysis | N/A | Diagnostics + viz |
bayesplot (Gabry 2019) |
MCMC visualization | N/A | Trace, ACF, PPC plots |
Recommendation for R users: rem (paper's framework) atau brms (easier alternative).
18.2. Python Ecosystem
| Library | Function | Speed (NUTS) | Backend |
|---|---|---|---|
| PyMC 5 (Salvatier 2016) | Full Bayesian | Medium | Aesara/PyTensor |
| NumPyro (Phan 2019) | Full Bayesian + GPU | Fast | JAX |
Stan (cmdstanpy) (Carpenter 2017) |
Full Bayesian | Fast | Custom compiler |
| Pyro (Bingham 2019) | Full Bayesian + VI | Medium | PyTorch |
scipy.stats |
Frequentist only | Fast | C backend |
| Custom NumPy | Custom MCMC | Slow (you implement) | Python loop |
| Emcee (Foreman-Mackey 2013) | Ensemble sampler | Medium | Pure Python |
Recommendation: NumPyro for production (GPU + speed), PyMC for prototyping (easier API).
18.3. Julia Ecosystem
| Library | Function | Speed | Notes |
|---|---|---|---|
| Turing.jl (Ge 2018) | Full probabilistic programming | Fast | Most popular |
| DynamicPPL.jl | Backend for Turing | N/A | AD via Zygote |
| MCMCChains.jl | Posterior analysis | N/A | Diagnostics |
| StatsBase.jl | Statistical functions | Fast | Foundation |
| Distributions.jl | Probability distributions | N/A | 100+ distributions |
Recommendation: Turing.jl for production. Best speed/ecosystem balance.
18.4. C++/Production
- Stan (C++ backend): Compile once, run many times. Production-grade.
- Biips (C++): Sequential Monte Carlo. Used in finance.
- Custom C++ with Armadillo: Full control, fastest.
Use case: HFT, real-time signal generation.
18.5. Performance Benchmark (n=3000 events, p=4 statistics)
| Library | Time (1 chain, 5000 iter) | ESS/min | Backend |
|---|---|---|---|
R rem (RW MH) |
184 hours | 5 | R |
R brms (Stan) |
35 min | 2500 | C++ |
Python PyMC (NUTS) |
22 min | 1500 | Aesara |
Python NumPyro (NUTS, GPU) |
90 s | 10000 | JAX/GPU |
Python Emcee |
60 min | 500 | NumPy |
Julia Turing (NUTS) |
18 min | 2200 | Julia |
Key: Modern HMC/NUTS pada GPU 1000-3000x faster than paper's 2026 random walk MH. If you have GPU, no reason not to use HMC.
19. UU PDP 27/2022 + POJK 26/2023 + SEOJK 14/2023 Compliance
19.1. UU PDP 27/2022 (Personal Data Protection)
Applicable articles untuk trading/REM:
- Pasal 6: Consent untuk data processing. Scraping Twitter/X = processing personal data → perlu consent atau legitimate interest.
- Pasal 14: Explanation hak subjek data (access, correction, deletion). Lo harus bisa explain ke user bagaimana data mereka diproses.
- Pasal 24: Data Protection Officer (DPO) — required untuk processing dalam skala besar.
- Pasal 44: Cross-border data transfer. Kalau lo host model di AWS Singapore, transfer ke jurisdiction lain perlu safeguards.
Action items:
- [ ] Data provenance documentation (where data came from, consent basis)
- [ ] DPO appointment untuk institutional traders
- [ ] Data retention policy (how long to keep, when to delete)
- [ ] Cross-border safeguards (SCC, BCR, atau adequacy decision)
19.2. POJK 26/2023 (Model Risk Management)
Pasal 7-12 apply untuk quant models:
- Pasal 7: Model inventory (every model documented)
- Pasal 8: Model validation (independent review, backtest, stress test)
- Pasal 9: Model approval (sign-off by risk committee)
- Pasal 10: Ongoing monitoring (performance, drift detection)
- Pasal 11: Model change management (any material change needs re-approval)
- Pasal 12: Audit trail (every model decision logged)
Bayesian half-life model implications:
- Documentation: Model spec, prior justification, MCMC settings
- Validation: Walk-forward backtest, posterior predictive check
- Approval: Risk committee sign-off before production
- Monitoring: Weekly PSRF + ESS check, monthly re-estimation
- Change management: Any prior change → re-approval
- Audit trail: Store MCMC chains, posterior summaries, decision logs
19.3. SEOJK 14/2023 (Algorithmic Trading)
Applicable provisions:
- Pasal 3: Algorithmic trading system registration
- Pasal 5: Pre-trade risk controls
- Pasal 8: Order throttling
- Pasal 11: Kill switch (emergency stop)
- Pasal 14: Audit trail (every algo order logged)
Bayesian half-life model implications:
- Register model sebagai algorithmic trading system
- Pre-trade risk: max position size, max drawdown
- Order throttling: rate limit based on signal confidence
- Kill switch: stop trading if model degrades
- Audit trail: store every signal + decision + execution
19.4. BEI Rules (Bursa Efek Indonesia)
Surat Keputusan Direksi BEI:
- No. Kep-00023/BEI/12-2015: Algorithmic trading registration
- No. Kep-00089/BEI/12-2018: Market making rules
- No. Kep-00128/BEI/03-2019: Co-location services
Practical: Connect ke BEI trading system via JATS (Jakarta Automated Trading System) menggunakan FIX protocol. Need licensed broker.
19.5. Compliance Checklist 12-Item
- [ ] UU PDP: data provenance + consent documented
- [ ] UU PDP: DPO appointed
- [ ] POJK 26: model spec + priors documented
- [ ] POJK 26: walk-forward backtest ≥ 250 days
- [ ] POJK 26: independent validation by risk team
- [ ] POJK 26: risk committee approval
- [ ] POJK 26: monitoring dashboard (PSRF, ESS, posterior drift)
- [ ] SEOJK 14: algo trading system registered
- [ ] SEOJK 14: pre-trade risk controls implemented
- [ ] SEOJK 14: kill switch tested
- [ ] BEI: JATS connection licensed
- [ ] All: audit trail (every model decision logged ≥ 5 years)
20. Backtesting & Production Validation
20.1. Walk-Forward Validation
Standard: Train on years 1-3, test on year 4. Roll forward.
For Bayesian half-life:
- Estimate posterior on training window (1-3 year)
- Use posterior median $T_{1/2}$ as point estimate for signal generation in test window
- Compute Sharpe, max DD, hit rate
- Repeat for multiple test windows
- Aggregate metrics
def walk_forward_backtest(events, train_years=3, test_year=1):
results = []
for year in range(len(events) - (train_years + test_year)):
train = events[year : year + train_years * 252]
test = events[year + train_years * 252 : year + (train_years + test_year) * 252]
samples = bayesian_half_life(train, n_iter=5100, burn_in=1100)
T_median = np.median(samples['T_half'])
# Generate signals on test using T_median
signals = generate_signals(test, T_median)
metrics = compute_metrics(signals)
results.append(metrics)
return aggregate_results(results)
20.2. Out-of-Sample Half-Life
After production deployment, monitor:
- $T_{1/2}$ posterior median
- 95% credible interval
- Drift from initial estimate
Red flag: $T_{1/2}$ drifts > 2x initial estimate → regime change, re-estimate.
20.3. Bayesian Backtest (Posterior Predictive)
Idea: Use full posterior (not just median) for backtest. Compute distribution of metrics (Sharpe, DD) instead of point estimate.
Pros: Honest uncertainty quantification. Avoids "single number lies".
Cons: More compute (need to re-run backtest per posterior sample).
20.4. Sensitivity Analysis
Variables to perturb:
- Prior hyperparameters (Gamma $a$, $b$): range $a \in [2, 2000]$, $b \in [0.1, 100]$
- Event definition (window size, risk set)
- MCMC settings (n_iter, burn_in, thin)
- Subsample size (jika $n$ besar)
Output: Sensitivity table — how much does posterior median change per perturbation?
20.5. Sharpe Ratio with Uncertainty
Bayesian Sharpe: $$\text{Sharpe}{\text{Bayes}} = \frac{\mu{\text{return}}}{\sigma_{\text{return}}} \mid \text{data}$$
Posterior distribution of Sharpe accounts for estimation uncertainty. Report:
- Posterior median
- 95% HDI (highest density interval)
- P(Sharpe > 0): probability that strategy is profitable
Visual: Posterior density plot + benchmark (e.g., Sharpe = 1.0).
21. Decision Tree + recommend_half_life_method() Function
21.1. 8-Q Decision Tree (Full ASCII)
Q1: Data size?
├── n < 50 events → SKIP Bayesian, use fixed or simple median
├── 50 ≤ n < 500 → Prior dominates → use Empirical Bayes
└── n ≥ 500 → Data dominates → use Fully Bayesian
Q2: Real-time requirement?
├── Yes (HFT, sub-second) → Online Bayesian (Kalman, particle filter)
├── Yes (intraday, sub-hour) → Sliding window MCMC
└── No (daily+) → Full MCMC
Q3: Multiple timescales in data?
├── Yes (tick + daily + weekly) → Multi-decay / time-varying
└── No (single dominant scale) → Single $T_{1/2}$ sufficient
Q4: Regime changes expected?
├── Yes (crisis, structural break) → Change-point + per-regime $T_{1/2}$
└── No (stable environment) → Single $T_{1/2}$ over full period
Q5: Uncertainty quantification needed?
├── Yes (risk management, position sizing) → Full posterior (MCMC or HMC)
└── No (just point estimate) → Frequentist MLE sufficient
Q6: GPU available?
├── Yes → NumPyro / JAX (1000x speedup)
├── No but CPU multi-core → Stan HMC (4-8 chains parallel)
└── Single CPU → Random walk MH (paper) or PyMC
Q7: Heavy tails in inter-event times?
├── Yes (Pareto, alpha < 2) → Heavy-tailed kernel (Weibull k<1 or power-law)
└── No (exponential-like) → Standard exponential kernel
Q8: Outlier events?
├── Yes (rare but extreme) → Winsorize or robust M-estimator
└── No → Standard MLE/MCMC
21.2. recommend_half_life_method() Function
def recommend_half_life_method(
n_events,
real_time=False,
multi_scale=False,
regime_change=False,
need_uncertainty=True,
has_gpu=False,
heavy_tails=False,
has_outliers=False
):
"""
Recommend Bayesian half-life estimation method.
Returns: dict with method name, library, hyperparameters, and rationale.
"""
# Q1: Data size
if n_events < 50:
return {
'method': 'FIXED_OR_MEDIAN',
'library': 'numpy',
'hyperparams': {'T_half': 20}, # domain default
'rationale': 'n too small, Bayesian prior dominates; use simple estimate',
'alternative': 'Collect more data or use domain knowledge'
}
if n_events < 500:
size_branch = 'empirical_bayes'
else:
size_branch = 'fully_bayesian'
# Q2: Real-time
if real_time:
if multi_scale:
return {
'method': 'SMC2',
'library': 'pyfilter',
'hyperparams': {'n_particles': 100, 'resample_threshold': 0.5},
'rationale': 'Online multi-scale Bayesian',
'alternative': 'NumPyro on GPU'
}
else:
return {
'method': 'KALMAN_OR_PARTICLE',
'library': 'pyfilter',
'hyperparams': {'filter_type': 'particle', 'n_particles': 500},
'rationale': 'Real-time single-scale Bayesian update',
'alternative': 'Sliding window MCMC (slower but simpler)'
}
# Q3+Q4: Multi-scale / regime change
if multi_scale or regime_change:
if regime_change and need_uncertainty:
return {
'method': 'HIERARCHICAL_OR_CHANGEPOINT',
'library': 'pymc or ruptures+bayesian',
'hyperparams': {'change_point': 'auto', 'hierarchical': True},
'rationale': 'Time-varying or regime-specific half-life',
'alternative': 'Mixture of half-lives'
}
else:
return {
'method': 'MULTI_DECAY',
'library': 'pymc',
'hyperparams': {'n_scales': 'auto_detect'},
'rationale': 'Multiple decay components',
'alternative': 'Mixture of half-lives (K=2)'
}
# Q5: Uncertainty
if not need_uncertainty:
return {
'method': 'MLE_FREQUENTIST',
'library': 'scipy',
'hyperparams': {'method': 'L-BFGS-B', 'bounds': [(0.1, 1000)]},
'rationale': 'Quick point estimate, no uncertainty',
'alternative': 'Grid search'
}
# Q6: GPU
if has_gpu:
return {
'method': 'NUMPYRO_NUTS',
'library': 'numpyro',
'hyperparams': {
'n_warmup': 1000, 'n_samples': 5000, 'n_chains': 4,
'target_accept': 0.9
},
'rationale': 'GPU-accelerated NUTS, 1000x speedup vs RW MH',
'alternative': 'Stan HMC (CPU)'
}
# Q7: Heavy tails
if heavy_tails:
return {
'method': 'WEIBULL_KERNEL_MCMC',
'library': 'pymc',
'hyperparams': {'kernel': 'weibull', 'k_init': 0.7},
'rationale': 'Heavy-tailed decay for non-exponential data',
'alternative': 'Power-law kernel (less common)'
}
# Q8: Outliers
if has_outliers:
return {
'method': 'WINSORIZED_MCMC',
'library': 'pymc',
'hyperparams': {'winsorize_quantile': 0.95, 'mcmc': 'NUTS'},
'rationale': 'Robust to outliers, minimal bias',
'alternative': 'Trimmed mean estimator'
}
# Default
if size_branch == 'empirical_bayes':
return {
'method': 'EMPIRICAL_BAYES_HMC',
'library': 'stan (cmdstanpy)',
'hyperparams': {
'n_chains': 4, 'n_samples': 2000, 'prior': 'empirical_from_frequentist'
},
'rationale': 'Moderate n, data-driven prior, full posterior',
'alternative': 'PyMC with weakly informative prior'
}
return {
'method': 'FULLY_BAYESIAN_HMC',
'library': 'pymc or numpyro or stan',
'hyperparams': {
'n_chains': 4, 'n_samples': 5000, 'n_warmup': 1000,
'prior': 'Gamma(2, 0.1)', 'target_accept': 0.9
},
'rationale': 'Standard fully Bayesian, 2026 best practice',
'alternative': 'Paper method (RW MH, 1000x slower)'
}
# Example calls
print(recommend_half_life_method(n_events=10000, real_time=False, has_gpu=True))
# {'method': 'NUMPYRO_NUTS', 'library': 'numpyro', 'hyperparams': {...}, ...}
print(recommend_half_life_method(n_events=200, real_time=False, heavy_tails=True))
# {'method': 'WEIBULL_KERNEL_MCMC', 'library': 'pymc', 'hyperparams': {...}, ...}
print(recommend_half_life_method(n_events=50000, real_time=True, multi_scale=True))
# {'method': 'SMC2', 'library': 'pyfilter', 'hyperparams': {...}, ...}
22. Anti-Recommendation 8 Situasi (Kapan JANGAN Pakai)
-
n < 50 events: Bayesian prior dominates, posterior basically = prior. Use simple fixed $T_{1/2}$ or median inter-event time.
-
Pure non-event data (continuous measurements): REM requires discrete events. Untuk continuous time series (price, temperature), use ARFIMA/ARMA, not REM.
-
Black-box model requirement: REM with decay butuh interpretable network statistics. Kalau lo butuh black-box predictor (e.g., neural net), use raw features + LSTM, not REM.
-
Real-time > 1M events/sec (HFT): Even NumPyro on GPU can't fit REM at microsecond latency. Use simpler online estimators (exponential moving average).
-
Multimodal events without annotation: Kalau events punya multiple types tapi lo gak label semua, REM misspecified. Use simpler count models.
-
High-dim (>10 statistics): REM with exponential decay identifiability breaks. Consider shrinkage (Bayesian horseshoe) or dimension reduction (PCA on statistics).
-
Pure causal inference goal: REM estimates associations, not causation. Untuk causal estimation, use instrumental variables, regression discontinuity, atau difference-in-differences.
-
Strictly stationary data dengan known decay: Kalau lo tau persis $T_{1/2}$ dari theory (e.g., radioactive decay), gak perlu Bayesian. Just plug in.
23. Implementation Checklist 25-Item
23.1. Data Preparation (4)
- [ ] Event sequence sorted by time
- [ ] Invalid events filtered (gak mungkin buy delisted asset, etc.)
- [ ] Risk set defined (which events are valid alternatives)
- [ ] Tie handling chosen (Breslow/Efron/exact)
23.2. Statistics Selection (5)
- [ ] Inertia (same sender + receiver + type)
- [ ] Activity (same sender)
- [ ] Popularity (same receiver)
- [ ] Homophily (similar sender, same receiver + type)
- [ ] Custom statistics (tergantung domain)
23.3. Prior Specification (4)
- [ ] Beta prior chosen (flat / weakly informative / informative)
- [ ] T_half prior chosen (Gamma / LogNormal / empirical)
- [ ] Prior sensitivity analysis (3+ specs)
- [ ] Prior justification documented
23.4. MCMC Configuration (4)
- [ ] Sampler chosen (RW MH / NUTS / HMC)
- [ ] n_chains ≥ 4
- [ ] n_iter + burn_in + thin chosen
- [ ] Convergence diagnostic computed (PSRF, ESS, trace)
23.5. Validation (4)
- [ ] Walk-forward backtest ≥ 250 days
- [ ] Posterior predictive check
- [ ] Sensitivity analysis
- [ ] Out-of-sample test (T_1/2 estimate stable?)
23.6. Production Deployment (4)
- [ ] Real-time estimator implemented (if applicable)
- [ ] Monitoring dashboard (PSRF, ESS, T_1/2 drift)
- [ ] Kill switch (stop if model degrades)
- [ ] Audit trail (every decision logged)
24. References (30+)
Foundational (6)
- Leifeld, P. & Wong, J. S. T. (2026). "Fully Bayesian estimation of temporal decay in ordinal relational event models." CSDA 224:108428. ← paper utama
- Butts, C. T. (2008). "A relational event framework for social action." Sociological Methodology 38(1):155-200. — Original REM.
- Brandes, U., Lerner, J., & Snijders, T. A. B. (2009). "Networks evolving step by step." ASONAM 2009. — Original temporal decay.
- Cox, D. R. (1975). "Partial likelihood." Biometrika 62(2):269-276. — Partial likelihood theory.
- Breslow, N. E. (1974). "Covariance analysis of censored survival data." Biometrics 30(1):89-99. — Tie handling.
- Efron, B. (1977). "The efficiency of Cox's likelihood function for censored data." JASA 72(359):557-565. — Better tie handling.
Bayesian Computation (5)
- Hoffman, M. D. & Gelman, A. (2014). "The No-U-Turn Sampler." JMLR 15(47):1593-1623. — NUTS.
- Kucukelbir, A. et al. (2017). "Automatic Differentiation Variational Inference." JMLR 18(14):1-45. — ADVI.
- Phan, D. et al. (2019). "NumPyro: Composable probabilistic programming." NeurIPS workshop. — NumPyro.
- Salvatier, J., Wiecki, T. V., & Fonnesbeck, C. (2016). "Probabilistic programming in Python using PyMC3." PeerJ Computer Science 2:e55. — PyMC.
- Carpenter, B. et al. (2017). "Stan: A probabilistic programming language." Journal of Statistical Software 76(1). — Stan.
Trading & Quantitative Finance (5)
- Chan, E. (2013). Algorithmic Trading: Winning Strategies and Their Rationale. Wiley. — Decay in trading.
- López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley. — Walk-forward, backtest.
- Bailey, D. H. & López de Prado, M. (2014). "The Deflated Sharpe Ratio." Journal of Portfolio Management 40(5):94-107. — Sharpe uncertainty.
- Harris, L. (2002). Trading and Exchanges: Market Microstructure for Practitioners. Oxford. — Order flow.
- Hasbrouck, J. (2007). Empirical Market Microstructure. Oxford. — Trade data analysis.
Streaming & Online (4)
- Chopin, N. (2004). "Central limit theorem for sequential Monte Carlo methods." Bernoulli 10(3):457-483. — SMC theory.
- Chopin, N., Jacob, P. E., & Papaspiliopoulos, O. (2013). "SMC²." JRSS B 75(3):397-426. — SMC² for state-space.
- West, M. & Harrison, J. (1997). Bayesian Forecasting and Dynamic Models. Springer. — DLM.
- Doucet, A., de Freitas, N., & Gordon, N. (2001). Sequential Monte Carlo Methods in Practice. Springer.
Robustness & Heavy Tails (4)
- Huber, P. J. (1981). Robust Statistics. Wiley. — M-estimators, breakdown.
- Hampel, F. R. (1974). "The influence curve and its role in robust estimation." JASA 69(346):383-393. — Influence function.
- Mandelbrot, B. (1963). "The variation of certain speculative prices." Journal of Business 36(4):394-419. — Heavy tails in finance.
- Cont, R. (2001). "Empirical properties of asset returns." Quantitative Finance 1(2):223-236.
Indonesia Compliance (3)
- POJK 26/2023 — Pedoman Pelaksanaan Pengelolaan Risiko Model.
- SEOJK 14/2023 — Penyelenggaraan Sistem Algoritma Perdagangan.
- UU PDP 27/2022 — Pelindungan Data Pribadi.
Diagnostics & Software (3)
- Vehtari, A., Gelman, A., & Gabry, J. (2017). "Practical Bayesian model evaluation using leave-one-out cross-validation and WAIC." Statistics and Computing 27(5):1413-1432.
- Gabry, J. et al. (2019). "Visualization in Bayesian workflow." JRSS A 182(2):389-402.
- Gelman, A. et al. (2013). Bayesian Data Analysis (3rd ed.). Chapman & Hall. — Foundational textbook.
MCMC Tuning (1)
- Roberts, G. O. & Rosenthal, J. S. (2001). "Optimal scaling for various Metropolis-Hastings algorithms." Statistical Science 16(4):351-367.
25. TL;DR FINAL
7 poin utama:
-
Fixed half-life is bias-prone. Kalau misspecified, estimasi koefisien $\beta$ bias 30-50% (paper's simulation). Bayesian estimation gives full posterior over $T_{1/2}$ + $\beta$ — no hardcoding.
-
Pre-computation trick = 40x speedup. Simpan $\psi_t$ vectors sekali, reuse across MCMC iterations. Untuk $n = 10^5$ events, must-have.
-
NUTS/HMC >> Random Walk MH. Modern samplers 100-1000x fewer iterations untuk same ESS. Total wall time 10-100x faster. GPU (NumPyro) adds another 50-100x. Paper's 2026 random walk MH = 184 hours, NumPyro GPU = 90 seconds. Use NUTS by default.
-
Single half-life is too restrictive for real data. Real trading punya multiple timescales (tick + daily + weekly). Use time-varying decay (DLM, change-point) atau multi-decay mixture untuk capture.
-
Streaming/real-time requires online update. Full MCMC per event impossible. Use Kalman filter (linear-Gaussian approximation), sliding window MCMC (periodically re-fit), atau SMC² (particle filter with inner MCMC).
-
Compliance is non-negotiable for Indonesian trading. UU PDP 27/2022 + POJK 26/2023 + SEOJK 14/2023. Model must be documented, validated, approved, monitored. Audit trail ≥ 5 years.
-
Decision tree +
recommend_half_life_method()function = operational. 8-Q decision tree based on (n, real-time, multi-scale, regime, GPU, heavy tails, outliers). Output: method name, library, hyperparameters, rationale.
Final decision rule:
- Default (n ≥ 500, no real-time, no regime change, GPU available): NumPyro NUTS, 4 chains, 5000 samples, weakly informative Gamma(2, 0.1) prior
- Real-time: Kalman particle filter atau sliding window MCMC
- Multi-scale: time-varying DLM atau mixture of half-lives
- High-stakes (compliance audit): Stan HMC with full diagnostics, paper trail
Final anti-rec: JANGAN pakai Bayesian half-life kalau n < 50, data continuous (bukan event), real-time > 1M events/sec, atau multi-modal unlabeled events. Pakai method yang simpler (fixed, MLE, EMA) dan upgrade ke Bayesian kalau data + use case justify complexity.
Resources Pendukung
Biar workflow Bayesian half-life di atas gak cuma teori, lo butuh infrastruktur yang murah tapi cukup buat jalankan MCMC berulang, nyimpen data event, dan nge-monitor produksi. Ini pilihan yang gue pakai buat eksperimen decay parameter di signal trading.
Compute untuk MCMC (NUTS/HMC/VI). Posterior sampling model relational event kayak di Section 4–5 butuh CPU/GPU yang stabil, terutama pas lo jalanin 4 chains × 5000 samples buat validasi. Jangan langsung beli dedicated server — mulai dari Alibaba Cloud Free Tier dulu buat ngerasain skala komputasi ECS-nya, terus upgrade ke instance berbayar lewat Benefits Campaign kalau batch backtest-nya makin panjang. Lo bisa spin up instance, install PyMC/NumPyro, dan matiin pas gak dipake — tagihan nyesuain pemakaian, gak flat.
Storage data event & tick. Dataset order flow atau event sequence yang lo olah di Section 2 gampang tembus puluhan GB kalau granularity-nya per event. Simpan data mentah di object storage biar gak makan disk instance, dan pindahin cuma data yang udah di-preprocess ke cloud disk pas training. Pakai Benefits Campaign buat cek paket storage yang cocok sama budget eksperimen lo.
Experiment tracking. Setiap ganti prior (Gamma(2, 0.1) vs yang lain), ganti window size, atau ganti library (Stan vs NumPyro), hasilnya harus tercatat biar lo bisa bandingin ELBO/NUTS diagnostics antar run. Kalau belum punya sistem tracking, catat manual di spreadsheet dulu sambil jalan — nanti tinggal migrasi ke tool yang lebih proper kalau udah kebukti dipakai tiap minggu. Kalau butuh penyimpanan ekstra buat artifact run (trace, plot, log), cek paket yang lagi promo di Benefits Campaign.
Monitoring produksi & alerting. Begitu model half-life lo live (Section 16–17), lo perlu tau kapan posterior-nya mulai aneh — divergence, ESS rendah, atau decay parameter melonjak. Dashboard monitoring + alert sederhana udah cukup di tahap awal; yang penting ada notifikasi sebelum signal-nya misbehave, bukan sesudah. Infrastruktur monitoring ringan bisa digabung sama instance ECS yang lagi diskon di Benefits Campaign biar gak nambah biaya tetap.
Container buat reproducibility. Environment PyMC + Stan + Turing.jl gampang bentrok versi. Bungkus tiap eksperimen dalam container biar hasil run kemarin bisa direproduksi bulan depan tanpa drama dependency hell. Managed container service di Benefits Campaign ngebantu banget kalau lo jalanin batch eksperimen paralel.
Database buat fitted parameters. Setelah MCMC selesai, lo nyimpen hasilnya — posterior mean, credible interval, ESS, R-hat — buat dibaca ulang sama decision tree recommend_half_life_method() di Section 21. Database relasional biasa cukup; gak perlu fancy kalau volume-nya masih ribuan baris per bulan.
AI coding buat model code. Nulis model NumPyro/Stan yang bener — prior yang tepat, reparameterization biar gak divergen, likelihood Cox yang efisien — itu butuh iterasi. Pakai AI Scene Coding buat bantu generate skeleton model dari spesifikasi Section 4, terus lo review dan rapikan sendiri. Hemat banget pas lo masih eksplorasi 5–6 varian model dalam sehari.
AI buat debug diagnostics. Output NUTS yang penuh warning divergence atau chain yang gak converge itu nyebelin. Pakai AI Scene Coding buat bantu lo baca error traceback MCMC, saranin reparameterization (misal non-centered), dan kasih opsi prior lain yang lebih stabil. Pasangan yang pas sama workflow Section 13–14 yang lo terapin buat production.
Free tier buat proof-of-concept. Sebelum commit ke infrastruktur berbayar, uji dulu pipeline lo di Alibaba Cloud Free Tier — run satu chain kecil, cek flow data event → posterior → decision tree, baru scale up. Prinsip yang sama kayak walk-forward validation di Section 20: uji kecil dulu, validasi, baru deploy.
Opsi managed tambahan. Kalau konteks workload produksi yang butuh compute di artikel ini mau lo coba tanpa ribet kelola sendiri, ECS 9th-gen g9i Alibaba Cloud nyediain jalur yang bisa lo tes langsung — kuota awalnya cukup buat eksperimen.
Topik Terkait
Artikel lain yang relevan dengan topik AI agent, workflow, dan teknis toolkuy:
- Bayesian Partial Order Ranking Tanpa Asumsi Distribusi: PDP...
- Circular Correlation ρ+ & ρ- (Rivest 2026): Cara...
- HMM Init: Jangan Pakai Random, Pakai Distance-Based (k-means/PAM...
- Information Criterion buat Auto-Detect Seasonality Trading: BIC +...
- Look-Ahead Bias: 5 Tempat Future Data Leak di...
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬