Compare commits

...

9 commits

4 changed files with 157 additions and 35 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
1--transforming-sync-to-async/provided-code/target
target

107
Cargo.lock generated
View file

@ -95,6 +95,24 @@ dependencies = [
"event-listener",
]
[[package]]
name = "async-process"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
dependencies = [
"async-io",
"async-lock",
"autocfg",
"blocking",
"cfg-if",
"event-listener",
"futures-lite",
"rustix",
"signal-hook",
"windows-sys 0.48.0",
]
[[package]]
name = "async-std"
version = "1.12.0"
@ -106,6 +124,7 @@ dependencies = [
"async-global-executor",
"async-io",
"async-lock",
"async-process",
"crossbeam-utils",
"futures-channel",
"futures-core",
@ -369,19 +388,46 @@ dependencies = [
]
[[package]]
name = "futures-channel"
version = "0.3.21"
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.21"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
@ -405,27 +451,44 @@ dependencies = [
]
[[package]]
name = "futures-sink"
version = "0.3.21"
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.52",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.21"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.21"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
@ -663,6 +726,7 @@ dependencies = [
"async-std",
"chrono",
"clap",
"futures",
"yahoo_finance_api",
]
@ -1087,6 +1151,25 @@ dependencies = [
"serde",
]
[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.6"

View file

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

View file

@ -1,6 +1,12 @@
use async_std::prelude::*;
use chrono::prelude::*;
use clap::Parser;
use std::io::{Error, ErrorKind};
use futures::future::try_join_all;
use std::{
io::{Error, ErrorKind},
time::Duration,
};
use yahoo_finance_api as yahoo;
#[derive(Parser, Debug)]
@ -118,6 +124,52 @@ async fn fetch_closing_data(
}
}
fn output_csv_line(closes: Vec<f64>, from: DateTime<Utc>, symbol: &str) {
let period_max: f64 = max(&closes).unwrap();
let period_min: f64 = min(&closes).unwrap();
let last_price = *closes.last().unwrap_or(&0.0);
let (_, pct_change) = price_diff(&closes).unwrap_or((0.0, 0.0));
let sma = n_window_sma(30, &closes).unwrap_or_default();
// a simple way to output CSV data
println!(
"{},{},${:.2},{:.2}%,${:.2},${:.2},${:.2}",
from.to_rfc3339(),
symbol,
last_price,
pct_change * 100.0,
period_min,
period_max,
sma.last().unwrap_or(&0.0)
);
}
async fn fetch_and_output_closing_data(
symbol: &str,
from: DateTime<Utc>,
to: DateTime<Utc>,
) -> std::io::Result<()> {
let closes = fetch_closing_data(&symbol, &from, &to).await?;
if !closes.is_empty() {
output_csv_line(closes, from, symbol);
}
Ok(())
}
async fn fetch_and_output_symbol_data(
symbols: &str,
from: DateTime<Utc>,
to: DateTime<Utc>,
) -> std::io::Result<()> {
let mut fs = vec![];
for symbol in symbols.split(',') {
let f = fetch_and_output_closing_data(symbol, from, to);
fs.push(f);
}
try_join_all(fs).await?;
Ok(())
}
#[async_std::main]
async fn main() -> std::io::Result<()> {
let opts = Opts::parse();
@ -126,28 +178,13 @@ async fn main() -> std::io::Result<()> {
// a simple way to output a CSV header
println!("period start,symbol,price,change %,min,max,30d avg");
for symbol in opts.symbols.split(',') {
let closes = fetch_closing_data(&symbol, &from, &to).await?;
if !closes.is_empty() {
// min/max of the period. unwrap() because those are Option types
let period_max: f64 = max(&closes).unwrap();
let period_min: f64 = min(&closes).unwrap();
let last_price = *closes.last().unwrap_or(&0.0);
let (_, pct_change) = price_diff(&closes).unwrap_or((0.0, 0.0));
let sma = n_window_sma(30, &closes).unwrap_or_default();
// a simple way to output CSV data
println!(
"{},{},${:.2},{:.2}%,${:.2},${:.2},${:.2}",
from.to_rfc3339(),
symbol,
last_price,
pct_change * 100.0,
period_min,
period_max,
sma.last().unwrap_or(&0.0)
);
}
// initial data fetch
fetch_and_output_symbol_data(&opts.symbols, from, to).await?;
let mut interval = async_std::stream::interval(Duration::from_secs(30));
while let Some(_) = interval.next().await {
fetch_and_output_symbol_data(&opts.symbols, from, to).await?;
}
Ok(())
}