跳轉到

finlab.dataframe

finlab.dataframe.FinlabDataFrame

Bases: pd.DataFrame

回測語法糖 除了使用熟悉的 Pandas 語法外,我們也提供很多語法糖,讓大家開發程式時,可以用簡易的語法完成複雜的功能,讓開發策略更簡潔! 我們將所有的語法糖包裹在 FinlabDataFrame 中,用起來跟 pd.DataFrame 一樣,但是多了很多功能! 只要使用 finlab.data.get() 所獲得的資料,皆為 FinlabDataFrame 格式, 接下來我們就來看看, FinlabDataFrame 有哪些好用的語法糖吧!

當資料日期沒有對齊(例如: 財報 vs 收盤價 vs 月報)時,在使用以下運算符號:+, -, *, /, >, >=, ==, <, <=, &, |, ~,不需要先將資料對齊,因為 FinlabDataFrame 會自動幫你處理,以下是示意圖。

Screen-Shot-2021-10-26-at-5-32-44-AM

以下是範例:cond1cond2 分別為「每天」,和「每季」的資料,假如要取交集的時間,可以用以下語法:

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
擷取 1101 台泥 的訊號如下圖,可以看到 cond1cond2 訊號的頻率雖然不相同,但是由於 cond1cond2FinlabDataFrame,所以可以直接取交集,而不用處理資料頻率對齊的問題。
imageconds

總結來說,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:

股價在均線之上

from finlab import data
close = data.get('price:收盤價')
sma = close.average(10)
cond = close > sma
只需要簡單的語法,就可以將其中一部分的訊號繪製出來檢查:
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'])
sma

deadline()

財務季報索引轉換成公告截止日

將財務季報 (ex:2022Q1) 從文字格式轉為公告截止日的datetime格式, 通常使用情境為對不同週期的dataframe做reindex,常用於以公告截止日作為訊號產生日。

Returns:

Type Description
pd.DataFrame

data

Examples:

data.get('financial_statement:現金及約當現金').deadline()

fall(n=1)

數值下降中

取是否比前第n筆低,若符合條件的值則為True,反之為False。 Screen-Shot-2021-10-26-at-6-43-41-AM

Parameters:

Name Type Description Default
n positive-int

設定比較前第n筆低。

1

Returns:

Type Description
pd.DataFrame

data

Examples:

收盤價是否低於10日前股價

from finlab import data
data.get('price:收盤價').fall(10)

groupby_category()

資料按產業分群

類似 pd.DataFrame.groupby()的處理效果。

Returns:

Type Description
pd.DataFrame

data

Examples:

半導體平均股價淨值比時間序列

from finlab import data
pe = data.get('price_earning_ratio:股價淨值比')
pe.groupby_category().mean()['半導體'].plot()
pbmean

全球 2020 量化寬鬆加上晶片短缺,使得半導體股價淨值比衝高。

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 則賣出。 Screen-Shot-2021-10-26-at-6-35-05-AM 此函式有很多細部設定,可以讓你最多選擇 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'。可選 closeopen

'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:

data.get('monthly_revenue:當月營收').index_str_to_date()
data.get('financial_statement:現金及約當現金').index_str_to_date()

industry_rank(categories=None)

計算產業 ranking 排名,0 代表產業內最低,1 代表產業內最高

Parameters:

Name Type Description Default
categories list of str

欲考慮的產業,ex: ['貿易百貨', '雲端運算'],預設為全產業,請參考 data.get('security_industry_themes') 中的產業項目。

None

Examples:

本意比產業排名分數

from finlab import data

pe = data.get('price_earning_ratio:本益比')
pe_rank = pe.industry_rank()
print(pe_rank)

is_entry()

進場點

取進場訊號點,若符合條件的值則為True,反之為False。

Returns:

Type Description
pd.DataFrame

data

Examples:

策略為每日收盤價前10高,取進場點。

from finlab import data
data.get('price:收盤價').is_largest(10).is_entry()

is_exit()

出場點

取出場訊號點,若符合條件的值則為 True,反之為 False。

Returns:

Type Description
pd.DataFrame

data

Examples:

策略為每日收盤價前10高,取出場點。

from finlab import data
data.get('price:收盤價').is_largest(10).is_exit()

is_largest(n)

取每列前 n 筆大的數值

若符合 True ,反之為 False 。用來篩選每天數值最大的股票。

is-largest

Parameters:

Name Type Description Default
n positive-int

設定每列前 n 筆大的數值。

required

Returns:

Type Description
pd.DataFrame

data

Examples:

每季 ROA 前 10 名的股票

from finlab import data

roa = data.get('fundamental_features:ROA稅後息前')
good_stocks = roa.is_largest(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 檔股票

from finlab import data

pb = data.get('price_earning_ratio:股價淨值比')
cheap_stocks = pb.is_smallest(10)

quantile_row(c)

股票當天數值分位數

取得每列c定分位數的值。

Parameters:

Name Type Description Default
c positive-int

設定每列 n 定分位數的值。

required

Returns:

Type Description
pd.DataFrame

data

Examples:

取每日股價前90%分位數

from finlab import data
data.get('price:收盤價').quantile_row(0.9)

rise(n=1)

數值上升中

取是否比前第n筆高,若符合條件的值則為True,反之為False。 Screen-Shot-2021-10-26-at-6-43-41-AM

Parameters:

Name Type Description Default
n positive-int

設定比較前第n筆高。

1

Returns:

Type Description
pd.DataFrame

data

Examples:

收盤價是否高於10日前股價

from finlab import data
data.get('price:收盤價').rise(10)

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:

收盤價是否連兩日上漲

from finlab import data
data.get('price:收盤價').rise().sustain(2)