finance-query v3.0.0

Screeners#

The screener API lets you filter stocks and mutual funds by hundreds of financial criteria. FinanceQuery supports both Yahoo Finance's predefined screeners and a fully typed custom screener query builder that gives you IDE autocomplete and compile-time field safety.

Predefined Screeners#

Yahoo Finance maintains a set of curated screeners. Pass a Screener variant and a result count to finance::screener:

rust · no_run
use finance_query::{finance, Screener};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Top 25 day gainers
    let gainers = finance::screener(Screener::DayGainers, 25).await?;

    // Most actively traded stocks
    let actives = finance::screener(Screener::MostActives, 50).await?;
    println!("Most actives returned: {}", actives.quotes.len());

    // Process results
    for quote in &gainers.quotes {
        let change_pct = quote.regular_market_change_percent.raw.unwrap_or(0.0);
        println!("{}: {:+.2}%", quote.symbol, change_pct);
    }
    Ok(())
}
checked claims
Screenerverified current

Screener responses are large, but cheap to decode — a checked claim, re-verified against real measurements in CI:

de_screenermedian time 382.5 µs(limit < 2.0 ms)0limit 2.0 ms
de_screenerCPU instructions 3,849,278(limit < 7,000,000)0limit 7,000,000

Available Screener variants:

VariantDescription
DayGainersTop gaining stocks by % change
DayLosersTop losing stocks by % change
MostActivesHighest trading volume stocks
AggressiveSmallCapsHigh-risk small-cap stocks
ConservativeForeignFundsConservative international funds
GrowthTechnologyStocksHigh-growth technology companies
HighYieldBondHigh-yield bond funds
MostShortedStocksMost heavily shorted stocks
PortfolioAnchorsStable, large-cap anchor stocks
SmallCapGainersTop small-cap gainers
SolidLargeGrowthFundsLarge-cap growth mutual funds (4-5 star)
SolidMidcapGrowthFundsMid-cap growth mutual funds (4-5 star)
TopMutualFundsHighest-rated mutual funds
UndervaluedGrowthStocksUndervalued growth opportunities
UndervaluedLargeCapsUndervalued large-cap companies

Custom Screeners — Typed Query Builder#

The custom screener API uses typed field enums so your IDE can autocomplete field names and the compiler catches typos at build time.

Core Types#

TypeDescription
EquityScreenerQueryQuery for stocks (uses EquityField)
FundScreenerQueryQuery for mutual funds (uses FundField)
EquityField~80 typed field names for equity filters
FundFieldTyped field names for fund filters
ScreenerFieldExtTrait providing .gt(), .lt(), .between(), .eq_str() etc.

Basic Example#

rust · no_run
use finance_query::{finance, EquityScreenerQuery, EquityField, ScreenerFieldExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Find US large-cap value stocks with healthy volume
    let query = EquityScreenerQuery::new()
        .size(50)
        .sort_by(EquityField::IntradayMarketCap, false)   // descending
        .add_condition(EquityField::Region.eq_str("us"))
        .add_condition(EquityField::AvgDailyVol3M.gt(500_000.0))
        .add_condition(EquityField::IntradayMarketCap.gt(10_000_000_000.0))
        .add_condition(EquityField::PeRatio.between(10.0, 25.0));

    let results = finance::custom_screener(query).await?;
    println!("Found {} stocks", results.quotes.len());
    Ok(())
}
checked claims
EquityFieldverified current

Condition Methods (ScreenerFieldExt)#

Import ScreenerFieldExt to access the fluent condition builders on any field variant. This example runs as a real test — conditions are built offline:

rust · runnable
use finance_query::{EquityField, ScreenerFieldExt};

// Numeric comparisons
let _ = EquityField::PeRatio.gt(5.0); // P/E > 5
let _ = EquityField::PeRatio.lt(30.0); // P/E < 30
let _ = EquityField::PeRatio.gte(10.0); // P/E >= 10
let _ = EquityField::PeRatio.lte(25.0); // P/E <= 25
let _ = EquityField::PeRatio.eq_num(15.0); // P/E == 15 (exact)
let cond = EquityField::PeRatio.between(10.0, 25.0); // 10 <= P/E <= 25
assert_eq!(cond.field, EquityField::PeRatio);
println!("numeric field = {:?}", cond.field);

// String equality (for categorical fields)
let _ = EquityField::Region.eq_str("us");
let _ = EquityField::Sector.eq_str("Technology");
let cond = EquityField::Exchange.eq_str("NMS");
assert_eq!(cond.field, EquityField::Exchange);
println!("categorical field = {:?}", cond.field);
recorded outputcargo soothfast docs capture
numeric field = PeRatio
categorical field = Exchange

Controlling Results#

rust · runnable
use finance_query::{EquityField, EquityScreenerQuery};

let query = EquityScreenerQuery::new()
    .size(100) // number of results (max 250, default 25)
    .offset(50) // pagination offset
    .sort_by(EquityField::PeRatio, true) // sort field + ascending=true
    .include_fields(vec![
        // columns to return
        EquityField::Ticker,
        EquityField::CompanyShortName,
        EquityField::IntradayPrice,
        EquityField::PeRatio,
        EquityField::IntradayMarketCap,
    ]);

assert_eq!(query.size, 100);
assert_eq!(query.offset, 50);
assert_eq!(query.include_fields.len(), 5);
println!("size = {}", query.size);
println!("offset = {}", query.offset);
println!("include_fields.len() = {}", query.include_fields.len());
recorded outputcargo soothfast docs capture
size = 100
offset = 50
include_fields.len() = 5

OR Logic — add_or_conditions#

All add_condition calls are AND'd together by default. Use add_or_conditions when you want any of several values to match:

rust · runnable
use finance_query::{EquityField, EquityScreenerQuery, ScreenerFieldExt};

// US OR Canadian equities, large-cap
let query = EquityScreenerQuery::new()
    .add_or_conditions(vec![
        EquityField::Region.eq_str("us"),
        EquityField::Region.eq_str("ca"),
    ])
    .add_condition(EquityField::IntradayMarketCap.gt(5_000_000_000.0));

// Top level is AND: one OR sub-group plus one plain condition
assert_eq!(query.query.operands.len(), 2);
println!("top-level operands = {}", query.query.operands.len());
recorded outputcargo soothfast docs capture
top-level operands = 2

Preset Constructors#

EquityScreenerQuery includes three built-in presets:

rust · no_run
use finance_query::{EquityScreenerQuery, finance};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Most shorted US stocks with average volume > 200K
    let results = finance::custom_screener(EquityScreenerQuery::most_shorted()).await?;

    // High-dividend US stocks (forward yield > 3%, volume > 100K)
    let results = finance::custom_screener(EquityScreenerQuery::high_dividend()).await?;

    // US large-cap growth stocks (market cap > $10B, positive EPS growth)
    let results = finance::custom_screener(EquityScreenerQuery::large_cap_growth()).await?;
    println!("Large-cap growth: {}", results.quotes.len());
    Ok(())
}

Mutual Fund Screener#

Use FundScreenerQuery with FundField for mutual funds:

rust · no_run
use finance_query::{finance, FundScreenerQuery, FundField, ScreenerFieldExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let query = FundScreenerQuery::new()
        .size(25)
        .sort_by(FundField::PerformanceRating, false)
        .add_condition(FundField::RiskRating.lte(3.0))
        .include_fields(vec![
            FundField::Ticker,
            FundField::CompanyShortName,
            FundField::IntradayPrice,
            FundField::CategoryName,
            FundField::PerformanceRating,
            FundField::RiskRating,
        ]);

    let results = finance::custom_screener(query).await?;
    println!("Funds: {}", results.quotes.len());
    Ok(())
}
checked claims
FundFieldverified current

Available FundField variants:

VariantYahoo FieldDescription
Ticker"ticker"Ticker symbol (display only)
CompanyShortName"companyshortname"Fund name (display only)
EodPrice"eodprice"End-of-day price
IntradayPrice"intradayprice"Intraday price
IntradayPriceChange"intradaypricechange"Intraday price change
CategoryName"categoryname"Morningstar category
PerformanceRating"performanceratingoverall"Overall performance rating
InitialInvestment"initialinvestment"Minimum initial investment
AnnualReturnRank"annualreturnnavy1categoryrank"1-year return rank within category
RiskRating"riskratingoverall"Overall risk rating
Exchange"exchange"Exchange

EquityField Reference#

Price & Market Cap#

VariantDescription
TickerTicker symbol (display only)
CompanyShortNameCompany name (display only)
EodPriceEnd-of-day price
IntradayPriceCurrent intraday price
IntradayPriceChangeIntraday price change
PercentChangePercentage price change
Lastclose52WkHigh52-week high at last close
Lastclose52WkLow52-week low at last close
FiftyTwoWkPctChange52-week percentage change
IntradayMarketCapCurrent market capitalization
LastcloseMarketCapMarket cap at last close

Categorical (use eq_str)#

VariantExample values
Region"us", "gb", "jp", "ca"
Sector"Technology", "Healthcare", "Financials"
Industry"Semiconductors", "Software"
Exchange"NMS", "NYQ", "ASE"
PeerGroupPeer group identifier

Trading & Volume#

VariantDescription
BetaStock beta vs market
AvgDailyVol3M3-month average daily volume
DayVolumeIntraday volume
EodVolumeEnd-of-day volume
PctHeldInsider% held by insiders
PctHeldInst% held by institutions

Short Interest#

VariantDescription
ShortPctFloatShort % of float
ShortPctSharesOutShort % of shares outstanding
ShortInterestShort interest value
DaysToCoverDays to cover short
ShortInterestPctChangeShort interest % change

Valuation#

VariantDescription
PeRatioTrailing twelve-month P/E
PegRatio5Y5-year PEG ratio
PriceBookRatioPrice-to-book ratio
PriceTangibleBookPrice to tangible book value
PriceEarningsPrice to earnings (last close)
BookValueShareBook value per share
MarketCapToRevenueMarket cap / total revenue
TevToRevenueTEV / total revenue
TevEbitTEV / EBIT
TevEbitdaTEV / EBITDA

Profitability & Dividends#

VariantDescription
RoaReturn on assets (TTM)
RoeReturn on equity (TTM)
ReturnOnCapitalReturn on total capital (TTM)
ForwardDivYieldForward dividend yield
ForwardDivPerShareForward dividend per share
ConsecutiveDivYearsConsecutive years of dividend growth
NetIncomeMarginNet income margin (TTM)
GrossProfitMarginGross profit margin (TTM)
EbitdaMarginEBITDA margin (TTM)

Income Statement#

VariantDescription
TotalRevenuesTotal revenues (TTM)
GrossProfitGross profit (TTM)
EbitdaEBITDA (TTM)
Ebitda1YrGrowthEBITDA 1-year growth
NetIncomeNet income (TTM)
NetIncome1YrGrowthNet income 1-year growth
Revenue1YrGrowthRevenue 1-year growth
QuarterlyRevGrowthQuarterly revenue growth
EpsGrowthEPS growth (TTM)
DilutedEps1YrGrowthDiluted EPS 1-year growth
NetEpsBasicBasic EPS (TTM)
NetEpsDilutedDiluted EPS (TTM)
OperatingIncomeOperating income (TTM)
EbitEBIT (TTM)

Balance Sheet & Leverage#

VariantDescription
TotalAssetsTotal assets (TTM)
TotalDebtTotal debt (TTM)
TotalEquityTotal equity (TTM)
TotalCommonEquityTotal common equity (TTM)
TotalCurrentAssetsTotal current assets
TotalCurrentLiabTotal current liabilities
CashAndStInvestmentsCash and short-term investments
CommonSharesOutCommon shares outstanding
TotalSharesOutTotal shares outstanding
TotalDebtEquityTotal debt / equity
LtDebtEquityLong-term debt / equity
TotalDebtEbitdaTotal debt / EBITDA
NetDebtEbitdaNet debt / EBITDA
EbitInterestExpEBIT / interest expense
EbitdaInterestExpEBITDA / interest expense

Liquidity#

VariantDescription
QuickRatioQuick ratio (TTM)
CurrentRatioCurrent ratio (TTM)
AltmanZScoreAltman Z-score
OcfToCurrentLiabOperating cash flow / current liabilities

Cash Flow#

VariantDescription
CashFromOpsCash from operations (TTM)
CashFromOps1YrGrowthCash from ops 1-year growth
LeveredFcfLevered free cash flow (TTM)
LeveredFcf1YrGrowthLevered FCF 1-year growth
UnleveredFcfUnlevered free cash flow
CapexCapital expenditure (TTM)

ESG#

VariantDescription
EsgScoreOverall ESG score
EnvironmentalScoreEnvironmental score
GovernanceScoreGovernance score
SocialScoreSocial score
HighestControversyHighest controversy level

Next Steps#

built with cargo soothfast docs build source