Skip to content

Indicators

Supports TA-Lib and pandas_ta with hundreds of technical indicators. Calculate thousands of stocks over long time periods with a single line, suitable for individual stock analysis and machine learning.

Installing TA-Lib

For more parameters and functions, see the TA-Lib official documentation.

Computing RSI for All Stocks

Use data.indicator() to compute RSI (timeperiod=14):

from finlab import data
data.indicator('RSI', timeperiod=14)

The first 14 days may be NaN due to insufficient data.

Technical Indicators with Two Time Series (Stochastic Oscillator KD)

Use data.indicator('STOCH') to compute the Stochastic Oscillator (KD values), which returns two DataFrames (K and D).

from finlab import data
k, d = data.indicator('STOCH')
k

Stock Screening Using KD Values

List stocks where K > D on the most recent day:

(k > d).iloc[-1]
0015    False
0050     True
0051    False
0052     True
0053     True
        ...
9951     True
9955    False
9958    False
9960     True
9962     True
Name: 2021-07-13 00:00:00, Length: 2269, dtype: bool

Computing pandas_ta Technical Indicators

pandas_ta can also compute many technical indicators; see the official documentation for installation and available indicators.

pip install pandas-ta
Use it through data.indicator(), e.g. supertrend:

from finlab import data

values = data.indicator('supertrend')
If TA-Lib has no matching function, pandas_ta is used instead (may be slower).

Custom Indicators (Pandas Operations)

Build custom indicators directly with Pandas operations, no TA-Lib required:

Price & Volume Indicators

from finlab import data

close = data.get('price:收盤價')
volume = data.get('price:成交股數')
rev = data.get('monthly_revenue:當月營收')

# Momentum: N-day return
momentum_20 = close / close.shift(20) - 1

# Moving average deviation
ma60 = close.average(60)
bias = (close - ma60) / ma60

# Price-volume divergence: price at high but volume shrinking
price_high = close == close.rolling(60).max()
volume_low = volume < volume.average(20)
divergence = price_high & volume_low

# Monthly revenue growth
rev_yoy = rev / rev.shift(12) - 1       # year-over-year
rev_mom = rev / rev.shift(1) - 1        # month-over-month
rev_3m = rev.average(3) / rev.average(12) - 1  # 3-month avg vs 12-month avg

Factor Standardization with .cs

pe = data.get('price_earning_ratio:本益比')
roe = data.get('fundamental_features:股東權益報酬率')

# Multi-factor composite: standardize then equal-weight sum
score = roe.cs.zscore() + (-pe).cs.zscore()  # higher ROE, lower PE = better

# Select top 10% by composite score
position = score.cs.rank() > 0.9

Industry Neutralization with .sector

# Problem: raw ROE selection overweights high-ROE industries (e.g., semiconductors)
# Solution: within-industry standardization selects "industry standouts"

roe_neutral = roe.sector.zscore()       # industry-neutralized
rev_neutral = rev_yoy.sector.zscore()   # revenue growth also neutralized

# Composite factor
score = roe_neutral + rev_neutral
position = score.cs.rank() > 0.8

# Or use within-industry ranking directly
position = roe.sector.rank() > 0.7      # top 30% ROE within each industry

Weight Construction with .weight

from finlab.backtest import sim

position = score.cs.rank() > 0.8

# Refined weights: inverse-vol + industry cap + turnover limit
weights = (
    position
    .weight.inverse_volatility(window=60)
    .weight.cap_industry(max_weight=0.3)
    .weight.limit_turnover(max_turnover=0.3)
)

report = sim(weights, resample='Q')

Full accessor documentation

See finlab.dataframe reference for all .cs, .sector, and .weight methods.