koreal6803/finlab-ai/finlab

Claude Code and agent skill by koreal6803/finlab-ai

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Backtest and research stock strategies with the FinLab Python package on real market data: Taiwan stocks (台股) first, plus US, KR, JP, HK equities and ETFs/funds. Use whenever the user wants to backtest a strategy, screen stocks, or pull Taiwan stock data such as adjusted prices, monthly revenue, financial statements or institutional flows, even if they never name FinLab: 台股回測, 股票回測, 回測, 選股, 選股策略, 量化交易, 程式交易, 月營收, 三大法人, 財報, 美股回測, backtesting, trading strategies, stock data, stock selection, FinLabDataFrame, factor analysis, quant trading, US equity, S&P 500 / NASDAQ 100, SPY / QQQ, sector or leveraged ETFs, ETF rotation, 美股, or stock market analysis. Includes data access, strategy development, backtesting workflows, best practices, and US-market specifics (data availability map, filing-date-aligned quarterly fundamentals, US universe construction, USMarket vs. USFundMarket defaults, and ETF backtesting).

Install

npx vskill@latest install koreal6803/finlab-ai/finlab

SKILL.md

FinLab Quantitative Trading Package

Prerequisites

Before running any FinLab code, verify these in order:

  1. uv is installed (Python package manager):

``bash uv --version ``

If uv is not installed, tell the user to install it.

After installing, ensure uv is on PATH:

``bash source $HOME/.local/bin/env 2>/dev/null # Add uv to current shell ``

  1. FinLab is installed via uv (requires >= 2.2.15):

``bash uv python install 3.12 # Ensure Python is available (skip if already installed) uv pip install --system "finlab>=2.2.15" 2>/dev/null || uv pip install "finlab>=2.2.15" ``

Or use `uv run` for zero-setup execution (recommended for one-off scripts):

``bash uv run --with "finlab" python3 script.py ``

uv run --with auto-creates a temporary environment with dependencies — no venv management needed.

Prefer zero-install? Run notebooks directly in FinLab Studio — a hosted Jupyter environment with finlab preinstalled and your account already logged in.

  1. Logged in to FinLab (finlab >= 2.0; no legacy API token required):

Desktop (has a browser): log in once; credentials are cached locally:

``bash python -m finlab login ``

``python import finlab finlab.login() # reuses cached credentials, or starts browser login if none ``

Headless / cron / Docker: on a machine with a browser, log in and run:

``bash python -m finlab token --env ``

Set all three exported variables — FINLAB_REFRESH_TOKEN, FINLAB_SESSION_ID, and FINLAB_API_KEY — in the headless environment. FinLab uses them automatically. Treat the output as credentials: use your platform's secret storage and do not paste it into chat or commit it.

Google Colab: run finlab.login() in a cell and follow the login link.

Migrating from legacy tokens: FINLAB_API_TOKEN and finlab.login('<api_token>') are deprecated. Run python -m finlab migrate, set up browser login or the three environment variables above, then remove the old token from your configuration.

Legacy-token status: No removal version or date is publicly confirmed in the official authentication guide; the 2026/08/01 date in client warning text is not a removal announcement. Dropping the client-side fallback and rejecting legacy tokens server-side are separate changes, and a cached data.get() call does not test server authentication — use the supported login flow above.

Language

Respond in the user's language. If user writes in Chinese, respond in Chinese. If in English, respond in English.

Market Support

FinLab supports tw (default), us, kr, jp, hk, uk, us_fund (US ETFs/funds), rotc (Taiwan emerging) and tw_cb (Taiwan convertible bonds). Pick the market once per session with data.set_market(<code>); an unprefixed dataset name resolves to the active market's table (price:close → us_price:close under us). A name the active market lacks silently falls back to the TW table: Chinese keys (price:收盤價, monthly_revenue:當月營收) exist only for TW and rotc, so under us, data.get('price:收盤價') returns Taiwan prices. Outside TW, use English keys (price:close) or prefixed names (us_price:adj_close). data.set_market('rotc') (v2.0.9) enables 興櫃 (TW emerging) — use it when you need pre-listing price action or revenue factors that don't exist in the main TSE/OTC catalog. tw_cb is not a set_market code (it raises ValueError): read cb_price:* and pass sim(position, market=TWCBMarket()) (from finlab.markets.tw_cb import TWCBMarket).

The rest of this file plus dataframe-reference.md, backtesting-reference.md, best-practices.md, factor-analysis-reference.md, and machine-learning-reference.md are market-agnostic — the APIs behave the same across markets.

For US-market work — whether single-name equities (data.set_market('us')) or ETFs/funds (data.set_market('us_fund')) — read [us-market.md](us-market.md) first. Queries that should trigger it include: US equity, S&P 500, NASDAQ 100, 美股, SPY / QQQ, sector SPDRs, leveraged / inverse ETFs, ETF rotation, us_price:*, us_fund_price:*, data.us_universe(...), or us_income_statement:* / us_cash_flow:* / us_balance_sheet:*. It documents:

  • Which US data tables are safe for backtesting versus current-snapshot-only (analyst consensus, ratios, DCF are live-only — do not use them historically)
  • Quarterly fundamentals aligned on key_date — no .shift() workaround needed; the raw filing_date column is not the publication date
  • Report API names on US (creturn / daily_creturn / get_stats(); no get_equity())
  • US backtest defaults for both markets: USMarket (fee_ratio=0, tax_ratio=0, trade_at_price='close') and USFundMarket for ETF/fund backtests
  • How data.set_market(...) is the session-scope switch (there is no market= kwarg on data.get())
  • Dollar-volume-top-N universe construction, point-in-time S&P 500 / NASDAQ 100 membership via us_index_constituents:* (data.us_universe(index=...) is not point-in-time), quality gates, and sector-exclusion rationale
  • Lookahead-bias checklist specific to US data (rolling-window universe filters, survivorship avoidance)
  • ETF / sector-rotation backtesting via USFundMarket and us_fund_price:*

Other-market queries can skip that file.

Account Tiers & Usage

Tiers
TierDaily Limit
Free500 MB
VIP5000 MB

Check the current plan and quota with python -m finlab status.

Usage Reset
  • Resets daily at 8:00 AM UTC+8
  • When limit exceeded, user must wait for reset or upgrade to VIP at finlab.finance

Quick Start Example

python
from finlab import data
from finlab.backtest import sim
# 1. Fetch data
close = data.get("price:收盤價")
vol = data.get("price:成交股數")
pb = data.get("price_earning_ratio:股價淨值比")
# 2. Create conditions
cond1 = close.rise(10) # Rising last 10 days
cond2 = vol.average(20) > 1000*1000 # High liquidity
cond3 = pb.rank(axis=1, pct=True) < 0.3 # Low P/B ratio
# 3. Combine conditions and select stocks
position = cond1 & cond2 & cond3
position = pb[position].is_smallest(10) # Top 10 lowest P/B
# 4. Backtest
report = sim(position, resample="M", upload=False)
# 5. Print metrics - Two equivalent ways:
# Option A: Using metrics object
print(report.metrics.annual_return())
print(report.metrics.sharpe_ratio())
print(report.metrics.max_drawdown())
# Option B: Using get_stats() dictionary (different key names!)
stats = report.get_stats()
print(f"CAGR: {stats['cagr']:.2%}")
print(f"Sharpe: {stats['daily_sharpe']:.2f}")
print(f"MDD: {stats['max_drawdown']:.2%}")
# Benchmark stats (finlab >= 2.0.17): same keys via report.get_benchmark_stats()
# 6. Write the FinLab-generated HTML report (REQUIRED — do not hand-roll your own HTML)
report.to_html("report.html")
print("Open report.html to inspect equity curve, monthly returns, drawdown, and trade list.")

Core Workflow: 5-Step Strategy Development

Step 1: Fetch Data

Use data.get("<TABLE>:<COLUMN>") to retrieve data:

python
from finlab import data
# Price data
close = data.get("price:收盤價") # TWD
volume = data.get("price:成交股數") # shares
# Financial statements
roe = data.get("fundamental_features:ROE稅後") # %
revenue = data.get("monthly_revenue:當月營收") # thousand TWD, dated when disclosed: the 2026-10-12 row is September
eps = data.get("financial_statement:每股盈餘") # TWD, that quarter alone
# Valuation
pe = data.get("price_earning_ratio:本益比")
pb = data.get("price_earning_ratio:股價淨值比")
# Institutional trading
foreign_buy = data.get("institutional_investors_trading_summary:外陸資買賣超股數(不含外資自營商)") # shares
# Market benchmark
taiex = data.get("taiex_total_index:收盤指數") # TAIEX close
# Technical indicators
rsi = data.indicator("RSI", timeperiod=14)
macd, macd_signal, macd_hist = data.indicator("MACD", fastperiod=12, slowperiod=26, signalperiod=9)

Taiwan tables keep the exchange's units. Money in monthly_revenue:* and financial_statement:* is thousand TWD (千元): a monthly revenue of 214,752,761 is NT$214.75 billion. Prices and per-share figures are TWD; volumes and institutional net buys are shares. Income-statement fields of financial_statement:*, EPS included, cover that quarter alone, not the year to date. Monthly revenue is dated when it is disclosed, by the 10th of the following month: the row dated 2026-10-12 is September's revenue, so name the month it covers, not the month of its date. data.describe("<TABLE>:<COLUMN>") returns a field's catalog description.

Filter by market/category using `data.universe()`:

python
# Limit to specific industry
with data.universe(market='TSE_OTC', category=['水泥工業']):
price = data.get('price:收盤價')
# Set globally
data.set_universe(market='TSE_OTC', category='半導體')

Use data.search('keyword', market='<code>') to discover available datasets; market takes any set_market code from Market Support, or 'all' to search every market. Use keywords in the dataset's native language (e.g. data.search('營收', market='tw'), data.search('revenue', market='us')).

For retained publication versions (data.versions, as_of, version=), complete data.snapshot recording/replay, and per-stock/per-quarter date coverage checks before offline research, read data-reproducibility.md. A historical read of one table does not pin later date-conversion or backtest dependencies.

Step 2: Create Factors & Conditions

Use FinLabDataFrame methods to create boolean conditions:

python
# Trend
rising = close.rise(10) # Rising vs 10 days ago
sustained_rise = rising.sustain(3) # Rising for 3 consecutive days
# Moving averages
sma60 = close.average(60)
above_sma = close > sma60
# Ranking
top_market_value = data.get('etl:market_value').is_largest(50)
low_pe = pe.rank(axis=1, pct=True) < 0.2 # Bottom 20% by P/E
# Industry ranking
industry_top = roe.industry_rank() > 0.8 # Top 20% within industry

See dataframe-reference.md for all FinLabDataFrame methods.

Step 3: Construct Position DataFrame

Combine conditions with & (AND), | (OR), ~ (NOT):

python
# Simple position: hold stocks meeting all conditions
position = cond1 & cond2 & cond3
# Limit number of stocks
position = factor[condition].is_smallest(10) # Hold top 10
# Entry/exit signals with hold_until
entries = close > close.average(20)
exits = close < close.average(60)
position = entries.hold_until(exits, nstocks_limit=10, rank=-pb)

Important: Position DataFrame should have:

  • Index: DatetimeIndex (dates)
  • Columns: Stock IDs (e.g., '2330', '1101')
  • Values: Boolean (True = hold) or numeric (position size)
Step 4: Backtest
python
from finlab.backtest import sim
# Basic backtest
report = sim(position, resample="M")
# With risk management
report = sim(
position,
resample="M",
stop_loss=0.08,
take_profit=0.15,
trail_stop=0.05,
position_limit=1/3,
fee_ratio=1.425/1000/3,
tax_ratio=3/1000,
trade_at_price='open',
upload=False
)
# Extract metrics - Two ways:
# Option A: Using metrics object
print(f"Annual Return: {report.metrics.annual_return():.2%}")
print(f"Sharpe Ratio: {report.metrics.sharpe_ratio():.2f}")
print(f"Max Drawdown: {report.metrics.max_drawdown():.2%}")

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationWarning, 70 of 100Marginal. 1 run. Evaluated 8 months ago.

Source

Popularity

Repository stars
316
Repository forks
52
7-day trend score
29

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 19 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/koreal6803/finlab-ai/finlab/badge)](https://verified-skill.com/skills/koreal6803/finlab-ai/finlab)

Something wrong with this skill or its page? Tell us.