Skip to content

Instantly share code, notes, and snippets.

@al6x
Last active August 5, 2025 06:26
Show Gist options
  • Save al6x/a769abfe18bcef427951e440f49f5d6e to your computer and use it in GitHub Desktop.
Save al6x/a769abfe18bcef427951e440f49f5d6e to your computer and use it in GitHub Desktop.
Overlap Bias
using Random, Distributions, Statistics, DataFrames, Plots
# parameters
Random.seed!(1)
mu = 0.005 # drift per 30d step
sigma = 0.08 # volatility per step
steps = 12 * 45 * 250 # number of 30d steps
S0 = 1.0 # initial price
ν = 3 # degrees of freedom for Student-t (ν > 2)
lps = cumsum(rand(TDist(ν), steps) .* sigma .+ mu)
lrs30 = [lps[i] - lps[i-1] for i in 2:length(lps)]
lrs360o = [lps[i] - lps[i-12] for i in 13:length(lps)]
lrs360 = [lps[i] - lps[i-12] for i in 13:12:length(lps)]
p_tail(x) = begin
tq, n = 0.01, length(x) # tail quantile
nq = floor(Int, n * tq)
x = sort(x)
rtail = x[end-nq+1:end]
rp = reverse((1:length(rtail)) ./ n)
rtail, rp
end
rtailo, rpo = p_tail(lrs360o)
rtail, rp = p_tail(lrs360)
plot(
rtail, rp;
# rtailc, rpc;
xscale = :log10,
yscale = :log10,
label = "Overlapping",
xlabel = "Return (log scale)",
ylabel = "P(X ≥ x) (log scale)",
legend = :topright,
seriestype = :scatter,
markersize = 4,
markerstrokewidth = 0 # ← smaller points
)
plot!(
rtailo, rpo;
label = "Non-overlapping",
seriestype = :scatter,
markersize = 2,
markerstrokewidth = 0 # ← same here
)
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import t
# Parameters
np.random.seed(1)
mu = 0.005
sigma = 0.08
steps = 10 * 12 * 45 * 250 # number of 30d steps
S0 = 1.0
nu = 3 # degrees of freedom for Student-t
# Simulate log-price path from Student-t
lps = np.cumsum(t.rvs(df=nu, size=steps) * sigma + mu)
# Log returns
lrs30 = lps[1:] - lps[:-1] # 30d returns (no overlap)
lrs360o = lps[12:] - lps[:-12] # 360d overlapping
lrs360 = lps[12::12] - lps[:-12:12] # 360d non-overlapping
# Tail extraction function
def p_tail(x, tq=0.01):
x = np.sort(x)
n = len(x)
nq = int(np.floor(n * tq))
rtail = x[-nq:]
rp = np.flip(np.arange(1, nq + 1) / n)
return rtail, rp
# Compute right tails
rtailo, rpo = p_tail(lrs360o) # overlapping
rtail, rp = p_tail(lrs360) # non-overlapping
# Log-log scatter plot
plt.figure(figsize=(7, 5))
plt.scatter(rtail, rp, s=30, color="red", label='Non-overlapping', edgecolors='none') # larger markers
plt.scatter(rtailo, rpo, s=4, label='Overlapping', color="black", edgecolors='none')
plt.xscale('log')
plt.yscale('log')
plt.xlabel("log r (log scale)")
plt.ylabel("P(X ≥ x) (log scale)")
plt.legend(loc='upper right')
plt.grid(True, which='both', linestyle='--', linewidth=0.5)
plt.tight_layout()
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment