Skip to content

Commit

Permalink
add historical vol estimators
Browse files Browse the repository at this point in the history
  • Loading branch information
chungfam authored and chungfam committed Jul 9, 2024
1 parent e471d66 commit 0a3caee
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 2 deletions.
16 changes: 14 additions & 2 deletions benches/traquer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ fn criterion_benchmark(c: &mut Criterion) {
b.iter(|| black_box(volume::tvi(&stats.close, &stats.volume, 0.5).collect::<Vec<f64>>()))
});
c.bench_function("sig-volume-vpt", |b| {
b.iter(|| black_box(volume::vpt(&stats.close, &stats.volume, 0.5).collect::<Vec<f64>>()))
b.iter(|| black_box(volume::vpt(&stats.close, &stats.volume).collect::<Vec<f64>>()))
});
c.bench_function("sig-trend-supertrend", |b| {
b.iter(|| {
Expand Down Expand Up @@ -299,7 +299,8 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("sig-momentum-kdj", |b| {
b.iter(|| {
black_box(
momentum::kdj(&stats.high, &stats.low, &stats.close, 16, 3).collect::<Vec<_>>(),
momentum::kdj(&stats.high, &stats.low, &stats.close, 16, 3, None, None)
.collect::<Vec<_>>(),
)
})
});
Expand Down Expand Up @@ -478,6 +479,17 @@ fn criterion_benchmark(c: &mut Criterion) {
black_box(volatility::wcp(&stats.high, &stats.low, &stats.close).collect::<Vec<f64>>())
})
});
c.bench_function("sig-volatility-gkyz_hv", |b| {
b.iter(|| {
black_box(
volatility::gkyz_hv(&stats.open, &stats.high, &stats.low, &stats.close, 16)
.collect::<Vec<_>>(),
)
})
});
c.bench_function("sig-volatility-cc_hv", |b| {
b.iter(|| black_box(volatility::cc_hv(&stats.close, 16).collect::<Vec<_>>()))
});
c.bench_function("ma-ewma", |b| {
b.iter(|| black_box(smooth::ewma(&stats.close, 16).collect::<Vec<f64>>()))
});
Expand Down
79 changes: 79 additions & 0 deletions src/volatility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,3 +752,82 @@ pub fn wcp<'a>(
) -> impl Iterator<Item = f64> + 'a {
izip!(high, low, close).map(|(h, l, c)| (h + l + 2.0 * c) / 4.0)
}

/// Close-to-Close Historical Volatility
///
/// The simplest volatility estimator. Calculated using only stock's closing prices. Value is annualised.
///
/// ## Usage
///
/// Higher value implies increase volatility.
///
/// ## Sources
///
/// [[1]](https://harbourfronts.com/close-close-historical-volatility-calculation-volatility-analysis-python/)
///
/// # Examples
///
/// ```
/// use traquer::volatility;
///
/// volatility::cc_hv(
/// &vec![1.0,2.0,3.0,4.0,5.0,6.0,4.0,5.0],
/// 3).collect::<Vec<f64>>();
///
/// ```
pub fn cc_hv(data: &[f64], window: usize) -> impl Iterator<Item = f64> + '_ {
iter::repeat(f64::NAN).take(window).chain(
data.windows(2)
.map(|w| (w[1] / w[0]).ln().powi(2))
.collect::<Vec<f64>>()
.windows(window)
.map(|w| (w.iter().sum::<f64>() * 252.0 / window as f64).sqrt())
.collect::<Vec<f64>>(),
)
}

/// Garman-Klass-Yang-Zhang Historical Volatility
///
/// Extends Garman-Klass volatility estimator by taking into consideration overnight jumps. Value
/// is annualised.
///
/// ## Usage
///
/// Higher value implies increase volatility.
///
/// ## Sources
///
/// [[1]](https://harbourfronts.com/garman-klass-yang-zhang-historical-volatility-calculation-volatility-analysis-python/)
///
/// # Examples
///
/// ```
/// use traquer::volatility;
///
/// volatility::gkyz_hv(
/// &vec![1.0,2.0,3.0,4.0,5.0,6.0,4.0,5.0],
/// &vec![1.0,2.0,3.0,4.0,5.0,6.0,4.0,5.0],
/// &vec![1.0,2.0,3.0,4.0,5.0,6.0,4.0,5.0],
/// &vec![1.0,2.0,3.0,4.0,5.0,6.0,4.0,5.0],
/// 3).collect::<Vec<f64>>();
///
/// ```
pub fn gkyz_hv<'a>(
open: &'a [f64],
high: &'a [f64],
low: &'a [f64],
close: &'a [f64],
window: usize,
) -> impl Iterator<Item = f64> + 'a {
iter::repeat(f64::NAN).take(window).chain(
izip!(&open[1..], &high[1..], &low[1..], &close[1..], close)
.map(|(o, h, l, c, c0)| {
(o / c0).ln().powi(2) + 0.5 * (h / l).ln().powi(2)
- (2.0 * 2_f64.ln() - 1.0) * (c / o).ln().powi(2)
})
.collect::<Vec<f64>>()
.windows(window)
.map(|w| (w.iter().sum::<f64>() * 252.0 / window as f64).sqrt())
.collect::<Vec<f64>>(),
)
}
61 changes: 61 additions & 0 deletions tests/volatility_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -803,3 +803,64 @@ fn test_wcp() {
result
);
}

#[test]
fn test_cc_hv() {
let stats = common::test_data();
let result = volatility::cc_hv(&stats.close, 16).collect::<Vec<_>>();
assert_eq!(stats.close.len(), result.len());
assert_eq!(
vec![
1.5466252225674613,
1.1600956142944576,
1.1377538069208708,
1.0365183751845641,
0.8333933231891163,
0.7886313354821333,
0.6976132908975086,
0.6413848562022525,
0.6878616751364196,
0.6750178844345274,
0.6835988364394175,
0.6879642217531283,
0.6532534112956555,
0.6202239625971376,
0.6004459227341106,
0.5665520605752907,
0.5773661957866805,
0.5683025268885697
],
result[16..]
);
}

#[test]
fn test_gkyz_hv() {
let stats = common::test_data();
let result = volatility::gkyz_hv(&stats.open, &stats.high, &stats.low, &stats.close, 16)
.collect::<Vec<_>>();
assert_eq!(stats.close.len(), result.len());
assert_eq!(
vec![
1.2449176146400096,
1.1032341200989624,
0.9166361517142042,
0.9043585332042633,
0.8544447166060107,
0.8287797413114523,
0.7613077936213194,
0.744867758696185,
0.7420973336106507,
0.7402566589618695,
0.7225740295183557,
0.7325311315992543,
0.7480130797826274,
0.7207898315110103,
0.7295291396594658,
0.7351330923035614,
0.8608114872074828,
0.8604757592723771
],
result[16..]
);
}

0 comments on commit 0a3caee

Please sign in to comment.