1pub mod screener_types {
3 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8 pub enum ScreenerType {
9 AggressiveSmallCaps,
12 DayGainers,
14 DayLosers,
16 GrowthTechnologyStocks,
18 MostActives,
20 MostShortedStocks,
22 SmallCapGainers,
24 UndervaluedGrowthStocks,
26 UndervaluedLargeCaps,
28 ConservativeForeignFunds,
31 HighYieldBond,
33 PortfolioAnchors,
35 SolidLargeGrowthFunds,
37 SolidMidcapGrowthFunds,
39 TopMutualFunds,
41 }
42
43 impl ScreenerType {
44 pub fn as_scr_id(&self) -> &'static str {
46 match self {
47 ScreenerType::AggressiveSmallCaps => "aggressive_small_caps",
48 ScreenerType::DayGainers => "day_gainers",
49 ScreenerType::DayLosers => "day_losers",
50 ScreenerType::GrowthTechnologyStocks => "growth_technology_stocks",
51 ScreenerType::MostActives => "most_actives",
52 ScreenerType::MostShortedStocks => "most_shorted_stocks",
53 ScreenerType::SmallCapGainers => "small_cap_gainers",
54 ScreenerType::UndervaluedGrowthStocks => "undervalued_growth_stocks",
55 ScreenerType::UndervaluedLargeCaps => "undervalued_large_caps",
56 ScreenerType::ConservativeForeignFunds => "conservative_foreign_funds",
57 ScreenerType::HighYieldBond => "high_yield_bond",
58 ScreenerType::PortfolioAnchors => "portfolio_anchors",
59 ScreenerType::SolidLargeGrowthFunds => "solid_large_growth_funds",
60 ScreenerType::SolidMidcapGrowthFunds => "solid_midcap_growth_funds",
61 ScreenerType::TopMutualFunds => "top_mutual_funds",
62 }
63 }
64
65 pub fn parse(s: &str) -> Option<Self> {
75 s.parse().ok()
76 }
77
78 pub fn valid_types() -> &'static str {
80 "aggressive-small-caps, day-gainers, day-losers, growth-technology-stocks, \
81 most-actives, most-shorted-stocks, small-cap-gainers, undervalued-growth-stocks, \
82 undervalued-large-caps, conservative-foreign-funds, high-yield-bond, \
83 portfolio-anchors, solid-large-growth-funds, solid-midcap-growth-funds, \
84 top-mutual-funds"
85 }
86
87 pub fn all() -> &'static [ScreenerType] {
89 &[
90 ScreenerType::AggressiveSmallCaps,
91 ScreenerType::DayGainers,
92 ScreenerType::DayLosers,
93 ScreenerType::GrowthTechnologyStocks,
94 ScreenerType::MostActives,
95 ScreenerType::MostShortedStocks,
96 ScreenerType::SmallCapGainers,
97 ScreenerType::UndervaluedGrowthStocks,
98 ScreenerType::UndervaluedLargeCaps,
99 ScreenerType::ConservativeForeignFunds,
100 ScreenerType::HighYieldBond,
101 ScreenerType::PortfolioAnchors,
102 ScreenerType::SolidLargeGrowthFunds,
103 ScreenerType::SolidMidcapGrowthFunds,
104 ScreenerType::TopMutualFunds,
105 ]
106 }
107 }
108
109 impl std::str::FromStr for ScreenerType {
110 type Err = ();
111
112 fn from_str(s: &str) -> Result<Self, Self::Err> {
113 match s.to_lowercase().replace('_', "-").as_str() {
114 "aggressive-small-caps" => Ok(ScreenerType::AggressiveSmallCaps),
115 "day-gainers" | "gainers" => Ok(ScreenerType::DayGainers),
116 "day-losers" | "losers" => Ok(ScreenerType::DayLosers),
117 "growth-technology-stocks" | "growth-tech" => {
118 Ok(ScreenerType::GrowthTechnologyStocks)
119 }
120 "most-actives" | "actives" => Ok(ScreenerType::MostActives),
121 "most-shorted-stocks" | "most-shorted" => Ok(ScreenerType::MostShortedStocks),
122 "small-cap-gainers" => Ok(ScreenerType::SmallCapGainers),
123 "undervalued-growth-stocks" | "undervalued-growth" => {
124 Ok(ScreenerType::UndervaluedGrowthStocks)
125 }
126 "undervalued-large-caps" | "undervalued-large" => {
127 Ok(ScreenerType::UndervaluedLargeCaps)
128 }
129 "conservative-foreign-funds" => Ok(ScreenerType::ConservativeForeignFunds),
130 "high-yield-bond" => Ok(ScreenerType::HighYieldBond),
131 "portfolio-anchors" => Ok(ScreenerType::PortfolioAnchors),
132 "solid-large-growth-funds" => Ok(ScreenerType::SolidLargeGrowthFunds),
133 "solid-midcap-growth-funds" => Ok(ScreenerType::SolidMidcapGrowthFunds),
134 "top-mutual-funds" => Ok(ScreenerType::TopMutualFunds),
135 _ => Err(()),
136 }
137 }
138 }
139}
140
141pub mod sector_types {
145 use serde::{Deserialize, Serialize};
146
147 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149 #[serde(rename_all = "kebab-case")]
150 pub enum SectorType {
151 Technology,
153 FinancialServices,
155 ConsumerCyclical,
157 CommunicationServices,
159 Healthcare,
161 Industrials,
163 ConsumerDefensive,
165 Energy,
167 BasicMaterials,
169 RealEstate,
171 Utilities,
173 }
174
175 impl SectorType {
176 pub fn as_api_path(&self) -> &'static str {
178 match self {
179 SectorType::Technology => "technology",
180 SectorType::FinancialServices => "financial-services",
181 SectorType::ConsumerCyclical => "consumer-cyclical",
182 SectorType::CommunicationServices => "communication-services",
183 SectorType::Healthcare => "healthcare",
184 SectorType::Industrials => "industrials",
185 SectorType::ConsumerDefensive => "consumer-defensive",
186 SectorType::Energy => "energy",
187 SectorType::BasicMaterials => "basic-materials",
188 SectorType::RealEstate => "real-estate",
189 SectorType::Utilities => "utilities",
190 }
191 }
192
193 pub fn display_name(&self) -> &'static str {
195 match self {
196 SectorType::Technology => "Technology",
197 SectorType::FinancialServices => "Financial Services",
198 SectorType::ConsumerCyclical => "Consumer Cyclical",
199 SectorType::CommunicationServices => "Communication Services",
200 SectorType::Healthcare => "Healthcare",
201 SectorType::Industrials => "Industrials",
202 SectorType::ConsumerDefensive => "Consumer Defensive",
203 SectorType::Energy => "Energy",
204 SectorType::BasicMaterials => "Basic Materials",
205 SectorType::RealEstate => "Real Estate",
206 SectorType::Utilities => "Utilities",
207 }
208 }
209
210 pub fn valid_types() -> &'static str {
212 "technology, financial-services, consumer-cyclical, communication-services, \
213 healthcare, industrials, consumer-defensive, energy, basic-materials, \
214 real-estate, utilities"
215 }
216
217 pub fn all() -> &'static [SectorType] {
219 &[
220 SectorType::Technology,
221 SectorType::FinancialServices,
222 SectorType::ConsumerCyclical,
223 SectorType::CommunicationServices,
224 SectorType::Healthcare,
225 SectorType::Industrials,
226 SectorType::ConsumerDefensive,
227 SectorType::Energy,
228 SectorType::BasicMaterials,
229 SectorType::RealEstate,
230 SectorType::Utilities,
231 ]
232 }
233 }
234
235 impl std::str::FromStr for SectorType {
236 type Err = ();
237
238 fn from_str(s: &str) -> Result<Self, Self::Err> {
239 match s.to_lowercase().replace('_', "-").as_str() {
240 "technology" | "tech" => Ok(SectorType::Technology),
241 "financial-services" | "financials" | "financial" => {
242 Ok(SectorType::FinancialServices)
243 }
244 "consumer-cyclical" => Ok(SectorType::ConsumerCyclical),
245 "communication-services" | "communication" => Ok(SectorType::CommunicationServices),
246 "healthcare" | "health" => Ok(SectorType::Healthcare),
247 "industrials" | "industrial" => Ok(SectorType::Industrials),
248 "consumer-defensive" => Ok(SectorType::ConsumerDefensive),
249 "energy" => Ok(SectorType::Energy),
250 "basic-materials" | "materials" => Ok(SectorType::BasicMaterials),
251 "real-estate" | "realestate" => Ok(SectorType::RealEstate),
252 "utilities" | "utility" => Ok(SectorType::Utilities),
253 _ => Err(()),
254 }
255 }
256 }
257
258 impl std::fmt::Display for SectorType {
259 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260 write!(f, "{}", self.display_name())
261 }
262 }
263}
264
265pub mod screener_query {
269 use serde::{Deserialize, Serialize};
270
271 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
275 #[serde(rename_all = "UPPERCASE")]
276 pub enum QuoteType {
277 #[default]
279 #[serde(rename = "EQUITY")]
280 Equity,
281 #[serde(rename = "MUTUALFUND")]
283 MutualFund,
284 }
285
286 impl QuoteType {
287 pub fn valid_types() -> &'static str {
289 "equity, mutualfund"
290 }
291 }
292
293 impl std::str::FromStr for QuoteType {
294 type Err = ();
295
296 fn from_str(s: &str) -> Result<Self, Self::Err> {
297 match s.to_lowercase().replace(['-', '_'], "").as_str() {
298 "equity" | "stock" | "stocks" => Ok(QuoteType::Equity),
299 "mutualfund" | "fund" | "funds" => Ok(QuoteType::MutualFund),
300 _ => Err(()),
301 }
302 }
303 }
304
305 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
307 #[serde(rename_all = "UPPERCASE")]
308 pub enum SortType {
309 #[serde(rename = "ASC")]
311 Asc,
312 #[default]
314 #[serde(rename = "DESC")]
315 Desc,
316 }
317
318 impl std::str::FromStr for SortType {
319 type Err = ();
320
321 fn from_str(s: &str) -> Result<Self, Self::Err> {
322 match s.to_lowercase().as_str() {
323 "asc" | "ascending" => Ok(SortType::Asc),
324 "desc" | "descending" => Ok(SortType::Desc),
325 _ => Err(()),
326 }
327 }
328 }
329
330 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
332 #[serde(rename_all = "lowercase")]
333 pub enum Operator {
334 #[serde(rename = "eq")]
336 Eq,
337 #[serde(rename = "gt")]
339 Gt,
340 #[serde(rename = "gte")]
342 Gte,
343 #[serde(rename = "lt")]
345 Lt,
346 #[serde(rename = "lte")]
348 Lte,
349 #[serde(rename = "btwn")]
351 Between,
352 }
353
354 impl std::str::FromStr for Operator {
355 type Err = ();
356
357 fn from_str(s: &str) -> Result<Self, Self::Err> {
358 match s.to_lowercase().as_str() {
359 "eq" | "=" | "==" => Ok(Operator::Eq),
360 "gt" | ">" => Ok(Operator::Gt),
361 "gte" | ">=" => Ok(Operator::Gte),
362 "lt" | "<" => Ok(Operator::Lt),
363 "lte" | "<=" => Ok(Operator::Lte),
364 "btwn" | "between" => Ok(Operator::Between),
365 _ => Err(()),
366 }
367 }
368 }
369
370 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
372 #[serde(rename_all = "lowercase")]
373 pub enum LogicalOperator {
374 #[default]
376 And,
377 Or,
379 }
380
381 impl std::str::FromStr for LogicalOperator {
382 type Err = ();
383
384 fn from_str(s: &str) -> Result<Self, Self::Err> {
385 match s.to_lowercase().as_str() {
386 "and" | "&&" => Ok(LogicalOperator::And),
387 "or" | "||" => Ok(LogicalOperator::Or),
388 _ => Err(()),
389 }
390 }
391 }
392
393 #[allow(missing_docs)]
397 pub mod equity_fields {
398 pub const EOD_PRICE: &str = "eodprice";
400 pub const INTRADAY_PRICE_CHANGE: &str = "intradaypricechange";
401 pub const INTRADAY_PRICE: &str = "intradayprice";
402 pub const PERCENT_CHANGE: &str = "percentchange";
403 pub const LASTCLOSE_52WK_HIGH: &str = "lastclose52weekhigh.lasttwelvemonths";
404 pub const FIFTY_TWO_WK_PCT_CHANGE: &str = "fiftytwowkpercentchange";
405 pub const LASTCLOSE_52WK_LOW: &str = "lastclose52weeklow.lasttwelvemonths";
406 pub const INTRADAY_MARKET_CAP: &str = "intradaymarketcap";
407 pub const LASTCLOSE_MARKET_CAP: &str = "lastclosemarketcap.lasttwelvemonths";
408
409 pub const REGION: &str = "region";
411 pub const SECTOR: &str = "sector";
412 pub const PEER_GROUP: &str = "peer_group";
413 pub const INDUSTRY: &str = "industry";
414 pub const EXCHANGE: &str = "exchange";
415
416 pub const BETA: &str = "beta";
418 pub const AVG_DAILY_VOL_3M: &str = "avgdailyvol3m";
419 pub const PCT_HELD_INSIDER: &str = "pctheldinsider";
420 pub const PCT_HELD_INST: &str = "pctheldinst";
421 pub const DAY_VOLUME: &str = "dayvolume";
422 pub const EOD_VOLUME: &str = "eodvolume";
423
424 pub const SHORT_PCT_SHARES_OUT: &str = "short_percentage_of_shares_outstanding.value";
426 pub const SHORT_INTEREST: &str = "short_interest.value";
427 pub const SHORT_PCT_FLOAT: &str = "short_percentage_of_float.value";
428 pub const DAYS_TO_COVER: &str = "days_to_cover_short.value";
429 pub const SHORT_INTEREST_PCT_CHANGE: &str = "short_interest_percentage_change.value";
430
431 pub const BOOK_VALUE_SHARE: &str = "bookvalueshare.lasttwelvemonths";
433 pub const MARKET_CAP_TO_REVENUE: &str = "lastclosemarketcaptotalrevenue.lasttwelvemonths";
434 pub const TEV_TO_REVENUE: &str = "lastclosetevtotalrevenue.lasttwelvemonths";
435 pub const PRICE_BOOK_RATIO: &str = "pricebookratio.quarterly";
436 pub const PE_RATIO: &str = "peratio.lasttwelvemonths";
437 pub const PRICE_TANGIBLE_BOOK: &str = "lastclosepricetangiblebookvalue.lasttwelvemonths";
438 pub const PRICE_EARNINGS: &str = "lastclosepriceearnings.lasttwelvemonths";
439 pub const PEG_RATIO_5Y: &str = "pegratio_5y";
440
441 pub const CONSECUTIVE_DIV_YEARS: &str = "consecutive_years_of_dividend_growth_count";
443 pub const ROA: &str = "returnonassets.lasttwelvemonths";
444 pub const ROE: &str = "returnonequity.lasttwelvemonths";
445 pub const FORWARD_DIV_PER_SHARE: &str = "forward_dividend_per_share";
446 pub const FORWARD_DIV_YIELD: &str = "forward_dividend_yield";
447 pub const RETURN_ON_CAPITAL: &str = "returnontotalcapital.lasttwelvemonths";
448
449 pub const TEV_EBIT: &str = "lastclosetevebit.lasttwelvemonths";
451 pub const NET_DEBT_EBITDA: &str = "netdebtebitda.lasttwelvemonths";
452 pub const TOTAL_DEBT_EQUITY: &str = "totaldebtequity.lasttwelvemonths";
453 pub const LT_DEBT_EQUITY: &str = "ltdebtequity.lasttwelvemonths";
454 pub const EBIT_INTEREST_EXP: &str = "ebitinterestexpense.lasttwelvemonths";
455 pub const EBITDA_INTEREST_EXP: &str = "ebitdainterestexpense.lasttwelvemonths";
456 pub const TEV_EBITDA: &str = "lastclosetevebitda.lasttwelvemonths";
457 pub const TOTAL_DEBT_EBITDA: &str = "totaldebtebitda.lasttwelvemonths";
458
459 pub const QUICK_RATIO: &str = "quickratio.lasttwelvemonths";
461 pub const ALTMAN_Z_SCORE: &str =
462 "altmanzscoreusingtheaveragestockinformationforaperiod.lasttwelvemonths";
463 pub const CURRENT_RATIO: &str = "currentratio.lasttwelvemonths";
464 pub const OCF_TO_CURRENT_LIAB: &str =
465 "operatingcashflowtocurrentliabilities.lasttwelvemonths";
466
467 pub const TOTAL_REVENUES: &str = "totalrevenues.lasttwelvemonths";
469 pub const NET_INCOME_MARGIN: &str = "netincomemargin.lasttwelvemonths";
470 pub const GROSS_PROFIT: &str = "grossprofit.lasttwelvemonths";
471 pub const EBITDA_1YR_GROWTH: &str = "ebitda1yrgrowth.lasttwelvemonths";
472 pub const DILUTED_EPS_CONT_OPS: &str = "dilutedepscontinuingoperations.lasttwelvemonths";
473 pub const QUARTERLY_REV_GROWTH: &str = "quarterlyrevenuegrowth.quarterly";
474 pub const EPS_GROWTH: &str = "epsgrowth.lasttwelvemonths";
475 pub const NET_INCOME: &str = "netincomeis.lasttwelvemonths";
476 pub const EBITDA: &str = "ebitda.lasttwelvemonths";
477 pub const DILUTED_EPS_1YR_GROWTH: &str = "dilutedeps1yrgrowth.lasttwelvemonths";
478 pub const REVENUE_1YR_GROWTH: &str = "totalrevenues1yrgrowth.lasttwelvemonths";
479 pub const OPERATING_INCOME: &str = "operatingincome.lasttwelvemonths";
480 pub const NET_INCOME_1YR_GROWTH: &str = "netincome1yrgrowth.lasttwelvemonths";
481 pub const GROSS_PROFIT_MARGIN: &str = "grossprofitmargin.lasttwelvemonths";
482 pub const EBITDA_MARGIN: &str = "ebitdamargin.lasttwelvemonths";
483 pub const EBIT: &str = "ebit.lasttwelvemonths";
484 pub const BASIC_EPS_CONT_OPS: &str = "basicepscontinuingoperations.lasttwelvemonths";
485 pub const NET_EPS_BASIC: &str = "netepsbasic.lasttwelvemonths";
486 pub const NET_EPS_DILUTED: &str = "netepsdiluted.lasttwelvemonths";
487
488 pub const TOTAL_ASSETS: &str = "totalassets.lasttwelvemonths";
490 pub const COMMON_SHARES_OUT: &str = "totalcommonsharesoutstanding.lasttwelvemonths";
491 pub const TOTAL_DEBT: &str = "totaldebt.lasttwelvemonths";
492 pub const TOTAL_EQUITY: &str = "totalequity.lasttwelvemonths";
493 pub const TOTAL_CURRENT_ASSETS: &str = "totalcurrentassets.lasttwelvemonths";
494 pub const CASH_AND_ST_INVESTMENTS: &str =
495 "totalcashandshortterminvestments.lasttwelvemonths";
496 pub const TOTAL_COMMON_EQUITY: &str = "totalcommonequity.lasttwelvemonths";
497 pub const TOTAL_CURRENT_LIAB: &str = "totalcurrentliabilities.lasttwelvemonths";
498 pub const TOTAL_SHARES_OUT: &str = "totalsharesoutstanding";
499
500 pub const LEVERED_FCF: &str = "leveredfreecashflow.lasttwelvemonths";
502 pub const CAPEX: &str = "capitalexpenditure.lasttwelvemonths";
503 pub const CASH_FROM_OPS: &str = "cashfromoperations.lasttwelvemonths";
504 pub const LEVERED_FCF_1YR_GROWTH: &str = "leveredfreecashflow1yrgrowth.lasttwelvemonths";
505 pub const UNLEVERED_FCF: &str = "unleveredfreecashflow.lasttwelvemonths";
506 pub const CASH_FROM_OPS_1YR_GROWTH: &str = "cashfromoperations1yrgrowth.lasttwelvemonths";
507
508 pub const ESG_SCORE: &str = "esg_score";
510 pub const ENVIRONMENTAL_SCORE: &str = "environmental_score";
511 pub const GOVERNANCE_SCORE: &str = "governance_score";
512 pub const SOCIAL_SCORE: &str = "social_score";
513 pub const HIGHEST_CONTROVERSY: &str = "highest_controversy";
514 }
515
516 #[allow(missing_docs)]
518 pub mod fund_fields {
519 pub const EOD_PRICE: &str = "eodprice";
521 pub const INTRADAY_PRICE_CHANGE: &str = "intradaypricechange";
522 pub const INTRADAY_PRICE: &str = "intradayprice";
523
524 pub const CATEGORY_NAME: &str = "categoryname";
526 pub const PERFORMANCE_RATING: &str = "performanceratingoverall";
527 pub const INITIAL_INVESTMENT: &str = "initialinvestment";
528 pub const ANNUAL_RETURN_RANK: &str = "annualreturnnavy1categoryrank";
529 pub const RISK_RATING: &str = "riskratingoverall";
530 pub const EXCHANGE: &str = "exchange";
531 }
532
533 pub const VALID_EQUITY_FIELDS: &[&str] = &[
535 equity_fields::EOD_PRICE,
536 equity_fields::INTRADAY_PRICE_CHANGE,
537 equity_fields::INTRADAY_PRICE,
538 equity_fields::PERCENT_CHANGE,
539 equity_fields::LASTCLOSE_52WK_HIGH,
540 equity_fields::FIFTY_TWO_WK_PCT_CHANGE,
541 equity_fields::LASTCLOSE_52WK_LOW,
542 equity_fields::INTRADAY_MARKET_CAP,
543 equity_fields::LASTCLOSE_MARKET_CAP,
544 equity_fields::REGION,
545 equity_fields::SECTOR,
546 equity_fields::PEER_GROUP,
547 equity_fields::INDUSTRY,
548 equity_fields::EXCHANGE,
549 equity_fields::BETA,
550 equity_fields::AVG_DAILY_VOL_3M,
551 equity_fields::PCT_HELD_INSIDER,
552 equity_fields::PCT_HELD_INST,
553 equity_fields::DAY_VOLUME,
554 equity_fields::EOD_VOLUME,
555 equity_fields::SHORT_PCT_SHARES_OUT,
556 equity_fields::SHORT_INTEREST,
557 equity_fields::SHORT_PCT_FLOAT,
558 equity_fields::DAYS_TO_COVER,
559 equity_fields::SHORT_INTEREST_PCT_CHANGE,
560 equity_fields::BOOK_VALUE_SHARE,
561 equity_fields::MARKET_CAP_TO_REVENUE,
562 equity_fields::TEV_TO_REVENUE,
563 equity_fields::PRICE_BOOK_RATIO,
564 equity_fields::PE_RATIO,
565 equity_fields::PRICE_TANGIBLE_BOOK,
566 equity_fields::PRICE_EARNINGS,
567 equity_fields::PEG_RATIO_5Y,
568 equity_fields::CONSECUTIVE_DIV_YEARS,
569 equity_fields::ROA,
570 equity_fields::ROE,
571 equity_fields::FORWARD_DIV_PER_SHARE,
572 equity_fields::FORWARD_DIV_YIELD,
573 equity_fields::RETURN_ON_CAPITAL,
574 equity_fields::TEV_EBIT,
575 equity_fields::NET_DEBT_EBITDA,
576 equity_fields::TOTAL_DEBT_EQUITY,
577 equity_fields::LT_DEBT_EQUITY,
578 equity_fields::EBIT_INTEREST_EXP,
579 equity_fields::EBITDA_INTEREST_EXP,
580 equity_fields::TEV_EBITDA,
581 equity_fields::TOTAL_DEBT_EBITDA,
582 equity_fields::QUICK_RATIO,
583 equity_fields::ALTMAN_Z_SCORE,
584 equity_fields::CURRENT_RATIO,
585 equity_fields::OCF_TO_CURRENT_LIAB,
586 equity_fields::TOTAL_REVENUES,
587 equity_fields::NET_INCOME_MARGIN,
588 equity_fields::GROSS_PROFIT,
589 equity_fields::EBITDA_1YR_GROWTH,
590 equity_fields::DILUTED_EPS_CONT_OPS,
591 equity_fields::QUARTERLY_REV_GROWTH,
592 equity_fields::EPS_GROWTH,
593 equity_fields::NET_INCOME,
594 equity_fields::EBITDA,
595 equity_fields::DILUTED_EPS_1YR_GROWTH,
596 equity_fields::REVENUE_1YR_GROWTH,
597 equity_fields::OPERATING_INCOME,
598 equity_fields::NET_INCOME_1YR_GROWTH,
599 equity_fields::GROSS_PROFIT_MARGIN,
600 equity_fields::EBITDA_MARGIN,
601 equity_fields::EBIT,
602 equity_fields::BASIC_EPS_CONT_OPS,
603 equity_fields::NET_EPS_BASIC,
604 equity_fields::NET_EPS_DILUTED,
605 equity_fields::TOTAL_ASSETS,
606 equity_fields::COMMON_SHARES_OUT,
607 equity_fields::TOTAL_DEBT,
608 equity_fields::TOTAL_EQUITY,
609 equity_fields::TOTAL_CURRENT_ASSETS,
610 equity_fields::CASH_AND_ST_INVESTMENTS,
611 equity_fields::TOTAL_COMMON_EQUITY,
612 equity_fields::TOTAL_CURRENT_LIAB,
613 equity_fields::TOTAL_SHARES_OUT,
614 equity_fields::LEVERED_FCF,
615 equity_fields::CAPEX,
616 equity_fields::CASH_FROM_OPS,
617 equity_fields::LEVERED_FCF_1YR_GROWTH,
618 equity_fields::UNLEVERED_FCF,
619 equity_fields::CASH_FROM_OPS_1YR_GROWTH,
620 equity_fields::ESG_SCORE,
621 equity_fields::ENVIRONMENTAL_SCORE,
622 equity_fields::GOVERNANCE_SCORE,
623 equity_fields::SOCIAL_SCORE,
624 equity_fields::HIGHEST_CONTROVERSY,
625 ];
626
627 pub const VALID_FUND_FIELDS: &[&str] = &[
629 fund_fields::EOD_PRICE,
630 fund_fields::INTRADAY_PRICE_CHANGE,
631 fund_fields::INTRADAY_PRICE,
632 fund_fields::CATEGORY_NAME,
633 fund_fields::PERFORMANCE_RATING,
634 fund_fields::INITIAL_INVESTMENT,
635 fund_fields::ANNUAL_RETURN_RANK,
636 fund_fields::RISK_RATING,
637 fund_fields::EXCHANGE,
638 ];
639
640 pub fn is_valid_equity_field(field: &str) -> bool {
642 VALID_EQUITY_FIELDS.contains(&field)
643 }
644
645 pub fn is_valid_fund_field(field: &str) -> bool {
647 VALID_FUND_FIELDS.contains(&field)
648 }
649
650 pub fn is_valid_field(field: &str, quote_type: QuoteType) -> bool {
652 match quote_type {
653 QuoteType::Equity => is_valid_equity_field(field),
654 QuoteType::MutualFund => is_valid_fund_field(field),
655 }
656 }
657}
658
659pub mod indices {
661 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
663 pub enum Region {
664 Americas,
666 Europe,
668 AsiaPacific,
670 MiddleEastAfrica,
672 Currencies,
674 }
675
676 impl std::str::FromStr for Region {
677 type Err = ();
678
679 fn from_str(s: &str) -> Result<Self, Self::Err> {
680 match s.to_lowercase().replace(['-', '_'], "").as_str() {
681 "americas" | "america" => Ok(Region::Americas),
682 "europe" | "eu" => Ok(Region::Europe),
683 "asiapacific" | "asia" | "apac" => Ok(Region::AsiaPacific),
684 "middleeastafrica" | "mea" | "emea" => Ok(Region::MiddleEastAfrica),
685 "currencies" | "currency" | "fx" => Ok(Region::Currencies),
686 _ => Err(()),
687 }
688 }
689 }
690
691 impl Region {
692 pub fn parse(s: &str) -> Option<Self> {
694 s.parse().ok()
695 }
696
697 pub fn symbols(&self) -> &'static [&'static str] {
699 match self {
700 Region::Americas => AMERICAS,
701 Region::Europe => EUROPE,
702 Region::AsiaPacific => ASIA_PACIFIC,
703 Region::MiddleEastAfrica => MIDDLE_EAST_AFRICA,
704 Region::Currencies => CURRENCIES,
705 }
706 }
707
708 pub fn as_str(&self) -> &'static str {
710 match self {
711 Region::Americas => "americas",
712 Region::Europe => "europe",
713 Region::AsiaPacific => "asia-pacific",
714 Region::MiddleEastAfrica => "middle-east-africa",
715 Region::Currencies => "currencies",
716 }
717 }
718
719 pub fn all() -> &'static [Region] {
721 &[
722 Region::Americas,
723 Region::Europe,
724 Region::AsiaPacific,
725 Region::MiddleEastAfrica,
726 Region::Currencies,
727 ]
728 }
729 }
730
731 pub const AMERICAS: &[&str] = &[
733 "^GSPC", "^DJI", "^IXIC", "^NYA", "^XAX", "^RUT", "^VIX", "^GSPTSE", "^BVSP", "^MXX", "^IPSA", "^MERV", ];
746
747 pub const EUROPE: &[&str] = &[
749 "^FTSE", "^GDAXI", "^FCHI", "^STOXX50E", "^N100", "^BFX", "^BUK100P", "MOEX.ME", "^125904-USD-STRD", ];
759
760 pub const ASIA_PACIFIC: &[&str] = &[
762 "^N225", "^HSI", "000001.SS", "^KS11", "^TWII", "^STI", "^AXJO", "^AORD", "^NZ50", "^BSESN", "^JKSE", "^KLSE", ];
775
776 pub const MIDDLE_EAST_AFRICA: &[&str] = &[
778 "^TA125.TA", "^CASE30", "^JN0U.JO", ];
782
783 pub const CURRENCIES: &[&str] = &[
785 "DX-Y.NYB", "^XDB", "^XDE", "^XDN", "^XDA", ];
791
792 pub fn all_symbols() -> Vec<&'static str> {
794 Region::all()
795 .iter()
796 .flat_map(|r| r.symbols().iter().copied())
797 .collect()
798 }
799}
800
801#[allow(missing_docs)]
806pub mod fundamental_types {
807 pub const TOTAL_REVENUE: &str = "TotalRevenue";
811 pub const OPERATING_REVENUE: &str = "OperatingRevenue";
812 pub const COST_OF_REVENUE: &str = "CostOfRevenue";
813 pub const GROSS_PROFIT: &str = "GrossProfit";
814 pub const OPERATING_EXPENSE: &str = "OperatingExpense";
815 pub const SELLING_GENERAL_AND_ADMIN: &str = "SellingGeneralAndAdministration";
816 pub const RESEARCH_AND_DEVELOPMENT: &str = "ResearchAndDevelopment";
817 pub const OPERATING_INCOME: &str = "OperatingIncome";
818 pub const NET_INTEREST_INCOME: &str = "NetInterestIncome";
819 pub const INTEREST_EXPENSE: &str = "InterestExpense";
820 pub const INTEREST_INCOME: &str = "InterestIncome";
821 pub const NET_NON_OPERATING_INTEREST_INCOME_EXPENSE: &str =
822 "NetNonOperatingInterestIncomeExpense";
823 pub const OTHER_INCOME_EXPENSE: &str = "OtherIncomeExpense";
824 pub const PRETAX_INCOME: &str = "PretaxIncome";
825 pub const TAX_PROVISION: &str = "TaxProvision";
826 pub const NET_INCOME_COMMON_STOCKHOLDERS: &str = "NetIncomeCommonStockholders";
827 pub const NET_INCOME: &str = "NetIncome";
828 pub const DILUTED_EPS: &str = "DilutedEPS";
829 pub const BASIC_EPS: &str = "BasicEPS";
830 pub const DILUTED_AVERAGE_SHARES: &str = "DilutedAverageShares";
831 pub const BASIC_AVERAGE_SHARES: &str = "BasicAverageShares";
832 pub const EBIT: &str = "EBIT";
833 pub const EBITDA: &str = "EBITDA";
834 pub const RECONCILED_COST_OF_REVENUE: &str = "ReconciledCostOfRevenue";
835 pub const RECONCILED_DEPRECIATION: &str = "ReconciledDepreciation";
836 pub const NET_INCOME_FROM_CONTINUING_OPERATION_NET_MINORITY_INTEREST: &str =
837 "NetIncomeFromContinuingOperationNetMinorityInterest";
838 pub const NORMALIZED_EBITDA: &str = "NormalizedEBITDA";
839 pub const TOTAL_EXPENSES: &str = "TotalExpenses";
840 pub const TOTAL_OPERATING_INCOME_AS_REPORTED: &str = "TotalOperatingIncomeAsReported";
841
842 pub const TOTAL_ASSETS: &str = "TotalAssets";
846 pub const CURRENT_ASSETS: &str = "CurrentAssets";
847 pub const CASH_CASH_EQUIVALENTS_AND_SHORT_TERM_INVESTMENTS: &str =
848 "CashCashEquivalentsAndShortTermInvestments";
849 pub const CASH_AND_CASH_EQUIVALENTS: &str = "CashAndCashEquivalents";
850 pub const CASH_FINANCIAL: &str = "CashFinancial";
851 pub const RECEIVABLES: &str = "Receivables";
852 pub const ACCOUNTS_RECEIVABLE: &str = "AccountsReceivable";
853 pub const INVENTORY: &str = "Inventory";
854 pub const PREPAID_ASSETS: &str = "PrepaidAssets";
855 pub const OTHER_CURRENT_ASSETS: &str = "OtherCurrentAssets";
856 pub const TOTAL_NON_CURRENT_ASSETS: &str = "TotalNonCurrentAssets";
857 pub const NET_PPE: &str = "NetPPE";
858 pub const GROSS_PPE: &str = "GrossPPE";
859 pub const ACCUMULATED_DEPRECIATION: &str = "AccumulatedDepreciation";
860 pub const GOODWILL: &str = "Goodwill";
861 pub const GOODWILL_AND_OTHER_INTANGIBLE_ASSETS: &str = "GoodwillAndOtherIntangibleAssets";
862 pub const OTHER_INTANGIBLE_ASSETS: &str = "OtherIntangibleAssets";
863 pub const INVESTMENTS_AND_ADVANCES: &str = "InvestmentsAndAdvances";
864 pub const LONG_TERM_EQUITY_INVESTMENT: &str = "LongTermEquityInvestment";
865 pub const OTHER_NON_CURRENT_ASSETS: &str = "OtherNonCurrentAssets";
866 pub const TOTAL_LIABILITIES_NET_MINORITY_INTEREST: &str = "TotalLiabilitiesNetMinorityInterest";
867 pub const CURRENT_LIABILITIES: &str = "CurrentLiabilities";
868 pub const PAYABLES_AND_ACCRUED_EXPENSES: &str = "PayablesAndAccruedExpenses";
869 pub const ACCOUNTS_PAYABLE: &str = "AccountsPayable";
870 pub const CURRENT_DEBT: &str = "CurrentDebt";
871 pub const CURRENT_DEFERRED_REVENUE: &str = "CurrentDeferredRevenue";
872 pub const OTHER_CURRENT_LIABILITIES: &str = "OtherCurrentLiabilities";
873 pub const TOTAL_NON_CURRENT_LIABILITIES_NET_MINORITY_INTEREST: &str =
874 "TotalNonCurrentLiabilitiesNetMinorityInterest";
875 pub const LONG_TERM_DEBT: &str = "LongTermDebt";
876 pub const LONG_TERM_DEBT_AND_CAPITAL_LEASE_OBLIGATION: &str =
877 "LongTermDebtAndCapitalLeaseObligation";
878 pub const NON_CURRENT_DEFERRED_REVENUE: &str = "NonCurrentDeferredRevenue";
879 pub const NON_CURRENT_DEFERRED_TAXES_LIABILITIES: &str = "NonCurrentDeferredTaxesLiabilities";
880 pub const OTHER_NON_CURRENT_LIABILITIES: &str = "OtherNonCurrentLiabilities";
881 pub const STOCKHOLDERS_EQUITY: &str = "StockholdersEquity";
882 pub const COMMON_STOCK_EQUITY: &str = "CommonStockEquity";
883 pub const COMMON_STOCK: &str = "CommonStock";
884 pub const RETAINED_EARNINGS: &str = "RetainedEarnings";
885 pub const ADDITIONAL_PAID_IN_CAPITAL: &str = "AdditionalPaidInCapital";
886 pub const TREASURY_STOCK: &str = "TreasuryStock";
887 pub const TOTAL_EQUITY_GROSS_MINORITY_INTEREST: &str = "TotalEquityGrossMinorityInterest";
888 pub const WORKING_CAPITAL: &str = "WorkingCapital";
889 pub const INVESTED_CAPITAL: &str = "InvestedCapital";
890 pub const TANGIBLE_BOOK_VALUE: &str = "TangibleBookValue";
891 pub const TOTAL_DEBT: &str = "TotalDebt";
892 pub const NET_DEBT: &str = "NetDebt";
893 pub const SHARE_ISSUED: &str = "ShareIssued";
894 pub const ORDINARY_SHARES_NUMBER: &str = "OrdinarySharesNumber";
895
896 pub const OPERATING_CASH_FLOW: &str = "OperatingCashFlow";
900 pub const CASH_FLOW_FROM_CONTINUING_OPERATING_ACTIVITIES: &str =
901 "CashFlowFromContinuingOperatingActivities";
902 pub const NET_INCOME_FROM_CONTINUING_OPERATIONS: &str = "NetIncomeFromContinuingOperations";
903 pub const DEPRECIATION_AND_AMORTIZATION: &str = "DepreciationAndAmortization";
904 pub const DEFERRED_INCOME_TAX: &str = "DeferredIncomeTax";
905 pub const CHANGE_IN_WORKING_CAPITAL: &str = "ChangeInWorkingCapital";
906 pub const CHANGE_IN_RECEIVABLES: &str = "ChangeInReceivables";
907 pub const CHANGES_IN_ACCOUNT_RECEIVABLES: &str = "ChangesInAccountReceivables";
908 pub const CHANGE_IN_INVENTORY: &str = "ChangeInInventory";
909 pub const CHANGE_IN_ACCOUNT_PAYABLE: &str = "ChangeInAccountPayable";
910 pub const CHANGE_IN_OTHER_WORKING_CAPITAL: &str = "ChangeInOtherWorkingCapital";
911 pub const STOCK_BASED_COMPENSATION: &str = "StockBasedCompensation";
912 pub const OTHER_NON_CASH_ITEMS: &str = "OtherNonCashItems";
913 pub const INVESTING_CASH_FLOW: &str = "InvestingCashFlow";
914 pub const CASH_FLOW_FROM_CONTINUING_INVESTING_ACTIVITIES: &str =
915 "CashFlowFromContinuingInvestingActivities";
916 pub const NET_PPE_PURCHASE_AND_SALE: &str = "NetPPEPurchaseAndSale";
917 pub const PURCHASE_OF_PPE: &str = "PurchaseOfPPE";
918 pub const SALE_OF_PPE: &str = "SaleOfPPE";
919 pub const CAPITAL_EXPENDITURE: &str = "CapitalExpenditure";
920 pub const NET_BUSINESS_PURCHASE_AND_SALE: &str = "NetBusinessPurchaseAndSale";
921 pub const PURCHASE_OF_BUSINESS: &str = "PurchaseOfBusiness";
922 pub const SALE_OF_BUSINESS: &str = "SaleOfBusiness";
923 pub const NET_INVESTMENT_PURCHASE_AND_SALE: &str = "NetInvestmentPurchaseAndSale";
924 pub const PURCHASE_OF_INVESTMENT: &str = "PurchaseOfInvestment";
925 pub const SALE_OF_INVESTMENT: &str = "SaleOfInvestment";
926 pub const NET_OTHER_INVESTING_CHANGES: &str = "NetOtherInvestingChanges";
927 pub const FINANCING_CASH_FLOW: &str = "FinancingCashFlow";
928 pub const CASH_FLOW_FROM_CONTINUING_FINANCING_ACTIVITIES: &str =
929 "CashFlowFromContinuingFinancingActivities";
930 pub const NET_ISSUANCE_PAYMENTS_OF_DEBT: &str = "NetIssuancePaymentsOfDebt";
931 pub const NET_LONG_TERM_DEBT_ISSUANCE: &str = "NetLongTermDebtIssuance";
932 pub const LONG_TERM_DEBT_ISSUANCE: &str = "LongTermDebtIssuance";
933 pub const LONG_TERM_DEBT_PAYMENTS: &str = "LongTermDebtPayments";
934 pub const NET_SHORT_TERM_DEBT_ISSUANCE: &str = "NetShortTermDebtIssuance";
935 pub const NET_COMMON_STOCK_ISSUANCE: &str = "NetCommonStockIssuance";
936 pub const COMMON_STOCK_ISSUANCE: &str = "CommonStockIssuance";
937 pub const COMMON_STOCK_PAYMENTS: &str = "CommonStockPayments";
938 pub const REPURCHASE_OF_CAPITAL_STOCK: &str = "RepurchaseOfCapitalStock";
939 pub const CASH_DIVIDENDS_PAID: &str = "CashDividendsPaid";
940 pub const COMMON_STOCK_DIVIDEND_PAID: &str = "CommonStockDividendPaid";
941 pub const NET_OTHER_FINANCING_CHARGES: &str = "NetOtherFinancingCharges";
942 pub const END_CASH_POSITION: &str = "EndCashPosition";
943 pub const BEGINNING_CASH_POSITION: &str = "BeginningCashPosition";
944 pub const CHANGESIN_CASH: &str = "ChangesinCash";
945 pub const EFFECT_OF_EXCHANGE_RATE_CHANGES: &str = "EffectOfExchangeRateChanges";
946 pub const FREE_CASH_FLOW: &str = "FreeCashFlow";
947 pub const CAPITAL_EXPENDITURE_REPORTED: &str = "CapitalExpenditureReported";
948}
949
950#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
952pub enum StatementType {
953 Income,
955 Balance,
957 CashFlow,
959}
960
961impl StatementType {
962 pub fn as_str(&self) -> &'static str {
964 match self {
965 StatementType::Income => "income",
966 StatementType::Balance => "balance",
967 StatementType::CashFlow => "cashflow",
968 }
969 }
970
971 pub fn get_fields(&self) -> &'static [&'static str] {
975 match self {
976 StatementType::Income => &INCOME_STATEMENT_FIELDS,
977 StatementType::Balance => &BALANCE_SHEET_FIELDS,
978 StatementType::CashFlow => &CASH_FLOW_FIELDS,
979 }
980 }
981}
982
983const INCOME_STATEMENT_FIELDS: [&str; 30] = [
985 fundamental_types::TOTAL_REVENUE,
986 fundamental_types::OPERATING_REVENUE,
987 fundamental_types::COST_OF_REVENUE,
988 fundamental_types::GROSS_PROFIT,
989 fundamental_types::OPERATING_EXPENSE,
990 fundamental_types::SELLING_GENERAL_AND_ADMIN,
991 fundamental_types::RESEARCH_AND_DEVELOPMENT,
992 fundamental_types::OPERATING_INCOME,
993 fundamental_types::NET_INTEREST_INCOME,
994 fundamental_types::INTEREST_EXPENSE,
995 fundamental_types::INTEREST_INCOME,
996 fundamental_types::NET_NON_OPERATING_INTEREST_INCOME_EXPENSE,
997 fundamental_types::OTHER_INCOME_EXPENSE,
998 fundamental_types::PRETAX_INCOME,
999 fundamental_types::TAX_PROVISION,
1000 fundamental_types::NET_INCOME_COMMON_STOCKHOLDERS,
1001 fundamental_types::NET_INCOME,
1002 fundamental_types::DILUTED_EPS,
1003 fundamental_types::BASIC_EPS,
1004 fundamental_types::DILUTED_AVERAGE_SHARES,
1005 fundamental_types::BASIC_AVERAGE_SHARES,
1006 fundamental_types::EBIT,
1007 fundamental_types::EBITDA,
1008 fundamental_types::RECONCILED_COST_OF_REVENUE,
1009 fundamental_types::RECONCILED_DEPRECIATION,
1010 fundamental_types::NET_INCOME_FROM_CONTINUING_OPERATION_NET_MINORITY_INTEREST,
1011 fundamental_types::NORMALIZED_EBITDA,
1012 fundamental_types::TOTAL_EXPENSES,
1013 fundamental_types::TOTAL_OPERATING_INCOME_AS_REPORTED,
1014 fundamental_types::DEPRECIATION_AND_AMORTIZATION,
1015];
1016
1017const BALANCE_SHEET_FIELDS: [&str; 48] = [
1019 fundamental_types::TOTAL_ASSETS,
1020 fundamental_types::CURRENT_ASSETS,
1021 fundamental_types::CASH_CASH_EQUIVALENTS_AND_SHORT_TERM_INVESTMENTS,
1022 fundamental_types::CASH_AND_CASH_EQUIVALENTS,
1023 fundamental_types::CASH_FINANCIAL,
1024 fundamental_types::RECEIVABLES,
1025 fundamental_types::ACCOUNTS_RECEIVABLE,
1026 fundamental_types::INVENTORY,
1027 fundamental_types::PREPAID_ASSETS,
1028 fundamental_types::OTHER_CURRENT_ASSETS,
1029 fundamental_types::TOTAL_NON_CURRENT_ASSETS,
1030 fundamental_types::NET_PPE,
1031 fundamental_types::GROSS_PPE,
1032 fundamental_types::ACCUMULATED_DEPRECIATION,
1033 fundamental_types::GOODWILL,
1034 fundamental_types::GOODWILL_AND_OTHER_INTANGIBLE_ASSETS,
1035 fundamental_types::OTHER_INTANGIBLE_ASSETS,
1036 fundamental_types::INVESTMENTS_AND_ADVANCES,
1037 fundamental_types::LONG_TERM_EQUITY_INVESTMENT,
1038 fundamental_types::OTHER_NON_CURRENT_ASSETS,
1039 fundamental_types::TOTAL_LIABILITIES_NET_MINORITY_INTEREST,
1040 fundamental_types::CURRENT_LIABILITIES,
1041 fundamental_types::PAYABLES_AND_ACCRUED_EXPENSES,
1042 fundamental_types::ACCOUNTS_PAYABLE,
1043 fundamental_types::CURRENT_DEBT,
1044 fundamental_types::CURRENT_DEFERRED_REVENUE,
1045 fundamental_types::OTHER_CURRENT_LIABILITIES,
1046 fundamental_types::TOTAL_NON_CURRENT_LIABILITIES_NET_MINORITY_INTEREST,
1047 fundamental_types::LONG_TERM_DEBT,
1048 fundamental_types::LONG_TERM_DEBT_AND_CAPITAL_LEASE_OBLIGATION,
1049 fundamental_types::NON_CURRENT_DEFERRED_REVENUE,
1050 fundamental_types::NON_CURRENT_DEFERRED_TAXES_LIABILITIES,
1051 fundamental_types::OTHER_NON_CURRENT_LIABILITIES,
1052 fundamental_types::STOCKHOLDERS_EQUITY,
1053 fundamental_types::COMMON_STOCK_EQUITY,
1054 fundamental_types::COMMON_STOCK,
1055 fundamental_types::RETAINED_EARNINGS,
1056 fundamental_types::ADDITIONAL_PAID_IN_CAPITAL,
1057 fundamental_types::TREASURY_STOCK,
1058 fundamental_types::TOTAL_EQUITY_GROSS_MINORITY_INTEREST,
1059 fundamental_types::WORKING_CAPITAL,
1060 fundamental_types::INVESTED_CAPITAL,
1061 fundamental_types::TANGIBLE_BOOK_VALUE,
1062 fundamental_types::TOTAL_DEBT,
1063 fundamental_types::NET_DEBT,
1064 fundamental_types::SHARE_ISSUED,
1065 fundamental_types::ORDINARY_SHARES_NUMBER,
1066 fundamental_types::DEPRECIATION_AND_AMORTIZATION,
1067];
1068
1069const CASH_FLOW_FIELDS: [&str; 47] = [
1071 fundamental_types::OPERATING_CASH_FLOW,
1072 fundamental_types::CASH_FLOW_FROM_CONTINUING_OPERATING_ACTIVITIES,
1073 fundamental_types::NET_INCOME_FROM_CONTINUING_OPERATIONS,
1074 fundamental_types::DEPRECIATION_AND_AMORTIZATION,
1075 fundamental_types::DEFERRED_INCOME_TAX,
1076 fundamental_types::CHANGE_IN_WORKING_CAPITAL,
1077 fundamental_types::CHANGE_IN_RECEIVABLES,
1078 fundamental_types::CHANGES_IN_ACCOUNT_RECEIVABLES,
1079 fundamental_types::CHANGE_IN_INVENTORY,
1080 fundamental_types::CHANGE_IN_ACCOUNT_PAYABLE,
1081 fundamental_types::CHANGE_IN_OTHER_WORKING_CAPITAL,
1082 fundamental_types::STOCK_BASED_COMPENSATION,
1083 fundamental_types::OTHER_NON_CASH_ITEMS,
1084 fundamental_types::INVESTING_CASH_FLOW,
1085 fundamental_types::CASH_FLOW_FROM_CONTINUING_INVESTING_ACTIVITIES,
1086 fundamental_types::NET_PPE_PURCHASE_AND_SALE,
1087 fundamental_types::PURCHASE_OF_PPE,
1088 fundamental_types::SALE_OF_PPE,
1089 fundamental_types::CAPITAL_EXPENDITURE,
1090 fundamental_types::NET_BUSINESS_PURCHASE_AND_SALE,
1091 fundamental_types::PURCHASE_OF_BUSINESS,
1092 fundamental_types::SALE_OF_BUSINESS,
1093 fundamental_types::NET_INVESTMENT_PURCHASE_AND_SALE,
1094 fundamental_types::PURCHASE_OF_INVESTMENT,
1095 fundamental_types::SALE_OF_INVESTMENT,
1096 fundamental_types::NET_OTHER_INVESTING_CHANGES,
1097 fundamental_types::FINANCING_CASH_FLOW,
1098 fundamental_types::CASH_FLOW_FROM_CONTINUING_FINANCING_ACTIVITIES,
1099 fundamental_types::NET_ISSUANCE_PAYMENTS_OF_DEBT,
1100 fundamental_types::NET_LONG_TERM_DEBT_ISSUANCE,
1101 fundamental_types::LONG_TERM_DEBT_ISSUANCE,
1102 fundamental_types::LONG_TERM_DEBT_PAYMENTS,
1103 fundamental_types::NET_SHORT_TERM_DEBT_ISSUANCE,
1104 fundamental_types::NET_COMMON_STOCK_ISSUANCE,
1105 fundamental_types::COMMON_STOCK_ISSUANCE,
1106 fundamental_types::COMMON_STOCK_PAYMENTS,
1107 fundamental_types::REPURCHASE_OF_CAPITAL_STOCK,
1108 fundamental_types::CASH_DIVIDENDS_PAID,
1109 fundamental_types::COMMON_STOCK_DIVIDEND_PAID,
1110 fundamental_types::NET_OTHER_FINANCING_CHARGES,
1111 fundamental_types::END_CASH_POSITION,
1112 fundamental_types::BEGINNING_CASH_POSITION,
1113 fundamental_types::CHANGESIN_CASH,
1114 fundamental_types::EFFECT_OF_EXCHANGE_RATE_CHANGES,
1115 fundamental_types::FREE_CASH_FLOW,
1116 fundamental_types::CAPITAL_EXPENDITURE_REPORTED,
1117 fundamental_types::DEPRECIATION_AND_AMORTIZATION,
1118];
1119
1120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1122pub enum Frequency {
1123 Annual,
1125 Quarterly,
1127}
1128
1129impl Frequency {
1130 pub fn as_str(&self) -> &'static str {
1132 match self {
1133 Frequency::Annual => "annual",
1134 Frequency::Quarterly => "quarterly",
1135 }
1136 }
1137
1138 pub fn prefix(&self, field: &str) -> String {
1149 format!("{}{}", self.as_str(), field)
1150 }
1151}
1152
1153#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1155#[allow(dead_code)]
1156pub enum Interval {
1157 OneMinute,
1159 FiveMinutes,
1161 FifteenMinutes,
1163 ThirtyMinutes,
1165 OneHour,
1167 OneDay,
1169 OneWeek,
1171 OneMonth,
1173 ThreeMonths,
1175}
1176
1177#[allow(dead_code)]
1178impl Interval {
1179 pub fn as_str(&self) -> &'static str {
1181 match self {
1182 Interval::OneMinute => "1m",
1183 Interval::FiveMinutes => "5m",
1184 Interval::FifteenMinutes => "15m",
1185 Interval::ThirtyMinutes => "30m",
1186 Interval::OneHour => "1h",
1187 Interval::OneDay => "1d",
1188 Interval::OneWeek => "1wk",
1189 Interval::OneMonth => "1mo",
1190 Interval::ThreeMonths => "3mo",
1191 }
1192 }
1193}
1194
1195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1197#[allow(dead_code)]
1198pub enum TimeRange {
1199 OneDay,
1201 FiveDays,
1203 OneMonth,
1205 ThreeMonths,
1207 SixMonths,
1209 OneYear,
1211 TwoYears,
1213 FiveYears,
1215 TenYears,
1217 YearToDate,
1219 Max,
1221}
1222
1223#[allow(dead_code)]
1224impl TimeRange {
1225 pub fn as_str(&self) -> &'static str {
1227 match self {
1228 TimeRange::OneDay => "1d",
1229 TimeRange::FiveDays => "5d",
1230 TimeRange::OneMonth => "1mo",
1231 TimeRange::ThreeMonths => "3mo",
1232 TimeRange::SixMonths => "6mo",
1233 TimeRange::OneYear => "1y",
1234 TimeRange::TwoYears => "2y",
1235 TimeRange::FiveYears => "5y",
1236 TimeRange::TenYears => "10y",
1237 TimeRange::YearToDate => "ytd",
1238 TimeRange::Max => "max",
1239 }
1240 }
1241}
1242
1243#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
1248pub enum Region {
1249 Argentina,
1251 Australia,
1253 Brazil,
1255 Canada,
1257 China,
1259 Denmark,
1261 Finland,
1263 France,
1265 Germany,
1267 Greece,
1269 HongKong,
1271 India,
1273 Israel,
1275 Italy,
1277 Malaysia,
1279 NewZealand,
1281 Norway,
1283 Portugal,
1285 Russia,
1287 Singapore,
1289 Spain,
1291 Sweden,
1293 Taiwan,
1295 Thailand,
1297 Turkey,
1299 UnitedKingdom,
1301 #[default]
1303 UnitedStates,
1304 Vietnam,
1306}
1307
1308impl Region {
1309 pub fn lang(&self) -> &'static str {
1320 match self {
1321 Region::Argentina => "es-AR",
1322 Region::Australia => "en-AU",
1323 Region::Brazil => "pt-BR",
1324 Region::Canada => "en-CA",
1325 Region::China => "zh-CN",
1326 Region::Denmark => "da-DK",
1327 Region::Finland => "fi-FI",
1328 Region::France => "fr-FR",
1329 Region::Germany => "de-DE",
1330 Region::Greece => "el-GR",
1331 Region::HongKong => "zh-Hant-HK",
1332 Region::India => "en-IN",
1333 Region::Israel => "he-IL",
1334 Region::Italy => "it-IT",
1335 Region::Malaysia => "ms-MY",
1336 Region::NewZealand => "en-NZ",
1337 Region::Norway => "nb-NO",
1338 Region::Portugal => "pt-PT",
1339 Region::Russia => "ru-RU",
1340 Region::Singapore => "en-SG",
1341 Region::Spain => "es-ES",
1342 Region::Sweden => "sv-SE",
1343 Region::Taiwan => "zh-TW",
1344 Region::Thailand => "th-TH",
1345 Region::Turkey => "tr-TR",
1346 Region::UnitedKingdom => "en-GB",
1347 Region::UnitedStates => "en-US",
1348 Region::Vietnam => "vi-VN",
1349 }
1350 }
1351
1352 pub fn region(&self) -> &'static str {
1363 match self {
1364 Region::Argentina => "AR",
1365 Region::Australia => "AU",
1366 Region::Brazil => "BR",
1367 Region::Canada => "CA",
1368 Region::China => "CN",
1369 Region::Denmark => "DK",
1370 Region::Finland => "FI",
1371 Region::France => "FR",
1372 Region::Germany => "DE",
1373 Region::Greece => "GR",
1374 Region::HongKong => "HK",
1375 Region::India => "IN",
1376 Region::Israel => "IL",
1377 Region::Italy => "IT",
1378 Region::Malaysia => "MY",
1379 Region::NewZealand => "NZ",
1380 Region::Norway => "NO",
1381 Region::Portugal => "PT",
1382 Region::Russia => "RU",
1383 Region::Singapore => "SG",
1384 Region::Spain => "ES",
1385 Region::Sweden => "SE",
1386 Region::Taiwan => "TW",
1387 Region::Thailand => "TH",
1388 Region::Turkey => "TR",
1389 Region::UnitedKingdom => "GB",
1390 Region::UnitedStates => "US",
1391 Region::Vietnam => "VN",
1392 }
1393 }
1394
1395 pub fn cors_domain(&self) -> &'static str {
1406 match self {
1407 Region::Argentina => "ar.finance.yahoo.com",
1408 Region::Australia => "au.finance.yahoo.com",
1409 Region::Brazil => "br.financas.yahoo.com",
1410 Region::Canada => "ca.finance.yahoo.com",
1411 Region::China => "cn.finance.yahoo.com",
1412 Region::Denmark => "dk.finance.yahoo.com",
1413 Region::Finland => "fi.finance.yahoo.com",
1414 Region::France => "fr.finance.yahoo.com",
1415 Region::Germany => "de.finance.yahoo.com",
1416 Region::Greece => "gr.finance.yahoo.com",
1417 Region::HongKong => "hk.finance.yahoo.com",
1418 Region::India => "in.finance.yahoo.com",
1419 Region::Israel => "il.finance.yahoo.com",
1420 Region::Italy => "it.finance.yahoo.com",
1421 Region::Malaysia => "my.finance.yahoo.com",
1422 Region::NewZealand => "nz.finance.yahoo.com",
1423 Region::Norway => "no.finance.yahoo.com",
1424 Region::Portugal => "pt.finance.yahoo.com",
1425 Region::Russia => "ru.finance.yahoo.com",
1426 Region::Singapore => "sg.finance.yahoo.com",
1427 Region::Spain => "es.finance.yahoo.com",
1428 Region::Sweden => "se.finance.yahoo.com",
1429 Region::Taiwan => "tw.finance.yahoo.com",
1430 Region::Thailand => "th.finance.yahoo.com",
1431 Region::Turkey => "tr.finance.yahoo.com",
1432 Region::UnitedKingdom => "uk.finance.yahoo.com",
1433 Region::UnitedStates => "finance.yahoo.com",
1434 Region::Vietnam => "vn.finance.yahoo.com",
1435 }
1436 }
1437}
1438
1439impl std::str::FromStr for Region {
1440 type Err = ();
1441
1442 fn from_str(s: &str) -> Result<Self, Self::Err> {
1443 match s.to_uppercase().as_str() {
1444 "AR" => Ok(Region::Argentina),
1445 "AU" => Ok(Region::Australia),
1446 "BR" => Ok(Region::Brazil),
1447 "CA" => Ok(Region::Canada),
1448 "CN" => Ok(Region::China),
1449 "DK" => Ok(Region::Denmark),
1450 "FI" => Ok(Region::Finland),
1451 "FR" => Ok(Region::France),
1452 "DE" => Ok(Region::Germany),
1453 "GR" => Ok(Region::Greece),
1454 "HK" => Ok(Region::HongKong),
1455 "IN" => Ok(Region::India),
1456 "IL" => Ok(Region::Israel),
1457 "IT" => Ok(Region::Italy),
1458 "MY" => Ok(Region::Malaysia),
1459 "NZ" => Ok(Region::NewZealand),
1460 "NO" => Ok(Region::Norway),
1461 "PT" => Ok(Region::Portugal),
1462 "RU" => Ok(Region::Russia),
1463 "SG" => Ok(Region::Singapore),
1464 "ES" => Ok(Region::Spain),
1465 "SE" => Ok(Region::Sweden),
1466 "TW" => Ok(Region::Taiwan),
1467 "TH" => Ok(Region::Thailand),
1468 "TR" => Ok(Region::Turkey),
1469 "GB" | "UK" => Ok(Region::UnitedKingdom),
1470 "US" => Ok(Region::UnitedStates),
1471 "VN" => Ok(Region::Vietnam),
1472 _ => Err(()),
1473 }
1474 }
1475}
1476
1477#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
1483pub enum ValueFormat {
1484 #[default]
1487 Raw,
1488 Pretty,
1491 Both,
1494}
1495
1496impl std::str::FromStr for ValueFormat {
1497 type Err = ();
1498
1499 fn from_str(s: &str) -> Result<Self, Self::Err> {
1500 match s.to_lowercase().as_str() {
1501 "raw" => Ok(ValueFormat::Raw),
1502 "pretty" | "fmt" => Ok(ValueFormat::Pretty),
1503 "both" | "full" => Ok(ValueFormat::Both),
1504 _ => Err(()),
1505 }
1506 }
1507}
1508
1509impl ValueFormat {
1510 pub fn parse(s: &str) -> Option<Self> {
1512 s.parse().ok()
1513 }
1514
1515 pub fn as_str(&self) -> &'static str {
1517 match self {
1518 ValueFormat::Raw => "raw",
1519 ValueFormat::Pretty => "pretty",
1520 ValueFormat::Both => "both",
1521 }
1522 }
1523
1524 pub fn transform(&self, value: serde_json::Value) -> serde_json::Value {
1551 match self {
1552 ValueFormat::Both => value, _ => self.transform_recursive(value),
1554 }
1555 }
1556
1557 fn transform_recursive(&self, value: serde_json::Value) -> serde_json::Value {
1558 use serde_json::Value;
1559
1560 match value {
1561 Value::Object(map) => {
1562 if self.is_formatted_value(&map) {
1564 return self.extract_value(&map);
1565 }
1566
1567 let transformed: serde_json::Map<String, Value> = map
1569 .into_iter()
1570 .map(|(k, v)| (k, self.transform_recursive(v)))
1571 .collect();
1572 Value::Object(transformed)
1573 }
1574 Value::Array(arr) => Value::Array(
1575 arr.into_iter()
1576 .map(|v| self.transform_recursive(v))
1577 .collect(),
1578 ),
1579 other => other,
1581 }
1582 }
1583
1584 fn is_formatted_value(&self, map: &serde_json::Map<String, serde_json::Value>) -> bool {
1586 if !map.contains_key("raw") {
1590 return false;
1591 }
1592
1593 let known_keys = ["raw", "fmt", "longFmt"];
1594 let unknown_keys = map
1595 .keys()
1596 .filter(|k| !known_keys.contains(&k.as_str()))
1597 .count();
1598
1599 unknown_keys == 0
1601 }
1602
1603 fn extract_value(&self, map: &serde_json::Map<String, serde_json::Value>) -> serde_json::Value {
1605 match self {
1606 ValueFormat::Raw => {
1607 map.get("raw").cloned().unwrap_or(serde_json::Value::Null)
1609 }
1610 ValueFormat::Pretty => {
1611 map.get("fmt")
1613 .or_else(|| map.get("longFmt"))
1614 .cloned()
1615 .unwrap_or(serde_json::Value::Null)
1616 }
1617 ValueFormat::Both => {
1618 serde_json::Value::Object(map.clone())
1620 }
1621 }
1622 }
1623}
1624
1625#[cfg(test)]
1626mod tests {
1627 use super::*;
1628
1629 #[test]
1630 fn test_interval_as_str() {
1631 assert_eq!(Interval::OneMinute.as_str(), "1m");
1632 assert_eq!(Interval::FiveMinutes.as_str(), "5m");
1633 assert_eq!(Interval::OneDay.as_str(), "1d");
1634 assert_eq!(Interval::OneWeek.as_str(), "1wk");
1635 }
1636
1637 #[test]
1638 fn test_time_range_as_str() {
1639 assert_eq!(TimeRange::OneDay.as_str(), "1d");
1640 assert_eq!(TimeRange::OneMonth.as_str(), "1mo");
1641 assert_eq!(TimeRange::OneYear.as_str(), "1y");
1642 assert_eq!(TimeRange::Max.as_str(), "max");
1643 }
1644}