I was trying to be funny. Today is Thanksgiving.
fail - lol
I was trying to be funny. Today is Thanksgiving.
Got them in this order:
- Mean Reversion Trading Systems
- Quantitative Trading Systems
- Modelling Trading System Performance
On stationarity, firstly what works is to transform your prices in some way to make them stationary. I risk adjust everything, which makes everything a lot more stationary, and means you can fit things across regimes and pool data across instruments. It also means that non Gaussian price distributions become very closer to Gaussian.
Secondly, for stationarity in the sense of 'does this model work across different regimes / time periods' or do I need to keep (over)fitting it for more recent data? Clearly it depends on the strategy. For slower systems and lower SR systems like I use, the source of profitability seems to be fairly consistent and it's appropriate to use as much data as possible. Some people have used hundreds of years of data to test trend following. A HFT firm will use a few months of data, tops. Everyone else is somewhere in the middle.
GAT
AKA Robert Carver
You can't change the distribution by just normalizing data. Risk adjusting hence also does not change the distribution of data. That is quite basic statistical knowledge.
You can confirm the above in the following papers. But there are tons others out there. You can shift the mean by transforming variables but most statistical moments remain anchored to the underlying distribution.
2016, “Improved Shape Parameter Estimation in K Clutter with Neural Networks and Deep Learning”. International Journal of Interactive Multimedia and Artificial Intelligence, Vol. 3, No. 7, pp. 3-13.
2015, “A Neural Network Approach to Weibull Distributed Sea Clutter Parameter’s Estimation”. Revista Iberoamericana de Inteligencia Artificial, Vol. 18, No. 56, pp. 3-13.
2015, “Estimation of the Relation between Weibull Distributed Sea Clutter and the CA-CFAR Scale Factor”. Journal of Tropical Engineering, Vol. 25, No. 2, pp. 19-28.
PS. I am not the author of above papers
Hmm, I have to disagree with you there. I think you are conflating the non-normal nature of the distribution with stochastic/uncertain volatility. You can rescale the returns by the expected volatility (e.g. I rescale returns by the ATM implied vol for some studies) and that does create a historically-consistent set of returns. However, the resulting distribution will still be fat-tailed and skewed.Consider Gaussian returns with mean zero over 10 years. In the first 5 years the standard deviation is 20%. Then it falls to 10%. The resulting total distribution will be fat tailed, with a standard deviation of 15%.
Now divide all returns by a standard deviation estimate from the last 30 days. The resulting distribution will be almost perfectly Gaussian, apart from the 30 day adjustment period which will produce a few returns that are a little too small.
Hmm, I have to disagree with you there. I think you are conflating the non-normal nature of the distribution with stochastic/uncertain volatility. You can rescale the returns by the expected volatility (e.g. I rescale returns by the ATM implied vol for some studies) and that does create a historically-consistent set of returns. However, the resulting distribution will still be fat-tailed and skewed.
Here is a quick example. Taking returns of SP500 since 1990 and rescaling by VIX (which is a superior predictor of realized volatility) produces the following Q-Q plot:This also works quite well with real financial data.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.graphics.gofplots import qqplot
from scipy.stats import shapiro
from scipy.stats import normaltest
def dtidx(x):
idx = pd.DatetimeIndex(pd.to_datetime(x))
return idx.tz_localize('UTC').tz_convert('US/Eastern')
def read_yahoo(name):
o = pd.read_csv(name + '.csv')
o['Date'] = dtidx(o['Date'])
o.set_index('Date', inplace=True)
o['Return'] = np.log(o['Adj Close']/o['Adj Close'].shift()).fillna(0)
return o
vix = read_yahoo('VIX')
spx = read_yahoo('SPX')
df = pd.DataFrame({'r':spx['Return'],'v':vix['Close'].shift()/1600})
df['q'] = df['r']/df['v']
qqplot(df['q'].dropna(), line='s')
plt.show()
stat_s, p_s = shapiro(df['q'].dropna())
print('Shapiro=%.3f, p=%.3f' % (stat_s, p_s))
stat_d, p_d = normaltest(df['q'].dropna())
print('D’Agostino’s K^2=%.3f, p=%.3f' % (stat_d, p_d))

Here is a quick example. Taking returns of SP500 since 1990 and rescaling by VIX (which is a superior predictor of realized volatility) produces the following Q-Q plot:View attachment 245685
here's python code for those who cares:
Code:import pandas as pd import numpy as np import matplotlib.pyplot as plt from statsmodels.graphics.gofplots import qqplot from scipy.stats import shapiro from scipy.stats import normaltest def dtidx(x): idx = pd.DatetimeIndex(pd.to_datetime(x)) return idx.tz_localize('UTC').tz_convert('US/Eastern') def read_yahoo(name): o = pd.read_csv(name + '.csv') o['Date'] = dtidx(o['Date']) o.set_index('Date', inplace=True) o['Return'] = np.log(o['Adj Close']/o['Adj Close'].shift()).fillna(0) return o vix = read_yahoo('VIX') spx = read_yahoo('SPX') df = pd.DataFrame({'r':spx['Return'],'v':vix['Close'].shift()/1600}) df['q'] = df['r']/df['v'] qqplot(df['q'].dropna(), line='s') plt.show() stat_s, p_s = shapiro(df['q'].dropna()) print('Shapiro=%.3f, p=%.3f' % (stat_s, p_s)) stat_d, p_d = normaltest(df['q'].dropna()) print('D’Agostino’s K^2=%.3f, p=%.3f' % (stat_d, p_d))