
Vectorbt Expert
Backtest Indian ETF or equity allocations with VectorBT, OpenAlgo data, delivery-fee modeling, and benchmark comparisons before you commit capital.
Overview
vectorbt-expert is an agent skill most often used in Validate (also Build) that runs VectorBT plus OpenAlgo backtests with Indian equity fee and benchmark modeling.
Install
npx skills add https://github.com/marketcalls/vectorbt-backtesting-skills --skill vectorbt-expertWhat is this skill?
- Buy-and-hold and rule-based flows using vectorbt Portfolio APIs
- OpenAlgo client for NSE symbols and NSE_INDEX benchmarks
- Indian delivery fee model: 0.111% plus Rs 20 per order constants in examples
- Plotly dashboards and CAGR helpers against NIFTY and FD-rate baselines
- Configurable weights such as 60% NIFTYBEES / 40% GOLDBEES in sample configs
- Example INIT_CASH 10,00,000 in bundled backtest config
- FEES 0.00111 and FIXED_FEES Rs 20 per order in Indian delivery model
- Sample 60% NIFTYBEES / 40% GOLDBEES weights in reference strategy
Adoption & trust: 1.5k installs on skills.sh; 150 GitHub stars; 2/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
You have an allocation or signal idea for Indian ETFs but no reproducible way to test fees, benchmarks, and CAGR before risking real money.
Who is it for?
Indie traders and fintech side projects validating systematic strategies on NSE data via OpenAlgo.
Skip if: Live order routing compliance stacks, non-Indian markets without OpenAlgo feeds, or users who need institutional risk systems.
When should I use this skill?
User asks for VectorBT backtests with OpenAlgo, Indian ETF portfolios, fee-aware simulations, or benchmark plots.
What do I get? / Deliverables
You get executable backtest scripts, performance metrics, and charts grounded in OpenAlgo history and stated Indian cost assumptions.
- Backtest notebooks or scripts
- CAGR and benchmark comparison outputs
- Plotly performance charts
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Strategy proofing belongs in Validate because backtests answer whether a static or rules-based portfolio idea survives fees and benchmarks before full productization. Prototype subphase fits notebook-style VectorBT scripts that fetch history, simulate buys, and chart results without shipping a trading app.
Where it fits
You want to compare a 60/40 equity-gold ETF blend against NIFTY and an FD CAGR before sizing a personal allocation.
You are turning the backtest script into a repeatable CLI your agent runs nightly for strategy regression.
You model whether stated fees erase edge on a low-turnover delivery strategy pitched to subscribers.
How it compares
Research and prototype backtests in Python, not a hosted robo-advisor or MCP market-data server by itself.
Common Questions / FAQ
Who is vectorbt-expert for?
Solo builders and small quant projects who already use or can run OpenAlgo locally and want VectorBT patterns for Indian equities and ETFs.
When should I use vectorbt-expert?
Use it in Validate to prototype buy-and-hold or signal strategies, and in Build when hardening the same pipelines into CLI tools or internal analytics APIs.
Is vectorbt-expert safe to install?
Scripts expect API keys in environment variables; review the Security Audits panel on this Prism page and never commit live OpenAlgo credentials.
SKILL.md
READMESKILL.md - Vectorbt Expert
""" Buy & Hold Portfolio Backtest - VectorBT + OpenAlgo Strategy: Static allocation across ETFs (e.g., 60% NIFTYBEES + 40% GOLDBEES). One-time purchase on Day 1, hold forever. Fees: Indian delivery equity model (0.111% + Rs 20/order). Benchmark: NIFTY 50 Index via OpenAlgo (NSE_INDEX) + HDFC FD rate. """ import os from datetime import datetime, timedelta from pathlib import Path import numpy as np import pandas as pd import vectorbt as vbt import plotly.graph_objects as go from plotly.subplots import make_subplots from dotenv import find_dotenv, load_dotenv from openalgo import api # --- Config --- script_dir = Path(__file__).resolve().parent load_dotenv(find_dotenv(), override=False) SYMBOLS = ["NIFTYBEES", "GOLDBEES"] WEIGHTS = {"NIFTYBEES": 0.60, "GOLDBEES": 0.40} EXCHANGE = "NSE" INTERVAL = "D" INIT_CASH = 10_00_000 FEES = 0.00111 # Indian delivery equity FIXED_FEES = 20 # Rs 20 per order FD_CAGR = 0.0645 # HDFC Bank FD rate 6.45% BENCHMARK_SYMBOL = "NIFTY" BENCHMARK_EXCHANGE = "NSE_INDEX" def calc_cagr(start_val, end_val, years): """Calculate CAGR given start value, end value, and number of years.""" if start_val <= 0 or end_val <= 0 or years <= 0: return 0.0 return (end_val / start_val) ** (1 / years) - 1 # --- Fetch Data --- client = api( api_key=os.getenv("OPENALGO_API_KEY"), host=os.getenv("OPENALGO_HOST", "http://127.0.0.1:5000"), ) end_date = datetime.now().date() start_date = "2018-01-01" print(f"Fetching data for {SYMBOLS} ({EXCHANGE}) from {start_date} to {end_date}") dfs = {} for sym in SYMBOLS: df = client.history( symbol=sym, exchange=EXCHANGE, interval=INTERVAL, start_date=start_date, end_date=end_date.strftime("%Y-%m-%d"), ) if "timestamp" in df.columns: df["timestamp"] = pd.to_datetime(df["timestamp"]) df = df.set_index("timestamp") else: df.index = pd.to_datetime(df.index) df = df.sort_index() if df.index.tz is not None: df.index = df.index.tz_convert(None) dfs[sym] = df print(f" {sym}: {len(df)} bars from {df.index[0].date()} to {df.index[-1].date()}") # --- Build Price Panel --- close_prices = pd.DataFrame({sym: dfs[sym]["close"] for sym in SYMBOLS}).dropna() print(f"\nAligned data: {len(close_prices)} bars") # --- Buy & Hold: One-time allocation on Day 1 --- size_df = pd.DataFrame(np.nan, index=close_prices.index, columns=SYMBOLS) size_df.iloc[0] = [WEIGHTS[sym] for sym in SYMBOLS] pf = vbt.Portfolio.from_orders( close=close_prices, size=size_df, size_type="targetpercent", fees=FEES, fixed_fees=FIXED_FEES, init_cash=INIT_CASH, cash_sharing=True, call_seq="auto", group_by=True, freq="1D", min_size=1, size_granularity=1, ) # --- Benchmark --- print("\nFetching NIFTY 50 index data for benchmark...") df_nifty = client.history( symbol=BENCHMARK_SYMBOL, exchange=BENCHMARK_EXCHANGE, interval=INTERVAL, start_date=start_date, end_date=end_date.strftime("%Y-%m-%d"), ) if "timestamp" in df_nifty.columns: df_nifty["timestamp"] = pd.to_datetime(df_nifty["timestamp"]) df_nifty = df_nifty.set_index("timestamp") else: df_nifty.index = pd.to_datetime(df_nifty.index) df_nifty = df_nifty.sort_index() if df_nifty.index.tz is not None: df_nifty.index = df_nifty.index.tz_convert(None) nifty_close = df_nifty["close"].reindex(close_prices.index).ffill().bfill() pf_niftybees = vbt.Portfolio.from_holding( close_prices["NIFTYBEES"], init_cash=INIT_CASH, fees=FEES, freq="1D") pf_goldbees = vbt.Portfolio.from_holding( close_prices["GOLDBEES"], init_cash=INIT_CASH, fees=FEES, freq="1D") # --- Results --- print("\n" + "=" * 60) print(f" Buy & Hold: {WEIGHTS['NIFTYBEES']*100:.0f}% NIFTYBEES + {WEIGHTS['GOLDBEES']*100:.0f}% GOLDBEES") print("=" * 60) print(pf.stats()) # --- CAGR Calculations --- equity = pf.value() n_days = (close_prices.index[-1] - close_prices.index[0]).days n_years = n_days / 365.25 cagr_portfolio