擴充 FinLab 開發指南
本文說明如何貢獻程式碼、設定開發環境、遵循程式碼風格,以及如何擴充 FinLab 的功能。
開發環境設定
1. Fork 與 Clone 專案
# Fork finlab-python/finlab 到你的 GitHub 帳號
# Clone 你的 fork
git clone https://github.com/YOUR_USERNAME/finlab.git
cd finlab
# 新增 upstream remote
git remote add upstream https://github.com/finlab-python/finlab.git
2. 安裝開發依賴
# 使用 uv 管理依賴
pip install uv
# 安裝所有開發依賴
uv sync --all-groups
# 或使用 pip
pip install -e ".[dev,docs,test]"
3. 執行測試
# 執行所有測試
uv run pytest
# 執行特定測試
uv run pytest tests/backtest_test.py
# 執行測試並產生覆蓋率報告
uv run pytest --cov=finlab --cov-report=html
程式碼風格指南
Python 風格
遵循 PEP 8 與 Google Python Style Guide
# 好的範例
def calculate_moving_average(prices, window=20):
"""計算移動平均
Args:
prices (pd.Series): 價格序列
window (int): 視窗大小,預設 20
Returns:
pd.Series: 移動平均序列
"""
return prices.rolling(window).mean()
# 不好的範例
def calc_ma(p, w=20): # 命名不清楚
return p.rolling(w).mean() # 缺少文檔
Docstring 格式
使用 Google 風格:
def sim(position, resample='M', **kwargs):
"""執行回測
Args:
position (pd.DataFrame): 持倉訊號
resample (str): 重採樣頻率
**kwargs: 其他參數
Returns:
Report: 回測報告物件
Raises:
ValueError: 當 position 格式不正確時
Examples:
```python
position = close > close.average(20)
report = sim(position, resample='M')
```
"""
pass
擴充功能範例
1. 新增自訂技術指標
在 finlab/dataframe.py 新增方法:
class FinlabDataFrame(pd.DataFrame):
# ... 現有程式碼
def custom_indicator(self, param1, param2=10):
"""自訂技術指標
Args:
param1 (float): 參數 1
param2 (int): 參數 2,預設 10
Returns:
FinlabDataFrame: 計算結果
"""
result = self.rolling(param2).apply(
lambda x: your_calculation(x, param1)
)
return FinlabDataFrame(result)
2. 新增自訂分析模組
繼承 Analysis 類別:
# finlab/analysis/custom_analysis.py
from finlab.analysis import Analysis
class CustomAnalysis(Analysis):
def calculate_trade_info(self, report):
"""計算額外交易資訊"""
custom_data = ... # 你的邏輯
return [['custom_field', custom_data, 'entry_sig_date']]
def analyze(self, report):
"""執行分析"""
trades = report.get_trades()
result = ... # 你的分析邏輯
return result
def display(self):
"""顯示結果"""
return self.result
3. 新增自訂市場
繼承 Market 類別:
# finlab/markets/custom.py
from finlab.market import Market
import pandas as pd
class CustomMarket(Market):
@staticmethod
def get_name():
return 'custom_market'
def get_price(self, trade_at_price='close', adj=True):
# 你的資料載入邏輯
df = pd.read_csv('path/to/data.csv')
return df
測試撰寫指南
測試結構
# tests/test_custom_feature.py
import unittest
from finlab import data
from finlab.dataframe import FinlabDataFrame
class TestCustomFeature(unittest.TestCase):
def setUp(self):
"""測試前準備"""
self.close = data.get('price:收盤價')
def test_custom_indicator(self):
"""測試自訂指標"""
result = self.close.custom_indicator(param1=0.5, param2=10)
# 檢查結果型別
self.assertIsInstance(result, FinlabDataFrame)
# 檢查結果形狀
self.assertEqual(result.shape, self.close.shape)
# 檢查結果值
self.assertFalse(result.isna().all().all())
def tearDown(self):
"""測試後清理"""
pass
貢獻流程
1. 建立分支
# 更新 main 分支
git checkout main
git pull upstream main
# 建立新分支
git checkout -b feature/your-feature-name
2. 開發與測試
3. 提交程式碼
# 提交變更
git add .
git commit -m "feat: add custom indicator"
# 推送至你的 fork
git push origin feature/your-feature-name
4. 建立 Pull Request
- 前往 GitHub 上你的 fork
- 點擊 "New Pull Request"
- 填寫 PR 描述(說明變更內容與目的)
- 等待程式碼審查