Skip to content

Commit

Permalink
Added McGinley Dynamic, Average True Range, True Range, and On-Balanc…
Browse files Browse the repository at this point in the history
…e Volume.

Changed TEST_DATA into TestData struct.
Added 365 candles test data.
Split up `Line` trait into individual `Period, Value, and Next` traits.
New trait, `AsValue` used to allow for specialized values to be passed to `Next`
Varied Output from `Next` added.
README updates.
  • Loading branch information
Ohkthx committed Sep 9, 2023
1 parent 5936e17 commit f12d99c
Show file tree
Hide file tree
Showing 33 changed files with 1,953 additions and 180 deletions.
21 changes: 20 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "tatk"
license = "MIT"
version = "0.2.1"
version = "0.2.2"
edition = "2021"
description = "Technical Analysis Toolkit"
readme = "README.md"
Expand Down Expand Up @@ -45,3 +45,22 @@ required-features = ["test-data"]
name = "bbands"
path = "examples/bbands.rs"
required-features = ["test-data"]

[[example]]
name = "atr"
path = "examples/atr.rs"
required-features = ["test-data"]

[[example]]
name = "md"
path = "examples/md.rs"
required-features = ["test-data"]

[[example]]
name = "obv"
path = "examples/obv.rs"
required-features = ["test-data"]

[[example]]
name = "traits"
path = "examples/user_traits.rs"
41 changes: 31 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,58 @@ tatk = { git = "https://github.com/ohkthx/tatk-rs" }
- Simple Moving Average (SMA)
- Exponential Moving Average (EMA)
- Double Exponential Moving Average (DEMA)
- McGinley Dynamic Indicator (MD)
- On-Balance Volume (OBV)
- **Oscillators**
- Relative Strength Index (RSI)
- Bollinger Bands (BBands)
- Moving Average Convergence and Divergence (MACD)
- Bollinger Bands (BBands)
- True Range (TR)
- Average True Range (ATR)
- **Others**
- Variance (Var(X))
- Standard Deviation (SD/STDEV)
- Cross, checks two lines for Golden or Death cross.
- Cross (Cross), checks two lines for Golden or Death cross.

## Documentation

Most of the documentation can be accessed by clicking the following link: [docs.rs](https://docs.rs/tatk/latest/tatk/). That documentation is automatically generated and also accessible from [crates.io](https://crates.io/crates/tatk).

### TODO
### Traits

- Add additional indicators and test.
The following traits are either used by the crate on indicators or to be defined by the user for additional functionality.

- **Indicator**
- Stats - Basic statistics for the indicator such as: sum, mean, variance, and standard deviation.
- Period - Period of window of the data for the indicator.
- Value - Current value held by the indicator.
- Next - Add a new data point to the indicator to recalculate value.
- **User Defined**
- AsValue - Alternative value that can be passed to an Indicators `Next`.
- Open - Opening value for the data type.
- Close - Closing value for the data type.
- Low - Lowest value for the data type.
- High - Highest value for the data type.
- Volume - Total volume for the data type.
- **Others**
- HL2 - Average of the Highest and Lowest values, requires `High` and `Low` to be defined.
- HLC3 - Average of the Highest, Lowest, and Close values, requires `High`, `Low`, and `Close` to be defined.
- OHLC4 - Average of the Open, Highest, Lowest, and Close values, requires `Open`, `High`, `Low`, and `Close` to be defined.

## Examples

Following examples can be ran with: `cargo run --example short_id`

- **Simple Moving Average (SMA)**: [sma.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/sma.rs)
- `cargo run --example sma --all-features`
- **Exponential Moving Average (EMA)**: [ema.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/ema.rs)
- `cargo run --example ema --all-features`
- **Double Exponential Moving Average (DEMA)**: [dema.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/dema.rs)
- `cargo run --example dema --all-features`
- **Moving Average Convergence Divergence (MACD)**: [macd.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/macd.rs)
- `cargo run --example macd --all-features`
- **Relative Strength Indicator (RSI)**: [rsi.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/rsi.rs)
- `cargo run --example rsi --all-features`
- **Bollinger Bands (BBands)**: [bbands.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/bbands.rs)
- `cargo run --example bbands --all-features`
- **Average True Range (ATR)**: [atr.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/atr.rs)
- **McGinley Dynamic Indicator (MD)**: [md.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/md.rs)
- **On-Balance Volume (OBV)**: [obv.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/obv.rs)
- **Traits (Traits)**: [user_traits.rs](https://github.com/Ohkthx/tatk-rs/tree/main/examples/user_traits.rs)

## Tips Appreciated!

Expand Down
24 changes: 24 additions & 0 deletions examples/atr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Demonstrates how to initialize and use an ATR.
use tatk::indicators::ATR;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 14;
let candles = TestData::candles();

println!("Data (total): {:?}", candles.len());
println!("Period: {}", period);

// Create the ATR.
let mut atr = match ATR::new(period, &candles[..candles.len() - 2]) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};

// Extract last candle.
let last_candle = candles[candles.len() - 1];

println!("\nATR: {}", atr.value());
println!("Adding last candle. New ATR: {}", atr.next(last_candle));
}
15 changes: 8 additions & 7 deletions examples/bbands.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//! Demonstrates how to initialize and use Bollinger Bands (BB).
use tatk::indicators::{BBands, EMA};
use tatk::test_data::TEST_DATA;
use tatk::traits::Line;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 20;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", TEST_DATA);
println!("Data: {:?}", DATA);
println!("Period: {}", period);

// Use EMA as the line instead of the default SMA.
let ema = match EMA::new(period, TEST_DATA) {
let ema = match EMA::new(period, DATA) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};
Expand All @@ -26,10 +27,10 @@ fn main() {
bbands.lower(),
bbands.upper()
);

let next = bbands.next(107.0);
println!(
"Adding 107.00. New BBands: {}, lower: {}, upper: {}",
bbands.next(107.000000),
bbands.lower(),
bbands.upper()
next.1, next.0, next.2
);
}
11 changes: 6 additions & 5 deletions examples/dema.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
//! Demonstrates how to initialize and use a DEMA.
use tatk::indicators::DEMA;
use tatk::test_data::TEST_DATA;
use tatk::traits::Line;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 10;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", TEST_DATA);
println!("Data: {:?}", DATA);
println!("Period: {}", period);

let mut dema = match DEMA::new(period, TEST_DATA) {
let mut dema = match DEMA::new(period, DATA) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};

println!("\nDEMA: {}", dema.value());
println!("Adding 107.00. New DEMA: {}", dema.next(107.000000));
println!("Adding 107.00. New DEMA: {}", dema.next(107.0));
}
11 changes: 6 additions & 5 deletions examples/ema.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
//! Demonstrates how to initialize and use a EMA.
use tatk::indicators::EMA;
use tatk::test_data::TEST_DATA;
use tatk::traits::Line;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 10;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", TEST_DATA);
println!("Data: {:?}", DATA);
println!("Period: {}", period);

let mut ema = match EMA::new(period, TEST_DATA) {
let mut ema = match EMA::new(period, DATA) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};

println!("\nEMA: {}", ema.value());
println!("Adding 107.00. New EMA: {}", ema.next(107.000000));
println!("Adding 107.00. New EMA: {}", ema.next(107.0));
}
16 changes: 6 additions & 10 deletions examples/macd.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
//! Demonstrates how to initialize and use a MACD.
use tatk::indicators::MACD;
use tatk::test_data::TEST_DATA;
use tatk::traits::Line;

// 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,
// ];
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 10;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", TEST_DATA);
println!("Data: {:?}", DATA);
println!("Period: {}", period);

let mut macd = match MACD::new(12, 26, 9, TEST_DATA) {
let mut macd = match MACD::new(12, 26, 9, 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));
println!("Adding 107.00. New MACD: {}", macd.next(107.0).1);
}
21 changes: 21 additions & 0 deletions examples/md.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Demonstrates how to initialize and use a MD.
use tatk::indicators::MD;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 10;
let k: f64 = 0.6;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", DATA);
println!("Period: {}", period);

let mut md = match MD::new(period, DATA, k) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};

println!("\nMD: {}", md.value());
println!("Adding 107.00. New MD: {}", md.next(107.0));
}
24 changes: 24 additions & 0 deletions examples/obv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Demonstrates how to initialize and use an OBV.
use tatk::indicators::OBV;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 14;
let candles = TestData::candles();

println!("Data (total): {:?}", candles.len());
println!("Period: {}", period);

// Create the OBV.
let mut atr = match OBV::new(period, &candles[..candles.len() - 2]) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};

// Extract last candle.
let last_candle = candles[candles.len() - 1];

println!("\nOBV: {}", atr.value());
println!("Adding last candle. New OBV: {}", atr.next(last_candle));
}
11 changes: 6 additions & 5 deletions examples/rsi.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
//! Demonstrates how to initialize and use a RSI.
use tatk::indicators::RSI;
use tatk::test_data::TEST_DATA;
use tatk::traits::Line;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 14;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", TEST_DATA);
println!("Data: {:?}", DATA);
println!("Period: {}", period);

let mut rsi = match RSI::new(period, TEST_DATA) {
let mut rsi = match RSI::new(period, DATA) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};
Expand All @@ -24,5 +25,5 @@ fn main() {
rsi.is_oversold(),
rsi.is_overbought()
);
println!("Adding 107.00. New RSI: {}", rsi.next(107.000000));
println!("Adding 107.00. New RSI: {}", rsi.next(107.0));
}
11 changes: 6 additions & 5 deletions examples/sma.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
//! Demonstrates how to initialize and use a SMA.
use tatk::indicators::SMA;
use tatk::test_data::TEST_DATA;
use tatk::traits::Line;
use tatk::test_data::TestData;
use tatk::traits::{Next, Value};

fn main() {
let period: usize = 10;
const DATA: &[f64] = TestData::talib();

println!("Data: {:?}", TEST_DATA);
println!("Data: {:?}", DATA);
println!("Period: {}", period);

let mut sma = match SMA::new(period, TEST_DATA) {
let mut sma = match SMA::new(period, DATA) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};

println!("\nSMA: {}", sma.value());
println!("Adding 107.00. New SMA: {}", sma.next(107.000000));
println!("Adding 107.00. New SMA: {}", sma.next(107.0));
}
Loading

0 comments on commit f12d99c

Please sign in to comment.