I'm trying to get a better grasp on the suitability of Geometric Brownian Motion as a model for asset prices, and I've stumbled across a hurdle which I can't seem to get over. Assuming GBM, the asset price is given by
$ S_t = S_0 \exp\{ (\mu - \frac{1}{2}\sigma^2)t + \sigma W_t \} $,
which implies that daily log-returns are normally distributed:
$ \log(\frac{S_{t+1}}{S_t}) \sim \mathcal{N}(\mu - \frac{1}{2}\sigma^2, \sigma^2) $.
Now my problem is: how would you go about verifying this with empirical data? If I compute the sample mean of log-returns with real data, then I have to already assume the model in order to extract the drift $ \mu $ by subtracting half the variance. Is there a way to get the drift term directly from the data, without assuming the model? Or is the drift simply a theoretical quantity postulated in the SDE
$ dS_t = S_t (\mu dt + \sigma W_t) $
which defines GBM? I.e. does the drift correspond to any computable statistical quantity?
EDIT: here is my attempt to gain clarity by simulation:
T = 1
N = 1000
S0 = 1
mu = -0.00028117*252
sigma = 0.008723*252
seed = 1
f, g = f_g_black_scholes(lamda = mu, mu = sigma)
numpaths = 10000
paths = pd.DataFrame()
for k in range(1, numpaths):
t, S, W = euler_maruyama(seed=seed+k, X0=X0, T=T, N=N, f=f, g=g)
S = pd.DataFrame(S)
paths = pd.concat([paths, S], axis = 1)
final_price = paths.iloc[-1, :]
sigma_sim = np.std(np.log(final_price))
mu_sim = np.mean(np.log(final_price)) + 0.5*sigma_sim**2
The drift and volatility I estimated from S&P 500 data, and I made use of this implementation of the Euler-Maruyama solver to numerically generate sample paths. The results I obtain are:
mu = -0.070855
mu_sim = -0.010407
sigma = 2.198196
sigma_sim = 2.221657
As you can see there is still a significant discrepancy between the input drift and the result of the simulation. How should I make sense of this?