ta.* Function Reference
Technical analysis functions available in ATK PyneScript V6 — EMA, SMA, RSI, MACD, BBands, crossover, and more.
ta.* Namespace Overview#
The ta namespace provides a complete set of technical analysis functions that operate on pandas Series or DataFrame columns. All functions are designed to work inside build_indicator_frame or build_signal_frame — never inside build_visuals or build_trade_frame.
Moving Averages#
from source import ta
# Exponential Moving Average
ema_series = ta.ema(frame["close"], length=20)
# Simple Moving Average
sma_series = ta.sma(frame["close"], length=20)
# Running Moving Average (Wilder's)
rma_series = ta.rma(frame["close"], length=14)
# Weighted Moving Average
wma_series = ta.wma(frame["close"], length=20)
# Hull Moving Average
hma_series = ta.hma(frame["close"], length=20)Momentum and Oscillators#
# Relative Strength Index
rsi_series = ta.rsi(frame["close"], length=14)
# MACD — returns (macd_line, signal_line, histogram)
macd, signal, hist = ta.macd(frame["close"], fast=12, slow=26, signal=9)
# Stochastic — returns (k, d)
k, d = ta.stoch(frame["high"], frame["low"], frame["close"], k=14, d=3, smooth_k=3)
# Average True Range
atr_series = ta.atr(frame["high"], frame["low"], frame["close"], length=14)
# Commodity Channel Index
cci_series = ta.cci(frame["high"], frame["low"], frame["close"], length=20)Bollinger Bands#
# Returns (upper, basis, lower)
upper, basis, lower = ta.bbands(
frame["close"],
length=20,
std=2.0,
mamode="sma",
)
frame["ub"] = upper.reset_index(drop=True)
frame["cb"] = basis.reset_index(drop=True)
frame["lb"] = lower.reset_index(drop=True)Crossover Signals#
# Returns boolean Series — True on the bar where fast crosses above slow
buy_signal = ta.crossover(ema_fast, ema_slow).fillna(False)
# Returns boolean Series — True on the bar where fast crosses below slow
sell_signal = ta.crossunder(ema_fast, ema_slow).fillna(False)Always call .fillna(False) on crossover/crossunder results before using them in boolean conditions or np.where. The first few bars produce NaN due to lookback requirements.
Supertrend#
# Returns (supertrend_line, direction_series)
# direction: 1 = uptrend, -1 = downtrend
supertrend, direction = ta.supertrend(
frame["high"], frame["low"], frame["close"],
length=10,
multiplier=3.0,
)Usage Patterns#
Source Fallback Pattern#
Always implement a safe fallback when using input.source:
source_name = str(p.get("source_type", "close") or "close")
source_series = frame[source_name] if source_name in frame.columns else frame["close"]
frame["ema_value"] = ta.ema(source_series, int(p.get("length", 20) or 20))Full Indicator Example#
import pandas as pd
from source import indicator, input, plot, ta
indicator("EMA Crossover", overlay=True, max_bars_back=240)
fast_length = input.int(10, title="Fast EMA", key="fast_length", minval=1)
slow_length = input.int(21, title="Slow EMA", key="slow_length", minval=2)
def build_indicator_frame(df: pd.DataFrame, params: dict | None = None) -> pd.DataFrame:
frame = df.copy().reset_index(drop=True)
p = {
"fast_length": int(fast_length),
"slow_length": int(slow_length),
} | dict(params or {})
frame["ema_fast"] = ta.ema(frame["close"], int(p["fast_length"]))
frame["ema_slow"] = ta.ema(frame["close"], int(p["slow_length"]))
frame["buy_signal"] = ta.crossover(frame["ema_fast"], frame["ema_slow"]).fillna(False)
frame["sell_signal"] = ta.crossunder(frame["ema_fast"], frame["ema_slow"]).fillna(False)
return frameStage Ownership Rules#
All ta.* calls belong in build_indicator_frame (indicators) or build_signal_frame (strategies). Never call ta.* inside build_visuals or build_trade_frame. Those stages consume already-computed columns — they do not run new calculations.
See also: