Integrating pandas-ta-classic with vectorbt
vectorbt is a vectorized backtesting library built on NumPy and pandas. Unlike event-driven frameworks, it operates on entire time-series at once, making parameter sweeps fast. Since pandas-ta-classic returns pandas Series and DataFrames natively, the two integrate without a bridge function.
The key connector is df.ta.tsignals(), which converts a boolean trend Series into vectorbt-compatible entry and exit boolean arrays.
1. The Integration Pattern
import pandas as pd
import pandas_ta_classic as ta
import vectorbt as vbt
Step 1 — Define a trend as a boolean Series:
def trend(df: pd.DataFrame, fast: int = 50, slow: int = 200) -> pd.Series:
return ta.ma("sma", df["Close"], length=fast) > ta.ma("sma", df["Close"], length=slow)
A trend is True when the condition holds, False otherwise. Any boolean expression over indicator output works here.
Step 2 — Convert the trend to entry/exit signals with tsignals:
signals = df.ta.tsignals(trend(df), asbool=True, trade_offset=1)
# signals columns: TS_Trends, TS_Trades, TS_Entries, TS_Exits
asbool=True— returns boolean arrays, which is whatvbt.Portfolio.from_signals()expects.trade_offset=1— shifts entries/exits by one bar to avoid look-ahead bias in backtesting. Use0for live signals.
Step 3 — Run the backtest:
vbt.settings.portfolio["freq"] = "1D"
vbt.settings.portfolio["fees"] = 0.0025
vbt.settings.portfolio["slippage"] = 0.0025
pf = vbt.Portfolio.from_signals(
df["Close"],
entries=signals.TS_Entries,
exits=signals.TS_Exits,
)
print(pf.stats())
2. Comparing Against Buy-and-Hold
pf_bnh = vbt.Portfolio.from_holding(df["Close"])
print("Strategy:")
print(pf.stats()[["Total Return [%]", "Sharpe Ratio", "Max Drawdown [%]"]])
print("\nBuy and Hold:")
print(pf_bnh.stats()[["Total Return [%]", "Sharpe Ratio", "Max Drawdown [%]"]])
3. Plotting
pf.trades.plot(title="Trades").show()
pf.value().vbt.plot(title="Equity Curve").show()
pf.drawdown().vbt.plot(title="Drawdown").show()
4. Multi-Output Indicators
Indicators that return a DataFrame (MACD, Bollinger Bands) work directly — index them by column name before passing to the trend function:
def macd_trend(df: pd.DataFrame) -> pd.Series:
macd = ta.macd(df["Close"], fast=12, slow=26, signal=9)
return macd["MACDh_12_26_9"] > 0 # positive histogram = bullish
Full example: See
examples/VectorBT_Backtest_with_Pandas_TA.ipynbfor a complete workflow including multi-ticker data acquisition, benchmark comparison, and full equity curve plots.