From a4c4e98faf7f27d1d6ba13892e5fda6bbcdc46ec Mon Sep 17 00:00:00 2001 From: Victor Dudochkin Date: Mon, 12 Apr 2021 11:20:52 +0700 Subject: [PATCH 1/4] Codecov and other changes --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/codecov.yml | 9 +++++ .github/workflows/audit.yaml | 17 ++++++++ .github/workflows/coverage.yaml | 49 +++++++++++++++++++++++ .github/workflows/tests.yml | 27 +++++++++++++ README.md | 20 +++++---- 7 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 .github/codecov.yml create mode 100644 .github/workflows/audit.yaml create mode 100644 .github/workflows/coverage.yaml create mode 100644 .github/workflows/tests.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index af039b6..d0c94b6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -15,4 +15,4 @@ It would be nice to have screenshot or result image uploaded Some minimal reproduce code is highly recommended **Version Information** -Please give us what version you are using. If you are pulling `Plotters` directly from git repo, please mention this as well +Please give us what version you are using. If you are pulling `UX Indicators` directly from git repo, please mention this as well diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index cbf5a68..54e6204 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,6 @@ --- name: Feature request -about: Suggest an idea to Plotter maintainers +about: Suggest an idea to UX Indicators maintainers title: "[Feature Request]" labels: feature request assignees: '' diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 0000000..f2cf6e4 --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,9 @@ +comment: + layout: "diff, flags, files" + require_changes: true + +coverage: + status: + project: + default: + informational: true diff --git a/.github/workflows/audit.yaml b/.github/workflows/audit.yaml new file mode 100644 index 0000000..e0c79d5 --- /dev/null +++ b/.github/workflows/audit.yaml @@ -0,0 +1,17 @@ +name: Security audit +on: + pull_request: + push: + branches: + - master + schedule: + - cron: '0 0 * * 0' + +jobs: + security_audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml new file mode 100644 index 0000000..340704c --- /dev/null +++ b/.github/workflows/coverage.yaml @@ -0,0 +1,49 @@ +name: Test coverage + +#on: +# push: +# branches: +# - main +# pull_request: + +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: full + +jobs: + coverage: + name: Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + profile: minimal + default: true + + - name: Restore cache + uses: Swatinem/rust-cache@v1 + + - name: Run cargo-tarpaulin + uses: actions-rs/tarpaulin@v0.1 + with: + args: '--all-features --run-types Doctests,Tests' + timeout: 120 + + - name: Upload to codecov.io + uses: codecov/codecov-action@239febf655bba88b16ff5dea1d3135ea8663a1f9 + with: + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Archive code coverage results + uses: actions/upload-artifact@v2 + with: + name: code-coverage-report + path: cobertura.xml + retention-days: 30 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..6893c69 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,27 @@ +name: Tests + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose + + clippy_check: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - run: rustup component add clippy + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-features diff --git a/README.md b/README.md index 0b9a625..303aa88 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ -# UX Indicators -
+[![](https://dudochkin-victor.github.io/assets/ux-indicators/logo-wide.svg)](#top) +# UX Indicators + [![API Docs][docrs-badge]][docrs-url] [![Crates.io][crates-badge]][crates-url] +[![Code coverage][codecov-badge]][codecov-url] +[![Tests][tests-badge]][tests-url] [![MPL-2.0 licensed][license-badge]][license-url] [![Gitter chat][gitter-badge]][gitter-url] -[![Rustc Version 1.45+][rust-badge]][rust-url] [![loc][loc-badge]][loc-url]
@@ -16,11 +18,13 @@ [crates-url]: https://crates.io/crates/ux-indicators [license-badge]: https://img.shields.io/badge/license-MPL--2.0-blue.svg?style=flat-square [license-url]: https://github.com/angular-rust/ux-indicators/blob/master/LICENSE -[gitter-badge]: https://img.shields.io/gitter/room/angular_rust/angular_rust.svg?style=flat-square +[gitter-badge]: https://img.shields.io/gitter/room/angular_rust/community.svg?style=flat-square [gitter-url]: https://gitter.im/angular_rust/community -[rust-badge]: https://img.shields.io/badge/rustc-1.45-lightgrey.svg?style=flat-square -[rust-url]: https://blog.rust-lang.org/2020/07/16/Rust-1.45.0.html -[loc-badge]: https://tokei.rs/b1/github/angular-rust/ux-indicators?category=code +[tests-badge]: https://img.shields.io/github/workflow/status/angular-rust/ux-indicators/tests?label=tests&logo=github&style=flat-square +[tests-url]: https://github.com/angular-rust/ux-indicators/actions/workflows/tests.yml +[codecov-badge]: https://img.shields.io/codecov/c/github/angular-rust/ux-indicators?logo=codecov&style=flat-square&token=M517IMMA0L +[codecov-url]: https://codecov.io/gh/angular-rust/ux-indicators +[loc-badge]: https://img.shields.io/tokei/lines/github/angular-rust/ux-indicators?style=flat-square [loc-url]: https://github.com/angular-rust/ux-indicators ux-indicators is a Centralized State Management And Design Patterns for Rust. @@ -58,7 +62,7 @@ Install UX Indicators: We believe the wider community can create better code. The first tool for improving the community is to tell the developers about the project by giving it a star. More stars - more members. - ![Star a repo](https://dudochkin-victor.github.io/assets/star-me-wide.svg) + [![](https://dudochkin-victor.github.io/assets/star-me-wide.svg)](https://github.com/angular-rust/ux-indicators#top) Angular Rust is a community effort and we welcome all kinds of contributions, big or small, from developers of all backgrounds. We want the Angular Rust community to be a fun and friendly place, so please review our [Code of Conduct](CODE_OF_CONDUCT.md) to learn what behavior will not be tolerated. From 23be03448864689bf65c4a8162dc109e45c56d95 Mon Sep 17 00:00:00 2001 From: Victor Dudochkin Date: Mon, 12 Apr 2021 17:47:19 +0700 Subject: [PATCH 2/4] Test workflow --- .github/workflows/coverage.yaml | 2 +- Cargo.toml | 10 +-- README.md | 2 +- benches/{indicators.rs.md => indicators.md} | 0 examples/ema.rs | 8 +- src/data_item.rs | 46 ++++++----- src/indicator.rs | 61 ++++++-------- src/indicators/atr.rs | 71 ++++++++-------- src/indicators/bbands.rs | 58 ++++++------- src/indicators/ema.rs | 44 +++++----- src/indicators/fsto.rs | 38 ++++----- src/indicators/ker.rs | 40 ++++----- src/indicators/macd.rs | 54 ++++++------ src/indicators/max.rs | 38 ++++----- src/indicators/mfi.rs | 55 ++++++------- src/indicators/min.rs | 36 ++++---- src/indicators/mod.rs | 2 +- src/indicators/obv.rs | 75 +++++++++-------- src/indicators/roc.rs | 46 +++++------ src/indicators/rsi.rs | 46 +++++------ src/indicators/sd.rs | 40 ++++----- src/indicators/sma.rs | 43 +++++----- src/indicators/ssto.rs | 36 ++++---- src/indicators/tr.rs | 70 ++++++++-------- src/indicators/wma.rs | 61 ++++++++------ src/lib.rs | 91 ++++++++++++--------- src/main.rs | 6 +- src/test_helper.rs | 8 +- src/traits.rs | 4 +- src/utils.rs | 2 +- tests/test.rs | 2 +- 31 files changed, 551 insertions(+), 544 deletions(-) rename benches/{indicators.rs.md => indicators.md} (100%) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 340704c..b9cf34a 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -1,4 +1,4 @@ -name: Test coverage +name: Coverage #on: # push: diff --git a/Cargo.toml b/Cargo.toml index 31007c9..2362a1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ maintenance = { status = "actively-developed" } name = "indicators" [dependencies] -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_derive = "1.0" lazy_static = "1.4" @@ -43,7 +43,7 @@ cucumber_rust = "0.6" # cucumber = "0.3.1" -[[bench]] -name = "indicators" -path = "benches/indicators.rs" -harness = false \ No newline at end of file +# [[bench]] +# name = "indicators" +# path = "benches/indicators.rs" +# harness = false \ No newline at end of file diff --git a/README.md b/README.md index 303aa88..a40ee40 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ [license-url]: https://github.com/angular-rust/ux-indicators/blob/master/LICENSE [gitter-badge]: https://img.shields.io/gitter/room/angular_rust/community.svg?style=flat-square [gitter-url]: https://gitter.im/angular_rust/community -[tests-badge]: https://img.shields.io/github/workflow/status/angular-rust/ux-indicators/tests?label=tests&logo=github&style=flat-square +[tests-badge]: https://img.shields.io/github/workflow/status/angular-rust/ux-indicators/Tests?label=tests&logo=github&style=flat-square [tests-url]: https://github.com/angular-rust/ux-indicators/actions/workflows/tests.yml [codecov-badge]: https://img.shields.io/codecov/c/github/angular-rust/ux-indicators?logo=codecov&style=flat-square&token=M517IMMA0L [codecov-url]: https://codecov.io/gh/angular-rust/ux-indicators diff --git a/benches/indicators.rs.md b/benches/indicators.md similarity index 100% rename from benches/indicators.rs.md rename to benches/indicators.md diff --git a/examples/ema.rs b/examples/ema.rs index 0ac9bf4..623e6fa 100644 --- a/examples/ema.rs +++ b/examples/ema.rs @@ -1,11 +1,7 @@ -extern crate csv; extern crate core; +extern crate csv; -use indicators::{ - indicators::ExponentialMovingAverage as Ema, - DataItem, - Next -}; +use indicators::{indicators::ExponentialMovingAverage as Ema, DataItem, Next}; fn main() { let mut ema = Ema::new(9).unwrap(); diff --git a/src/data_item.rs b/src/data_item.rs index b48c07d..1305173 100644 --- a/src/data_item.rs +++ b/src/data_item.rs @@ -5,28 +5,30 @@ use crate::traits::{Close, High, Low, Open, Volume}; /// Data item is used as an input for indicators. /// -/// # Example -/// -/// ``` -/// use core::DataItem; -/// use core::{Open, High, Low, Close, Volume}; -/// -/// let item = DataItem::builder() -/// .open(20.0) -/// .high(25.0) -/// .low(15.0) -/// .close(21.0) -/// .volume(7500.0) -/// .build() -/// .unwrap(); -/// -/// assert_eq!(item.open(), 20.0); -/// assert_eq!(item.high(), 25.0); -/// assert_eq!(item.low(), 15.0); -/// assert_eq!(item.close(), 21.0); -/// assert_eq!(item.volume(), 7500.0); -/// ``` -/// + +// # Example +// +// ``` +// use core::DataItem; +// use core::{Open, High, Low, Close, Volume}; +// +// let item = DataItem::builder() +// .open(20.0) +// .high(25.0) +// .low(15.0) +// .close(21.0) +// .volume(7500.0) +// .build() +// .unwrap(); +// +// assert_eq!(item.open(), 20.0); +// assert_eq!(item.high(), 25.0); +// assert_eq!(item.low(), 15.0); +// assert_eq!(item.close(), 21.0); +// assert_eq!(item.volume(), 7500.0); +// ``` +// + #[derive(Debug, Clone)] pub struct DataItem { open: f64, diff --git a/src/indicator.rs b/src/indicator.rs index 6c4cdbf..7fab50a 100644 --- a/src/indicator.rs +++ b/src/indicator.rs @@ -3,13 +3,13 @@ #![allow(unused_imports)] use crate::indicators::SimpleMovingAverage; -use crate::{Next}; +use crate::Next; -use std::collections::VecDeque; +use crate::errors::Error; +use std::cell::RefCell; use std::collections::HashMap; +use std::collections::VecDeque; use std::rc::Rc; -use std::cell::RefCell; -use crate::errors::Error; #[derive(Debug, Clone)] pub enum DataPoint { @@ -93,9 +93,9 @@ pub enum SlotType { pub struct Slot { pub name: String, slot_type: SlotType, - state: f64, // used to store value when it input type - pub changed: bool, // when it input type, - connected: bool, // when in input type, + state: f64, // used to store value when it input type + pub changed: bool, // when it input type, + connected: bool, // when in input type, connections: Vec>>, // used to keep references when it output type } @@ -103,7 +103,7 @@ impl Slot { pub fn new(slot_type: SlotType) -> Self { Self { name: String::from("slot"), - slot_type: slot_type, + slot_type, state: 0.0, changed: false, connected: false, @@ -113,7 +113,7 @@ impl Slot { // output is multiple, input is single pub fn connect(&mut self, wire: Rc>) -> Result<(), Error> { if self.slot_type == SlotType::Output { - return Ok(()) + return Ok(()); } // self.wire = Some(wire) Err("The error message".into()) @@ -131,7 +131,7 @@ impl Slot { self.state = val; } - // fetch data from buffer + // fetch data from buffer pub fn get(&mut self) -> f64 { self.changed = false; self.state @@ -156,9 +156,7 @@ impl Indicator { pub fn slot(&self, name: &str) -> Option>> { None } - pub fn stuff(&self) { - - } + pub fn stuff(&self) {} } #[derive(Debug, Clone)] @@ -178,7 +176,7 @@ pub struct Input { impl Input { pub fn new(input_type: InputType) -> Self { Self { - input_type: input_type, + input_type, slots: vec![], timeseries: VecDeque::new(), } @@ -192,10 +190,10 @@ impl Input { DataPoint::Ohlcv(_) => { // let a: Ohlcv = val; self.timeseries.push_back(item); - }, + } _ => { print!("unhandled node type") - }, + } } } } @@ -207,12 +205,10 @@ pub struct View { impl View { pub fn new() -> Self { - Self { - plots: vec![], - } + Self { plots: vec![] } } - pub fn attach(&mut self, plot: Rc){ + pub fn attach(&mut self, plot: Rc) { self.plots.push(plot); } } @@ -231,9 +227,7 @@ impl Plot { } } // draw to view - pub fn draw(&self){ - - } + pub fn draw(&self) {} pub fn slot(&self, name: &str) -> Option>> { None @@ -263,11 +257,11 @@ pub fn example() { // input -> indicator let input_close = input.slot("close").unwrap(); let mut input_close = input_close.borrow_mut(); - { + { let indicator_close = indicator.slot("close").unwrap(); let _ = input_close.connect(Rc::clone(&indicator_close)); } - + // // indicator -> plot let indicator_output = indicator.slot("output").unwrap(); let mut indicator_output = indicator_output.borrow_mut(); @@ -275,16 +269,15 @@ pub fn example() { let plot_close = plot.slot("close").unwrap(); let _ = indicator_output.connect(Rc::clone(&plot_close)); } - let rcplot = Rc::new(plot); // put plot into view view.attach(Rc::clone(&rcplot)); - + let a: &Plot = rcplot.as_ref(); a.draw(); - input.push(DataPoint::Ohlcv(Ohlcv{ + input.push(DataPoint::Ohlcv(Ohlcv { timestamp: 1, open: 0.1, high: 0.1, @@ -305,18 +298,18 @@ pub fn example() { match item { Node::View(val) => { let a: &View = val; - }, + } Node::Plot(val) => { let a: &Plot = val; - }, + } Node::Text(val) => { let a: String = val.to_string(); - }, + } _ => { print!("unhandled node type") - }, + } } - } + } } // pub struct Inticator { @@ -343,4 +336,4 @@ pub fn example() { // pub fn get_contents(&self) -> u32 { // 0 // } -// } \ No newline at end of file +// } diff --git a/src/indicators/atr.rs b/src/indicators/atr.rs index b920bcb..da7b464 100644 --- a/src/indicators/atr.rs +++ b/src/indicators/atr.rs @@ -6,15 +6,14 @@ use crate::errors::*; use crate::indicators::{ExponentialMovingAverage, TrueRange}; use crate::{Close, High, Low, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct AtrFactory { -} +pub struct AtrFactory {} impl AtrFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -24,7 +23,6 @@ impl Factory for AtrFactory { } } - /// Average true range (ATR). /// /// A technical analysis volatility indicator, originally developed by J. Welles Wilder. @@ -43,37 +41,38 @@ impl Factory for AtrFactory { /// # Parameters /// /// * _length_ - smoothing period of EMA (integer greater than 0) -/// -/// # Example -/// -/// ``` -/// extern crate core; -/// #[macro_use] extern crate assert_approx_eq; -/// -/// use core::{Next, DataItem}; -/// use core::indicators::AverageTrueRange; -/// -/// fn main() { -/// let data = vec![ -/// // open, high, low, close, atr -/// (9.7 , 10.0, 9.0, 9.5 , 1.0), // tr = high - low = 10.0 - 9.0 = 1.0 -/// (9.9 , 10.4, 9.8, 10.2 , 0.95), // tr = high - prev_close = 10.4 - 9.5 = 0.9 -/// (10.1 , 10.7, 9.4, 9.7 , 1.125), // tr = high - low = 10.7 - 9.4 = 1.3 -/// (9.1 , 9.2 , 8.1, 8.4 , 1.3625), // tr = prev_close - low = 9.7 - 8.1 = 1.6 -/// ]; -/// let mut indicator = AverageTrueRange::new(3).unwrap(); -/// -/// for (open, high, low, close, atr) in data { -/// let di = DataItem::builder() -/// .high(high) -/// .low(low) -/// .close(close) -/// .open(open) -/// .volume(1000.0) -/// .build().unwrap(); -/// assert_approx_eq!(indicator.next(&di), atr); -/// } -/// } + +// +// # Example +// +// ``` +// extern crate core; +// #[macro_use] extern crate assert_approx_eq; +// +// use core::{Next, DataItem}; +// use core::indicators::AverageTrueRange; +// +// fn main() { +// let data = vec![ +// // open, high, low, close, atr +// (9.7 , 10.0, 9.0, 9.5 , 1.0), // tr = high - low = 10.0 - 9.0 = 1.0 +// (9.9 , 10.4, 9.8, 10.2 , 0.95), // tr = high - prev_close = 10.4 - 9.5 = 0.9 +// (10.1 , 10.7, 9.4, 9.7 , 1.125), // tr = high - low = 10.7 - 9.4 = 1.3 +// (9.1 , 9.2 , 8.1, 8.4 , 1.3625), // tr = prev_close - low = 9.7 - 8.1 = 1.6 +// ]; +// let mut indicator = AverageTrueRange::new(3).unwrap(); +// +// for (open, high, low, close, atr) in data { +// let di = DataItem::builder() +// .high(high) +// .low(low) +// .close(close) +// .open(open) +// .volume(1000.0) +// .build().unwrap(); +// assert_approx_eq!(indicator.next(&di), atr); +// } +// } #[derive(Debug, Clone)] pub struct AverageTrueRange { diff --git a/src/indicators/bbands.rs b/src/indicators/bbands.rs index 56e73dd..f3915b4 100644 --- a/src/indicators/bbands.rs +++ b/src/indicators/bbands.rs @@ -6,15 +6,14 @@ use crate::errors::*; use crate::indicators::StandardDeviation as Sd; use crate::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct BBandsFactory { -} +pub struct BBandsFactory {} impl BBandsFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -38,31 +37,32 @@ impl Factory for BBandsFactory { /// * _BBMiddle Band_ - Simple Moving Average (SMA). /// * _BBUpper Band_ = SMA + SD of observation * multipler (usually 2.0) /// * _BBLower Band_ = SMA - SD of observation * multipler (usually 2.0) -/// -/// # Example -/// -///``` -/// use core::indicators::{BollingerBands, BollingerBandsOutput}; -/// use core::Next; -/// -/// let mut bb = BollingerBands::new(3, 2.0_f64).unwrap(); -/// -/// let out_0 = bb.next(2.0); -/// -/// let out_1 = bb.next(5.0); -/// -/// assert_eq!(out_0.average, 2.0); -/// assert_eq!(out_0.upper, 2.0); -/// assert_eq!(out_0.lower, 2.0); -/// -/// assert_eq!(out_1.average, 3.5); -/// assert_eq!(out_1.upper, 6.5); -/// assert_eq!(out_1.lower, 0.5); -/// ``` -/// -/// # Links -/// -/// ![Bollinger Bands, Wikipedia](https://en.wikipedia.org/wiki/Bollinger_Bands) + +// +// # Example +// +//``` +// use core::indicators::{BollingerBands, BollingerBandsOutput}; +// use core::Next; +// +// let mut bb = BollingerBands::new(3, 2.0_f64).unwrap(); +// +// let out_0 = bb.next(2.0); +// +// let out_1 = bb.next(5.0); +// +// assert_eq!(out_0.average, 2.0); +// assert_eq!(out_0.upper, 2.0); +// assert_eq!(out_0.lower, 2.0); +// +// assert_eq!(out_1.average, 3.5); +// assert_eq!(out_1.upper, 6.5); +// assert_eq!(out_1.lower, 0.5); +// ``` +// +// # Links +// +// ![Bollinger Bands, Wikipedia](https://en.wikipedia.org/wiki/Bollinger_Bands) #[derive(Debug, Clone)] pub struct BollingerBands { diff --git a/src/indicators/ema.rs b/src/indicators/ema.rs index 21424cd..62cb218 100644 --- a/src/indicators/ema.rs +++ b/src/indicators/ema.rs @@ -5,15 +5,14 @@ use std::fmt; use crate::errors::*; use crate::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct EmaFactory { -} +pub struct EmaFactory {} impl EmaFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -51,24 +50,25 @@ impl Factory for EmaFactory { /// # Parameters /// /// * _length_ - number of periods (integer greater than 0) -/// -/// # Example -/// -/// ``` -/// use core::indicators::ExponentialMovingAverage; -/// use core::Next; -/// -/// let mut ema = ExponentialMovingAverage::new(3).unwrap(); -/// assert_eq!(ema.next(2.0), 2.0); -/// assert_eq!(ema.next(5.0), 3.5); -/// assert_eq!(ema.next(1.0), 2.25); -/// assert_eq!(ema.next(6.25), 4.25); -/// ``` -/// -/// # Links -/// -/// * [Exponential moving average, Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) -/// + +// +// # Example +// +// ``` +// use core::indicators::ExponentialMovingAverage; +// use core::Next; +// +// let mut ema = ExponentialMovingAverage::new(3).unwrap(); +// assert_eq!(ema.next(2.0), 2.0); +// assert_eq!(ema.next(5.0), 3.5); +// assert_eq!(ema.next(1.0), 2.25); +// assert_eq!(ema.next(6.25), 4.25); +// ``` +// +// # Links +// +// * [Exponential moving average, Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) +// #[derive(Debug, Clone)] pub struct ExponentialMovingAverage { diff --git a/src/indicators/fsto.rs b/src/indicators/fsto.rs index a86fd5f..a68f5e5 100644 --- a/src/indicators/fsto.rs +++ b/src/indicators/fsto.rs @@ -6,15 +6,14 @@ use crate::errors::*; use crate::indicators::{Maximum, Minimum}; use crate::{Close, High, Low, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct FstoFactory { -} +pub struct FstoFactory {} impl FstoFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -44,20 +43,21 @@ impl Factory for FstoFactory { /// # Parameters /// /// * _length_ - number of periods (integer greater than 0). Default is 14. -/// -/// # Example -/// -/// ``` -/// use core::indicators::FastStochastic; -/// use core::Next; -/// -/// let mut stoch = FastStochastic::new(5).unwrap(); -/// assert_eq!(stoch.next(20.0), 50.0); -/// assert_eq!(stoch.next(30.0), 100.0); -/// assert_eq!(stoch.next(40.0), 100.0); -/// assert_eq!(stoch.next(35.0), 75.0); -/// assert_eq!(stoch.next(15.0), 0.0); -/// ``` + +// +// # Example +// +// ``` +// use core::indicators::FastStochastic; +// use core::Next; +// +// let mut stoch = FastStochastic::new(5).unwrap(); +// assert_eq!(stoch.next(20.0), 50.0); +// assert_eq!(stoch.next(30.0), 100.0); +// assert_eq!(stoch.next(40.0), 100.0); +// assert_eq!(stoch.next(35.0), 75.0); +// assert_eq!(stoch.next(15.0), 0.0); +// ``` #[derive(Debug, Clone)] pub struct FastStochastic { @@ -69,7 +69,7 @@ pub struct FastStochastic { impl FastStochastic { pub fn new(length: u32) -> Result { let indicator = Self { - length: length, + length, minimum: Minimum::new(length)?, maximum: Maximum::new(length)?, }; diff --git a/src/indicators/ker.rs b/src/indicators/ker.rs index 6461b9d..fdf5fd9 100644 --- a/src/indicators/ker.rs +++ b/src/indicators/ker.rs @@ -6,15 +6,14 @@ use std::fmt; use crate::errors::*; use crate::traits::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct KerFactory { -} +pub struct KerFactory {} impl KerFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -32,21 +31,22 @@ impl Factory for KerFactory { /// # Parameters /// /// * _length_ - number of periods (integer greater than 0) -/// -/// # Example -/// -/// ``` -/// use core::indicators::EfficiencyRatio; -/// use core::Next; -/// -/// let mut er = EfficiencyRatio::new(4).unwrap(); -/// assert_eq!(er.next(10.0), 1.0); -/// assert_eq!(er.next(13.0), 1.0); -/// assert_eq!(er.next(12.0), 0.5); -/// assert_eq!(er.next(13.0), 0.6); -/// assert_eq!(er.next(18.0), 0.8); -/// assert_eq!(er.next(19.0), 0.75); -/// ``` + +// +// # Example +// +// ``` +// use core::indicators::EfficiencyRatio; +// use core::Next; +// +// let mut er = EfficiencyRatio::new(4).unwrap(); +// assert_eq!(er.next(10.0), 1.0); +// assert_eq!(er.next(13.0), 1.0); +// assert_eq!(er.next(12.0), 0.5); +// assert_eq!(er.next(13.0), 0.6); +// assert_eq!(er.next(18.0), 0.8); +// assert_eq!(er.next(19.0), 0.75); +// ``` pub struct EfficiencyRatio { length: u32, @@ -59,7 +59,7 @@ impl EfficiencyRatio { Err(Error::from_kind(ErrorKind::InvalidParameter)) } else { let indicator = Self { - length: length, + length, prices: VecDeque::with_capacity(length as usize + 1), }; Ok(indicator) diff --git a/src/indicators/macd.rs b/src/indicators/macd.rs index 5faa832..17ac5f3 100644 --- a/src/indicators/macd.rs +++ b/src/indicators/macd.rs @@ -6,15 +6,14 @@ use crate::errors::*; use crate::indicators::ExponentialMovingAverage as Ema; use crate::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct MacdFactory { -} +pub struct MacdFactory {} impl MacdFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -45,29 +44,30 @@ impl Factory for MacdFactory { /// * _fast_length_ - length for the fast EMA. Default is 12. /// * _slow_length_ - length for the slow EMA. Default is 26. /// * _signal_length_ - length for the signal EMA. Default is 9. -/// -/// # Example -/// -/// ``` -/// use core::indicators::MovingAverageConvergenceDivergence as Macd; -/// use core::Next; -/// -/// let mut macd = Macd::new(3, 6, 4).unwrap(); -/// -/// assert_eq!(round(macd.next(2.0)), (0.0, 0.0, 0.0)); -/// assert_eq!(round(macd.next(3.0)), (0.21, 0.09, 0.13)); -/// assert_eq!(round(macd.next(4.2)), (0.52, 0.26, 0.26)); -/// assert_eq!(round(macd.next(7.0)), (1.15, 0.62, 0.54)); -/// assert_eq!(round(macd.next(6.7)), (1.15, 0.83, 0.32)); -/// assert_eq!(round(macd.next(6.5)), (0.94, 0.87, 0.07)); -/// -/// fn round(nums: (f64, f64, f64)) -> (f64, f64, f64) { -/// let n0 = (nums.0 * 100.0).round() / 100.0; -/// let n1 = (nums.1 * 100.0).round() / 100.0; -/// let n2 = (nums.2 * 100.0).round() / 100.0; -/// (n0, n1, n2) -/// } -/// ``` + +// +// # Example +// +// ``` +// use core::indicators::MovingAverageConvergenceDivergence as Macd; +// use core::Next; +// +// let mut macd = Macd::new(3, 6, 4).unwrap(); +// +// assert_eq!(round(macd.next(2.0)), (0.0, 0.0, 0.0)); +// assert_eq!(round(macd.next(3.0)), (0.21, 0.09, 0.13)); +// assert_eq!(round(macd.next(4.2)), (0.52, 0.26, 0.26)); +// assert_eq!(round(macd.next(7.0)), (1.15, 0.62, 0.54)); +// assert_eq!(round(macd.next(6.7)), (1.15, 0.83, 0.32)); +// assert_eq!(round(macd.next(6.5)), (0.94, 0.87, 0.07)); +// +// fn round(nums: (f64, f64, f64)) -> (f64, f64, f64) { +// let n0 = (nums.0 * 100.0).round() / 100.0; +// let n1 = (nums.1 * 100.0).round() / 100.0; +// let n2 = (nums.2 * 100.0).round() / 100.0; +// (n0, n1, n2) +// } +// ``` #[derive(Debug, Clone)] pub struct MovingAverageConvergenceDivergence { diff --git a/src/indicators/max.rs b/src/indicators/max.rs index 0bf974a..848b5bd 100644 --- a/src/indicators/max.rs +++ b/src/indicators/max.rs @@ -6,15 +6,14 @@ use std::fmt; use crate::errors::*; use crate::{High, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct MaxFactory { -} +pub struct MaxFactory {} impl MaxFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -29,20 +28,21 @@ impl Factory for MaxFactory { /// # Parameters /// /// * _n_ - size of the time frame (integer greater than 0). Default value is 14. -/// -/// # Example -/// -/// ``` -/// use core::indicators::Maximum; -/// use core::Next; -/// -/// let mut max = Maximum::new(3).unwrap(); -/// assert_eq!(max.next(7.0), 7.0); -/// assert_eq!(max.next(5.0), 7.0); -/// assert_eq!(max.next(4.0), 7.0); -/// assert_eq!(max.next(4.0), 5.0); -/// assert_eq!(max.next(8.0), 8.0); -/// ``` + +// +// # Example +// +// ``` +// use core::indicators::Maximum; +// use core::Next; +// +// let mut max = Maximum::new(3).unwrap(); +// assert_eq!(max.next(7.0), 7.0); +// assert_eq!(max.next(5.0), 7.0); +// assert_eq!(max.next(4.0), 7.0); +// assert_eq!(max.next(4.0), 5.0); +// assert_eq!(max.next(8.0), 8.0); +// ``` #[derive(Debug, Clone)] pub struct Maximum { @@ -61,7 +61,7 @@ impl Maximum { } let indicator = Self { - n: n, + n, vec: vec![-INFINITY; n], max_index: 0, cur_index: 0, diff --git a/src/indicators/mfi.rs b/src/indicators/mfi.rs index 5385804..85335c6 100644 --- a/src/indicators/mfi.rs +++ b/src/indicators/mfi.rs @@ -6,15 +6,14 @@ use std::fmt; use crate::errors::*; use crate::{Close, High, Low, Next, Reset, Volume}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct MfiFactory { -} +pub struct MfiFactory {} impl MfiFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -49,27 +48,28 @@ impl Factory for MfiFactory { /// # Parameters /// /// * _n_ - number of periods, integer greater than 0 -/// -/// # Example -/// -/// ``` -/// use core::indicators::MoneyFlowIndex; -/// use core::{Next, DataItem}; -/// -/// let mut mfi = MoneyFlowIndex::new(3).unwrap(); -/// let di = DataItem::builder() -/// .high(3.0) -/// .low(1.0) -/// .close(2.0) -/// .open(1.5) -/// .volume(1000.0) -/// .build().unwrap(); -/// mfi.next(&di); -/// -/// ``` -/// # Links -/// * [Money Flow Index, Wikipedia](https://en.wikipedia.org/wiki/Money_flow_index) -/// * [Money Flow Index, stockcharts](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:money_flow_index_mfi) + +// +// # Example +// +// ``` +// use core::indicators::MoneyFlowIndex; +// use core::{Next, DataItem}; +// +// let mut mfi = MoneyFlowIndex::new(3).unwrap(); +// let di = DataItem::builder() +// .high(3.0) +// .low(1.0) +// .close(2.0) +// .open(1.5) +// .volume(1000.0) +// .build().unwrap(); +// mfi.next(&di); +// +// ``` +// # Links +// * [Money Flow Index, Wikipedia](https://en.wikipedia.org/wiki/Money_flow_index) +// * [Money Flow Index, stockcharts](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:money_flow_index_mfi) #[derive(Debug, Clone)] pub struct MoneyFlowIndex { @@ -87,7 +87,7 @@ impl MoneyFlowIndex { 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)), _ => { let indicator = Self { - n: n, + n, money_flows: VecDeque::with_capacity(n as usize + 1), prev_typical_price: 0.0, total_positive_money_flow: 0.0, @@ -112,7 +112,7 @@ impl<'a, T: High + Low + Close + Volume> Next<&'a T> for MoneyFlowIndex { self.money_flows.push_back(0.0); self.prev_typical_price = typical_price; self.is_new = false; - return 50.0; + 50.0 } else { let money_flow = typical_price * input.volume(); @@ -248,5 +248,4 @@ mod tests { let mfi = MoneyFlowIndex::new(10).unwrap(); assert_eq!(format!("{}", mfi), "MFI(10)"); } - } diff --git a/src/indicators/min.rs b/src/indicators/min.rs index 89ee975..6e33a69 100644 --- a/src/indicators/min.rs +++ b/src/indicators/min.rs @@ -6,15 +6,14 @@ use std::fmt; use crate::errors::*; use crate::{Low, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct MinFactory { -} +pub struct MinFactory {} impl MinFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -29,19 +28,20 @@ impl Factory for MinFactory { /// # Parameters /// /// * _n_ - size of the time frame (integer greater than 0). Default value is 14. -/// -/// # Example -/// -/// ``` -/// use core::indicators::Minimum; -/// use core::Next; -/// -/// let mut min = Minimum::new(3).unwrap(); -/// assert_eq!(min.next(10.0), 10.0); -/// assert_eq!(min.next(11.0), 10.0); -/// assert_eq!(min.next(12.0), 10.0); -/// assert_eq!(min.next(13.0), 11.0); -/// ``` + +// +// # Example +// +// ``` +// use core::indicators::Minimum; +// use core::Next; +// +// let mut min = Minimum::new(3).unwrap(); +// assert_eq!(min.next(10.0), 10.0); +// assert_eq!(min.next(11.0), 10.0); +// assert_eq!(min.next(12.0), 10.0); +// assert_eq!(min.next(13.0), 11.0); +// ``` #[derive(Debug, Clone)] pub struct Minimum { @@ -60,7 +60,7 @@ impl Minimum { } let indicator = Self { - n: n, + n, vec: vec![INFINITY; n], min_index: 0, cur_index: 0, diff --git a/src/indicators/mod.rs b/src/indicators/mod.rs index 2441736..5eb8377 100644 --- a/src/indicators/mod.rs +++ b/src/indicators/mod.rs @@ -47,4 +47,4 @@ mod mfi; pub use self::mfi::MoneyFlowIndex; mod obv; -pub use self::obv::OnBalanceVolume; \ No newline at end of file +pub use self::obv::OnBalanceVolume; diff --git a/src/indicators/obv.rs b/src/indicators/obv.rs index 5d33f23..d0b1ec4 100644 --- a/src/indicators/obv.rs +++ b/src/indicators/obv.rs @@ -4,15 +4,14 @@ use std::fmt; use crate::{Close, Next, Reset, Volume}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct ObvFactory { -} +pub struct ObvFactory {} impl ObvFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -42,39 +41,40 @@ impl Factory for ObvFactory { /// Where: /// /// obv - on the balance volume -/// -/// # Example -/// -/// ``` -/// use core::indicators::OnBalanceVolume; -/// use core::{Next, DataItem}; -/// -/// let mut obv = OnBalanceVolume::new(); -/// -/// let di1 = DataItem::builder() -/// .high(3.0) -/// .low(1.0) -/// .close(2.0) -/// .open(1.5) -/// .volume(1000.0) -/// .build().unwrap(); -/// -/// let di2 = DataItem::builder() -/// .high(3.0) -/// .low(1.0) -/// .close(1.5) -/// .open(1.5) -/// .volume(300.0) -/// .build().unwrap(); -/// -/// assert_eq!(obv.next(&di1), 1000.0); -/// assert_eq!(obv.next(&di2), 700.0); -/// ``` -/// -/// # Links -/// -/// * [On Balance Volume, Wikipedia](https://en.wikipedia.org/wiki/On-balance_volume) -/// * [On Balance Volume, stockcharts](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:on_balance_volume_obv) + +// +// # Example +// +// ``` +// use core::indicators::OnBalanceVolume; +// use core::{Next, DataItem}; +// +// let mut obv = OnBalanceVolume::new(); +// +// let di1 = DataItem::builder() +// .high(3.0) +// .low(1.0) +// .close(2.0) +// .open(1.5) +// .volume(1000.0) +// .build().unwrap(); +// +// let di2 = DataItem::builder() +// .high(3.0) +// .low(1.0) +// .close(1.5) +// .open(1.5) +// .volume(300.0) +// .build().unwrap(); +// +// assert_eq!(obv.next(&di1), 1000.0); +// assert_eq!(obv.next(&di2), 700.0); +// ``` +// +// # Links +// +// * [On Balance Volume, Wikipedia](https://en.wikipedia.org/wiki/On-balance_volume) +// * [On Balance Volume, stockcharts](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:on_balance_volume_obv) #[derive(Debug, Clone)] pub struct OnBalanceVolume { @@ -179,5 +179,4 @@ mod tests { let obv = OnBalanceVolume::new(); assert_eq!(format!("{}", obv), "OBV"); } - } diff --git a/src/indicators/roc.rs b/src/indicators/roc.rs index 2b26745..66b62d9 100644 --- a/src/indicators/roc.rs +++ b/src/indicators/roc.rs @@ -6,15 +6,14 @@ use std::fmt; use crate::errors::*; use crate::traits::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct RocFactory { -} +pub struct RocFactory {} impl RocFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -39,24 +38,25 @@ impl Factory for RocFactory { /// # Parameters /// /// * _length_ - number of periods (_n_), integer greater than 0 -/// -/// # Example -/// -/// ``` -/// use core::indicators::RateOfChange; -/// use core::Next; -/// -/// let mut roc = RateOfChange::new(2).unwrap(); -/// assert_eq!(roc.next(10.0), 0.0); // 0 -/// assert_eq!(roc.next(9.7).round(), -3.0); // (9.7 - 10) / 10 * 100 = -3 -/// assert_eq!(roc.next(20.0).round(), 100.0); // (20 - 10) / 10 * 100 = 100 -/// assert_eq!(roc.next(20.0).round(), 106.0); // (20 - 9.7) / 9.7 * 100 = 106 -/// ``` -/// -/// # Links -/// -/// * [Rate of Change, Wikipedia](https://en.wikipedia.org/wiki/Momentum_(technical_analysis)) -/// + +// +// # Example +// +// ``` +// use core::indicators::RateOfChange; +// use core::Next; +// +// let mut roc = RateOfChange::new(2).unwrap(); +// assert_eq!(roc.next(10.0), 0.0); // 0 +// assert_eq!(roc.next(9.7).round(), -3.0); // (9.7 - 10) / 10 * 100 = -3 +// assert_eq!(roc.next(20.0).round(), 100.0); // (20 - 10) / 10 * 100 = 100 +// assert_eq!(roc.next(20.0).round(), 106.0); // (20 - 9.7) / 9.7 * 100 = 106 +// ``` +// +// # Links +// +// * [Rate of Change, Wikipedia](https://en.wikipedia.org/wiki/Momentum_(technical_analysis)) +// #[derive(Debug, Clone)] pub struct RateOfChange { @@ -70,7 +70,7 @@ impl RateOfChange { 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)), _ => { let indicator = Self { - length: length, + length, prices: VecDeque::with_capacity(length as usize + 1), }; Ok(indicator) diff --git a/src/indicators/rsi.rs b/src/indicators/rsi.rs index 628e964..ba4dd1b 100644 --- a/src/indicators/rsi.rs +++ b/src/indicators/rsi.rs @@ -6,15 +6,14 @@ use crate::errors::*; use crate::indicators::ExponentialMovingAverage as Ema; use crate::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct RsiFactory { -} +pub struct RsiFactory {} impl RsiFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -68,24 +67,25 @@ impl Factory for RsiFactory { /// # Parameters /// /// * _n_ - number of periods (integer greater than 0). Default value is 14. -/// -/// # Example -/// -/// ``` -/// use core::indicators::RelativeStrengthIndex; -/// use core::Next; -/// -/// let mut rsi = RelativeStrengthIndex::new(3).unwrap(); -/// assert_eq!(rsi.next(10.0), 50.0); -/// assert_eq!(rsi.next(10.5).round(), 86.0); -/// assert_eq!(rsi.next(10.0).round(), 35.0); -/// assert_eq!(rsi.next(9.5).round(), 16.0); -/// ``` -/// -/// # Links -/// * [Relative strength index (Wikipedia)](https://en.wikipedia.org/wiki/Relative_strength_index) -/// * [RSI (Investopedia)](http://www.investopedia.com/terms/r/rsi.asp) -/// + +// +// # Example +// +// ``` +// use core::indicators::RelativeStrengthIndex; +// use core::Next; +// +// let mut rsi = RelativeStrengthIndex::new(3).unwrap(); +// assert_eq!(rsi.next(10.0), 50.0); +// assert_eq!(rsi.next(10.5).round(), 86.0); +// assert_eq!(rsi.next(10.0).round(), 35.0); +// assert_eq!(rsi.next(9.5).round(), 16.0); +// ``` +// +// # Links +// * [Relative strength index (Wikipedia)](https://en.wikipedia.org/wiki/Relative_strength_index) +// * [RSI (Investopedia)](http://www.investopedia.com/terms/r/rsi.asp) +// #[derive(Debug, Clone)] pub struct RelativeStrengthIndex { @@ -99,7 +99,7 @@ pub struct RelativeStrengthIndex { impl RelativeStrengthIndex { pub fn new(n: u32) -> Result { let rsi = Self { - n: n, + n, up_ema_indicator: Ema::new(n)?, down_ema_indicator: Ema::new(n)?, prev_val: 0.0, diff --git a/src/indicators/sd.rs b/src/indicators/sd.rs index f8c8b47..640cde7 100644 --- a/src/indicators/sd.rs +++ b/src/indicators/sd.rs @@ -5,15 +5,14 @@ use std::fmt; use crate::errors::*; use crate::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct SdFactory { -} +pub struct SdFactory {} impl SdFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -40,22 +39,23 @@ impl Factory for SdFactory { /// # Parameters /// /// * _n_ - number of periods (integer greater than 0) -/// -/// # Example -/// -/// ``` -/// use core::indicators::StandardDeviation; -/// use core::Next; -/// -/// let mut sd = StandardDeviation::new(3).unwrap(); -/// assert_eq!(sd.next(10.0), 0.0); -/// assert_eq!(sd.next(20.0), 5.0); -/// ``` -/// -/// # Links -/// -/// * [Standard Deviation, Wikipedia](https://en.wikipedia.org/wiki/Standard_deviation) -/// + +// +// # Example +// +// ``` +// use core::indicators::StandardDeviation; +// use core::Next; +// +// let mut sd = StandardDeviation::new(3).unwrap(); +// assert_eq!(sd.next(10.0), 0.0); +// assert_eq!(sd.next(20.0), 5.0); +// ``` +// +// # Links +// +// * [Standard Deviation, Wikipedia](https://en.wikipedia.org/wiki/Standard_deviation) +// #[derive(Debug, Clone)] pub struct StandardDeviation { diff --git a/src/indicators/sma.rs b/src/indicators/sma.rs index 925f34c..7fb859e 100644 --- a/src/indicators/sma.rs +++ b/src/indicators/sma.rs @@ -5,22 +5,21 @@ use std::fmt; use crate::errors::*; +use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -use std::cell::RefCell; -use crate::errors::{ErrorKind, Error}; +use crate::errors::{Error, ErrorKind}; use crate::{Close, Next, Reset}; -use crate::{Slot, SlotPtr, SlotType, Frame}; +use crate::{Frame, Slot, SlotPtr, SlotType}; -use crate::{Factory}; +use crate::Factory; -pub struct SmaFactory { -} +pub struct SmaFactory {} impl SmaFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -74,27 +73,33 @@ pub struct SimpleMovingAverage<'a> { pub inputs: HashMap<&'a str, Rc>>, pub outputs: HashMap<&'a str, Rc>>, } - + impl<'a> SimpleMovingAverage<'a> { pub fn new(period: u32) -> Result { match period { // 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)), _ => { let indicator = Self { - period: period, + period, index: 0, count: 0, sum: 0.0, vec: vec![0.0; period as usize], - inputs: [("input", Rc::new(RefCell::new(Slot::new(SlotType::Input))))].iter().cloned().collect(), - outputs: [("output", Rc::new(RefCell::new(Slot::new(SlotType::Output))))].iter().cloned().collect(), + inputs: [("input", Rc::new(RefCell::new(Slot::new(SlotType::Input))))] + .iter() + .cloned() + .collect(), + outputs: [("output", Rc::new(RefCell::new(Slot::new(SlotType::Output))))] + .iter() + .cloned() + .collect(), }; Ok(indicator) } } } - + // fn slot(&mut self, name: &str) -> Option<&mut Rc>> { // self.inputs.get_mut(name) // } @@ -110,10 +115,10 @@ impl<'a> SimpleMovingAverage<'a> { // println!("HERE {:?}", slot.borrow_mut()); let input = slot.borrow_mut().get(); - + self.index = (self.index + 1) % (self.period as usize); let old_val = self.vec[self.index]; - + self.vec[self.index] = input; // fill counter upto period @@ -137,7 +142,7 @@ impl<'a> SimpleMovingAverage<'a> { impl<'a> Next for SimpleMovingAverage<'a> { type Output = Box<[f64]>; - + fn next(&mut self, input: f64) -> Self::Output { self.index = (self.index + 1) % (self.period as usize); @@ -164,7 +169,6 @@ impl<'a> Next for SimpleMovingAverage<'a> { // } impl<'a> Reset for SimpleMovingAverage<'a> { - fn reset(&mut self) { self.index = 0; self.count = 0; @@ -235,11 +239,10 @@ impl<'a> fmt::Display for SimpleMovingAverage<'a> { mod tests { use super::*; use crate::test_helper::*; - use crate::{Slot, SlotPtr, SlotType, Frame}; + use crate::{Frame, Slot, SlotPtr, SlotType}; // test_indicator!(SimpleMovingAverage); - #[test] fn test_new() { initialize(); @@ -277,7 +280,7 @@ mod tests { // } assert_eq!(step(&mut sma, 4.0), 4.0); assert_eq!(step(&mut sma, 5.0), 4.5); - assert_eq!(step(&mut sma, 6.0), 5.0); + assert_eq!(step(&mut sma, 6.0), 5.0); assert_eq!(step(&mut sma, 6.0), 5.25); assert_eq!(step(&mut sma, 6.0), 5.75); assert_eq!(step(&mut sma, 6.0), 6.0); @@ -306,8 +309,6 @@ mod tests { // let a: HashMap<&str, SlotPtr> = [("input", ptr)].iter().cloned().collect(); - - // #[test] // fn test_next() { // initialize(); diff --git a/src/indicators/ssto.rs b/src/indicators/ssto.rs index dd64d0d..574b83f 100644 --- a/src/indicators/ssto.rs +++ b/src/indicators/ssto.rs @@ -6,15 +6,14 @@ use crate::errors::Result; use crate::indicators::{ExponentialMovingAverage, FastStochastic}; use crate::{Close, High, Low, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct SstoFactory { -} +pub struct SstoFactory {} impl SstoFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -32,20 +31,21 @@ impl Factory for SstoFactory { /// /// * _stochastic_n_ - number of periods for fast stochastic (integer greater than 0). Default is 14. /// *_ema_n_ - length for EMA (integer greater than 0). Default is 3. -/// -/// # Example -/// -/// ``` -/// use core::indicators::SlowStochastic; -/// use core::Next; -/// -/// let mut stoch = SlowStochastic::new(3, 2).unwrap(); -/// assert_eq!(stoch.next(10.0), 50.0); -/// assert_eq!(stoch.next(50.0).round(), 83.0); -/// assert_eq!(stoch.next(50.0).round(), 94.0); -/// assert_eq!(stoch.next(30.0).round(), 31.0); -/// assert_eq!(stoch.next(55.0).round(), 77.0); -/// ``` + +// +// # Example +// +// ``` +// use core::indicators::SlowStochastic; +// use core::Next; +// +// let mut stoch = SlowStochastic::new(3, 2).unwrap(); +// assert_eq!(stoch.next(10.0), 50.0); +// assert_eq!(stoch.next(50.0).round(), 83.0); +// assert_eq!(stoch.next(50.0).round(), 94.0); +// assert_eq!(stoch.next(30.0).round(), 31.0); +// assert_eq!(stoch.next(55.0).round(), 77.0); +// ``` #[derive(Clone, Debug)] pub struct SlowStochastic { diff --git a/src/indicators/tr.rs b/src/indicators/tr.rs index 6af49a6..089debe 100644 --- a/src/indicators/tr.rs +++ b/src/indicators/tr.rs @@ -5,15 +5,14 @@ use std::fmt; use crate::helpers::max3; use crate::{Close, High, Low, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct TrFactory { -} +pub struct TrFactory {} impl TrFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -36,37 +35,38 @@ impl Factory for TrFactory { /// /// TR = max[(high - low), abs(high - closeprev), abs(low - closeprev)] /// -/// # Example -/// -/// ``` -/// extern crate core; -/// #[macro_use] extern crate assert_approx_eq; -/// -/// use core::{Next, DataItem}; -/// use core::indicators::TrueRange; -/// -/// fn main() { -/// let data = vec![ -/// // open, high, low, close, tr -/// (9.7 , 10.0, 9.0, 9.5 , 1.0), // tr = high - low = 10.0 - 9.0 = 1.0 -/// (9.9 , 10.4, 9.8, 10.2 , 0.9), // tr = high - prev_close = 10.4 - 9.5 = 0.9 -/// (10.1 , 10.7, 9.4, 9.7 , 1.3), // tr = high - low = 10.7 - 9.4 = 1.3 -/// (9.1 , 9.2 , 8.1, 8.4 , 1.6), // tr = prev_close - low = 9.7 - 8.1 = 1.6 -/// ]; -/// let mut indicator = TrueRange::new(); -/// -/// for (open, high, low, close, tr) in data { -/// let di = DataItem::builder() -/// .high(high) -/// .low(low) -/// .close(close) -/// .open(open) -/// .volume(1000.0) -/// .build().unwrap(); -/// assert_approx_eq!(indicator.next(&di), tr); -/// } -/// } -/// ``` + +// # Example +// +// ``` +// extern crate core; +// #[macro_use] extern crate assert_approx_eq; +// +// use core::{Next, DataItem}; +// use core::indicators::TrueRange; +// +// fn main() { +// let data = vec![ +// // open, high, low, close, tr +// (9.7 , 10.0, 9.0, 9.5 , 1.0), // tr = high - low = 10.0 - 9.0 = 1.0 +// (9.9 , 10.4, 9.8, 10.2 , 0.9), // tr = high - prev_close = 10.4 - 9.5 = 0.9 +// (10.1 , 10.7, 9.4, 9.7 , 1.3), // tr = high - low = 10.7 - 9.4 = 1.3 +// (9.1 , 9.2 , 8.1, 8.4 , 1.6), // tr = prev_close - low = 9.7 - 8.1 = 1.6 +// ]; +// let mut indicator = TrueRange::new(); +// +// for (open, high, low, close, tr) in data { +// let di = DataItem::builder() +// .high(high) +// .low(low) +// .close(close) +// .open(open) +// .volume(1000.0) +// .build().unwrap(); +// assert_approx_eq!(indicator.next(&di), tr); +// } +// } +// ``` #[derive(Debug, Clone)] pub struct TrueRange { diff --git a/src/indicators/wma.rs b/src/indicators/wma.rs index 66b776e..8319424 100644 --- a/src/indicators/wma.rs +++ b/src/indicators/wma.rs @@ -3,22 +3,21 @@ use std::fmt; -use rust_decimal_macros::*; use rust_decimal::prelude::*; +use rust_decimal_macros::*; use std::collections::VecDeque; -use crate::errors::{ErrorKind, Error}; +use crate::errors::{Error, ErrorKind}; use crate::{Close, Next, Reset}; -use crate::{Factory}; use crate::indicators::SimpleMovingAverage; +use crate::Factory; -pub struct WmaFactory { -} +pub struct WmaFactory {} impl WmaFactory { pub fn new() -> Self { - Self{} + Self {} } } @@ -44,16 +43,18 @@ impl Factory for WmaFactory { /// /// * _period_ - number of periods (integer greater than 0) /// -/// # Example -/// -/// ``` -/// use core::indicators::WeightedMovingAverage; -/// use core::Next; -/// -/// let mut wma = WeightedMovingAverage::new(3).unwrap(); -/// assert_eq!(wma.next(10.0), f64::INFINITY); -/// ``` -/// + +// # Example +// +// ``` +// use core::indicators::WeightedMovingAverage; +// use core::Next; +// +// let mut wma = WeightedMovingAverage::new(3).unwrap(); +// assert_eq!(wma.next(10.0), f64::INFINITY); +// ``` +// + /// # Links /// /// * [Weighted Moving Average, Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average) @@ -64,7 +65,7 @@ pub struct WeightedMovingAverage { period: u32, index: usize, count: u32, - sum: Decimal, /* Flat sum of previous numbers. */ + sum: Decimal, /* Flat sum of previous numbers. */ weight_sum: Decimal, /* Weighted sum of previous numbers. */ vec: VecDeque, } @@ -76,7 +77,7 @@ impl WeightedMovingAverage { // 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)), _ => { let indicator = WeightedMovingAverage { - period: period, + period, index: 0, count: 0, sum: Decimal::zero(), @@ -91,7 +92,7 @@ impl WeightedMovingAverage { impl Next for WeightedMovingAverage { type Output = f64; - + fn next(&mut self, input: f64) -> Self::Output { // self.index = (self.index + 1) % (self.period as usize); @@ -102,15 +103,19 @@ impl Next for WeightedMovingAverage { if self.count < self.period - 1 { self.count += 1; self.vec.push_back(input); - self.weight_sum += Decimal::from_f64(input).unwrap() * Decimal::from_u32(self.count).unwrap(); + self.weight_sum += + Decimal::from_f64(input).unwrap() * Decimal::from_u32(self.count).unwrap(); self.sum += Decimal::from_f64(input).unwrap(); return f64::INFINITY; } - let weights: Decimal = Decimal::from_u32(self.period).unwrap() * (Decimal::from_u32(self.period).unwrap() + Decimal::from_u32(1).unwrap()) / Decimal::from_u32(2).unwrap(); + let weights: Decimal = Decimal::from_u32(self.period).unwrap() + * (Decimal::from_u32(self.period).unwrap() + Decimal::from_u32(1).unwrap()) + / Decimal::from_u32(2).unwrap(); // sliding window - self.weight_sum += Decimal::from_f64(input).unwrap() * Decimal::from_u32(self.period).unwrap(); + self.weight_sum += + Decimal::from_f64(input).unwrap() * Decimal::from_u32(self.period).unwrap(); self.sum += Decimal::from_f64(input).unwrap(); let output: Decimal = self.weight_sum / weights; @@ -118,8 +123,11 @@ impl Next for WeightedMovingAverage { self.vec.push_back(input); self.weight_sum -= self.sum; self.sum -= Decimal::from_f64(self.vec.pop_front().unwrap()).unwrap(); - - output.round_dp_with_strategy(3, RoundingStrategy::RoundHalfUp).to_f64().unwrap() + + output + .round_dp_with_strategy(3, RoundingStrategy::RoundHalfUp) + .to_f64() + .unwrap() } } @@ -132,7 +140,6 @@ impl<'a, T: Close> Next<&'a T> for WeightedMovingAverage { } impl Reset for WeightedMovingAverage { - fn reset(&mut self) { self.index = 0; self.count = 0; @@ -173,12 +180,12 @@ mod tests { fn test_next() { initialize(); let _params = &TESTS["wma"]; - println!(""); + println!(); for _test in _params.tests.iter() { let _period = _test.options[0]; let _input = &_test.inputs[0]; let _output = &_test.outputs[0]; - + println!("WMA WITH PERIOD {}", _period); let mut indicator = WeightedMovingAverage::new(_period as u32).unwrap(); for val in _input.iter() { diff --git a/src/lib.rs b/src/lib.rs index efe997a..0c0a0cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,17 @@ +#![allow( + clippy::too_many_arguments, + clippy::let_and_return, + clippy::from_over_into, + clippy::upper_case_acronyms, + clippy::new_ret_no_self, + clippy::wrong_self_convention, + clippy::new_without_default, + clippy::float_cmp, + clippy::assign_op_pattern, + clippy::absurd_extreme_comparisons, + clippy::collapsible_else_if, +)] + //! ta is a Rust library for technical analysis. It provides number of technical indicators //! that can be used to build trading strategies for stock markets, futures, forex, cryptocurrencies, etc. //! @@ -9,43 +23,44 @@ //! //! Since `Next` is a generic trait, most of the indicators can work with both input types: `f64` and more complex //! structures like [DataItem](struct.DataItem.html). -//! -//! # Example -//! ``` -//! use core::indicators::ExponentialMovingAverage; -//! use core::Next; -//! -//! // it can return an error, when an invalid length is passed (e.g. 0) -//! let mut ema = ExponentialMovingAverage::new(3).unwrap(); -//! -//! assert_eq!(ema.next(2.0), 2.0); -//! assert_eq!(ema.next(5.0), 3.5); -//! assert_eq!(ema.next(1.0), 2.25); -//! assert_eq!(ema.next(6.25), 4.25); -//! ``` -//! -//! # List of indicators -//! -//! * Trend -//! * [Exponential Moving Average (EMA)](indicators/struct.ExponentialMovingAverage.html) -//! * [Simple Moving Average (SMA)](indicators/struct.SimpleMovingAverage.html) -//! * Oscillators -//! * [Relative Strength Index (RSI)](indicators/struct.RelativeStrengthIndex.html) -//! * [Fast Stochastic](indicators/struct.FastStochastic.html) -//! * [Slow Stochastic](indicators/struct.SlowStochastic.html) -//! * [Moving Average Convergence Divergence (MACD)](indicators/struct.MovingAverageConvergenceDivergence.html) -//! * [Money Flow Index (MFI)](indicators/struct.MoneyFlowIndex.html) -//! * Other -//! * [Standard Deviation (SD)](indicators/struct.StandardDeviation.html) -//! * [Bollinger Bands (BB)](indicators/struct.BollingerBands.html) -//! * [Maximum](indicators/struct.Maximum.html) -//! * [Minimum](indicators/struct.Minimum.html) -//! * [True Range](indicators/struct.TrueRange.html) -//! * [Average True Range (ATR)](indicators/struct.AverageTrueRange.html) -//! * [Efficiency Ratio (ER)](indicators/struct.EfficiencyRatio.html) -//! * [Rate of Change (ROC)](indicators/struct.RateOfChange.html) -//! * [On Balance Volume (OBV)](indicators/struct.OnBalanceVolume.html) -//! + +// +// # Example +// ``` +// use core::indicators::ExponentialMovingAverage; +// use core::Next; +// +// // it can return an error, when an invalid length is passed (e.g. 0) +// let mut ema = ExponentialMovingAverage::new(3).unwrap(); +// +// assert_eq!(ema.next(2.0), 2.0); +// assert_eq!(ema.next(5.0), 3.5); +// assert_eq!(ema.next(1.0), 2.25); +// assert_eq!(ema.next(6.25), 4.25); +// ``` +// +// # List of indicators +// +// * Trend +// * [Exponential Moving Average (EMA)](indicators/struct.ExponentialMovingAverage.html) +// * [Simple Moving Average (SMA)](indicators/struct.SimpleMovingAverage.html) +// * Oscillators +// * [Relative Strength Index (RSI)](indicators/struct.RelativeStrengthIndex.html) +// * [Fast Stochastic](indicators/struct.FastStochastic.html) +// * [Slow Stochastic](indicators/struct.SlowStochastic.html) +// * [Moving Average Convergence Divergence (MACD)](indicators/struct.MovingAverageConvergenceDivergence.html) +// * [Money Flow Index (MFI)](indicators/struct.MoneyFlowIndex.html) +// * Other +// * [Standard Deviation (SD)](indicators/struct.StandardDeviation.html) +// * [Bollinger Bands (BB)](indicators/struct.BollingerBands.html) +// * [Maximum](indicators/struct.Maximum.html) +// * [Minimum](indicators/struct.Minimum.html) +// * [True Range](indicators/struct.TrueRange.html) +// * [Average True Range (ATR)](indicators/struct.AverageTrueRange.html) +// * [Efficiency Ratio (ER)](indicators/struct.EfficiencyRatio.html) +// * [Rate of Change (ROC)](indicators/struct.RateOfChange.html) +// * [On Balance Volume (OBV)](indicators/struct.OnBalanceVolume.html) +// mod utils; @@ -76,4 +91,4 @@ mod tests { fn it_works() { assert_eq!(2 + 2, 4); } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 5c41fc8..6aa7541 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,4 @@ #![allow(unused_variables)] #![allow(unused_imports)] -use indicators; - -fn main() { - -} \ No newline at end of file +fn main() {} diff --git a/src/test_helper.rs b/src/test_helper.rs index 81bae90..554e1aa 100644 --- a/src/test_helper.rs +++ b/src/test_helper.rs @@ -1,7 +1,7 @@ -use std::sync::Once; -use std::fs; -use std::collections::HashMap; use lazy_static::lazy_static; +use std::collections::HashMap; +use std::fs; +use std::sync::Once; use serde::{Deserialize, Serialize}; // use serde_json::{Map, Value}; @@ -162,4 +162,4 @@ pub fn initialize() { // println!("With text: {}", TESTS["abs"].name); } }); -} \ No newline at end of file +} diff --git a/src/traits.rs b/src/traits.rs index 943292a..3482fa5 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -45,7 +45,7 @@ pub trait Volume { fn volume(&self) -> f64; } -/// Factory trait to create indicator +/// Factory trait to create indicator pub trait Factory { fn create() -> Box>>; -} \ No newline at end of file +} diff --git a/src/utils.rs b/src/utils.rs index f09adc8..1cf2dfe 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,4 +9,4 @@ pub fn set_panic_hook() { // https://github.com/rustwasm/console_error_panic_hook#readme #[cfg(feature = "console_error_panic_hook")] console_error_panic_hook::set_once(); -} \ No newline at end of file +} diff --git a/tests/test.rs b/tests/test.rs index 0da945e..1208c37 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,4 +1,4 @@ -extern crate csv; extern crate core; +extern crate csv; // TODO: implement some integration tests From 5d177cff8f0b56700602bf27c334cce1c4734a1b Mon Sep 17 00:00:00 2001 From: Victor Dudochkin Date: Sun, 18 Apr 2021 13:20:45 +0700 Subject: [PATCH 3/4] Facade --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a40ee40..3dab7ef 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ ux-indicators is a Centralized State Management And Design Patterns for Rust. **Angular Rust** is a high productivity, `platform-agnostic` frontend framework for the [Rust language](https://www.rust-lang.org/). It now supports desktop and web development. Angular Rust currently uses GTK for desktop development and WebAssembly for web development. We are planning to add support for mobile development. +![Angular Rust structure](https://dudochkin-victor.github.io/assets/angular-rust/structure.svg) + ## Features - [x] Graphic abstraction for cairo and web canvas, implemented in [UX Animate](https://github.com/angular-rust/ux-animate) From 9a4148ad8691a3ba1b9ed4e6cb8614f70fcffe9b Mon Sep 17 00:00:00 2001 From: Victor Dudochkin Date: Sun, 18 Apr 2021 17:41:50 +0700 Subject: [PATCH 4/4] Facade --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3dab7ef..49c0aa3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ [loc-badge]: https://img.shields.io/tokei/lines/github/angular-rust/ux-indicators?style=flat-square [loc-url]: https://github.com/angular-rust/ux-indicators -ux-indicators is a Centralized State Management And Design Patterns for Rust. +**UX Indicators** is a Rust library for technical analysis in Angular Rust. It provides a range of technical indicators that can be used to build trading strategies for stock markets, futures, forex, cryptocurrencies, and more. + +> **work in progress** **Angular Rust** is a high productivity, `platform-agnostic` frontend framework for the [Rust language](https://www.rust-lang.org/). It now supports desktop and web development. Angular Rust currently uses GTK for desktop development and WebAssembly for web development. We are planning to add support for mobile development.