快速上手之因子开发

1. 因子开发平台简介

因子开发管理平台Starfish是一个面向专业投资团队的一站式量化投资分析平台,依托DolphinDB高性能分布式计算引擎,总结行业经验,提供一个从数据管理、因子研究到策略回测的完整解决方案。通过低代码开发环境和严格的权限管理,既保障团队高效协作,又确保知识产权安全,同时配备完善的可视化分析,满足机构级量化投资的全流程需求。

本产品主要围绕量化投研的因子、策略开发阶段设计,实现了从开发、分析、上线的完整流程,结合DolphinDB的高性能特色,为用户打造出适配于各种数据源及多品种回测的投研平台。具有以下特点:

高性能计算能力
  • 高性能时序数据处理功能

  • 支持并行计算和分布式处理

  • 上千个高性能计算函数

  • 高性能回测框架,支持中高低频回测、多品种回测。

团队协作与知识产权保护
  • 知识产权保护,代码加密机制保护核心算法

  • 资源共享,研究成果安全共享与复用

  • 协作功能,团队协作工作流,代码评审机制,任务进度跟踪

低代码开发环境
  • 多种内置因子及模板使用

  • 标准化因子开发流程

多层级权限管理
  • 基于角色的访问控制

  • 自定义权限组

  • 数据权限

可视化分析
  • 因子评价分析图表

  • 策略收益结果图表

  • 自定义报告模板

  • 报告支持导出(PDF)

API接口服务
  • 支持批量请求处理

  • 详细API文档

  • 示例代码库

2. 安装与使用

2.1 部署

请参考 Starfish 部署手册。部署前,请了解产品的使用要求:
  • 操作系统要求: 部署DolphinDB数据库,并确保DolphinDB版本为2.00.14或3.00.2及以上版本;
  • 依赖要求:需要在控制节点、所有数据节点、计算节点均下载及加载模拟撮合(Matching Engine Simulator)和回测(Backtest)插件;
  • 证书:支持starfish功能的商业版证书。

2.2 登录

打开浏览器,输入 <http://<server_ip>>:<port>。

左侧导航栏点击因子平台,第一次使用请使用管理员账户。

2.3 权限配置

由于因子开发管理平台有严格的权限划分,因此在使用功能前,需要建立部门,并对账号赋予使用权限。

  1. 左侧导航栏进入系统管理 - 部门管理。

  2. 点击【创建】,进入部门创建界面。

  3. 填写部门名称及id,将admin选择为管理员。

  4. 刷新当前页面,出现因子与评价、策略与回测等导航栏页面。

3. 因子与评价

因子是指能够影响资产回报的特征或属性。在投资中,因子通常用于解释不同资产(如股票、债券等)表现差异的原因。因子可以是基本面的(如市盈率、账面价值等)、技术面的(如动量、波动率等)或宏观经济的(如利率、通货膨胀等)。同时,研究人员需要避免错误或无效的因子,因此还需要对因子进行评价,筛选出优质因子,优化组合,提升配置效率。

本平台提供因子开发、因子计算、因子评价等功能,帮助用户开发及管理海量因子。同时内置World Quant Alpha101等7种常见因子库,以及alphalens单因子评价方法方便用户快速上手。

3.1 基础概念

  • 因子代码:单个因子公式的函数代码;

  • 因子模块:包含多个因子函数的模块;

  • 因子计算模板:将因子代码带入到数据中计算的方法,通常分为SQL模板以及面板模板;

  • 因子评价模板:通用的对因子值进行评价或回测的计算代码;

  • 可视化报告:因子评价的结果进行可视化输出的内容。

3.2 开发流程

该流程图是一个因子开发与评价的过程。通过因子公式探索和开发因子代码,建立因子模块和计算模板;随后进入计算阶段,在进行点击测试后填写因子计算模板参数;经过计算后可以预览因子值结果,并根据需要决定是否进行因子评价;如果进行评价,则需填写评价模板参数,生成评价结果预览,最终可选择是否生成评价可视化报告。

3.3 因子开发

3.3.1 新建因子模块

因子模块通常是一个类型的因子集合。

属性:因子的计算类型及频率,通常会与因子计算模板的属性匹配进行推荐;

标签:可以自定义标签,对因子进行分类;

备注:记录因子的使用方法或实现思路等。

3.3.2 因子代码开发

因子通常表示为数学公式,因子代码开发的过程是使用 DolphinScript 实现该公式,因此本平台支持使用DolphinScript的内置函数,包括聚合算子以及滑动窗口函数等。

此外,编辑页面提供了丰富的代码开发功能。包括函数高亮,内置函数的语法及描述,同时也支持追踪最近五条保存的历史记录。

3.3.3 进阶功能 - 自定义算子

当部分复杂因子需要自定义函数时,有两种方法:

方法一:将自定义函数存储在公共脚本库下的函数模块库中。例如将算子helperFunction1(a,b)代码存入了 helperFunction 模块中。因子代码中以helperFunction::helperFunction1(a,b)的形式调用该函数;该方法适用于对所有用户公开代码及公开使用的函数。

方法二:将自定义函数存储在该因子模块的第一位。如图所示,同一模块下的因子可以使用该算子。该方法适用于用户需要自定义算子,但不希望公开该代码。

3.4 因子计算模板开发

3.4.1 新建因子计算模板

计算模板是将因子代码代入数据计算的过程,因此计算模板可适配于多个数据源或者多个同类型的因子计算。

属性:因子模板的计算类型及频率,通常会与因子的属性匹配,进行推荐;

标签:可以自定义标签,对因子模板进行分类;

备注:记录因子模板的使用方法或实现思路等。

3.4.2 计算模板开发

因子计算模板仅支持一个函数定义,如有自定义辅助函数请存储在公共脚本库下的函数模块库中使用。

在Starfish中,推荐用户使用元编程的方式开发因子计算模板。

以下为供开发参考的元编程模板。

def demo(data, factorName, factorParameter, startDate, endDate){
    // 因子计算模板参考
    // data: 数据源, TABLE
    // factorName: 计算的因子, STRING
    // factorParameter: 因子函数入参参数, STRING
    // startDate, endDate: 计算起止时间, DATE

    //step1: 处理因子入参参数,生成元编程列
    args = ((factorParameter.strReplace(" ","")).split(","))
    args = each(sqlCol, args)

    //step2: 生成元编程select
    selects = (
        sqlCol( `tradetime), 
        sqlCol(`securityid),
        sqlColAlias(makeUnifiedCall(funcByName("string"), factorName), "factorname"),
        sqlColAlias(makeUnifiedCall(funcByName(factorName), args),"value"))
    
    //step3: 指定数据库与表
    from_tb = data

    //step4: 生成元编程whereCondition
    whereConditions = expr(startDate, <=, sqlCol(`tradetime), <=, endDate)

    //step5: 生成sql语句并执行
    ret = sql(
        select = selects,
        from = from_tb,
        where = whereConditions)
    return ret.eval()
}

此处模板调用因子函数的方法:通过将因子名作为参数,模板内部调用因子。

  • 需要有参数为因子函数的名称,例如factorName。

  • funcByName获取因子函数定义,再通过makeUnifiedCall来使用指定参数args调用该因子函数并生成脚本,可参考代码中step 2。

  • 最后返回一个tradetime, securityid, factorName, value四列的表格。

3.4.3 内置计算模板介绍

Starfish自带四种常用的计算模板,分别为sql_without_group_by, sql_with_group_by, prepData, panel_call,具体代码及参数使用请在平台内查看。

  • sql_without_group_by: 该模板适用于中高频的数据,以SQL的方式调用因子模块代码,不涉及group by分组。支持列名映射。

  • sql_with_group_by: 该模板适用于中高频的数据,以SQL的方式调用因子模块代码,对时间列聚合成天后,与股票列进行分组计算。支持列名映射。

  • prepData: 该模板适用于低频的数据,对列名映射后,与panel_call模板配合使用。

  • panel_call: 该模板适用于低频的数据,将数据转置成面板数据后进行计算。不支持列名映射。

3.5 因子计算

在完成因子代码开发以及因子计算模板代码开发后,需要实际带入计算测试,查看因子值。

具体步骤如下:

步骤一:回到我的因子界面,对需要测试的因子模块,点击测试。

步骤二:选择需要计算的因子,可以单选或多选。计算逻辑为多个因子并发计算,返回单独的结果。

步骤三:选择对应的因子计算模板,填写参数。

注意:

  • 模板必须有参数的类型为因子函数入参。系统会把选择的因子名输入给因子计算模板。例如此处选择了alpha模块的alpha101因子,factorName参数获得数据值为 "alpha::alpha101"

  • 用户自定义的因子计算模板不固定数据类型。

  • 填完数据类型及数据值后,点击【保存预设】,方便后续使用。

  • 因子计算支持多个模板串行调用。如果需要使用多个计算模板,点击添加计算模板,后续模板需要使用前置模板的结果时,在数据类型中选择 前置模板运行结果,数据值选择需要的模板结果。

步骤四:查看结果,返回选中因子的测试状态及结果。

3.6 因子评价

因子评价通常包括对因子进行收益分析、风险调整收益、回归分析、分组、极值分析等等,用于全面评估因子的有效性和稳定性。本平台内置Alphalens评价方法,用于单因子分析。

3.6.1 评价模板开发

因子评价模板代码的开发方式与因子计算模板相同,均为一个函数形式调用。

以 alphalensMain 为例:

def alphalensMain(factorResult, 
    priceTable, priceDate, startDate, endDate, priceSymbol, priceCol,
    quantile=5,
    period="1,5,10", 
    filter_zscore=20, 
    max_loss=0.35, 
    zero_aware=false, 
    cumulative_returns=true, 
    long_short=true) {
        
    factor = select tradetime, securityid, value from factorResult

    // prices
    whereConditions = expr(startDate, <=, sqlCol(priceDate), <=, endDate)
    pivotBy = [sqlColAlias(sqlCol(priceDate), `date), sqlCol(priceSymbol)]
    prices = sql(
          select=sqlCol(priceCol), 
          from=priceTable, 
          where=whereConditions, 
          groupBy=pivotBy, 
          groupFlag=2
          ).eval();

    //Empty groupby or groupby_labels
    groupby = NULL
    groupby_labels = NULL
    binning_by_group=false
    group_neutral=false
    by_group=false

    //quantiles
    quantiles = int(quantile)
    bins = NULL

    //periods
    periods = int(period.split(","))

    // alpahlens
    dicts = alphalens::plot_factorAnalysis(
            factor=factor, 
            prices=prices, 
            groupby=groupby,
            binning_by_group=binning_by_group,
            quantiles=quantiles,
            bins=bins,
            periods=periods,
            filter_zscore=filter_zscore,
            groupby_labels=groupby_labels,
            max_loss=max_loss,
            zero_aware=zero_aware,
            cumulative_returns=cumulative_returns,
            long_short=long_short,
            group_neutral=group_neutral,
            by_group=by_group
            )

    // res: key+table
    res = alphalens::extract_result_tables(dicts)

    return res
}
  • 评价模板名称应与其函数名称相同。

  • 辅助函数应放置于函数模块库中,alphalens相关代码也可在函数模块库中查看,以alphalens::plot_factorAnalysis形式调用。

  • 结果需要返回为一个字典,可以包含多张表。其中key为表名,value为表格内容。

3.6.2 评价模板使用

同因子计算模板,评价模板需要使用者输入参数值。

以下是对alphalensMain模板参数的数据类型及含义解释:

参数

含义

数据类型

factorResult 因子值结果,需包含交易时间列tradetime、股票列securityid以及因子值列value TABLE或前置因子测试结果
priceTable 基准数据库 TABLE
priceDate 基准数据的交易时间列名 STRING
startDate, endDate 基准数据的起止时间 DATE
priceSymbol 基准数据的股票列名 STRING
priceCol 基准数据的价格列名,例如close STRING
quantile 因子分组数量,默认为5 INT
period 计算因子收益时向前查看的时间窗口长度,也称调仓周期,默认为1天,5天,10天,"1,5,10"用逗号隔开 STRING
filter_zscore 与均值相差超过 N 个标准差的收益值会被认为是异常值并被替换为空值,默认为20。 INT
max_loss 如果因子数据中丢失的值占总数据量的比例超过 max_loss设置的比例,则会抛出异常,默认为0.35 DOUBLE
zero_aware 在计算因子收益时如何处理零值,false意味着忽略零值,true意味着考虑零值的存在,默认为false BOOL
cumulative_returns 是否计算和返回累积收益,默认为true BOOL
long_short 收益计算时是否考虑多空组合投资的方法,做多因子值最高的组合,同时做空因子值最低的组合。默认为true BOOL

因子评价模板的结果为字典形式时,可以配合使用可视化模板,生成可视化报告,方便用户对于因子表现有更为直观的方式。Alphalens的评价方法同时也配备了内置的可视化模板。

3.7 因子发布

因子开发的过程通常是独立的,但是因子的使用是团队协同。因子在验证有效后会上线使用,或用于策略中。因此本平台支持将个人因子发布公开。

3.7.1 发布流程

  • 因子发布时,可以选择其生成的评价报告提供给审批人查阅。

  • 支持对因子代码进行加密,公开后,他人无法查看因子代码,仅能使用该因子进行计算。

  • 因子审批的相关消息会同步通知,请查阅右上角的消息按钮。

3.7.2 公共因子库

平台内已内置7个公开因子模块,分别为:

  • alpha101: 101 Formulaic Alphas 论文中给出的世界顶级量化对冲基金 WorldQuant 所使用的 101 个因子公式。

  • alpha191: 国泰君安 191 Alpha 因子,来源于国泰君安在2017 年 6 月份公布的研报《基于短周期价量特征的多因子选股体系——数量化专题之九十三》,属于短周期价量因子。

  • common: 常用的三个因子

  • mytt: MyTT指标库,来源于My麦语言、T通达信、T同花顺的指标公式,实现的常见指标包括MACD、RSI、BOLL、ATR、KDJ、CCI、PSY等。

  • snapshot: snapshot数据常用的高频因子

  • ta: 技术分析(Technical Analysis)指标库

  • tick: tick级别数据常用的高频因子

内置的公共因子计算模板库已在上文讲解,不再赘述。

3.7.3 定时因子任务

上线因子通常需要对每日数据进行计算后入库,本平台支持对因子计算任务进行定时设置。

步骤一:创建

选择【工作流】-【创建】后,配置好任务参数。

本平台内置中、高、低频的三个因子库,列名为username, tradetime, securityid, factorname, value。因子计算模板需要返回tradetime, securityid, factorname, value四列,入库时系统会自动加上username列。

此外,用户同时也可以选择自己的库表写入,因子计算模板返回的内容,应与库表格式一致。

步骤二:定时设置

返回列表,对该工作流进行定时设置。执行频率可以为月、周、天,频率必须间隔5分钟。

3.8 实战

本节以 World Quant Alpha 101为例,介绍如何进行因子开发:

((close - open) / ((high - low) + 0.001))

3.8.1 数据准备

如果已有日频数据,可跳过本节。

步骤一:进入数据管理 - 数据导入 - 找到kDaySimu模板

步骤二:点击【运行】

步骤三:填写参数

注:

  • dbName请勿与现有库名重复

  • dbName请以dfs://开头

  • 如果非admin账户,dbName需要以自己有权限的命名开头

  • numOfYear从2010年开始模拟,图中为模拟3年数据,2010.01.01 - 2012.12.31

完成后,点击【确认】

步骤四确认导入状态

成功即可进入下一节,失败请删除库表后重试。

3.8.2 新建因子

步骤一:进入因子与评价 - 我的因子 - 点击【创建】

步骤二:填写新因子相关信息

  • *为必填项目,只需填写因子模块名称即可

  • 完成后,点击【确定】按钮

步骤三:进入因子代码编辑页面

  • 默认会提供World Quant Alpha101中的41因子和101因子代码。在World Quant Alpha101 中,大多数因子计算都涉及横向与纵向的计算。但非行业因子中的41、101号因子等除了可以用矩阵入参之外,也可以向量入参用 SQL 调用。

3.8.3 因子计算

步骤一:点击【测试】 - 填写参数

步骤二:选择因子:可同时选择一个模块下多个因子进行计算

步骤三:模板参数配置

  1. 选择模板 - sql_without_groupby,该模板将直接对数据进行计算,不进行group by分组。

  2. 填写参数:填写 3.1中创建的库表,如为其他数据库,则选择对应库名

  3. 填写完成后点击【保存预设】,方便下次使用。

步骤四:点击【确定】,开始计算

注: 如果为自己的库表,需要进行列名映射:

oriName 为表中的列名,tarName 为因子中的列名 open, close, high, low 等;

需要指定标的列名 securityidName 以及交易时间列名 tradetimeName。

步骤五:查看运行结果 - 点击【查看】

图中为WQAlpha101的计算结果,value列为因子值。

注:该结果为临时数据,并未落库,如果需要入库请在工作流中设置任务,计算后入库。

3.8.4 因子评价

步骤一:点击【生成评价报告】 - 选择alphalensMain

步骤二:填写参数

步骤三:结果解释

运行成功后,会出现数据结果,如果需要查看可视化信息,请点击【查看可视化报告】

报告主要分为四个部分:描述性统计,信息系数(IC)分析,收益分析,换手率分析。图中为模拟数据,可能出现异常值。

  1. 描述性统计

    观察因子在不同分组下的分布

  2. IC 分析

    IC (信息系数, Information Coefficient) 是衡量因子预测力的一个核心指标,反映了因子值与实际收益之间的相关性。一个有效的因子,应当具备较高的 IC 绝对值,并能在一段时间内保持 IC 的持续性和稳定性。这里我们绘制了 IC 分析的相关图表,如 IC 时间序列、月度 IC 均值等。

    通过对上述一系列 IC 分析图表的综合分析,我们可以较为全面地评估该因子的预测力和有效性,判断其是否值得信赖和持续投资。例如,如果一个因子在长期内保持着较高且稳定的 IC 水平,那它就很可能是一个值得重视的有效因子。

  3. 收益分析

    收益分析,是单因子评估过程中最为核心和关键的一个环节。本报告生成一组全面的因子收益分析图表,包括不同持仓期内的累计收益率走势、按分位数分组的收益分布等。有了这些丰富的视觉呈现,我们就可以对因子的盈利能力有更直观的感受,并分析其在不同市场环境下的表现,为投资策略的进一步优化提供方向,如挖掘其表现最佳的持仓期限、结合不同市场环境作出调整等。

  4. 换手率分析

    投资组合的换手率是评估交易活跃程度和执行成本的一个重要指标。高换手率意味着更频繁的交易,从而带来更高的交易成本和潜在的负面冲击。而低换手率则可能导致投资组合无法及时调整,错失获利机会。报告生成换手率分析的可视化图表,展示不同持仓期下的组合平均换手率、分位数换手率等数据,帮助我们评估因子的交易活跃程度和执行成本。