finlab by koreal6803/finlab-ai
npx skills add https://github.com/koreal6803/finlab-ai --skill finlab在运行任何 FinLab 代码之前,请按顺序验证以下事项:
已安装 uv (Python 包管理器):
uv --version
如果未安装 uv,请告知用户安装它。
安装后,确保 uv 在 PATH 中:
source $HOME/.local/bin/env 2>/dev/null # 将 uv 添加到当前 shell
2. 已通过 uv 安装 FinLab (需要版本 >= 1.5.9):
uv python install 3.12 # 确保 Python 可用 (如果已安装则跳过)
uv pip install --system "finlab>=1.5.9" 2>/dev/null || uv pip install "finlab>=1.5.9"
或者使用 uv run 进行零配置执行 (推荐用于一次性脚本):
uv run --with "finlab" python3 script.py
会自动创建一个包含依赖项的临时环境 —— 无需管理虚拟环境。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
uv run --with如果没有令牌,请使用 finlab 的内置登录功能 (在 >= 1.5.9 版本中可用):
import finlab
finlab.login() # 打开浏览器进行 Google OAuth,自动保存令牌
这将自动处理完整的 OAuth 流程 (浏览器登录、令牌获取、.env 存储)。
使用用户的语言进行回复。 如果用户使用中文,则用中文回复。如果使用英文,则用英文回复。
| 等级 | 每日限额 | 令牌模式 |
|---|---|---|
| 免费版 | 500 MB | 以 #free 结尾 |
| VIP 版 | 5000 MB | 无后缀 |
from finlab import data
from finlab.backtest import sim
# 1. 获取数据
close = data.get("price:收盤價")
vol = data.get("price:成交股數")
pb = data.get("price_earning_ratio:股價淨值比")
# 2. 创建条件
cond1 = close.rise(10) # 过去 10 天上涨
cond2 = vol.average(20) > 1000*1000 # 高流动性
cond3 = pb.rank(axis=1, pct=True) < 0.3 # 低市净率
# 3. 组合条件并选择股票
position = cond1 & cond2 & cond3
position = pb[position].is_smallest(10) # 市净率最低的前 10 只
# 4. 回测
report = sim(position, resample="M", upload=False)
# 5. 打印指标 - 两种等效方式:
# 选项 A: 使用 metrics 对象
print(report.metrics.annual_return())
print(report.metrics.sharpe_ratio())
print(report.metrics.max_drawdown())
# 选项 B: 使用 get_stats() 字典 (注意键名不同!)
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
使用 data.get("<表名>:<列名>") 来获取数据:
from finlab import data
# 价格数据
close = data.get("price:收盤價")
volume = data.get("price:成交股數")
# 财务报表
roe = data.get("fundamental_features:ROE稅後")
revenue = data.get("monthly_revenue:當月營收")
# 估值
pe = data.get("price_earning_ratio:本益比")
pb = data.get("price_earning_ratio:股價淨值比")
# 机构交易
foreign_buy = data.get("institutional_investors_trading_summary:外陸資買賣超股數(不含外資自營商)")
# 技术指标
rsi = data.indicator("RSI", timeperiod=14)
macd, macd_signal, macd_hist = data.indicator("MACD", fastperiod=12, slowperiod=26, signalperiod=9)
使用 data.universe() 按市场/类别过滤:
# 限制在特定行业
with data.universe(market='TSE_OTC', category=['水泥工業']):
price = data.get('price:收盤價')
# 全局设置
data.set_universe(market='TSE_OTC', category='半導體')
完整的数据目录请参阅 data-reference.md。
使用 FinLabDataFrame 方法来创建布尔条件:
# 趋势
rising = close.rise(10) # 相对于 10 天前上涨
sustained_rise = rising.sustain(3) # 连续上涨 3 天
# 移动平均线
sma60 = close.average(60)
above_sma = close > sma60
# 排名
top_market_value = data.get('etl:market_value').is_largest(50)
low_pe = pe.rank(axis=1, pct=True) < 0.2 # 市盈率最低的 20%
# 行业内排名
industry_top = roe.industry_rank() > 0.8 # 行业内前 20%
所有 FinLabDataFrame 方法请参阅 dataframe-reference.md。
使用 & (与)、| (或)、~ (非) 组合条件:
# 简单持仓:持有满足所有条件的股票
position = cond1 & cond2 & cond3
# 限制股票数量
position = factor[condition].is_smallest(10) # 持有前 10 只
# 使用 hold_until 的入场/出场信号
entries = close > close.average(20)
exits = close < close.average(60)
position = entries.hold_until(exits, nstocks_limit=10, rank=-pb)
重要提示: 持仓数据框应具有:
from finlab.backtest import sim
# 基本回测
report = sim(position, resample="M")
# 带风险管理
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
)
# 提取指标 - 两种方式:
# 选项 A: 使用 metrics 对象
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%}")
# 选项 B: 使用 get_stats() 字典 (注意:键名不同!)
stats = report.get_stats()
print(f"CAGR: {stats['cagr']:.2%}") # 是 'cagr' 而不是 'annual_return'
print(f"Sharpe: {stats['monthly_sharpe']:.2f}") # 是 'monthly_sharpe' 而不是 'sharpe_ratio'
print(f"MDD: {stats['max_drawdown']:.2%}") # 名称相同
完整的 sim() API 请参阅 backtesting-reference.md。
将回测结果转换为实盘交易:
from finlab.online.order_executor import Position, OrderExecutor
from finlab.online.sinopac_account import SinopacAccount
# 1. 将报告转换为持仓
position = Position.from_report(report, fund=1000000)
# 2. 连接券商账户
acc = SinopacAccount()
# 3. 创建执行器并预览订单
executor = OrderExecutor(position, account=acc)
executor.create_orders(view_only=True) # 先预览
# 4. 执行订单 (准备就绪时)
executor.create_orders()
完整的券商设置和 OrderExecutor API 请参阅 trading-reference.md。
| 文件 | 内容 |
|---|---|
| data-reference.md | data.get()、data.universe()、900+ 字段 |
| backtesting-reference.md | sim() 参数、止损、再平衡 |
| trading-reference.md | 券商设置、OrderExecutor、Position |
| factor-examples.md | 60+ 策略示例 |
| dataframe-reference.md | FinLabDataFrame 方法 |
| factor-analysis-reference.md | IC、Shapley、因子分析 |
| best-practices.md | 常见错误、未来函数偏差 |
| machine-learning-reference.md | ML 特征工程 |
关键: 避免使用未来数据做出过去决策:
# ✅ 正确:使用 shift(1) 获取前一个值
prev_close = close.shift(1)
# ❌ 错误:不要使用 iloc[-2] (可能导致未来函数)
# prev_close = close.iloc[-2] # 错误
# ✅ 正确:即使有像 "2025Q1" 这样的字符串,也保持索引不变
# FinLabDataFrame 会自动按形状对齐
# ❌ 错误:不要手动分配给 df.index
# df.index = new_index # 禁止
更多反模式请参阅 best-practices.md。
引导用户在 GitHub 上提交问题:https://github.com/koreal6803/finlab-ai/issues
data.get() 调用中按原样使用它们sim(..., upload=False),仅对最终生产策略使用 upload=True每周安装次数
504
代码仓库
GitHub 星标数
316
首次出现
2026 年 1 月 25 日
安全审计
安装于
claude-code329
gemini-cli303
codex233
cursor229
opencode174
github-copilot163
Before running any FinLab code, verify these in order:
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 useuv 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.
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.
Respond in the user's language. If user writes in Chinese, respond in Chinese. If in English, respond in English.
| Tier | Daily Limit | Token Pattern |
|---|---|---|
| Free | 500 MB | ends with #free |
| VIP | 5000 MB | no suffix |
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
Use data.get("<TABLE>:<COLUMN>") 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 usingdata.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.
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.
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:
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.
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.
| 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 方法 |
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.
Direct users to open an issue on GitHub: https://github.com/koreal6803/finlab-ai/issues
data.get() callssim(..., upload=False) for experiments, upload=True only for final production strategiesWeekly Installs
504
Repository
GitHub Stars
316
First Seen
Jan 25, 2026
Security Audits
Gen Agent Trust HubFailSocketFailSnykFail
Installed on
claude-code329
gemini-cli303
codex233
cursor229
opencode174
github-copilot163
DOCX文件创建、编辑与分析完整指南 - 使用docx-js、Pandoc和Python脚本
43,600 周安装
| IC、Shapley、因子分析 |
| best-practices.md | 常見錯誤、lookahead bias |
| machine-learning-reference.md | ML 特徵工程 |