finlab.dataframe
finlab.dataframe.FinlabDataFrame
Bases: pd.DataFrame
回測語法糖
除了使用熟悉的 Pandas 語法外,我們也提供很多語法糖,讓大家開發程式時,可以用簡易的語法完成複雜的功能,讓開發策略更簡潔!
我們將所有的語法糖包裹在 FinlabDataFrame
中,用起來跟 pd.DataFrame
一樣,但是多了很多功能!
只要使用 finlab.data.get()
所獲得的資料,皆為 FinlabDataFrame
格式,
接下來我們就來看看, FinlabDataFrame
有哪些好用的語法糖吧!
當資料日期沒有對齊(例如: 財報 vs 收盤價 vs 月報)時,在使用以下運算符號:+
, -
, *
, /
, >
, >=
, ==
, <
, <=
, &
, |
, ~
,不需要先將資料對齊,因為 FinlabDataFrame
會自動幫你處理,以下是示意圖。
以下是範例:cond1
與 cond2
分別為「每天」,和「每季」的資料,假如要取交集的時間,可以用以下語法:
from finlab import data
# 取得 FinlabDataFrame
close = data.get('price:收盤價')
roa = data.get('fundamental_features:ROA稅後息前')
# 運算兩個選股條件交集
cond1 = close > 37
cond2 = roa > 0
cond_1_2 = cond1 & cond2
cond1
跟 cond2
訊號的頻率雖然不相同,但是由於 cond1
跟 cond2
是 FinlabDataFrame
,所以可以直接取交集,而不用處理資料頻率對齊的問題。

總結來說,FinlabDataFrame 與一般 dataframe 唯二不同之處:
1. 多了一些 method,如df.is_largest()
, df.sustain()
...等。
2. 在做四則運算、不等式運算前,會將 df1、df2 的 index 取聯集,column 取交集。
average(n)
取 n 筆移動平均
若股票在時間窗格內,有 N/2 筆 NaN,則會產生 NaN。
Parameters:
Name | Type | Description | Default |
---|---|---|---|
n |
positive-int
|
設定移動窗格數。 |
required |
Returns:
Type | Description |
---|---|
pd.DataFrame
|
data |
Examples:
股價在均線之上
只需要簡單的語法,就可以將其中一部分的訊號繪製出來檢查:import matplotlib.pyplot as plt
close.loc['2021', '2330'].plot()
sma.loc['2021', '2330'].plot()
cond.loc['2021', '2330'].mul(20).add(500).plot()
plt.legend(['close', 'sma', 'cond'])

deadline()
fall(n=1)
groupby_category()
hold_until(exit, nstocks_limit=None, stop_loss=-np.inf, take_profit=np.inf, trade_at='close', rank=None)
訊號進出場
這大概是所有策略撰寫中,最重要的語法糖,上述語法中 entries
為進場訊號,而 exits
是出場訊號。所以 entries.hold_until(exits)
,就是進場訊號為 True
時,買入並持有該檔股票,直到出場訊號為 True
則賣出。
此函式有很多細部設定,可以讓你最多選擇 N 檔股票做輪動。另外,當超過 N 檔進場訊號發生,也可以按照客制化的排序,選擇優先選入的股票。最後,可以設定價格波動當輪動訊號,來增加出場的時機點。
Parameters:
Name | Type | Description | Default |
---|---|---|---|
exit |
pd.Dataframe
|
出場訊號。 |
required |
nstocks_limit |
int)`
|
輪動檔數上限,預設為None。 |
None
|
stop_loss |
float
|
價格波動輪動訊號,預設為None,不生成輪動訊號。範例:0.1,代表成本價下跌 10% 時產生出場訊號。 |
-np.inf
|
take_profit |
float
|
價格波動輪動訊號,預設為None,不生成輪動訊號。範例:0.1,代表成本價上漲 10% 時產生出場訊號。 |
np.inf
|
trade_at |
str
|
價格波動輪動訊號參考價,預設為'close'。可選 |
'close'
|
rank |
pd.Dataframe
|
當天進場訊號數量超過 nstocks_limit 時,以 rank 數值越大的股票優先進場。 |
None
|
Returns:
Type | Description |
---|---|
pd.DataFrame
|
data |
Examples:
價格 > 20 日均線入場, 價格 < 60 日均線出場,最多持有10檔,超過 10 個進場訊號,則以股價淨值比小的股票優先選入。
from finlab import data
from finlab.backtest import sim
close = data.get('price:收盤價')
pb = data.get('price_earning_ratio:股價淨值比')
sma20 = close.average(20)
sma60 = close.average(60)
entries = close > sma20
exits = close < sma60
#pb前10小的標的做輪動
position = entries.hold_until(exits, nstocks_limit=10, rank=-pb)
sim(position)
index_str_to_date()
財務月季報索引格式轉換
將以下資料的索引轉換成datetime格式:
月營收 (ex:2022-M1) 從文字格式轉為公告截止日。
財務季報 (ex:2022-Q1) 從文字格式轉為財報電子檔資料上傳日。
通常使用情境為對不同週期的dataframe做reindex,常用於以公告截止日作為訊號產生日。
Returns:
Type | Description |
---|---|
pd.DataFrame
|
data |
Examples:
industry_rank(categories=None)
計算產業 ranking 排名,0 代表產業內最低,1 代表產業內最高
Parameters:
Name | Type | Description | Default |
---|---|---|---|
categories |
list of str
|
欲考慮的產業,ex: ['貿易百貨', '雲端運算'],預設為全產業,請參考 |
None
|
Examples:
本意比產業排名分數
is_entry()
is_exit()
is_largest(n)
取每列前 n 筆大的數值
若符合 True
,反之為 False
。用來篩選每天數值最大的股票。
Parameters:
Name | Type | Description | Default |
---|---|---|---|
n |
positive-int
|
設定每列前 n 筆大的數值。 |
required |
Returns:
Type | Description |
---|---|
pd.DataFrame
|
data |
Examples:
每季 ROA 前 10 名的股票
is_smallest(n)
取每列前 n 筆小的數值
若符合 True
,反之為 False
。用來篩選每天數值最小的股票。
Parameters:
Name | Type | Description | Default |
---|---|---|---|
n |
positive-int
|
設定每列前 n 筆小的數值。 |
required |
Returns:
Type | Description |
---|---|
pd.DataFrame
|
data |
Examples:
股價淨值比最小的 10 檔股票
quantile_row(c)
rise(n=1)
sustain(nwindow, nsatisfy=None)
持續 N 天滿足條件
取移動 nwindow 筆加總大於等於nsatisfy,若符合條件的值則為True,反之為False。
Parameters:
Name | Type | Description | Default |
---|---|---|---|
nwindow |
positive-int
|
設定移動窗格。 |
required |
nsatisfy |
positive-int
|
設定移動窗格計算後最低滿足數值。 |
None
|
Returns:
Type | Description |
---|---|
pd.DataFrame
|
data |
Examples:
收盤價是否連兩日上漲