学术研究里的可复现性一直是个问题,金融学也不例外。一篇论文提出了一个指标,接下来每个人在使用它的时候都要各自花时间去编程再实现一遍,俗称“重复造轮子”。这是个无奈的事情,因为大部分研究者发表论文都不会公布源代码和数据,发布的代码也不一定能无修改运行。这样的事让我深恶痛绝。研究应该尽可能地关注创新和实现,而不是浪费时间去重复造轮子。这就是我开发 frds 的动机——做个一键计算各种常用金融学术指标的开源框架。
frds - financial research data services 是一个基于Python3.8开发的计算常用金融学术指标的开源库,源代码托管在GitHub,发布于PyPI。我的愿景是整合金融学研究里常用的各种数据源,然后标准化并实现重要论文里的指标。因为之前有做了一个市场微结构指标的学术数据库的经验,这次打算进一步地整合并开源。
简明的图形界面
frds 的目标是提供一个最简单的方式去获取计算好的标准化指标,因此跨平台的图形界面是和其核心与各种内置指标同步开发的。
简单的安装配置
frds 是一个Python库,因此可以通过pip
一键安装:
$ pip install frds --upgrade
注意,因为 frds 使用了Python3.8中多进程共享内存的新功能,因此请使用Python3.8及以上的版本。安装后会在用户目录下创建一个名为frds
的目录:
- Windows下地址为:
%USERPROFILE%frds
, - Mac/Linux下地址为:
~/frds
。
该目录内含有一个data
目录用于储存下载的原始数据,一个result
目录用于储存计算出来的指标,以及一个名为config.ini
的配置文件包含以下默认内容:
[Paths]
base_dir: ~/frds
data_dir: ${base_dir}/data
result_dir: ${base_dir}/result
[Login]
wrds_username:
wrds_password:
用户需要把自己的WRDS用户名和密码键入。如果对于明文储存的密码有担心的话,也可以缺省并在每次启动图形界面时手动输入。
使用示例
最简单的使用方法是打开一个终端,并运行以下命令来启动图形界面:
$ python -m frds.gui.run
通过使用图形界面,用户可以自行选择需要计算的指标,修改数据储存路径等。若不运行图形界面,也可以通过以下命令来以默认参数计算全部内置指标并将结果储存在默认路径下。
$ python -m frds.run
举个例子,下图是 Accounting Restatement 的结果。frds 会从WRDS下载:
- Compustat Fundamental Annual
- AuditAnalytics Non-Reliance Restatement
按GVKEY和Fiscal Year合并,并计算过去财年里各种 restatements 的数量。结果保存为Stata的.dta
格式数据集,存在result
目录下。
在Python中使用 frds
在Python中使用frds也是非常简单的:
from frds import Professor
from frds.measures import AccountingRestatement, ROA, FirmSize, ROE, AssetTangibility
measures = [
# 带参数的指标
AccountingRestatement(years=1), # 本财年内的各种restatement数量
AccountingRestatement(years=2), # 过去两个财年内的各种restatement数量
# 不带参数或使用默认参数的指标
ROA(),
FirmSize(),
# 这个list可以非常长,frds.Professor会自动控制并行计算的指标数量在CPU核心数以内
ROE(),
AssetTangibility,
]
config = dict(
wrds_username="your_wrds_username",
wrds_password="you_wrds_password",
result_dir="path/to/where/you/want/to/store/the/result/",
data_dir="path/to/where/you/want/to/store/the/data/",
)
if __name__ == "__main__":
# Professor会调度和分发工作给frds.ra.ResearchAssistant来完成计算和数据储存
# Professor(主进程)和 ResearchAssistant(子进程)间通过共享内存来交换数据
# 在Windows环境下为spawn,Unix/Mac下为fork
with Professor(config=config) as prof:
prof.calculate(measures)
内置指标
frds 致力于标准化尽可能多的指标。目前内置支持的指标目录可以在GitHub上浏览。我会不断更新并加入更多的指标到 frds 中来。
开发你自己的指标
开发和使用你自己的指标也是非常简单的,你可以查看GitHub上的README来了解如何通过简单的继承frds.measures.Measure
来实现一个定制化的指标——你只需要描述需要的数据源、数据集和使用到的变量名,实现一个名为estimate
的函数来即可。
from typing import Dict, List, Tuple
import numpy as np
import pandas as pd
from frds import Professor
from frds.measures import Measure
from frds.data import Dataset
# 给出要使用到的数据集和变量
DATASETS_REQUIRED: List[Dataset] = [
Dataset(source='wrds',
library="comp",
table="funda",
vars=["datadate", "gvkey", "at", "ib"],
date_vars=["datadate"],
)
]
# 给出结果数据集的变量标签(label)
VARIABLE_LABELS: Dict[str, str] = {}
class NewMeasure(Measure):
"""自定义的新measure"""
def __init__(self):
# Note: `name` will be used to name the result dataset.
# So this will lead to a `New Measure.dta` in the `result` folder.
# If the new measure contains custom parameters, please also implement
# the `__str__()` function to differentiate
super().__init__(name="New Measure", datasets_required=DATASETS_REQUIRED)
def estimate(self, nparrays: List[np.recarray]) -> Tuple[pd.DataFrame, Dict[str, str]]:
# do something with nparrays and produce a `result` pandas DataFrame
# ...
assert isinstance(result, pd.DataFrame)
return result, VARIABLE_LABELS
measures = [
NewMeasure(),
]
if __name__ == "__main__":
with Professor(config=config) as prof:
prof.calculate(measures)
开发计划
后续的计划就是拓展数据源。目前只有WRDS,下面要加入SEC EDGAR,Federal Reserve Board H.15 Release,等等。然后把我之前写过的指标统统都翻译到Python然后丢进来。如果有志同道合的朋友想要加入进来一起开发就更好了。项目源码在GitHub,MIT许可。
GitHub地址:https://github.com/mgao6767/frds
项目官网:frds.io 不过现在没空写文档,后续会陆续完善。
我的个人主页:https://mingze-gao.com/