US examples
PEG ratio strategy
On this page4
The PEG ratio (Price/Earnings to Growth) asks whether a stock's price is reasonable for how fast its earnings grow; a lower PEG suggests the stock is undervalued given its growth. This strategy targets growth at a reasonable price (GARP), for investors who want growing companies without overpaying for them.
Strategy logic
- Revenue trend filter: the 3-quarter average revenue is more than 1.1 times the 12-quarter average, and this quarter's revenue is at least 90% of the prior quarter's. This ensures the company's revenue is on an upward path.
- PEG: P/E (price divided by trailing-12-month diluted EPS) divided by the year-over-year earnings growth rate in percent.
- PEG ranking: among stocks that pass the revenue filter, hold the 10 with the lowest PEG.
- Rebalance monthly, with a 10% stop-loss on each position.
Requiring both revenue momentum and a low PEG avoids two common pitfalls: buying cheap stocks with deteriorating fundamentals, and overpaying for high-growth stocks.
Code
strategy.py
from finlab import data
from finlab.backtest import sim
from finlab.markets.us import USMarket
data.set_market('us')
close = data.get('price:adj_close')
close = close[close.index.dayofweek < 5] # remove weekends
# Revenue data from US income statement
revenue = data.get('us_income_statement:revenue')
rev_ma3 = revenue.average(3)
rev_ma12 = revenue.average(12)
# Revenue trend filter
cond1 = rev_ma3 / rev_ma12 > 1.1
cond2 = revenue / revenue.shift(1) > 0.9
cond_all = cond1 & cond2
# PE ratio (price / trailing-12-month diluted EPS) and earnings growth
price = data.get('price:close')
eps = data.get('us_income_statement:eps_diluted')
pe = price / eps.rolling(4).sum()
net_income = data.get('us_income_statement:net_income')
earnings_growth = net_income / net_income.shift(4) - 1
# PEG ratio = PE / Earnings Growth Rate (in %)
peg = pe / (earnings_growth * 100)
# Multiply PEG by revenue condition; non-qualifying stocks become 0
position = peg * cond_all
# Remove stocks that do not pass the revenue filter
# Without this line, is_smallest might fill remaining slots with non-qualifying stocks
position = position[position > 0]
# Select the 10 stocks with the lowest PEG
position = position.is_smallest(10)
report = sim(
position,
resample='M',
stop_loss=0.1,
market=USMarket(),
fee_ratio=0.001,
tax_ratio=0,
)
report.display()How to adjust it
rev_ma3 / rev_ma12 > 1.1: the 3-quarter moving average of revenue must beat the 12-quarter average by at least 10%. This confirms an accelerating revenue trend rather than a one-time spike.revenue / revenue.shift(1) > 0.9: this quarter's revenue must be at least 90% of the prior quarter's, which keeps sudden revenue collapses out of the portfolio.pe / (earnings_growth * 100): the PEG, from the P/E and the year-over-year earnings growth in percent. A PEG of 1.0 is often considered fair value; below 1.0 suggests the stock is cheap for its growth.is_smallest(10): the 10 cheapest stocks by PEG among those passing the revenue filter.stop_loss=0.1: a 10% stop-loss protects against rapid declines in individual holdings.resample='M': rebalances monthly to pick up the latest quarterly earnings. Earnings growth is reported quarterly in the US, so the selection updates as new financial data becomes available.
The strategy tends to do well during earnings-driven market rallies and may underperform during speculative momentum bubbles, when valuations are ignored.
Related pages
- Quality small caps Combine valuation with cash flow, ROE and growth checks.
- Price deviation & ROE filter Momentum with a profitability guard rail.
- Load more data Find US statement fields and build valuation ratios.
- Write better rules
is_smallest,averageand other selection tools.
Was this page helpful?