A modular Python library for comprehensive stock valuation using multiple methodologies
Project description
ValueInvest
A modular Python library for comprehensive stock valuation using multiple methodologies with real-time data fetching and news sentiment analysis.
✨ Recent Updates
2026-03-28: Major data quality and valuation fixes
- Fixed 12+ fields returning None/0 from
Stock.from_api()(operating_cash_flow, ebitda, sector, inventory, prior_* data, etc.) - Fixed Graham Number, Magic Formula, and Value Trap detector edge cases
- Added
revenue_cagr_5y,earnings_cagr_5y, and other computed properties - See CHANGELOG.md for detailed changes
Features
- Real-time Data Fetching: A-shares (AKShare), US stocks (yfinance), optional Tushare
- Graham Valuation: Graham Number, Graham Formula, NCAV (Net-Net)
- Discounted Cash Flow: DCF (10-year projection), Reverse DCF
- Earnings Power Value: Zero-growth intrinsic value
- Dividend Models: Gordon Growth, Two-Stage DDM
- Growth Valuation: PEG Ratio, GARP, Rule of 40
- Bank Valuation: P/B Valuation, Residual Income Model
- News & Sentiment Analysis: Keyword-based and LLM-based sentiment analysis
- Analyst Data: Company guidance and analyst expectations
- Insider Trading: Track executive buy/sell activity (A-share & US)
- Buyback Analysis: Share repurchase tracking and shareholder yield
- Free Cash Flow Analysis: FCF quality, SBC impact, and profitability metrics
- Quality Scoring: Piotroski F-Score, Altman Z-Score for financial health
- Earnings Manipulation Detection: Beneish M-Score for fraud risk assessment
- Relative Valuation: PE/PB comparison vs historical and peer averages
- Cyclical Stock Analysis: Cycle position scoring, cyclical-adjusted valuation (PB/PE/FCF), market-specific strategies
- Implied Growth Analysis: Market-implied growth rates from multiple methods, historical comparison, reasonableness scoring
- QFQ/HFQ Price Adjustment: Proper price adjustment for valuation comparison and real returns
Installation
# Install from PyPI
pip install valueinvest # Core library (no data sources)
# Install with data sources
pip install "valueinvest[fetch]" # All data sources
pip install "valueinvest[us]" # US stocks only (yfinance)
pip install "valueinvest[ashare]" # A-shares only (AKShare, free)
pip install "valueinvest[tushare]" # A-shares with Tushare (requires token)
# For development (from source)
git clone https://github.com/wangzhe3224/valueinvest.git
cd valueinvest
uv venv --python 3.11
source .venv/bin/activate
pip install -e ".[fetch]" # All data sources
pip install -e ".[learn,fetch]" # Learning + all data sources
## Quick Start
### Command Line
```bash
# Analyze A-share stock
python scripts/stock_analyzer.py 600887 # 伊利股份
python scripts/stock_analyzer.py 600900 # 长江电力
python scripts/stock_analyzer.py 601398 --bank # 工商银行 (force bank analysis)
# Analyze US stock
python scripts/stock_analyzer.py AAPL
# Options
python scripts/stock_analyzer.py 600887 --period 3y # 3-year history
python scripts/stock_analyzer.py 600900 --dividend # Force dividend analysis
python scripts/stock_analyzer.py 601398 --growth # Force growth analysis
# With news analysis
python scripts/stock_analyzer.py 600887 --news # Include news sentiment
python scripts/stock_analyzer.py AAPL --news --llm # Use LLM for analysis
python scripts/stock_analyzer.py 600887 --news --news-days 60 # 60-day news
# With insider trading analysis
python scripts/stock_analyzer.py 600887 --insider # Include insider trading
python scripts/stock_analyzer.py AAPL --insider --insider-days 180 # 180-day insider trades
# With buyback analysis (recommended for US stocks)
python scripts/stock_analyzer.py AAPL --buyback # Include buyback analysis
python scripts/stock_analyzer.py 600887 --buyback # A-share buyback analysis
# With FCF (Free Cash Flow) analysis
python scripts/stock_analyzer.py AAPL --fcf # Include FCF analysis
python scripts/stock_analyzer.py AAPL --fcf --fcf-years 7 # 7-year FCF history
python scripts/stock_analyzer.py AAPL --buyback --fcf # Full shareholder return analysis
### Python API
```python
from valueinvest import Stock, ValuationEngine
# Fetch real-time data
stock = Stock.from_api("600887") # A-share
stock = Stock.from_api("AAPL") # US stock
# Fetch price history separately
history = Stock.fetch_price_history("600887", period="5y")
# QFQ (前复权) - for valuation comparison
print(f"Price CAGR: {history.cagr:.2f}%")
# HFQ (后复权) - real returns including dividends
print(f"Real CAGR: {history.cagr_hfq:.2f}%")
# Run valuation
engine = ValuationEngine()
results = engine.run_all(stock)
# Category-specific methods
results = engine.run_dividend(stock) # Dividend stocks
results = engine.run_bank(stock) # Banks
results = engine.run_growth(stock) # Growth stocks
# Batch analysis - compare multiple stocks
result = engine.analyze_batch(['AAPL', 'MSFT', 'GOOGL'])
print(engine.format_batch_table(result))
# Filter results
for s in result.undervalued:
print(f"{s.ticker}: {s.upside_pct:+.1f}% upside")
News & Sentiment Analysis
Basic Usage
from valueinvest.news.registry import NewsRegistry
from valueinvest.news.analyzer.keyword_analyzer import KeywordSentimentAnalyzer
# Fetch news (auto-detect market: A-share or US)
fetcher = NewsRegistry.get_fetcher("600887")
result = fetcher.fetch_all("600887", days=30)
# Analyze sentiment with keyword matching
analyzer = KeywordSentimentAnalyzer()
analysis = analyzer.analyze_batch(result.news, "600887")
# Access results
print(f"Sentiment Score: {analysis.sentiment_score:+.2f}") # -1 to 1
print(f"Sentiment Label: {analysis.sentiment_label}") # positive/negative/neutral
print(f"Key Themes: {analysis.key_themes}")
print(f"Risks: {analysis.risks}")
print(f"Catalysts: {analysis.catalysts}")
# News counts
print(f"Positive: {analysis.positive_count}")
print(f"Negative: {analysis.negative_count}")
print(f"Neutral: {analysis.neutral_count}")
LLM-based Analysis (Optional)
For higher quality analysis, use the LLM analyzer with OpenAI:
from valueinvest.news.analyzer.llm_analyzer import LLMSentimentAnalyzer
import os
os.environ["OPENAI_API_KEY"] = "sk-xxx"
analyzer = LLMSentimentAnalyzer(model="gpt-4o-mini")
analysis = analyzer.analyze_batch(result.news, "AAPL")
# LLM provides additional insights
for item in analysis.news:
print(f"Rationale: {item.rationale}") # Explanation for each news item
Agent-based Analysis (No API Key Required)
Use coding agents for deep analysis without external API dependencies:
from valueinvest.news.analyzer.agent_analyzer import (
AgentSentimentAnalyzer,
create_agent_analysis_prompt,
enhance_analysis_with_agent_result,
)
# Create agent analyzer with stock context
analyzer = AgentSentimentAnalyzer(
stock_name="伊利股份",
current_price=26.0,
company_type="value",
)
# Get initial analysis (keyword-based as foundation)
analysis = analyzer.analyze_batch(news, "600887")
# Create prompt for coding agent (use with ultrabrain/deep)
prompt = create_agent_analysis_prompt(
ticker="600887",
stock_name="伊利股份",
current_price=26.0,
company_type="value",
news=news,
days=30,
)
# After getting response from coding agent, enhance the analysis:
agent_response = {
"sentiment_score": 0.65,
"key_themes": ["业绩增长", "分红提升"],
"risks": ["竞争加剧"],
"catalysts": ["新品发布"],
}
enhanced = enhance_analysis_with_agent_result(analysis, agent_response)
CLI usage for agent-based analysis:
# Use coding agent for deep news analysis
python scripts/stock_analyzer.py 600887 --news --agent
Guidance & Analyst Data
# Access analyst guidance
if analysis.has_guidance:
guidance = analysis.latest_guidance
print(f"Fiscal Year: {guidance.fiscal_year} Q{guidance.quarter}")
# Company guidance
if guidance.has_company_guidance:
print(f"EPS Guidance: {guidance.company_eps_low}-{guidance.company_eps_high}")
# Analyst expectations
if guidance.has_analyst_data:
print(f"Analyst EPS Mean: {guidance.analyst_eps_mean}")
print(f"Analyst Count: {guidance.analyst_count}")
print(f"Rating: {guidance.analyst_rating.value}")
# Compare guidance vs consensus
print(f"vs Consensus: {guidance.guidance_vs_consensus}") # above/below/in_line
Insider Trading
Basic Usage
from valueinvest.insider import InsiderRegistry
# Auto-detect market
fetcher = InsiderRegistry.get_fetcher("600887")
result = fetcher.fetch_insider_trades("600887", days=365)
# Access summary
print(f"Sentiment: {result.summary.sentiment}") # bullish/bearish/neutral
print(f"Buys: {result.summary.buy_count}, Sells: {result.summary.sell_count}")
print(f"Net shares: {result.summary.net_shares:+,.0f}")
print(f"Net value: ¥{result.summary.net_value:+,.0f}")
# Access individual trades
for trade in result.trades[:5]:
print(f"{trade.trade_date}: {trade.insider_name} {trade.trade_type.value} {trade.shares:,.0f} @ ¥{trade.price}")
Insider Trading Data Sources
| Source | Markets | Data | Auth |
|---|---|---|---|
| AKShare (同花顺) | A-shares | ✅ 高管增减持 | Free |
| yfinance | US/Intl | ✅ Insider purchases | Free |
Buyback Analysis
For US stocks, buyback yield is often more important than dividend yield (e.g., AAPL returns ~2.3% via buyback vs ~0.4% dividend).
Basic Usage
from valueinvest.buyback import BuybackRegistry
# Auto-detect market
fetcher = BuybackRegistry.get_fetcher("AAPL")
result = fetcher.fetch_buyback("AAPL", days=365)
# Access summary
summary = result.summary
print(f"Buyback Yield: {summary.buyback_yield:.2f}%")
print(f"Dividend Yield: {summary.dividend_yield:.2f}%")
print(f"Total Shareholder Yield: {summary.total_shareholder_yield:.2f}%")
print(f"Sentiment: {summary.sentiment.value}") # aggressive/moderate/minimal/none
# Yearly buyback amounts
for year, amount in summary.yearly_amounts.items():
print(f"{year}: ${amount/1e9:.2f}B")
# Access individual records
for record in result.records[:5]:
print(f"{record.execution_date}: ${record.amount/1e9:.2f}B")
Buyback Data Sources
| Source | Markets | Data | Auth |
|---|---|---|---|
| AKShare (东方财富) | A-shares | ✅ 回购计划与执行 | Free |
| yfinance | US/Intl | ✅ Cash flow buyback | Free |
CLI Usage
python scripts/stock_analyzer.py AAPL --buyback # US stock buyback analysis
python scripts/stock_analyzer.py 600887 --buyback # A-share buyback analysis
python scripts/stock_analyzer.py AAPL --buyback --buyback-days 730 # 2-year history
Free Cash Flow (FCF) Analysis
FCF analysis helps evaluate the quality of a company's cash generation, including SBC (Stock-Based Compensation) impact on true profitability.
Basic Usage
from valueinvest.cashflow import CashFlowRegistry
# Auto-detect market
fetcher = CashFlowRegistry.get_fetcher("AAPL")
result = fetcher.fetch_cashflow("AAPL", years=5)
# Access summary
summary = result.summary
print(f"FCF Quality: {summary.fcf_quality.value}") # EXCELLENT/GOOD/ACCEPTABLE/POOR/NEGATIVE
print(f"FCF Trend: {summary.fcf_trend.value}") # IMPROVING/STABLE/DECLINING/VOLATILE
print(f"FCF Yield: {summary.fcf_yield:.2f}%")
print(f"FCF Margin: {summary.fcf_margin:.2f}%")
# SBC-adjusted (True FCF)
print(f"True FCF (SBC-adjusted): ${summary.latest_true_fcf/1e9:.2f}B")
print(f"True FCF Yield: {summary.true_fcf_yield:.2f}%")
print(f"SBC as % of FCF: {summary.sbc_as_pct_of_fcf:.1f}%")
# Profitability quality
print(f"FCF / Net Income: {summary.fcf_to_net_income:.2f}x")
print(f"FCF CAGR: {summary.fcf_cagr:.1f}%")
Key Metrics
| Metric | Description |
|---|---|
| FCF Quality | EXCELLENT (>15% yield), GOOD (10-15%), ACCEPTABLE (5-10%), POOR (0-5%), NEGATIVE (<0) |
| FCF Trend | IMPROVING, STABLE, DECLINING, VOLATILE |
| FCF Yield | FCF / Market Cap |
| FCF Margin | FCF / Revenue |
| True FCF | FCF - SBC (stock-based compensation) |
| FCF / Net Income | Cash quality of earnings (>1.0 is excellent) |
FCF Data Sources
| Source | Markets | Data | Auth |
|---|---|---|---|
| yfinance | US/Intl | ✅ Cash flow statement | Free |
CLI Usage
python scripts/stock_analyzer.py AAPL --fcf # FCF analysis (default 5 years)
python scripts/stock_analyzer.py AAPL --fcf --fcf-years 7 # 7-year FCF history
python scripts/stock_analyzer.py AAPL --buyback --fcf # Combined shareholder return analysis
Piotroski F-Score
The Piotroski F-Score is a 9-point scale that evaluates the financial strength of a company, developed by accounting professor Joseph Piotroski. It's particularly useful for identifying high-quality value stocks.
Basic Usage
from valueinvest import Stock
from valueinvest.valuation import ValuationEngine
from valueinvest.valuation.quality import calculate_f_score
# Method 1: Via Engine (uses Stock's prior year fields)
stock = Stock(
ticker="AAPL",
name="Apple Inc.",
current_price=180.0,
shares_outstanding=15.5e9,
net_income=100e9,
total_assets=350e9,
total_liabilities=120e9,
current_assets=60e9,
fcf=110e9,
operating_margin=30.0,
revenue=400e9,
# Prior year data for trend analysis
prior_roa=0.28,
prior_debt_ratio=0.35,
prior_current_ratio=0.9,
prior_shares_outstanding=16.0e9,
prior_gross_margin=28.0,
prior_asset_turnover=1.1,
)
engine = ValuationEngine()
result = engine.run_single(stock, "piotroski_f")
print(f"F-Score: {result.details['f_score']}/9")
print(f"Risk Level: {result.details['risk_level']}")
# Method 2: Via convenience function
fscore = calculate_f_score(
stock,
prior_roa=0.28,
prior_debt_ratio=0.35,
prior_current_ratio=0.9,
prior_shares_outstanding=16.0e9,
prior_gross_margin=28.0,
prior_asset_turnover=1.1,
)
print(f"F-Score: {fscore.total_score}/9")
print(f"Profitability: {fscore.profitability_score}/4")
print(f"Leverage: {fscore.leverage_score}/3")
print(f"Efficiency: {fscore.efficiency_score}/2")
The 9 Criteria
| Category | Criteria | Points |
|---|---|---|
| Profitability | ROA > 0 | 1 |
| Operating Cash Flow > 0 | 1 | |
| ROA improved vs prior year | 1 | |
| OCF > Net Income (earnings quality) | 1 | |
| Leverage/Liquidity | Debt ratio decreased | 1 |
| Current ratio increased | 1 | |
| No significant share dilution | 1 | |
| Operating Efficiency | Gross margin improved | 1 |
| Asset turnover improved | 1 |
Interpretation
| Score | Interpretation | Risk Level |
|---|---|---|
| 8-9 | Strong - Excellent financial health | Low |
| 6-7 | Good - Solid financial position | Low |
| 4-5 | Average - Some financial concerns | Medium |
| 0-3 | Weak - Poor financial health | High |
CLI Usage
python scripts/stock_analyzer.py 600887 --method piotroski_f
Beneish M-Score
The Beneish M-Score is an 8-variable model developed by Professor Messod D. Beneish to detect earnings manipulation. It identifies companies that may be manipulating their financial statements.
Basic Usage
from valueinvest import Stock
from valueinvest.valuation import ValuationEngine
from valueinvest.valuation.mscore import calculate_m_score
# Method 1: Via Engine (requires prior year data in Stock)
stock = Stock(
ticker="AAPL",
name="Apple Inc.",
current_price=180.0,
revenue=400e9,
net_income=100e9,
total_assets=350e9,
accounts_receivable=30e9,
# Prior year data for comparison
prior_revenue=380e9,
prior_gross_margin=28.0,
prior_total_assets=330e9,
)
engine = ValuationEngine()
result = engine.run_single(stock, "beneish_m")
print(f"M-Score: {result.details['m_score']}")
print(f"Manipulation Risk: {result.details['manipulation_risk']}")
# Method 2: Via convenience function
m_result = calculate_m_score(
stock,
prior_revenue=380e9,
prior_gross_margin=28.0,
prior_total_assets=330e9,
)
print(f"M-Score: {m_result.m_score:.2f}")
print(f"Is Manipulator: {m_result.is_manipulator}")
The 8 Variables
| Variable | Name | What It Measures |
|---|---|---|
| DSRI | Days Sales Receivable Index | Revenue inflation via loose credit |
| GMI | Gross Margin Index | Deteriorating margins |
| AQI | Asset Quality Index | Increased intangibles/other assets |
| SGI | Sales Growth Index | Pressure from high growth |
| DEPI | Depreciation Index | Aggressive depreciation policy |
| SGAI | SG&A Index | Declining efficiency |
| LVGI | Leverage Index | Increasing debt |
| TATA | Total Accruals to Total Assets | Low earnings quality |
Interpretation
| M-Score | Interpretation | Risk Level |
|---|---|---|
| < -2.22 | Non-manipulator | Low |
| -2.22 to -1.78 | Potential manipulator | Medium |
| > -1.78 | High probability manipulator | High |
CLI Usage
python scripts/stock_analyzer.py AAPL --method beneish_m
Relative Valuation (PE/PB)
Relative valuation compares current multiples to historical averages and peer groups - the standard approach used in professional equity research.
PE Relative Valuation
Compares current P/E ratio to historical and peer averages. Best for profitable companies with stable earnings.
Basic Usage
from valueinvest import Stock
from valueinvest.valuation import ValuationEngine
stock = Stock(
ticker="AAPL",
name="Apple Inc.",
current_price=180.0,
eps=6.0,
pe_ratio=30.0,
historical_pe=[25, 28, 30, 32, 27], # 5-year history
)
engine = ValuationEngine()
result = engine.run_single(stock, "pe_relative")
print(f"Current P/E: {result.details['current_pe']:.1f}x")
print(f"Historical Avg: {result.details['historical_avg_pe']:.1f}x")
print(f"Percentile: {result.details['percentile_in_history']:.0f}th")
print(f"vs Historical: {result.details['vs_historical_pct']:+.1f}%")
Interpretation
- Bottom quartile (0-25th percentile): Potentially undervalued or deteriorating fundamentals
- Middle range (40-60th percentile): Fair value
- Top quartile (75-100th percentile): Potentially overvalued or improving fundamentals
PB Relative Valuation
Compares current P/B ratio to historical and peer averages. Best for banks, financials, and asset-heavy companies.
Basic Usage
from valueinvest import Stock
from valueinvest.valuation import ValuationEngine
stock = Stock(
ticker="601398",
name="工商银行",
current_price=5.0,
bvps=8.0,
pb_ratio=0.625,
historical_pb=[0.7, 0.8, 0.65, 0.75, 0.72], # 5-year history
)
engine = ValuationEngine()
result = engine.run_single(stock, "pb_relative")
print(f"Current P/B: {result.details['current_pb']:.2f}x")
print(f"Historical Avg: {result.details['historical_avg_pb']:.2f}x")
print(f"Fair Value: ${result.fair_value:.2f}")
When to Use P/B Relative
- Banks and financial institutions
- Asset-heavy industries (manufacturing, utilities)
- Value investing strategies
- Companies trading below book value (P/B < 1.0)
CLI Usage
# PE Relative
python scripts/stock_analyzer.py AAPL --method pe_relative
# PB Relative
python scripts/stock_analyzer.py 601398 --method pb_relative
Cyclical Stock Analysis
The cyclical stock analysis module provides comprehensive tools for analyzing cyclical stocks (shipping, steel, metals, energy, etc.) with different strategies for A-share and US markets.
Key Features
- Cycle Position Scoring: Multi-dimensional scoring (valuation, financial, industry, sentiment) to determine cycle phase (Bottom → Top)
- Cyclical-Adjusted Valuation Methods:
- Cyclical PB: Dynamic PB thresholds based on cycle phase (A-share: Buy < 1.0-1.2x, US: Buy < 1.0-1.4x)
- Cyclical PE: Normalized earnings using 3-5 year averages to avoid "cycle top low PE trap"
- Cyclical FCF: Free cash flow yield analysis (A-share: Buy > 10%, US: Buy > 12%)
- Cyclical Dividend: Dividend sustainability assessment for US stocks
- Differentiated Strategies:
- A-Share: Trading-oriented (1-3 year holding, +50-200% target return)
- US: Dividend-defensive (5-10 year holding, 6-10% annual return)
- Investment Rating: 强烈推荐/推荐/中性/谨慎/不推荐 with 0-100 scoring
Basic Usage
from valueinvest.cyclical import (
CyclicalAnalysisEngine,
CyclicalStock,
CycleType,
MarketType,
)
# Create stock data
stock = CyclicalStock(
ticker="601919",
name="中远海控",
market=MarketType.A_SHARE,
current_price=15.79,
cycle_type=CycleType.SHIPPING,
pb=1.09,
bvps=14.5,
eps=1.73,
pe=9.1,
fcf_yield=0.079, # 7.9%
fcf_per_share=1.25,
fcf_to_net_income=1.1,
dividend_yield=0.05, # 5.0%
debt_ratio=0.35,
roe=0.12, # 12.0%
historical_pb=[1.5, 2.0, 1.8, 2.5, 1.2],
)
# Run complete analysis
engine = CyclicalAnalysisEngine()
result = engine.analyze(stock)
# View results
print(f"股票: {result.stock.name} ({result.stock.ticker})")
print(f"周期阶段: {result.cycle_analysis.phase_display}")
print(f"周期得分: {result.cycle_analysis.total_score:.2f}/5.0")
print(f"综合评分: {result.overall_score}/100")
print(f"投资评级: {result.investment_rating}")
print(f"投资行动: {result.strategy_recommendation.action_display}")
print(f"建议仓位: {result.strategy_recommendation.target_allocation:.1%}")
print(f"目标价格: ¥{result.strategy_recommendation.target_price:.2f}")
Cycle Types
| Cycle Type | Examples | Characteristics |
|---|---|---|
| SHIPPING | 中远海控, 中远海能 | BDI-driven, 3-5 year cycles |
| COMMODITY | 中国铝业, 紫金矿业 | Metal prices, global demand |
| CAPACITY | 宝钢股份, 万华化学 | Supply-demand, capex cycles |
| ENERGY | 中国石油, Exxon | Oil/gas prices, OPEC policy |
| FINANCIAL | Banks, Insurance | Interest rate, credit cycles |
| REAL_ESTATE | Developers | Property market, policy |
Cycle Phases
| Phase | Score | Strategy | Valuation Focus |
|---|---|---|---|
| Bottom | 0-2.0 | Strong Buy | PB < 1.0, FCF yield > 10% |
| Early Upside | 2.0-3.0 | Buy | PB 1.0-1.5, momentum building |
| Mid Upside | 3.0-3.5 | Hold/Add | PB 1.5-2.0, ride the trend |
| Late Upside | 3.5-4.0 | Reduce | PB > 2.0, take profits |
| Top | 4.0-5.0 | Sell | PB > 2.5-3.0, exit position |
CLI Usage
# Analyze cyclical stock
python scripts/stock_analyzer.py 601919 --cyclical
python scripts/stock_analyzer.py 601919 --cyclical --cycle-type SHIPPING
# With news analysis
python scripts/stock_analyzer.py 601919 --cyclical --news
Example Analyses
- 中远海控 (601919): Shipping cyclical - see
scripts/analyze_cyclical_stock.py - 云天化 (600096): Phosphorus chemical cyclical - see
scripts/analyze_600096.pyand report atreports/600096/2026-03-09_600096_analysis.md
News Data Sources
| Source | Markets | News | Guidance | Auth |
|---|---|---|---|---|
| AKShare | A-shares | ✅ East Money | ❌ | Free |
| yfinance | US/Intl | ✅ Yahoo Finance | ✅ Analyst data | Free |
Data Sources
| Source | Markets | Auth | Install |
|---|---|---|---|
| AKShare | A-shares | Free | pip install valueinvest[ashare] |
| yfinance | US/Intl | Free | pip install valueinvest[us] |
| Tushare | A-shares | Token | TUSHARE_TOKEN=xxx pip install valueinvest[tushare] |
Auto-detection by ticker format:
- 6 digits (600887) → AKShare
- Letters (AAPL) → yfinance
QFQ vs HFQ Price Adjustment
| Type | Use Case | Characteristics |
|---|---|---|
| QFQ (前复权) | Valuation comparison | Current price unchanged, historical adjusted |
| HFQ (后复权) | Real investment returns | Historical unchanged, dividends compounded |
history = Stock.fetch_price_history("600900", period="5y")
# QFQ: Price-only growth (for comparing with valuation)
print(f"QFQ CAGR: {history.cagr:.2f}%")
# HFQ: Total return including dividends reinvested
print(f"HFQ CAGR: {history.cagr_hfq:.2f}%")
# Recent prices
stats_qfq = history.get_price_stats(days=30, adjust="qfq")
stats_hfq = history.get_price_stats(days=30, adjust="hfq")
Company Type Detection
Automatic classification based on ticker and financials:
- Utilities (600900, etc.) → Dividend
- Banks (601398, etc.) → Bank
- Dividend yield > 3% → Dividend
- HFQ CAGR > 10% → Growth
- HFQ CAGR < 5% → Value
Available Valuation Methods
| Method | Best For | Key Formula |
|---|---|---|
| Graham Number | Defensive investors | √(22.5 × EPS × BVPS) |
| Graham Formula | Moderate growth | V = (EPS × (8.5 + 2g) × 4.4) / Y |
| NCAV | Deep value | (Assets - Liabilities) / Shares |
| DCF | Growth companies | PV(Free Cash Flows) + Terminal Value |
| Reverse DCF | Any | What growth is priced in? |
| EPV | Mature companies | Distributable CF / Cost of Capital |
| DDM | Dividend stocks | D / (r - g) |
| Two-Stage DDM | Dividend growth | Stage 1 + Terminal perpetuity |
| PEG | Profitable growth | P/E ÷ Growth Rate |
| GARP | Growth at reasonable price | Future EPS × Target P/E, discounted |
| Rule of 40 | SaaS/Subscription | Growth % + Margin % ≥ 40 |
| P/B Valuation | Banks | Fair P/B = (ROE - g) / (COE - g) |
| Residual Income | Banks | Book Value + PV(Excess Returns) |
| PE Relative | Peer comparison | Current PE vs Historical/Peer Avg |
| PB Relative | Asset-heavy, Banks | Current PB vs Historical/Peer Avg |
| Beneish M-Score | Fraud detection | 8-variable earnings manipulation score |
| Piotroski F-Score | Quality screening | 9-point financial strength score |
| Altman Z-Score | Bankruptcy risk | Z = 1.2X1 + 1.4X2 + 3.3X3 + 0.6X4 + 1.0X5 |
| Cyclical PB | Cyclical stocks | Dynamic PB thresholds based on cycle phase |
| Cyclical PE | Cyclical stocks | Normalized earnings using 3-5 year average |
| Cyclical FCF | Cyclical stocks | FCF yield with cycle-adjusted thresholds |
| Cyclical Dividend | Cyclical stocks (US) | Dividend sustainability + FCF coverage |
Project Structure
valueinvest/
├── exceptions.py # Custom exceptions (DataFetchError, etc.)
├── stock.py # Stock dataclass, StockHistory
├── moat/ # Economic moat scoring
│ ├── base.py # MoatResult, MoatSignal, MoatType enum
│ ├── signals.py # 11 moat signal functions
│ └── engine.py # MoatAnalysisEngine
├── roic/ # ROIC vs WACC analysis
│ ├── base.py # ROICResult, WACCResult, EconomicProfitResult
│ ├── roic.py # ROIC calculation
│ ├── wacc.py # WACC calculation
│ └── engine.py # EconomicProfitEngine
├── capital/ # Capital allocation quality
│ ├── base.py # CapitalAllocationResult, AllocationSignal
│ ├── signals.py # 12 allocation signal functions
│ └── engine.py # CapitalAllocationEngine
├── implied_growth/ # Implied growth rate analysis
│ ├── base.py # ImpliedGrowthResult, GrowthComparison, GrowthReasonableness
│ ├── analyzer.py # Reverse DCF, PEG, Gordon Growth, Earnings Yield
│ └── engine.py # ImpliedGrowthEngine
├── valuation/
│ ├── base.py # Base classes
│ ├── engine.py # Unified engine
│ ├── graham.py # Graham methods
│ ├── dcf.py # DCF methods
│ ├── epv.py # Earnings Power Value
│ ├── ddm.py # Dividend models
│ ├── growth.py # Growth valuation
│ ├── bank.py # Bank valuation
│ ├── quality.py # Piotroski F-Score, Altman Z-Score, Owner Earnings
│ ├── value_trap.py # Value trap detection
│ ├── magic_formula.py # Magic Formula
│ ├── mscore.py # Beneish M-Score (earnings manipulation)
│ └── relative.py # PE/PB Relative valuation
├── news/ # News & sentiment analysis
│ ├── base.py # NewsItem, Guidance, NewsAnalysisResult
│ ├── registry.py # Market detection & fetcher registry
│ ├── fetcher/
│ │ ├── base.py # BaseNewsFetcher (ABC)
│ │ ├── akshare_news.py # A-share news (East Money)
│ │ └── yfinance_news.py # US stock news & analyst data
│ └── analyzer/
│ ├── base.py # BaseSentimentAnalyzer (ABC)
│ ├── keyword_analyzer.py # Keyword-based sentiment
│ ├── llm_analyzer.py # LLM-based sentiment (OpenAI)
│ └── agent_analyzer.py # Coding agent-based sentiment
├── insider/ # Insider trading data
│ ├── base.py # InsiderTrade, InsiderSummary, InsiderFetchResult
│ ├── registry.py # Market detection & fetcher registry
│ └── fetcher/
│ ├── base.py # BaseInsiderFetcher (ABC)
│ ├── akshare_insider.py # A-share (同花顺高管增减持)
│ └── yfinance_insider.py # US stock insider transactions
├── buyback/ # Buyback/repurchase analysis
│ ├── base.py # BuybackRecord, BuybackSummary, BuybackFetchResult
│ ├── registry.py # Market detection & fetcher registry
│ └── fetcher/
│ ├── base.py # BaseBuybackFetcher (ABC)
│ ├── akshare_buyback.py # A-share (东方财富回购数据)
│ └── yfinance_buyback.py # US stock cash flow buyback
├── cashflow/ # Free Cash Flow analysis
│ ├── base.py # CashFlowRecord, CashFlowSummary, CashFlowFetchResult
│ ├── registry.py # Market detection & fetcher registry
│ └── fetcher/
│ ├── base.py # BaseCashFlowFetcher (ABC)
│ └── yfinance_cashflow.py # US stock cash flow data
├── cyclical/ # Cyclical stock analysis
│ ├── base.py # CyclicalStock, CycleScore, ValuationResult
│ ├── enums.py # CycleType, CyclePhase, MarketType, etc.
│ ├── engine.py # CyclicalAnalysisEngine
│ ├── position_scorer.py # Cycle position scoring system
│ ├── valuation/ # Cyclical valuation methods
│ │ ├── cyclical_pb.py # Cyclical PB valuation
│ │ ├── cyclical_pe.py # Cyclical PE valuation
│ │ ├── cyclical_fcf.py # Cyclical FCF valuation
│ │ └── cyclical_dividend.py # Cyclical dividend valuation
│ └── strategy/ # Market-specific strategies
│ ├── ashare_strategy.py # A-share (trading-oriented)
│ └── us_strategy.py # US (dividend-defensive)
├── data/
│ ├── presets.py # Pre-configured stocks
│ └── fetcher/ # Data fetching
│ ├── base.py # Base classes
│ ├── akshare.py # A-shares (free)
│ ├── yfinance.py # US/Intl stocks
│ └── tushare.py # A-shares (token)
└── reports/
├── reporter.py # Report formatting
└── enhanced_reporter.py # Enhanced report with news
scripts/stock_analyzer.py # CLI entry point
AGENTS.md # AI Agent quick reference
## Example Output
### With News Analysis
====================================================================== 伊利股份 (600887) - 深度分析报告
【公司概况】 公司: 伊利股份 代码: 600887 类型: 价值股 当前股价: ¥26.48 总市值: ¥1675亿
【最新财务数据】 营业收入: ¥903亿 净利润: ¥104亿 每股收益 (EPS): ¥1.65 每股净资产 (BVPS): ¥8.90 市盈率 (PE): 16.0倍 市净率 (PB): 2.97倍
====================================================================== 【新闻情感分析】
情感得分: 📈 +0.25 (positive) 分析新闻数: 25 条 (7日内: 8) 正面/负面/中性: 12/5/8 置信度: 72% 趋势: ➡️ 稳定
【关键主题】 • 原材料成本下降 • 渠道扩张 • 产品创新
【风险提示】 ⚠️ 竞争加剧 ⚠️ 成本波动
【潜在催化剂】 ✅ 新品发布 ✅ 旺季销售
【近期重要新闻】 [+] 02-15 伊利股份发布业绩预告,净利润增长20%... [+] 02-14 公司宣布分红方案,股息率提升至3.5%... [ ] 02-12 行业分析:乳制品市场稳中有升...
====================================================================== 【估值汇总】
| 方法 | 公允价值 | 溢价/折价 | 评估 |
|---|---|---|---|
| Graham Number | ¥ 18.18 | -31.3% | Overvalued |
| DDM (Gordon Growth) | ¥ 20.94 | -20.9% | Overvalued |
| GARP | ¥ 19.54 | -26.2% | Overvalued |
| Reverse DCF | ¥ 26.48 | +0.0% | Priced in |
| Graham Formula | ¥ 46.17 | +74.4% | Undervalued |
====================================================================== 【综合结论】
估值区间: ¥18-21 (保守) / ¥26 (现价) / ¥40+ (乐观)
【综合评级】: 🟡 合理 + 正面消息
投资建议:
- 目标买入价: ¥22 (15%安全边际)
- 止损位: ¥16
- 情绪面: 近期消息偏正面,可积极关注
## Extending the News Module
### Adding a New Market
```python
from valueinvest.news.base import Market
from valueinvest.news.fetcher.base import BaseNewsFetcher
from valueinvest.news.registry import NewsRegistry
class HKNewsFetcher(BaseNewsFetcher):
market = Market.HK
@property
def source_name(self) -> str:
return "hk_source"
def fetch_news(self, ticker, days=30, start_date=None, end_date=None):
# Implement news fetching for Hong Kong stocks
...
def fetch_guidance(self, ticker):
# Implement guidance fetching
...
# Register the new fetcher
NewsRegistry.register_fetcher(Market.HK, HKNewsFetcher)
# Register market detector
NewsRegistry.register_detector(
lambda t: Market.HK if t.isdigit() and len(t) == 5 else None
)
Extending the Insider Module
Adding a New Market
from valueinvest.news.base import Market
from valueinvest.insider.base import InsiderTrade, InsiderFetchResult
from valueinvest.insider.fetcher.base import BaseInsiderFetcher
from valueinvest.insider.registry import InsiderRegistry
class HKInsiderFetcher(BaseInsiderFetcher):
market = Market.HK
@property
def source_name(self) -> str:
return "hk_source"
def fetch_insider_trades(self, ticker, days=90, start_date=None, end_date=None):
# Implement insider trading fetching for Hong Kong stocks
...
# Register the new fetcher
InsiderRegistry.register_fetcher(Market.HK, HKInsiderFetcher)
License
MIT License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file valueinvest-1.3.2.tar.gz.
File metadata
- Download URL: valueinvest-1.3.2.tar.gz
- Upload date:
- Size: 313.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2153fa84c817726fd263a95175d611a6eeb7f80cf1ad9013509f4ad6ba758e3b
|
|
| MD5 |
c1de66538af622e9cea1ba90e4b53078
|
|
| BLAKE2b-256 |
67986ddf89607b8ed11de91f35d810382e4f6f6c7f2efa65c37dbe6f269aaecb
|
File details
Details for the file valueinvest-1.3.2-py3-none-any.whl.
File metadata
- Download URL: valueinvest-1.3.2-py3-none-any.whl
- Upload date:
- Size: 248.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b9608fba038ba21fef1dcfbef91dfe408f0a2e25ee968729884b3f26ec3e05d
|
|
| MD5 |
7604d37e908cc790ac2c4280fac32b09
|
|
| BLAKE2b-256 |
7877783e064846281def31dbaaec101340a9bc81cd2962a90b24238cdedaf690
|