use super::condition::ScreenerField;
use serde::Serialize;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum EquityField {
Ticker,
CompanyShortName,
EodPrice,
IntradayPrice,
IntradayPriceChange,
PercentChange,
Lastclose52WkHigh,
FiftyTwoWkPctChange,
Lastclose52WkLow,
IntradayMarketCap,
LastcloseMarketCap,
Region,
Sector,
PeerGroup,
Industry,
Exchange,
Beta,
AvgDailyVol3M,
PctHeldInsider,
PctHeldInst,
DayVolume,
EodVolume,
ShortPctSharesOut,
ShortInterest,
ShortPctFloat,
DaysToCover,
ShortInterestPctChange,
BookValueShare,
MarketCapToRevenue,
TevToRevenue,
PriceBookRatio,
PeRatio,
PriceTangibleBook,
PriceEarnings,
PegRatio5Y,
ConsecutiveDivYears,
Roa,
Roe,
ForwardDivPerShare,
ForwardDivYield,
ReturnOnCapital,
TevEbit,
NetDebtEbitda,
TotalDebtEquity,
LtDebtEquity,
EbitInterestExp,
EbitdaInterestExp,
TevEbitda,
TotalDebtEbitda,
QuickRatio,
AltmanZScore,
CurrentRatio,
OcfToCurrentLiab,
TotalRevenues,
NetIncomeMargin,
GrossProfit,
Ebitda1YrGrowth,
DilutedEpsContOps,
QuarterlyRevGrowth,
EpsGrowth,
NetIncome,
Ebitda,
DilutedEps1YrGrowth,
Revenue1YrGrowth,
OperatingIncome,
NetIncome1YrGrowth,
GrossProfitMargin,
EbitdaMargin,
Ebit,
BasicEpsContOps,
NetEpsBasic,
NetEpsDiluted,
TotalAssets,
CommonSharesOut,
TotalDebt,
TotalEquity,
TotalCurrentAssets,
CashAndStInvestments,
TotalCommonEquity,
TotalCurrentLiab,
TotalSharesOut,
LeveredFcf,
Capex,
CashFromOps,
LeveredFcf1YrGrowth,
UnleveredFcf,
CashFromOps1YrGrowth,
EsgScore,
EnvironmentalScore,
GovernanceScore,
SocialScore,
HighestControversy,
}
impl EquityField {
pub fn as_str(&self) -> &'static str {
match self {
EquityField::Ticker => "ticker",
EquityField::CompanyShortName => "companyshortname",
EquityField::EodPrice => "eodprice",
EquityField::IntradayPrice => "intradayprice",
EquityField::IntradayPriceChange => "intradaypricechange",
EquityField::PercentChange => "percentchange",
EquityField::Lastclose52WkHigh => "lastclose52weekhigh.lasttwelvemonths",
EquityField::FiftyTwoWkPctChange => "fiftytwowkpercentchange",
EquityField::Lastclose52WkLow => "lastclose52weeklow.lasttwelvemonths",
EquityField::IntradayMarketCap => "intradaymarketcap",
EquityField::LastcloseMarketCap => "lastclosemarketcap.lasttwelvemonths",
EquityField::Region => "region",
EquityField::Sector => "sector",
EquityField::PeerGroup => "peer_group",
EquityField::Industry => "industry",
EquityField::Exchange => "exchange",
EquityField::Beta => "beta",
EquityField::AvgDailyVol3M => "avgdailyvol3m",
EquityField::PctHeldInsider => "pctheldinsider",
EquityField::PctHeldInst => "pctheldinst",
EquityField::DayVolume => "dayvolume",
EquityField::EodVolume => "eodvolume",
EquityField::ShortPctSharesOut => "short_percentage_of_shares_outstanding.value",
EquityField::ShortInterest => "short_interest.value",
EquityField::ShortPctFloat => "short_percentage_of_float.value",
EquityField::DaysToCover => "days_to_cover_short.value",
EquityField::ShortInterestPctChange => "short_interest_percentage_change.value",
EquityField::BookValueShare => "bookvalueshare.lasttwelvemonths",
EquityField::MarketCapToRevenue => "lastclosemarketcaptotalrevenue.lasttwelvemonths",
EquityField::TevToRevenue => "lastclosetevtotalrevenue.lasttwelvemonths",
EquityField::PriceBookRatio => "pricebookratio.quarterly",
EquityField::PeRatio => "peratio.lasttwelvemonths",
EquityField::PriceTangibleBook => "lastclosepricetangiblebookvalue.lasttwelvemonths",
EquityField::PriceEarnings => "lastclosepriceearnings.lasttwelvemonths",
EquityField::PegRatio5Y => "pegratio_5y",
EquityField::ConsecutiveDivYears => "consecutive_years_of_dividend_growth_count",
EquityField::Roa => "returnonassets.lasttwelvemonths",
EquityField::Roe => "returnonequity.lasttwelvemonths",
EquityField::ForwardDivPerShare => "forward_dividend_per_share",
EquityField::ForwardDivYield => "forward_dividend_yield",
EquityField::ReturnOnCapital => "returnontotalcapital.lasttwelvemonths",
EquityField::TevEbit => "lastclosetevebit.lasttwelvemonths",
EquityField::NetDebtEbitda => "netdebtebitda.lasttwelvemonths",
EquityField::TotalDebtEquity => "totaldebtequity.lasttwelvemonths",
EquityField::LtDebtEquity => "ltdebtequity.lasttwelvemonths",
EquityField::EbitInterestExp => "ebitinterestexpense.lasttwelvemonths",
EquityField::EbitdaInterestExp => "ebitdainterestexpense.lasttwelvemonths",
EquityField::TevEbitda => "lastclosetevebitda.lasttwelvemonths",
EquityField::TotalDebtEbitda => "totaldebtebitda.lasttwelvemonths",
EquityField::QuickRatio => "quickratio.lasttwelvemonths",
EquityField::AltmanZScore => {
"altmanzscoreusingtheaveragestockinformationforaperiod.lasttwelvemonths"
}
EquityField::CurrentRatio => "currentratio.lasttwelvemonths",
EquityField::OcfToCurrentLiab => {
"operatingcashflowtocurrentliabilities.lasttwelvemonths"
}
EquityField::TotalRevenues => "totalrevenues.lasttwelvemonths",
EquityField::NetIncomeMargin => "netincomemargin.lasttwelvemonths",
EquityField::GrossProfit => "grossprofit.lasttwelvemonths",
EquityField::Ebitda1YrGrowth => "ebitda1yrgrowth.lasttwelvemonths",
EquityField::DilutedEpsContOps => "dilutedepscontinuingoperations.lasttwelvemonths",
EquityField::QuarterlyRevGrowth => "quarterlyrevenuegrowth.quarterly",
EquityField::EpsGrowth => "epsgrowth.lasttwelvemonths",
EquityField::NetIncome => "netincomeis.lasttwelvemonths",
EquityField::Ebitda => "ebitda.lasttwelvemonths",
EquityField::DilutedEps1YrGrowth => "dilutedeps1yrgrowth.lasttwelvemonths",
EquityField::Revenue1YrGrowth => "totalrevenues1yrgrowth.lasttwelvemonths",
EquityField::OperatingIncome => "operatingincome.lasttwelvemonths",
EquityField::NetIncome1YrGrowth => "netincome1yrgrowth.lasttwelvemonths",
EquityField::GrossProfitMargin => "grossprofitmargin.lasttwelvemonths",
EquityField::EbitdaMargin => "ebitdamargin.lasttwelvemonths",
EquityField::Ebit => "ebit.lasttwelvemonths",
EquityField::BasicEpsContOps => "basicepscontinuingoperations.lasttwelvemonths",
EquityField::NetEpsBasic => "netepsbasic.lasttwelvemonths",
EquityField::NetEpsDiluted => "netepsdiluted.lasttwelvemonths",
EquityField::TotalAssets => "totalassets.lasttwelvemonths",
EquityField::CommonSharesOut => "totalcommonsharesoutstanding.lasttwelvemonths",
EquityField::TotalDebt => "totaldebt.lasttwelvemonths",
EquityField::TotalEquity => "totalequity.lasttwelvemonths",
EquityField::TotalCurrentAssets => "totalcurrentassets.lasttwelvemonths",
EquityField::CashAndStInvestments => {
"totalcashandshortterminvestments.lasttwelvemonths"
}
EquityField::TotalCommonEquity => "totalcommonequity.lasttwelvemonths",
EquityField::TotalCurrentLiab => "totalcurrentliabilities.lasttwelvemonths",
EquityField::TotalSharesOut => "totalsharesoutstanding",
EquityField::LeveredFcf => "leveredfreecashflow.lasttwelvemonths",
EquityField::Capex => "capitalexpenditure.lasttwelvemonths",
EquityField::CashFromOps => "cashfromoperations.lasttwelvemonths",
EquityField::LeveredFcf1YrGrowth => "leveredfreecashflow1yrgrowth.lasttwelvemonths",
EquityField::UnleveredFcf => "unleveredfreecashflow.lasttwelvemonths",
EquityField::CashFromOps1YrGrowth => "cashfromoperations1yrgrowth.lasttwelvemonths",
EquityField::EsgScore => "esg_score",
EquityField::EnvironmentalScore => "environmental_score",
EquityField::GovernanceScore => "governance_score",
EquityField::SocialScore => "social_score",
EquityField::HighestControversy => "highest_controversy",
}
}
pub fn all() -> &'static [EquityField] {
&[
EquityField::Ticker,
EquityField::CompanyShortName,
EquityField::EodPrice,
EquityField::IntradayPrice,
EquityField::IntradayPriceChange,
EquityField::PercentChange,
EquityField::Lastclose52WkHigh,
EquityField::FiftyTwoWkPctChange,
EquityField::Lastclose52WkLow,
EquityField::IntradayMarketCap,
EquityField::LastcloseMarketCap,
EquityField::Region,
EquityField::Sector,
EquityField::PeerGroup,
EquityField::Industry,
EquityField::Exchange,
EquityField::Beta,
EquityField::AvgDailyVol3M,
EquityField::PctHeldInsider,
EquityField::PctHeldInst,
EquityField::DayVolume,
EquityField::EodVolume,
EquityField::ShortPctSharesOut,
EquityField::ShortInterest,
EquityField::ShortPctFloat,
EquityField::DaysToCover,
EquityField::ShortInterestPctChange,
EquityField::BookValueShare,
EquityField::MarketCapToRevenue,
EquityField::TevToRevenue,
EquityField::PriceBookRatio,
EquityField::PeRatio,
EquityField::PriceTangibleBook,
EquityField::PriceEarnings,
EquityField::PegRatio5Y,
EquityField::ConsecutiveDivYears,
EquityField::Roa,
EquityField::Roe,
EquityField::ForwardDivPerShare,
EquityField::ForwardDivYield,
EquityField::ReturnOnCapital,
EquityField::TevEbit,
EquityField::NetDebtEbitda,
EquityField::TotalDebtEquity,
EquityField::LtDebtEquity,
EquityField::EbitInterestExp,
EquityField::EbitdaInterestExp,
EquityField::TevEbitda,
EquityField::TotalDebtEbitda,
EquityField::QuickRatio,
EquityField::AltmanZScore,
EquityField::CurrentRatio,
EquityField::OcfToCurrentLiab,
EquityField::TotalRevenues,
EquityField::NetIncomeMargin,
EquityField::GrossProfit,
EquityField::Ebitda1YrGrowth,
EquityField::DilutedEpsContOps,
EquityField::QuarterlyRevGrowth,
EquityField::EpsGrowth,
EquityField::NetIncome,
EquityField::Ebitda,
EquityField::DilutedEps1YrGrowth,
EquityField::Revenue1YrGrowth,
EquityField::OperatingIncome,
EquityField::NetIncome1YrGrowth,
EquityField::GrossProfitMargin,
EquityField::EbitdaMargin,
EquityField::Ebit,
EquityField::BasicEpsContOps,
EquityField::NetEpsBasic,
EquityField::NetEpsDiluted,
EquityField::TotalAssets,
EquityField::CommonSharesOut,
EquityField::TotalDebt,
EquityField::TotalEquity,
EquityField::TotalCurrentAssets,
EquityField::CashAndStInvestments,
EquityField::TotalCommonEquity,
EquityField::TotalCurrentLiab,
EquityField::TotalSharesOut,
EquityField::LeveredFcf,
EquityField::Capex,
EquityField::CashFromOps,
EquityField::LeveredFcf1YrGrowth,
EquityField::UnleveredFcf,
EquityField::CashFromOps1YrGrowth,
EquityField::EsgScore,
EquityField::EnvironmentalScore,
EquityField::GovernanceScore,
EquityField::SocialScore,
EquityField::HighestControversy,
]
}
}
impl std::str::FromStr for EquityField {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
EquityField::all()
.iter()
.find(|f| f.as_str() == s)
.copied()
.ok_or(())
}
}
impl Serialize for EquityField {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl ScreenerField for EquityField {
fn as_str(&self) -> &'static str {
self.as_str()
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FundField {
Ticker,
CompanyShortName,
EodPrice,
IntradayPriceChange,
IntradayPrice,
CategoryName,
PerformanceRating,
InitialInvestment,
AnnualReturnRank,
RiskRating,
Exchange,
}
impl FundField {
pub fn as_str(&self) -> &'static str {
match self {
FundField::Ticker => "ticker",
FundField::CompanyShortName => "companyshortname",
FundField::EodPrice => "eodprice",
FundField::IntradayPriceChange => "intradaypricechange",
FundField::IntradayPrice => "intradayprice",
FundField::CategoryName => "categoryname",
FundField::PerformanceRating => "performanceratingoverall",
FundField::InitialInvestment => "initialinvestment",
FundField::AnnualReturnRank => "annualreturnnavy1categoryrank",
FundField::RiskRating => "riskratingoverall",
FundField::Exchange => "exchange",
}
}
pub fn all() -> &'static [FundField] {
&[
FundField::Ticker,
FundField::CompanyShortName,
FundField::EodPrice,
FundField::IntradayPriceChange,
FundField::IntradayPrice,
FundField::CategoryName,
FundField::PerformanceRating,
FundField::InitialInvestment,
FundField::AnnualReturnRank,
FundField::RiskRating,
FundField::Exchange,
]
}
}
impl std::str::FromStr for FundField {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
FundField::all()
.iter()
.find(|f| f.as_str() == s)
.copied()
.ok_or(())
}
}
impl Serialize for FundField {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl ScreenerField for FundField {
fn as_str(&self) -> &'static str {
self.as_str()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_equity_field_as_str() {
assert_eq!(EquityField::PeRatio.as_str(), "peratio.lasttwelvemonths");
assert_eq!(EquityField::AvgDailyVol3M.as_str(), "avgdailyvol3m");
assert_eq!(EquityField::Region.as_str(), "region");
assert_eq!(EquityField::IntradayMarketCap.as_str(), "intradaymarketcap");
assert_eq!(EquityField::Ticker.as_str(), "ticker");
}
#[test]
fn test_equity_field_from_str_round_trip() {
for field in EquityField::all() {
let s = field.as_str();
let parsed: EquityField = s.parse().unwrap_or_else(|_| {
panic!("Failed to parse EquityField from '{s}'");
});
assert_eq!(&parsed, field, "Round-trip failed for field '{s}'");
}
}
#[test]
fn test_equity_field_from_str_unknown_returns_err() {
assert!("invalid_field_name".parse::<EquityField>().is_err());
assert!("".parse::<EquityField>().is_err());
}
#[test]
fn test_equity_field_serializes_as_string() {
let json = serde_json::to_value(EquityField::PeRatio).unwrap();
assert_eq!(json, "peratio.lasttwelvemonths");
}
#[test]
fn test_fund_field_as_str() {
assert_eq!(
FundField::PerformanceRating.as_str(),
"performanceratingoverall"
);
assert_eq!(FundField::RiskRating.as_str(), "riskratingoverall");
assert_eq!(FundField::CategoryName.as_str(), "categoryname");
}
#[test]
fn test_fund_field_from_str_round_trip() {
for field in FundField::all() {
let s = field.as_str();
let parsed: FundField = s.parse().unwrap_or_else(|_| {
panic!("Failed to parse FundField from '{s}'");
});
assert_eq!(&parsed, field, "Round-trip failed for fund field '{s}'");
}
}
#[test]
fn test_fund_field_from_str_unknown_returns_err() {
assert!("intradaymarketcap".parse::<FundField>().is_err());
}
}