use crate::types::IndexId;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CikEntry {
pub index: String,
pub ticker: String,
pub name: String,
pub trust_cik: String,
pub series_id: Option<String>,
}
impl CikEntry {
pub fn submissions_url(&self) -> String {
format!(
"https://data.sec.gov/submissions/CIK{}.json",
self.trust_cik
)
}
pub fn primary_doc_url(&self, accession: &str) -> String {
let no_dash: String = accession.chars().filter(|c| *c != '-').collect();
let cik_num = self
.trust_cik
.trim_start_matches('0')
.parse::<u64>()
.unwrap_or(0);
format!("https://www.sec.gov/Archives/edgar/data/{cik_num}/{no_dash}/primary_doc.xml")
}
}
pub fn entry_for(index: IndexId) -> CikEntry {
match index {
IndexId::Sp500 => CikEntry {
index: "sp500".into(),
ticker: "IVV".into(),
name: "iShares Core S&P 500 ETF".into(),
trust_cik: "0001100663".into(),
series_id: Some("S000004310".into()),
},
IndexId::Sp400 => CikEntry {
index: "sp400".into(),
ticker: "IJH".into(),
name: "iShares Core S&P Mid-Cap ETF".into(),
trust_cik: "0001100663".into(),
series_id: Some("S000004307".into()),
},
IndexId::Sp600 => CikEntry {
index: "sp600".into(),
ticker: "IJR".into(),
name: "iShares Core S&P Small-Cap ETF".into(),
trust_cik: "0001100663".into(),
series_id: Some("S000004313".into()),
},
IndexId::Ndx => CikEntry {
index: "ndx".into(),
ticker: "QQQ".into(),
name: "Invesco QQQ Trust, Series 1".into(),
trust_cik: "0001067839".into(),
series_id: None,
},
IndexId::Dji => CikEntry {
index: "dji".into(),
ticker: "DIA".into(),
name: "SPDR Dow Jones Industrial Average ETF Trust".into(),
trust_cik: "0001041130".into(),
series_id: None,
},
}
}
pub fn all_entries() -> Vec<CikEntry> {
IndexId::ALL.iter().map(|id| entry_for(*id)).collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_entries_have_correct_count() {
assert_eq!(all_entries().len(), 5);
}
#[test]
fn each_cik_is_10_digits() {
for e in all_entries() {
assert_eq!(
e.trust_cik.len(),
10,
"cik {} not zero-padded 10 digits",
e.trust_cik
);
assert!(e.trust_cik.chars().all(|c| c.is_ascii_digit()));
}
}
#[test]
fn series_ids_well_formed() {
for e in all_entries() {
if let Some(sid) = e.series_id {
assert!(
sid.starts_with('S') && sid.len() == 10,
"bad series id: {sid}"
);
}
}
}
#[test]
fn dji_has_no_series() {
assert!(entry_for(IndexId::Dji).series_id.is_none());
}
#[test]
fn submissions_url_shape() {
let e = entry_for(IndexId::Sp500);
assert_eq!(
e.submissions_url(),
"https://data.sec.gov/submissions/CIK0001100663.json"
);
}
#[test]
fn primary_doc_url_strips_dashes() {
let e = entry_for(IndexId::Sp500);
let url = e.primary_doc_url("0001752724-24-043113");
assert_eq!(
url,
"https://www.sec.gov/Archives/edgar/data/1100663/000175272424043113/primary_doc.xml"
);
}
}