暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

用 DolphinDB 挖因子的九重境界,来看看你在哪一层

437

以下文字描述皆由  Generative AI 协助生成。如有雷同,感谢 AI 技术。

但文中所有 Demo 均为精心挑选之作,真实可靠。感兴趣的诸位欢迎联系小助手(dolphindb1),一同开启量化修真之路。

01

凡人境:用函数计算时序因子

    data = table(take(`000001, 6) as code, 2024.01.01..2024.01.06 as date, [10.5, 11.2, 13, 11.2, 12.5, 13.6] as high, [9, 10, 11, 10, 11, 12] as low, [10, 11, 12, 11 ,12, 13] as close)
    def factorLevel1(data, window) {
    // WR = MAX(HIGH(n)) - CLOSE MAX(HIGH(n)) - MIN(LOW(n)) * 100
    return (mmax(data['high'], window) - data['close']) \ (mmax(data['high'], window) - mmin(data['low'], window)) * 100
    }
    update data set WR = factorLevel1(data, 3)


    // code date ... WR
    // 000001 2024.01.01 ... 10
    // 000001 2024.01.02 ... 11
    // 000001 2024.01.03 ... 25
    // 000001 2024.01.04 ... 66
    // 000001 2024.01.05 ... 33
    // 000001 2024.01.06 ... 16
    若想踏上 DolphinDB 因子挖掘登神长阶,唯有打好基础方可立足。此"凡人境"乃最浅显之法门,借一函数便能算出 WR 这一经典的技术指标因子。虽显简陋,却为后学铺就了平坦之路。

    02

    锻体境:用 iif 向量化计算因子

      def factorLevel2(data, threshould) {
      return iif(data['WR'] > threshould, 1, 0)
      }
      update data set buyFlag = factorLevel2(data, 30)


      // code date ... WR buyFlag
      // 000001 2024.01.01 ... 10 0
      // 000001 2024.01.02 ... 11 0
      // 000001 2024.01.03 ... 25 0
      // 000001 2024.01.04 ... 66 1
      // 000001 2024.01.05 ... 33 1
      // 000001 2024.01.06 ... 16 0

      行至此阶,便能见识 iif 威能。它辗转向量化 SIMD 优化,化繁为简,计算起 buyFlag 此等条件因子来行云流水。待你融会贯通,方知量海可随手驭矣。

      03

      通灵境:用部分应用函数计算时序因子

        def factorLevel3(data, factorName, addWith) {
        return data[factorName] + addWith
        }
        addWith10 = factorLevel3{ , , 10}
        update data set addWith10 = addWith10(data, 'WR')


        // code date ... WR addWith
        // 000001 2024.01.01 ... 10 20
        // 000001 2024.01.02 ... 11 21
        // 000001 2024.01.03 ... 25 35
        // 000001 2024.01.04 ... 66 76
        // 000001 2024.01.05 ... 33 43
        // 000001 2024.01.06 ... 16 26
        所谓的部分应用,正是将多参数函数的某些参数先固定下来,使其转化为较少参数的新函数。要知宽客常常需重复对同一参数列表调用某函数,倘能如是先为部分参数行了化算,不啻为大开方便之门。所谓半有半无,半凝半遁,亦在于此。希望诸君能参透其中的哲理,从而把控全局,发挥参数的最大作用。

        04

        玄妙境:用不定参函数计算因子

          def factorLevel4(args) {
          res = 0
          for (arg in args) {
          res += arg
          }
          return res
          }
          res = call(factorLevel4, 1..5)


          // 15
          所谓不定参数,即函数参数的个数可以是不确定的,完全由调用时传入的实参决定。这种弹性抽象,赋予了因子构建过程前所未有的灵活性。

          不定参数擅长于将任意多个输入"打包"集中处理,这种能力非常契合金融计算中的各类累加、归并等操作需求。更重要的是,我们从中可以窥见一条通往真正函数式编程的途径 - 利用不定参数编写出各种高阶函数,然后通过组合这些高阶函数,来构建出任意复杂的计算流程。这无疑将使因子编程的表现力和可维护性,都得到了极大的提升。掌握了不定参数的玄妙所在,我们就能在更高的层次上重塑因子构建的范式。

          05

          臻化境:用 SQL + 函数计算单只股票因子

            res = select *, mstd(close, 3) as std3, mavg(close, 3) as avg3 from data


            // code date close ... std3 avg3
            // 000001 2024.01.01 10 ...
            // 000001 2024.01.02 11 ...
            // 000001 2024.01.03 12 ... 1 11
            // 000001 2024.01.04 13 ... 0.57 11.33
            // 000001 2024.01.05 14 ... 0.57 11.66
            // 000001 2024.01.06 15 ... 1 12

            细思量之,SQL与函数两柄利器并施才有大用场。如是计算 std3、avg3 等时序因子,行阵并举,浑然天成,可谓登堂入室,臻于化境。

            06

            SQL+ 函数+ context by算多只股票因子

              newData = table(`000001`000001`000001`000002`000002`000002 as code, 2024.01.01..2024.01.06 as date, [10, 11, 12, 9, 8, 7] as close)
              update newData set ret = close \ prev(close) - 1 context by code


              // code date close ret
              // 000001 2024.01.01 10 0
              // 000001 2024.01.02 11 0.1
              // 000001 2024.01.03 12 0.0909
              // 000002 2024.01.04 9 0
              // 000002 2024.01.05 8 -0.1111
              // 000002 2024.01.06 7 -0.125
              在“分身境”这一层次上,我们揭开了跨多只股票进行高效因子计算的奥秘。通过巧妙地运用 context by 语法,我们可以在SQL查询中轻松引入跨标的概念,为投资策略编写带来了全新的编程范式。
              观察示例中的update语句,我们可以看到 context by code 这一关键语句。它的作用是按 code 这一列将数据划分为不同的上下文环境,从而使得像 prev 这样的窗口函数能够分别在不同股票代码的范围内独立运作。
              借助这一语法,我们可以对多只股票的数据在同一查询中进行计算操作,从而高效地完成像收益率等常见的跨股票因子计算。

              07

              凝神境:用矩阵数据计算面板因子

                retPanel = exec ret from newData pivot by date, code
                retRank = rowRank(retPanel)


                // date 000001 000002
                // 2024.01.01
                // 2024.01.02 1 0
                // 2024.01.03 1 0

                这一境界的关键,是将面板数据计算引入了多标的的维度。

                原本时序数据只局限于单一标的的变化,借助 pivot 转换后的矩阵面板形式,我们就能同时纳入同一时点其他标的的信息,从而在一个新的维度上构建因子,如 rowRank 等。这种多维度的计算思路,使得因子构建不再被单一时序所约束,从而发挥出了更大的潜能。掌握了这一技艺,我们就能游刃有余地在更高维度中遨游,为投资策略赢得肆意的施展空间。

                08

                飞仙境:矩阵数据计算复杂因子(时序+面板)

                  t = table(take(2024.01.01..2024.12.31, 3660) as date, take(lpad(1..10 $ STRING, 6, "0"), 3660) as code, rand(100, 3660) as vwap, rand(100, 3660) as open, rand(100, 3660) as vol)
                  vwap = exec vwap from t pivot by date, code
                  open = exec open from t pivot by date, code
                  vol = exec vol from t pivot by date, code


                  //alpha 98
                  //(rank(decay_linear(correlation(vwap, sum(adv5, 26.4719), 4.58418), 7.18088)) - rank(decay_linear(Ts_Rank(Ts_ArgMin(correlation(rank(open), rank(adv15), 20.8187), 8.62571), 6.95668), 8.07206)))
                  def WQAlpha98(vwap, open, vol){
                  return rowRank(X=mavg(mcorr(vwap, msum(mavg(vol, 5), 26), 5), 1..7), percent=true) - rowRank(X=mavg(mrank(9 - mimin(mcorr(rowRank(X=open, percent=true), rowRank(X=mavg(vol, 15), percent=true), 21), 9), true, 7), 1..8), percent=true)
                  }


                  res = WQAlpha98(vwap, open, vol).round(4)


                  // 000001 000002 000003 000004 000005 000006 000007 000008 000009 000010
                  // 2024.02.10 -0.1 -0.8 0.5 -0.4 -0.2 -0.4 0.2 0.1 0.5 0.7
                  // 2024.02.11 -0.2 -0.8 0.7 -0.3 -0.4 -0.3 0.2 0.2 0.2 0.7
                  // 2024.02.12 -0.1 -0.5 0.5 -0.4 -0.2 0.1 0 0.1 0.1 0.4
                  // 2024.02.13 0 0.4 0.1 -0.3 0.1 0.1 -0.1 0.1 0.1 0.4

                  在“飞仙境”这个层次,我们完全打开了时序和面板两个数据视角,将矩阵计算的能力推向了极致。以 WQAlpha98 因子为例,它巧妙地将时序函数如 mavg、msum 和面板函数如 mcorr、mrank 融合到了一起,使我们能够在任意高维数据空间中自由遨游,构建出无与伦比的复杂投资策略。

                  通过大量运用嵌套调用和高阶函数编程,我们获得了一种全新的、极具表现力的因子编程范式。单一的运算限制不复存在,我们可以在时序、面板、函数的无缝集成中尽情施展,将"量化"的终极目标发挥到了极致,赢得了投资领域的最高境界。

                  接下来,预约直播,解锁第9重境界 —— 未来境!Shark GPLearn 自动因子挖掘

                  新上线的 Shark GPLearn 高性能因子挖掘平台,已随 DolphinDB V3.00版本一同正式发布。欢迎预约新版本特性讲解直播👇👇深入了解、申请试用该功能。

                  直播时间:4月10日(本周三)晚上七点半 报名方式:扫描海报下方二维码观看直播

                  09

                  未来境:GPLearn 自动因子挖掘

                    /* 
                    step1:数据获取和特征提取(数据预处理)
                    */
                    dbName = "dfs://stockDayK"
                    tbName = "stockDayK"
                    // 选股票数据
                    codeList = exec SecurityID
                    from (select count(*) from loadTable(dbName, tbName) group by SecurityID)
                    where left(SecurityID, 1) in ["0", "3", "6"] 共5283只股票
                    // 计算日频收益率
                    testData = select SecurityID, DateTime, percentChange(close) as ret, open, close, high, low, double(volume) as volume, vwap
                    from loadTable(dbName, tbName)
                    where SecurityID in codeList
                    context by SecurityID
                    // 计算20日后的收益率(预期目标)
                    testData = select *, move(ret, 20) as ret20, prev(ret) as ret1 from testData context by SecurityID
                    // 过滤预期目标为空的数据,并排序
                    testData = select * from testData where ret20 != NULL order by SecurityID, DateTime


                    /*
                    step2:遗传算法进行因子挖掘(模型训练)
                    */
                    // 输入数据:ret, open, close, high, low, volume, vwap
                    trainData = select SecurityID, ret, open, close, high, low, volume, vwap from testData
                    // 预测目标:ret20,20日后的收益率
                    targetData = testData["ret20"]


                    // 自定义适应度函数(优化目标)
                    myFitness = <spearman(stand(rev(5, x)), y)> // 其中 x 表示计算结果,y 表示预测目标
                    // rev 函数用于中位数去极值
                    // stand 函数用于标准化
                    // spearman 函数用于计算 rankIC


                    // 创建 gplearn 训练模型
                    // syntax(createGPLearnEngine)
                    engine = createGPLearnEngine(trainData, targetData, groupCol="SecurityID",
                    populationSize=1000, generations=3, tournamentSize=20, initDepth=[1, 4], windowRange=2..243,
                    crossoverProb=0.8, subtreeMutationProb=0.01, hoistMutationProb=0.0,pointMutationProb=0.01)
                    // 设置自定义适应度函数
                    setGpFitnessFunc(engine, myFitness)
                    // 训练获取 10 个因子公式
                    res = engine.gpFit(10, true)

                    在“未来境”这一全新领域,我们开启了自动因子挖掘的壮阔征程。通过运用先进的 Shark GPLearn 框架,对暴力求解和组合优化等算法思想的巧妙应用,算法以模拟生物进化的方式,不断生成新的公式组合,并基于事先设定的优化目标函数如 rankIC 进行评分,保留优胜劣汰。经过不懈的迭代,最终精锐因子就会浮出水面。

                    Explore More



                    文章转载自DolphinDB智臾科技,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论