-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ability to check if or to EMAs in comparison to SMA.
Renamed project from sigta-rs to tatk-rs. Added MACD indicator.
- Loading branch information
Showing
11 changed files
with
254 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//! Demonstrates how to initialize and use a MACD. | ||
use tatk::indicators::MACD; | ||
use tatk::test_data::TEST_DATA; | ||
|
||
// const TEST_DATA: &[f64] = &[ | ||
// 11.13, 11.3, 11.59, 11.71, 11.8, 11.8, 12.07, 12.14, 12.04, 12.02, 12.34, 12.61, 12.59, 12.66, | ||
// 12.82, 12.93, 12.79, 12.21, | ||
// ]; | ||
|
||
fn main() { | ||
let period: usize = 10; | ||
|
||
println!("Data: {:?}", TEST_DATA); | ||
println!("Period: {}", period); | ||
|
||
let mut macd = match MACD::new(12, 26, 9, TEST_DATA) { | ||
Ok(value) => value, | ||
Err(error) => panic!("{}", error), | ||
}; | ||
|
||
println!("\nMACD: {}, signal: {}", macd.value(), macd.signal_value()); | ||
println!("Adding 107.00. New MACD: {}", macd.next(107.000000)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
//! Moving Average Convergence and Divergence (MACD) | ||
//! | ||
//! # Formula | ||
//! | ||
//! MACD = SHORT_EMA - LONG_EMA | ||
//! | ||
//! MACD = x - y | ||
//! | ||
//! where: | ||
//! | ||
//! * `x` = Short EMA of period `n` | ||
//! * `y` = Long EMA of period `n` | ||
use super::EMA; | ||
use crate::error::TAError; | ||
|
||
/// Moving Average Convergence and Divergence (MACD) | ||
/// | ||
/// # Formula | ||
/// | ||
/// MACD = SHORT_EMA - LONG_EMA | ||
/// | ||
/// MACD = x - y | ||
/// | ||
/// where: | ||
/// | ||
/// * `x` = Short EMA of period `n` | ||
/// * `y` = Long EMA of period `n` | ||
#[derive(Debug)] | ||
pub struct MACD { | ||
/// MACD's current value. | ||
value: f64, | ||
/// Short EMA | ||
ema_short: EMA, | ||
/// Long EMA | ||
ema_long: EMA, | ||
/// Signal Line, EMA of MACD values. | ||
ema_signal: EMA, | ||
/// If the MACD crossed the signal. | ||
crossed: bool, | ||
} | ||
|
||
impl MACD { | ||
/// Creates a new MACD with the supplied period and initial data. Often the short line is | ||
/// period of 12, long is a period of 26, and signal is period of 9. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `short` - Period of the short EMA. | ||
/// * `long` - Period of the long EMA. | ||
/// * `signal` - Period of the signal EMA. | ||
/// * `data` - Array of values to create the MACD from. | ||
pub fn new(short: usize, long: usize, signal: usize, data: &[f64]) -> Result<Self, TAError> { | ||
if short > long { | ||
return Err(TAError::InvalidLine("long".to_string())); | ||
} else if data.len() < short { | ||
return Err(TAError::InvalidLine("data".to_string())); | ||
} else if data.len() < signal { | ||
return Err(TAError::InvalidLine("data".to_string())); | ||
} | ||
|
||
// Build short EMA up to the long. | ||
let mut ema_short = match EMA::new(short, &data[..long]) { | ||
Ok(value) => value, | ||
Err(error) => return Err(error), | ||
}; | ||
|
||
// Build long EMA. | ||
let mut ema_long = match EMA::new(long, &data[..long]) { | ||
Ok(value) => value, | ||
Err(error) => return Err(error), | ||
}; | ||
|
||
// Add the first value. | ||
let mut signals: Vec<f64> = vec![ema_short.value() - ema_long.value()]; | ||
|
||
// Process the remainder of the data, building a signal line. | ||
for n in long..data.len() { | ||
let short_value = ema_short.next(data[n].clone()); | ||
let long_value = ema_long.next(data[n].clone()); | ||
|
||
signals.push(short_value - long_value); | ||
} | ||
|
||
// Build signal EMA of MACDs. | ||
let ema_signal = match EMA::new(signal, &signals) { | ||
Ok(value) => value, | ||
Err(error) => return Err(error), | ||
}; | ||
|
||
Ok(Self { | ||
value: ema_short.value() - ema_long.value(), | ||
ema_short, | ||
ema_long, | ||
ema_signal, | ||
crossed: false, | ||
}) | ||
} | ||
|
||
/// Current and most recent value calculated. | ||
pub fn value(&self) -> f64 { | ||
self.value | ||
} | ||
|
||
/// Current and most recent signal value calculated. | ||
pub fn signal_value(&self) -> f64 { | ||
self.ema_signal.value() | ||
} | ||
|
||
/// Check if the value crossed the signal. | ||
pub fn crossed(&self) -> bool { | ||
self.crossed | ||
} | ||
|
||
/// Returns true if the value is above the signal. | ||
pub fn is_above(&self) -> bool { | ||
self.value > self.signal_value() | ||
} | ||
|
||
/// Returns true if the value is below the signal. | ||
pub fn is_below(&self) -> bool { | ||
self.value < self.signal_value() | ||
} | ||
|
||
/// Supply an additional value to recalculate a new MACD. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `value` - New value to add to period. | ||
pub fn next(&mut self, value: f64) -> f64 { | ||
let was_below: bool = self.is_below(); | ||
|
||
let short_value = self.ema_short.next(value); | ||
let long_value = self.ema_long.next(value); | ||
|
||
// Calculate the new MACD and signal. | ||
self.value = short_value - long_value; | ||
self.ema_signal.next(self.value); | ||
|
||
// Update if it crossed the signal or not. | ||
if was_below && self.is_below() { | ||
self.crossed = false; | ||
} else if !was_below && self.is_above() { | ||
self.crossed = false; | ||
} else { | ||
self.crossed = true; | ||
} | ||
|
||
self.value | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
//! Indicators generated from samples used for signals. | ||
mod dema; | ||
mod ema; | ||
mod macd; | ||
mod sma; | ||
|
||
pub use dema::DEMA; | ||
pub use ema::EMA; | ||
pub use macd::MACD; | ||
pub use sma::SMA; |
Oops, something went wrong.