finlab について
finlab は、マーケットデータを使った戦略研究やバックテストに取り組む人向けの Python パッケージ兼エージェントスキルです。データ取得、ファクター作成、シミュレーション、HTML レポート生成までの手順を案内し、市場別の資料も備えています。
主な機能
- 01複数の対応市場からデータを取得
- 02ファクターとポジションの作成
- 03sim による戦略バックテスト
- 04FinLab HTML レポートの生成
- 05ファクター分析と機械学習の手順
- 06注文執行への対応(任意)
活用シーン
- 01戦略に必要な市場データセットの探索
- 02クオンツシグナルの作成と検証
- 03バックテストの HTML レポート作成
- 04バックテスト結果から注文を作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ koreal6803/ finlab-ai --skill finlabインストール後、Claude Code で/finlabを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
backtesting-reference.mdbest-practices.mddataframe-reference.mdfactor-analysis-reference.mdfactor-examples.mdmachine-learning-reference.mdtrading-reference.mdus-market.md詳細
FinLab 定量取引パッケージ
前提条件
FinLab のコードを実行する前に、次の項目を順番に確認してください。
-
uv がインストールされていること(Python パッケージマネージャー):
uv --versionuv がインストールされていない場合は、ユーザーにインストールするよう案内してください。
インストール後、
uvが PATH に含まれていることを確認してください:source $HOME/.local/bin/env 2>/dev/null # Add uv to current shell -
FinLab が uv 経由でインストールされていること(>= 2.2.15 が必要です):
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"または、セットアップ不要で実行するには
uv runを使用してください(単発スクリプトに推奨):uv run --with "finlab" python3 script.pyuv run --withは依存関係を含む一時環境を自動作成するため、仮想環境を管理する必要はありません。インストールせずに使いたいですか? FinLab Studio でノートブックを直接実行してください。
finlabがプリインストールされ、アカウントにログイン済みのホスト型 Jupyter 環境です。 -
FinLab にログインしていること(finlab >= 2.0。従来の API トークンは不要です):
デスクトップ(ブラウザーを使用可能): 一度ログインすると、認証情報がローカルにキャッシュされます:
python -m finlab loginimport finlab finlab.login() # reuses cached credentials, or starts browser login if noneヘッドレス環境/cron/Docker: ブラウザーを使用できるマシンでログインし、次を実行してください:
python -m finlab token --envヘッドレス環境で、エクスポートする3つの変数(
FINLAB_REFRESH_TOKEN、FINLAB_SESSION_ID、FINLAB_API_KEY)をすべて設定してください。FinLab はこれらを自動的に使用します。出力は認証情報として扱ってください。お使いのプラットフォームのシークレットストレージを使用し、チャットに貼り付けたり、コミットしたりしないでください。Google Colab: セルで
finlab.login()を実行し、ログインリンクに従ってください。従来のトークンからの移行:
FINLAB_API_TOKENとfinlab.login('<api_token>')は非推奨です。python -m finlab migrateを実行して、ブラウザーログインまたは上記の3つの環境変数を設定し、古いトークンを設定から削除してください。従来のトークンの状況: 公式認証ガイドでは、削除されるバージョンや日付は公表されていません。クライアントの警告文に記載された
2026/08/01は、削除の告知ではありません。クライアント側のフォールバックの廃止と、サーバー側での従来のトークンの拒否は別々の変更です。また、キャッシュされたdata.get()の呼び出しではサーバー認証を検証できません。上記のサポートされているログイン方法を使用してください。
言語
ユーザーの言語で回答してください。 ユーザーが中国語で書いた場合は中国語で、英語で書いた場合は英語で回答してください。
市場のサポート
FinLab は、tw(デフォルト)、us、kr、jp、hk、uk、us_fund(米国 ETF/ファンド)、rotc(台湾の新興株)、tw_cb(台湾の転換社債)をサポートしています。セッションごとに一度、data.set_market(<code>) で市場を選択します。接頭辞のないデータセット名は、アクティブな市場のテーブルに解決されます(us の場合、price:close → us_price:close)。アクティブな市場に存在しない名前は、警告なしで TW のテーブルにフォールバックします。中国語のキー(price:收盤價、monthly_revenue:當月營收)は TW と rotc にしか存在しないため、us で data.get('price:收盤價') を呼び出すと、台湾の株価が返されます。TW 以外では、英語のキー(price:close)または接頭辞付きの名前(us_price:adj_close)を使用してください。data.set_market('rotc')(v2.0.9)を使うと、興櫃(台湾の新興株)を有効にできます。上場前の値動きや、メインの TSE/OTC カタログには存在しない売上高ファクターが必要な場合に使用してください。tw_cb は set_market のコードではありません(ValueError が発生します)。cb_price:* を読み込み、sim(position, market=TWCBMarket()) を渡してください(from finlab.markets.tw_cb import TWCBMarket)。
このファイルの残りの部分に加え、dataframe-reference.md、backtesting-reference.md、best-practices.md、factor-analysis-reference.md、machine-learning-reference.md は、すべて市場に依存しません。API の動作は市場間で同じです。
米国市場を扱う場合、個別株(data.set_market('us'))でも ETF/ファンド(data.set_market('us_fund'))でも、まず us-market.md をお読みください。該当する質問には、米国株、S&P 500、NASDAQ 100、美股、SPY/QQQ、セクター SPDR、レバレッジ型/インバース型 ETF、ETF ローテーション、us_price:*、us_fund_price:*、data.us_universe(...)、us_income_statement:*/us_cash_flow:*/us_balance_sheet:* などがあります。このファイルでは、以下について説明しています。
- バックテストに安全に使用できる米国のデータテーブルと、現在のスナップショット専用のテーブル(アナリストのコンセンサス、比率、DCF はライブデータ専用であり、過去のデータとして使用しないでください)
key_dateに揃えられた四半期ごとのファンダメンタルズ。.shift()による回避策は不要です。生のfiling_date列は公表日ではありません- 米国の
ReportAPI 名(creturn/daily_creturn/get_stats()。get_equity()はありません) - 両市場における米国のバックテストのデフォルト設定:
USMarket(fee_ratio=0、tax_ratio=0、trade_at_price='close')と、ETF/ファンドのバックテスト用のUSFundMarket data.set_market(...)がセッションスコープの切り替え方法であること(data.get()にmarket=キーワード引数はありません)- ドル建て売買代金の上位 N 銘柄によるユニバース構築、
us_index_constituents:*による時点情報を考慮した S&P 500/NASDAQ 100 の構成銘柄(data.us_universe(index=...)は時点情報を考慮しません)、品質基準、セクターを除外する理由 - 米国データに特有の先読みバイアスのチェックリスト(ローリングウィンドウのユニバースフィルター、生存者バイアスの回避)
USFundMarketとus_fund_price:*を使った ETF/セクターローテーションのバックテスト
その他の市場に関する質問では、このファイルを省略できます。
アカウントのティアと使用量
ティア
| ティア | 1 日あたりの上限 |
|---|---|
| Free | 500 MB |
| VIP | 5000 MB |
現在のプランとクォータは、python -m finlab status で確認できます。
使用量のリセット
- 毎日 UTC+8 の午前 8:00 にリセットされます
- 上限を超えた場合は、リセットを待つか、finlab.finance で VIP にアップグレードしてください
クイックスタートの例
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.")
コアワークフロー:戦略開発の 5 ステップ
ステップ 1:データを取得する
data.get("<TABLE>:<COLUMN>") を使用してデータを取得します。
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)
台湾のテーブルでは、取引所の単位が使用されます。monthly_revenue:* と financial_statement:* の金額は千 TWD(千元)です。月次売上高が 214,752,761 の場合、NT$214.75 billion に相当します。株価と 1 株当たりの数値は TWD、出来高と機関投資家の買い越し株数は株数です。EPS を含む financial_statement:* の損益計算書項目は、年初来ではなく、その四半期単独の数値を示します。月次売上高の日付は開示日です。開示日は翌月 10 日までです。日付が 2026-10-12 の行は 9 月の売上高を示すため、日付の月ではなく、対象月を記載してください。data.describe("<TABLE>:<COLUMN>") はフィールドのカタログ説明を返します。
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='半導體')
利用可能なデータセットを調べるには、data.search('keyword', market='<code>') を使用します。market には、市場サポートの set_market コード、またはすべての市場を検索する 'all' を指定できます。データセットの元の言語でキーワードを指定してください(例:data.search('營收', market='tw')、data.search('revenue', market='us'))。
ステップ 2:ファクターと条件を作成する
FinLabDataFrame のメソッドを使用して、ブール値の条件を作成します。
# 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
FinLabDataFrame のすべてのメソッドについては、dataframe-reference.md を参照してください。
ステップ 3:ポジションの DataFrame を作成する
条件を &(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)
重要: ポジションの DataFrame は次の形式にしてください。
- インデックス:DatetimeIndex(日付)
- 列:銘柄 ID(例:'2330'、'1101')
- 値:ブール値(True = 保有)または数値(ポジションサイズ)
ステップ 4:バックテスト
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['daily_sharpe']:.2f}") # 'daily_sharpe' = metrics.sharpe_ratio(), not 'monthly_sharpe'
print(f"MDD: {stats['max_drawdown']:.2%}") # same name
# Benchmark comparison (finlab >= 2.0.17): same ffn keys, computed on the
# market benchmark over the backtest period — no need to recompute from
# market.get_benchmark()
bench = report.get_benchmark_stats()
print(f"Benchmark CAGR: {bench['cagr']:.2%} | MDD: {bench['max_drawdown']:.2%}")
sim() API の詳細については、backtesting-reference.md を参照してください。
ステップ 4.5:FinLab HTML レポートを作成する(必須)
ユーザーが確認する各バックテストには、FinLab が生成する HTML ファイルを 1 つ添えてください。
report = sim(position, resample="M", upload=False)
report.to_html("report.html") # the FinLab-generated file is the deliverable
標準の成果物は report.to_html() が生成するファイルです。ユーザーから明示的に依頼されない限り、別のレポート(カスタム HTML ページ、Plotly の要約、ダッシュボード、Markdown ファイルなど)を独自に作成しないでください。結果を要約する場合は、ターミナルに短い要約を出力し、FinLab レポートを案内してください。例外として、バッチ実行(パラメーターのスイープ、多数のバリエーションのスクリーニング)では、実行ごとの HTML 作成を省略し、ユーザーが確認する最終戦略のレポートのみを作成します。
同じセッションで複数の戦略を実行する場合は、ユーザーが上書きせずに比較できるよう、内容が分かるファイル名を選んでください(例:momentum_top10.html、value_lowpb.html)。ファイルを書き込んだら、ユーザーが開けるようにパスを伝えてください。report.to_terminal() は GUI のないターミナルで補助としてのみ使用し、HTML の代わりにはなりません。
ファイルに含まれる内容の詳細については、backtesting-reference.md の「report.to_html() — 標準の成果物」セクションを参照してください。
ステップ 5:注文を執行する(任意)
バックテストの結果を実取引に変換します。
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()
ブローカーの設定と OrderExecutor API の詳細については、trading-reference.md を参照してください。
参考ファイル
| ファイル | 内容 |
|---|---|
| backtesting-reference.md | sim() のパラメーター、stop-loss、リバランシング |
| 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 の特徴量エンジニアリング |
| us-market.md | 米国市場の詳細:データマップ、四半期の整合、デフォルト、ユニバースの構築 |
新機能(v1.5.8 以降)
最近のリリースで追加された機能への簡潔なバージョン別案内です。各リファレンスファイルには、対象の API が (vX.Y.Z) と記載されています。
v2.0.15 (2026-07-18)
df.sector(by=...):sector アクセサーでカスタム分類を指定できるようになりました。dict/pd.Series(stock_id → グループ)または時系列のpd.DataFrameを指定できます。リストにない銘柄は除外されます。すべてのsector.*メソッドで利用できます。dataframe-reference.md を参照してください。df.sector.map(mapping):グループ単位のスカラー値(セクターウェイトなど)を DataFrame 全体の形状に展開し、ファクターの合成に利用できます。dataframe-reference.md を参照してください。df.weight.by_group(weights, by, default):セクター/グループごとに資金を配分します。保有比率を正規化し、各グループの合計がその配分比率と一致するようにします。配分不足分は現金として残ります。dataframe-reference.md を参照してください。
v2.0.12 (2026-06-01)
sim()/hold_until():trail_stop_activation—trail_stopが有効になる前に、含み益が最低限の水準に達することを要求します。backtesting-reference.md および dataframe-reference.md を参照してください。report.to_html(path, title=...):スタンドアロン HTML にブラウザータブのタイトルと FinLab ファビコンが設定されるようになりました。複数の戦略レポートがあるフォルダーを区別するには、titleを指定してください。backtesting-reference.md を参照してください。- ダッシュボードの設定モーダル:言語/ライト・ダークテーマ/ローソク足の配色(デフォルト、east-red、west-green)を1つのパネルに集約しました。
v2.0.9 (2026-05-27)
data.set_market("rotc"):興櫃が正式な市場コードになりました。price:收盤價/monthly_revenue:*などはrotc_カタログを参照し、sim()はROTCMarketのデフォルト設定を使用します。data.search(market="rotc"):新興市場のカタログのみを対象にします。
v2.0.1 (2026-04-26)
python -m finlab cloud(CLI):戦略をfinlab-auto-updateCloud Functions ランタイムにデプロイし、Asia/Taipei の日次スケジュールを設定できます。利用可能なコマンドはdeploy、get、list、run、logs、schedule set/delete、delete、statusです。trading-reference.md を参照してください。- 全市場の月次戦略における
sim()のピーク RSS を約800 MB削減(従来は約2.0~2.2 GiB → 約1.29 GiB)しました。以前は OOM になっていた s-tier クラウドワーカーを利用できます。
v2.0.0 (2026-04-22) — メジャーリリース
finlab.exceptions:構造化されたエラー階層(FinlabError、DataError、BacktestErrorなど)。backtesting-reference.md を参照してください。data.get(lazy=True)/data.gets(..., lazy=True):一括取得と計算の遅延実行に対応しました。DataContext.overrideコンテキストマネージャーでスコープを指定した状態管理もできます。df.cs/df.sector/df.weightアクセサー、rolling().std/var/skew/kurt/median。dataframe-reference.md を参照してください。- リアルタイムのポジションストリーミング向けに
PositionStreamMixinを追加しました。trading-reference.md を参照してください。 from finlab import FinlabDataFrameをトップレベルでエクスポートしました。backtest.sim()をテスト可能な5つのステージに再構成しました。optimize.combinationsからeval()を削除しました。
v1.5.13 (2026-03-22)
universe(index=...)/us_universe(index=...):S&P 500/NASDAQ 100 に基づいて米国株を絞り込めます。- 新しい市場コード
TW_CB(台湾転換社債)を追加しました。
v1.5.11 (2026-03-11)
data.get_role()/data.is_vip():ユーザーのクォータ区分を確認できます。- レポートを標準的な Firestore フローに移行しました(ユーザー側での操作は不要です)。
v1.5.9
finlab.schemas:型付きのPositionEntry、OrderEntry、PortfolioDataコントラクトを追加しました。OrderExecutor.generate_orders(as_entries, quantity_type)およびgenerate_order_entries()を追加しました。PortfolioSyncManager.get_data_typed()/set_data_typed()を追加しました。data.get()でクォータ使用率が80%に達した際の警告を追加しました。sim()が市場ごとのデフォルトのfee_ratio/tax_ratioを使用するようになりました(TW の値をハードコードしなくなりました)。
v1.5.8(ベースライン)
verify_strategy():先読みバイアスを自動検出します。report.to_terminal():Jupyter 以外で実行する場合に ASCII レポートを出力します。- 戦略の全体的な実行速度が3.4倍になりました。
金融データの整合
最終的なポジションに対しても、reindex() や reindex_like() は決して使用しないでください。FinLabDataFrame は、算術演算、比較演算、ブール演算の際に日付と銘柄列を自動的に再形成します。例:sales_to_price = eps_sales / close。pandas/NumPy を使って手動で整合させたり、この動作を回避したりしないでください。日次データと組み合わせる前に、四半期ごとのシフトとローリングウィンドウを計算してください。リバランススケジュールは sim(position, resample=...) で設定します。日付の確認には index_str_to_date() のみを使用してください。エラーが発生した場合は、型を確認し、dataframe-reference.md を参照してください。
先読みバイアスの防止
重要: 過去の判断に未来のデータを使用しないでください。
# ✅ 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 operators align dates and stock columns automatically
# ❌ BAD: Don't manually assign to df.index
# df.index = new_index # FORBIDDEN
その他のアンチパターンについては、best-practices.md を参照してください。
パフォーマンスのデフォルト設定
デフォルトでは lazy=True を渡し、デバッグ時に限り eager な pandas に切り替えてください。 data.get(..., lazy=True) と data.gets(..., lazy=True) (v2.0.0) は、DataFrame ではなく LazyWide を返します。終端呼び出しでデータが実体化されるまで計算グラフの実行を遅延するため、演算を連結すると不要な処理を避けられます(単一 CPU)。FinLabDataFrame のメソッドと sim() はそのまま受け取れるため、sim() の前に collect しないでください。sim() はリバランス日だけを計算します。pandas にアクセスする場合(.loc、.iloc、.columns、.index、pd.concat)は、1 回だけ collect し(close = price.collect())、その結果を再利用してください。.collect() を呼び出すたびに、グラフ全体が再計算されます。
# ✅ Default: fetch lazy directly
price, volume, pe = data.gets(
'price:收盤價', 'price:成交股數', 'price_earning_ratio:本益比',
lazy=True,
)
# ✅ Debug: eager pandas for row-level inspection
close = data.get('price:收盤價')
print(close.loc['2024-01-15', '2330'])
フィードバック
GitHub で issue を作成するようユーザーに案内してください:https://github.com/koreal6803/finlab-ai/issues
注記
- 一部のデータ列名には中国語が使われています。これは想定どおりなので、
data.get()の呼び出しではそのまま使用してください - データの頻度はさまざまです:日次(価格)、月次(売上高)、四半期ごと(財務諸表)
sim()のデフォルトはupload=Noneです (v2.1.0):アップロードが行われるのはFINLAB_FORCED_STRATEGY_NAMEが設定されている場合のみです(クラウドでスケジュールされた実行、FinLab Studio ウェブサイトで実行するノートブック)。FINLAB_STRATEGY_NAMEだけではアップロードされなくなりました。ローカルスクリプト、Jupyter、Colab では、upload=Trueを渡すか、後からreport.upload()を呼び出さない限りアップロードされません。upload=Falseの場合、アップロードは行われません。