traits are async

This commit is contained in:
Paul Campbell 2024-03-10 16:56:02 +00:00
parent 7bfb2b915e
commit b109fc9394
3 changed files with 50 additions and 31 deletions

View file

@ -128,6 +128,17 @@ version = "4.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
[[package]]
name = "async-trait"
version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.52",
]
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -661,6 +672,7 @@ name = "manning-lp-async-rust-project-1-m1"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-trait",
"chrono", "chrono",
"clap", "clap",
"yahoo_finance_api", "yahoo_finance_api",

View file

@ -10,4 +10,5 @@ version = "0.1.0"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
clap = {version = "3.1.8", features = ["derive"]} clap = {version = "3.1.8", features = ["derive"]}
yahoo_finance_api = "1.1" yahoo_finance_api = "1.1"
async-trait = "0.1"
async-std = { version = "1.6", features = ["attributes", "tokio1"] } async-std = { version = "1.6", features = ["attributes", "tokio1"] }

View file

@ -32,7 +32,7 @@ trait AsyncStockSignal {
/// ///
/// The signal (using the provided type) or `None` on error/invalid data. /// The signal (using the provided type) or `None` on error/invalid data.
/// ///
fn calculate(&self, series: &[f64]) -> Option<Self::SignalType>; async fn calculate(&self, series: &[f64]) -> Option<Self::SignalType>;
} }
/// ///
@ -156,7 +156,7 @@ struct PriceDifference;
impl AsyncStockSignal for PriceDifference { impl AsyncStockSignal for PriceDifference {
type SignalType = (f64, f64); type SignalType = (f64, f64);
fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> { async fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> {
price_diff(series) price_diff(series)
} }
} }
@ -165,7 +165,7 @@ struct MinPrice;
impl AsyncStockSignal for MinPrice { impl AsyncStockSignal for MinPrice {
type SignalType = f64; type SignalType = f64;
fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> { async fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> {
min(series) min(series)
} }
} }
@ -174,7 +174,7 @@ struct MaxPrice;
impl AsyncStockSignal for MaxPrice { impl AsyncStockSignal for MaxPrice {
type SignalType = f64; type SignalType = f64;
fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> { async fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> {
max(series) max(series)
} }
} }
@ -185,7 +185,7 @@ struct WindowedSMA {
impl AsyncStockSignal for WindowedSMA { impl AsyncStockSignal for WindowedSMA {
type SignalType = Vec<f64>; type SignalType = Vec<f64>;
fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> { async fn calculate(&self, series: &[f64]) -> Option<Self::SignalType> {
n_window_sma(self.window_size, series) n_window_sma(self.window_size, series)
} }
} }
@ -195,68 +195,74 @@ mod tests {
#![allow(non_snake_case)] #![allow(non_snake_case)]
use super::*; use super::*;
#[test] #[async_std::test]
fn test_PriceDifference_calculate() { async fn test_PriceDifference_calculate() {
let signal = PriceDifference {}; let signal = PriceDifference {};
assert_eq!(signal.calculate(&[]), None); assert_eq!(signal.calculate(&[]).await, None);
assert_eq!(signal.calculate(&[1.0]), Some((0.0, 0.0))); assert_eq!(signal.calculate(&[1.0]).await, Some((0.0, 0.0)));
assert_eq!(signal.calculate(&[1.0, 0.0]), Some((-1.0, -1.0))); assert_eq!(signal.calculate(&[1.0, 0.0]).await, Some((-1.0, -1.0)));
assert_eq!( assert_eq!(
signal.calculate(&[2.0, 3.0, 5.0, 6.0, 1.0, 2.0, 10.0]), signal
.calculate(&[2.0, 3.0, 5.0, 6.0, 1.0, 2.0, 10.0])
.await,
Some((8.0, 4.0)) Some((8.0, 4.0))
); );
assert_eq!( assert_eq!(
signal.calculate(&[0.0, 3.0, 5.0, 6.0, 1.0, 2.0, 1.0]), signal.calculate(&[0.0, 3.0, 5.0, 6.0, 1.0, 2.0, 1.0]).await,
Some((1.0, 1.0)) Some((1.0, 1.0))
); );
} }
#[test] #[async_std::test]
fn test_MinPrice_calculate() { async fn test_MinPrice_calculate() {
let signal = MinPrice {}; let signal = MinPrice {};
assert_eq!(signal.calculate(&[]), None); assert_eq!(signal.calculate(&[]).await, None);
assert_eq!(signal.calculate(&[1.0]), Some(1.0)); assert_eq!(signal.calculate(&[1.0]).await, Some(1.0));
assert_eq!(signal.calculate(&[1.0, 0.0]), Some(0.0)); assert_eq!(signal.calculate(&[1.0, 0.0]).await, Some(0.0));
assert_eq!( assert_eq!(
signal.calculate(&[2.0, 3.0, 5.0, 6.0, 1.0, 2.0, 10.0]), signal
.calculate(&[2.0, 3.0, 5.0, 6.0, 1.0, 2.0, 10.0])
.await,
Some(1.0) Some(1.0)
); );
assert_eq!( assert_eq!(
signal.calculate(&[0.0, 3.0, 5.0, 6.0, 1.0, 2.0, 1.0]), signal.calculate(&[0.0, 3.0, 5.0, 6.0, 1.0, 2.0, 1.0]).await,
Some(0.0) Some(0.0)
); );
} }
#[test] #[async_std::test]
fn test_MaxPrice_calculate() { async fn test_MaxPrice_calculate() {
let signal = MaxPrice {}; let signal = MaxPrice {};
assert_eq!(signal.calculate(&[]), None); assert_eq!(signal.calculate(&[]).await, None);
assert_eq!(signal.calculate(&[1.0]), Some(1.0)); assert_eq!(signal.calculate(&[1.0]).await, Some(1.0));
assert_eq!(signal.calculate(&[1.0, 0.0]), Some(1.0)); assert_eq!(signal.calculate(&[1.0, 0.0]).await, Some(1.0));
assert_eq!( assert_eq!(
signal.calculate(&[2.0, 3.0, 5.0, 6.0, 1.0, 2.0, 10.0]), signal
.calculate(&[2.0, 3.0, 5.0, 6.0, 1.0, 2.0, 10.0])
.await,
Some(10.0) Some(10.0)
); );
assert_eq!( assert_eq!(
signal.calculate(&[0.0, 3.0, 5.0, 6.0, 1.0, 2.0, 1.0]), signal.calculate(&[0.0, 3.0, 5.0, 6.0, 1.0, 2.0, 1.0]).await,
Some(6.0) Some(6.0)
); );
} }
#[test] #[async_std::test]
fn test_WindowedSMA_calculate() { async fn test_WindowedSMA_calculate() {
let series = vec![2.0, 4.5, 5.3, 6.5, 4.7]; let series = vec![2.0, 4.5, 5.3, 6.5, 4.7];
let signal = WindowedSMA { window_size: 3 }; let signal = WindowedSMA { window_size: 3 };
assert_eq!( assert_eq!(
signal.calculate(&series), signal.calculate(&series).await,
Some(vec![3.9333333333333336, 5.433333333333334, 5.5]) Some(vec![3.9333333333333336, 5.433333333333334, 5.5])
); );
let signal = WindowedSMA { window_size: 5 }; let signal = WindowedSMA { window_size: 5 };
assert_eq!(signal.calculate(&series), Some(vec![4.6])); assert_eq!(signal.calculate(&series).await, Some(vec![4.6]));
let signal = WindowedSMA { window_size: 10 }; let signal = WindowedSMA { window_size: 10 };
assert_eq!(signal.calculate(&series), Some(vec![])); assert_eq!(signal.calculate(&series).await, Some(vec![]));
} }
} }