Compare commits
9 commits
89487c8865
...
38cd013ab9
Author | SHA1 | Date | |
---|---|---|---|
38cd013ab9 | |||
235104ae75 | |||
1c302990af | |||
d3091369f4 | |||
1337176474 | |||
61904a1ef1 | |||
fe660459d9 | |||
15d919e62c | |||
45841db4ed |
4 changed files with 157 additions and 35 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
1--transforming-sync-to-async/provided-code/target
|
1--transforming-sync-to-async/provided-code/target
|
||||||
|
target
|
||||||
|
|
107
Cargo.lock
generated
107
Cargo.lock
generated
|
@ -95,6 +95,24 @@ dependencies = [
|
||||||
"event-listener",
|
"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]]
|
[[package]]
|
||||||
name = "async-std"
|
name = "async-std"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
|
@ -106,6 +124,7 @@ dependencies = [
|
||||||
"async-global-executor",
|
"async-global-executor",
|
||||||
"async-io",
|
"async-io",
|
||||||
"async-lock",
|
"async-lock",
|
||||||
|
"async-process",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -369,19 +388,46 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures"
|
||||||
version = "0.3.21"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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 = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.21"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
|
@ -405,27 +451,44 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-macro"
|
||||||
version = "0.3.21"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.21"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.21"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -663,6 +726,7 @@ dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"futures",
|
||||||
"yahoo_finance_api",
|
"yahoo_finance_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1087,6 +1151,25 @@ dependencies = [
|
||||||
"serde",
|
"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]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
|
|
@ -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-std = { version = "1.6", features = ["attributes", "tokio1"] }
|
async-std = { version = "1.6", features = ["attributes", "tokio1", "unstable"] }
|
||||||
|
futures = "0.3"
|
||||||
|
|
81
src/main.rs
81
src/main.rs
|
@ -1,6 +1,12 @@
|
||||||
|
use async_std::prelude::*;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
|
||||||
use clap::Parser;
|
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;
|
use yahoo_finance_api as yahoo;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[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_std::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
let opts = Opts::parse();
|
let opts = Opts::parse();
|
||||||
|
@ -126,28 +178,13 @@ async fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
// a simple way to output a CSV header
|
// a simple way to output a CSV header
|
||||||
println!("period start,symbol,price,change %,min,max,30d avg");
|
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
|
// initial data fetch
|
||||||
println!(
|
fetch_and_output_symbol_data(&opts.symbols, from, to).await?;
|
||||||
"{},{},${:.2},{:.2}%,${:.2},${:.2},${:.2}",
|
|
||||||
from.to_rfc3339(),
|
let mut interval = async_std::stream::interval(Duration::from_secs(30));
|
||||||
symbol,
|
while let Some(_) = interval.next().await {
|
||||||
last_price,
|
fetch_and_output_symbol_data(&opts.symbols, from, to).await?;
|
||||||
pct_change * 100.0,
|
|
||||||
period_min,
|
|
||||||
period_max,
|
|
||||||
sma.last().unwrap_or(&0.0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue