波动率算法修改为一段时间内方差的均值,可以使用指数衰减的权重因子为时间序列靠后的数据赋予更高的权重,使当前的波动率受近期影响大于远期影响。塔勒布在《动态对冲》的Chapter-6
Volatility and
Correlation中通过设定证券的收益率序列均值为0,将单日收益率转换为单日的“波动率价格序列”,然后进行滤波平滑处理。
The first advanced volatility estimator was created by Parkinson in
1980, and instead of using closing prices it uses the high and low
price. One drawback of this estimator is that it assumes continuous
trading, hence it underestimates the volatility as potential movements
when the market is shut are ignored.
Later in 1980 the Garman-Klass volatility estimator was created. It
is an extension of Parkinson which includes opening and closing prices
(if opening prices are not available the close from the previous day can
be used instead). As overnight jumps are ignored the measure
underestimates the volatility.
All of the previous advanced volatility measures assume the average
return (or drift) is zero. Securities which have a drift, or non-zero
mean, require a more sophisticated measure of volatility. The
Rogers-Satchell volatility created in the early 1990s is able to
properly measure the volatility for securities with non-zero mean. It
does not, however, handle jumps, hence it underestimates the
volatility.
Yang-Zhang modified the Garman-Klass volatility measure in order to
let it handle jumps. The measure does assume a zero drift, hence it will
overestimate the volatility if a security has a non-zero mean return. As
the effect of drift is small, the fact continuous prices are not
available usually means it underestimates the volatility (but by a
smaller amount than the previous alternative measures).
It is the sum of the overnight volatility (close-to-open volatility)
and a weighted average of the Rogers-Satchell volatility and the
open-to-close volatility. The assumption of continuous prices does mean
the measure tends to slightly underestimate the volatility.
\[
\sigma_{\rm YZ} = \sqrt{F} \sqrt{\sigma^2_{\rm overnight \ volatility} +
\sigma^2_{\rm open \ to \ close \ volatility} + (1-k)\sigma_{RS}^2}
\]
Trending
Markets Imply Weekly Volatility is Greater Than Daily Volatility
With 100% autocorrelation, returns are perfectly correlated (a
positive return is followed by a positive return, i.e. trending
markets). Should autocorrelation be -100% correlated then a positive
return is followed by a negative return (mean reverting or range trading
markets). If we assume markets are 100% daily correlated with a 1% daily
return, this means the weekly return is 5%. The daily volatility is
therefore c16% (1% × \(\sqrt{252}\))
while the weekly volatility of c35% (5% × \(\sqrt{52}\)) is more than twice as
large.
shift = size-1; for idx=size:array_length o = open(idx-shift:idx); h = high(idx-shift:idx); l = low(idx-shift:idx); c = close(idx-shift:idx); hv(idx) = sqrt(sum(log(h ./ c) .* log(h ./ o) + log(l ./ c) .* log(l ./ o)) ./ size) .* factor; end end
shift = size-1; k = 0.34 ./ (1.34 + (size + 1) ./ (size - 1)); for idx=size:array_length o = open(idx-shift:idx); h = high(idx-shift:idx); l = low(idx-shift:idx); c = close(idx-shift:idx); pc = pre_close(idx-shift:idx);
% overnight volatility loc = log(o ./ pc); ov = sum(power(loc - mean(loc), 2)) ./ (size - 1);
% open to close volatility lco = log(c ./ o); oc = sum(power(lco - mean(lco), 2)) ./ (size - 1);
% Rogers-Satchell volatility rs = sum(log(h ./ c) .* log(h ./ o) + log(l ./ c) .* log(l ./ o)) ./ size; hv(idx) = sqrt(ov + k .* oc + (1 - k) .* rs).* factor; end end
// result auto result = py::array_t<double>(buf_close.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
//// calculate function // 方差, var[0] = 0, var[1] = ret[0] auto size = buf_close.size; std::vector<double> var(size, 0.0); double ret = 0.0; for (int i = 1; i < size; i++) { ret = log(ptr_close[i] / ptr_close[i - 1]); var[i] = std::pow(ret, 2); }
// 波动率 for (int i = 0; i < time_period; i++) { ptr_result[i] = 0; }
for (int i = time_period; i < size; i++) { double tv = 0.0; for (int j = i - time_period + 1; j <= i; j++) { tv += var[j]; } ptr_result[i] = sqrt(tv / time_period) * factor; }
// result auto result = py::array_t<double>(buf_close.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
//// calculate function // 方差, var[0] = 0, var[1] = ret[0] auto size = buf_close.size; std::vector<double> var(size, 0.0); double ret = 0.0; for (int i = 1; i < size; i++) { ret = log(ptr_close[i] / ptr_close[i - 1]); var[i] = std::pow(ret, 2); }
// 指数加权 constdouble alpha = 2. / (time_period + 1); constdouble beta = 1. - alpha; double tv = var[0]; for (int i = 1; i < size; i++) { tv = alpha * var[i] + beta * tv; ptr_result[i] = sqrt(tv) * factor; } constint shift = int(log(0.05) / log(beta)); // 波动率 for (int i = 0; i < shift + 1; i++) { ptr_result[i] = 0; }
// 参数转换 py::buffer_info buf_x = close_x.request(); auto *ptr_x = static_cast<double *>(buf_x.ptr); py::buffer_info buf_y = close_y.request(); auto *ptr_y = static_cast<double *>(buf_y.ptr);
// result auto result = py::array_t<double>(buf_x.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
// 参数转换 py::buffer_info buf_x = close_x.request(); auto *ptr_x = static_cast<double *>(buf_x.ptr); py::buffer_info buf_y = close_y.request(); auto *ptr_y = static_cast<double *>(buf_y.ptr);
// result auto result = py::array_t<double>(buf_x.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
// result auto result = py::array_t<double>(buf_high.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
// calculate function auto size = buf_high.size; std::vector<double> var(size, 0.0); constdouble const_num = 0.25 / log(2.); for (int i = 0; i < size; i++) { var[i] = const_num * std::pow(log(ptr_high[i] / ptr_low[i]), 2); }
// 波动率 for (int i = 0; i < time_period; i++) { ptr_result[i] = 0; } for (int i = time_period - 1; i < size; i++) { double tv = 0.0; for (int j = i - time_period + 1; j <= i; j++) { tv += var[j]; } ptr_result[i] = sqrt(tv / time_period) * factor; } return result; }
// result auto result = py::array_t<double>(buf_high.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
// calculate function auto size = buf_high.size; std::vector<double> var(size, 0.0); for (int i = 0; i < size; i++) { double tmp = log(ptr_high[i] / ptr_close[i]) * log(ptr_high[i] / ptr_open[i]) + log(ptr_low[i] / ptr_close[i]) * log(ptr_low[i] / ptr_open[i]); var[i] = nan_to_num(tmp); }
// 波动率 for (int i = 0; i < time_period; i++) { ptr_result[i] = 0; }
for (int i = time_period - 1; i < size; i++) { double tv = 0.0; for (int j = i - time_period + 1; j <= i; j++) { tv += var[j]; } ptr_result[i] = sqrt(tv / time_period) * factor; } return result; }
// result auto result = py::array_t<double>(buf_high.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
// calculate function auto size = buf_high.size; std::vector<double> var(size, 0.0); constdouble const_num = 2. * log(2.) - 1.; for (int i = 0; i < size; i++) { var[i] = 0.5 * std::pow(log(ptr_high[i] / ptr_low[i]), 2) - const_num * std::pow(log(ptr_close[i] / ptr_open[i]), 2); }
// 波动率 for (int i = 0; i < time_period; i++) { ptr_result[i] = 0; }
for (int i = time_period - 1; i < size; i++) { double tv = 0.0; for (int j = i - time_period + 1; j <= i; j++) { tv += var[j]; } ptr_result[i] = sqrt(tv / time_period) * factor; } return result; }
// result auto result = py::array_t<double>(buf_high.size); py::buffer_info buffer_result = result.request(); auto *ptr_result = static_cast<double *>(buffer_result.ptr);
// calculate function auto size = buf_high.size; std::vector<double> var(size, 0.0); constdouble const_num = 2. * log(2.) - 1.; for (int i = 0; i < size; i++) { var[i] = std::pow(log(ptr_open[i] / ptr_pre_close[i]), 2) + 0.5 * std::pow(log(ptr_high[i] / ptr_low[i]), 2) - const_num * std::pow(log(ptr_close[i] / ptr_open[i]), 2); }
// 波动率 for (int i = 0; i < time_period; i++) { ptr_result[i] = 0; }
for (int i = time_period - 1; i < size; i++) { double tv = 0.0; for (int j = i - time_period + 1; j <= i; j++) { tv += var[j]; } ptr_result[i] = sqrt(tv / time_period) * factor; } return result; }