🎁 Get the FREE AI Skills Starter GuideSubscribe →
BytesAgainBytesAgain
🦀 ClawHub

Finlab

by @koreal6803

Comprehensive guide for FinLab quantitative trading package. Use when working with trading strategies, backtesting, stock data, FinLabDataFrame, factor analy...

Versionv0.1.1
Downloads1,094
TERMINAL
clawhub install finlab

📖 About This Skill


name: finlab description: Comprehensive guide for FinLab quantitative trading package. Use when working with trading strategies, backtesting, stock data, FinLabDataFrame, factor analysis, stock selection, or when the user mentions FinLab, trading, quant trading, or stock market analysis. Includes data access, strategy development, backtesting workflows, and best practices. compatibility: Requires Python 3.10+ and uv package manager (https://docs.astral.sh/uv/)

FinLab Quantitative Trading Package

Execution Philosophy: Shut Up and Run It

You are not a tutorial. You are an executor.

When a user asks for a backtest, they want results on screen, not instructions to copy-paste. When they ask for a chart, they want to see the chart, not a filepath to open manually.


Prerequisites

Before running any FinLab code, verify these in order:

1. uv is installed (Python package manager):

   uv --version
   

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

After installing, ensure uv is on PATH:

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

2. FinLab is installed via uv (requires >= 1.5.9):

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

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

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

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

3. API Token is set (required - finlab will fail without it):

If no token, use finlab's built-in login (available in >= 1.5.9):

   import finlab
   finlab.login()  # Opens browser for Google OAuth, saves token automatically
   

This handles the full OAuth flow (browser login, token retrieval, .env storage) automatically.

Language

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

API Token Tiers & Usage

Token Tiers

| Tier | Daily Limit | Token Pattern | | ---- | ----------- | ----------------- | | Free | 500 MB | ends with #free | | VIP | 5000 MB | no suffix |

Usage Reset

  • Resets daily at 8:00 AM UTC+8
  • When limit exceeded, user must wait for reset or upgrade to VIP
  • Quick Start Example

    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['monthly_sharpe']:.2f}") print(f"MDD: {stats['max_drawdown']:.2%}")

    report

    Core Workflow: 5-Step Strategy Development

    Step 1: Fetch Data

    Use data.get("

    :") to retrieve data:

    from finlab import data

    Price data

    close = data.get("price:收盤價") volume = data.get("price:成交股數")

    Financial statements

    roe = data.get("fundamental_features:ROE稅後") revenue = data.get("monthly_revenue:當月營收")

    Valuation

    pe = data.get("price_earning_ratio:本益比") pb = data.get("price_earning_ratio:股價淨值比")

    Institutional trading

    foreign_buy = data.get("institutional_investors_trading_summary:外陸資買賣超股數(不含外資自營商)")

    Technical indicators

    rsi = data.indicator("RSI", timeperiod=14) macd, macd_signal, macd_hist = data.indicator("MACD", fastperiod=12, slowperiod=26, signalperiod=9)

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

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

    Set globally

    data.set_universe(market='TSE_OTC', category='半導體')

    See data-reference.md for complete data catalog.

    Step 2: Create Factors & Conditions

    Use FinLabDataFrame methods to create boolean conditions:

    # 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):

    # 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

    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%}")

    Option B: Using get_stats() dictionary (note: different key names!)

    stats = report.get_stats() print(f"CAGR: {stats['cagr']:.2%}") # 'cagr' not 'annual_return' print(f"Sharpe: {stats['monthly_sharpe']:.2f}") # 'monthly_sharpe' not 'sharpe_ratio' print(f"MDD: {stats['max_drawdown']:.2%}") # same name

    See backtesting-reference.md for complete sim() API.

    Step 5: Execute Orders (Optional)

    Convert backtest results to live trading:

    from finlab.online.order_executor import Position, OrderExecutor
    from finlab.online.sinopac_account import SinopacAccount

    1. Convert report to position

    position = Position.from_report(report, fund=1000000)

    2. Connect broker account

    acc = SinopacAccount()

    3. Create executor and preview orders

    executor = OrderExecutor(position, account=acc) executor.create_orders(view_only=True) # Preview first

    4. Execute orders (when ready)

    executor.create_orders()

    See trading-reference.md for complete broker setup and OrderExecutor API.

    Reference Files

    | File | Content | | -------------------------------------------------------------- | ------------------------------------------ | | data-reference.md | data.get(), data.universe(), 900+ 欄位 | | backtesting-reference.md | sim() 參數、stop-loss、rebalancing | | trading-reference.md | 券商設定、OrderExecutor、Position | | factor-examples.md | 60+ 策略範例 | | dataframe-reference.md | FinLabDataFrame 方法 | | factor-analysis-reference.md | IC、Shapley、因子分析 | | best-practices.md | 常見錯誤、lookahead bias | | machine-learning-reference.md | ML 特徵工程 |

    Prevent Lookahead Bias

    Critical: Avoid using future data to make past decisions:

    # ✅ GOOD: Use shift(1) to get previous value
    prev_close = close.shift(1)

    ❌ BAD: Don't use iloc[-2] (can cause lookahead)

    prev_close = close.iloc[-2] # WRONG

    ✅ GOOD: Leave index as-is even with strings like "2025Q1"

    FinLabDataFrame aligns by shape automatically

    ❌ BAD: Don't manually assign to df.index

    df.index = new_index # FORBIDDEN

    See best-practices.md for more anti-patterns.

    Feedback

    Direct users to open an issue on GitHub: https://github.com/koreal6803/finlab-ai/issues

    Notes

  • Some data columns use Chinese names — this is expected, use them as-is in data.get() calls
  • Data frequency varies: daily (price), monthly (revenue), quarterly (financial statements)
  • Always use sim(..., upload=False) for experiments, upload=True only for final production strategies
  • ⚙️ Configuration

    Before running any FinLab code, verify these in order:

    1. uv is installed (Python package manager):

       uv --version
       

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

    After installing, ensure uv is on PATH:

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

    2. FinLab is installed via uv (requires >= 1.5.9):

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

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

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

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

    3. API Token is set (required - finlab will fail without it):

    If no token, use finlab's built-in login (available in >= 1.5.9):

       import finlab
       finlab.login()  # Opens browser for Google OAuth, saves token automatically
       

    This handles the full OAuth flow (browser login, token retrieval, .env storage) automatically.

    📋 Tips & Best Practices

  • Some data columns use Chinese names — this is expected, use them as-is in data.get() calls
  • Data frequency varies: daily (price), monthly (revenue), quarterly (financial statements)
  • Always use sim(..., upload=False) for experiments, upload=True only for final production strategies
  • BytesAgain
    Discover the best AI agent skills for your workflow.
    © 2026 BytesAgain. All rights reserved.
    BytesAgain is an independent skill directory. We index and link to third-party content (ClawHub, GitHub, LobeHub, Dify, etc.) for informational purposes only. All trademarks, skill names, and content are the property of their respective owners. BytesAgain does not claim ownership of any indexed content.