msyrs/src/download/jpmaqsdownload.rs
2024-11-08 17:10:38 +00:00

101 lines
3.1 KiB
Rust

use crate::download::oauth_client::OAuthClient;
use crate::download::requester::DQRequester;
use crate::download::requester::DQTimeseriesRequestArgs;
use crate::download::timeseries::DQTimeSeriesResponse;
use crate::download::timeseries::JPMaQSIndicator;
use std::error::Error;
const DEFAULT_JPMAQS_METRICS: [&str; 4] = ["value", "grading", "eop_lag", "mop_lag"];
fn ticker_to_expressions(ticker: &str) -> Vec<String> {
DEFAULT_JPMAQS_METRICS
.iter()
.map(|metric| format!("DB(JPMAQS,{},{})", ticker, metric))
.collect::<Vec<String>>()
}
fn construct_expressions(tickers: Vec<String>) -> Vec<String> {
tickers
.iter()
.flat_map(|ticker| ticker_to_expressions(ticker))
.collect()
}
fn is_jpmaq_expression(expression: &str) -> bool {
expression.starts_with("DB(JPMAQS,")
&& expression.ends_with(")")
&& expression.split(',').count() == 3
&& expression.split(',').nth(0).unwrap() == "DB(JPMAQS"
&& expression.split(',').nth(2).unwrap().ends_with(")")
}
fn all_jpmaq_expressions(expressions: Vec<String>) -> bool {
expressions
.iter()
.all(|expression| is_jpmaq_expression(expression))
}
#[derive(Debug, Clone)]
pub struct JPMaQSDownload {
requester: DQRequester,
}
impl Default for JPMaQSDownload {
fn default() -> Self {
let requester = DQRequester::default();
JPMaQSDownload { requester }
}
}
impl JPMaQSDownload {
pub fn new(client_id: String, client_secret: String) -> Self {
let oauth_client = OAuthClient::new(client_id.clone(), client_secret.clone());
let requester = DQRequester::new(oauth_client);
JPMaQSDownload { requester }
}
pub fn check_connection(&mut self) -> Result<(), Box<dyn Error>> {
self.requester.check_connection()
}
pub fn get_catalogue(&mut self) -> Result<Vec<String>, Box<dyn Error>> {
let dq_catalogue = self.requester.get_catalogue("JPMAQS", 1000)?;
Ok(dq_catalogue.all_instruments)
}
pub fn get_expressions(
&mut self,
expressions: Vec<String>,
) -> Result<Vec<DQTimeSeriesResponse>, Box<dyn Error>> {
let dqts_vec = self.requester.get_timeseries(DQTimeseriesRequestArgs {
expressions: expressions,
..Default::default()
})?;
Ok(dqts_vec)
}
pub fn get_indicators(
&mut self,
tickers: Vec<String>,
) -> Result<Vec<JPMaQSIndicator>, Box<dyn Error>> {
let expressions = construct_expressions(tickers);
assert!(all_jpmaq_expressions(expressions.clone()));
let dqts_vec = self.get_expressions(expressions)?;
println!("Retrieved {} time series", dqts_vec.len());
let start = std::time::Instant::now();
let indicators = dqts_vec
.iter()
.flat_map(|dqts| dqts.get_timeseries_by_ticker())
.map(|tsv| JPMaQSIndicator::new(tsv))
.collect::<Result<Vec<JPMaQSIndicator>, Box<dyn Error>>>()?;
println!(
"Converted time series to indicators in {:?}",
start.elapsed()
);
Ok(indicators)
}
}