跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 世界
  • 用户
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(不使用皮肤)
  • 不使用皮肤
折叠
品牌标识

AI量化投资实验室-社区&知识库

  1. 首页
  2. aitrader量化系统 代码学习&问题反馈
  3. 关于trend_score和ROC的计算问题

关于trend_score和ROC的计算问题

已定时 已固定 已锁定 已移动 aitrader量化系统 代码学习&问题反馈
9 帖子 6 发布者 491 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • X 离线
    X 离线
    xialei
    写于 最后由 xialei 编辑
    #1

    63267907-0fc9-447e-9653-e885459f441b-image.png
    trend_score
    根据该描述是如果要计算20日 trend_score 是不是就是20天的斜率值*拟合度R2的计算结果
    我使用from sklearn.linear_model import LinearRegression直接计算R2
    ROC是根据公式进行计算的:
    ROC = (当前收盘价 - N周期前收盘价) / N周期前收盘价 * 100
    最后回测出来的结果和平台展示的收益信息有一些不同,我最多只能跑到40多倍的收益,平台上显示是接近60倍的收益
    trend_score_R2计算.png
    而且最后买入的持仓也和平台上的显示不一致,这块有哪位大神能帮忙解答下?
    平台显示策略:
    c5be3cb1-9c57-4665-8b15-d1feb15c4c38-image.png
    我自己回测最后买的是沪深300和平台上买入创业版ETF不太一致:
    d58d4004-3969-481d-bfd6-13c495e96b79-image.png
    收益回测出来大概是49倍左右:
    e8e8cdda-90e5-4b13-8ef0-45805ce82f88-image.png

    1 条回复 最后回复
    0
    • M 离线
      M 离线
      moyulao
      写于 最后由 编辑
      #2

      你可以再看看排序值,他这里有一个规则应该是默认的,买入一个标的后,如果这个标的某天的排序值不是第一时,会卖出这个标的,然后再买入当天排序值最高的标的,6月24号买入纳指,25号卖出纳指、买入创业板这里是最明显的

      1 条回复 最后回复
      0
      • X 离线
        X 离线
        xialei
        写于 最后由 编辑
        #3

        嗯嗯,我估计是这个trend_score计算还有些区别,我再研究下。

        1 条回复 最后回复
        0
        • X 离线
          X 离线
          xialei
          写于 最后由 编辑
          #4
          此主題已被删除!
          1 条回复 最后回复
          0
          • J 离线
            J 离线
            jyliceberg
            编写于 最后由 编辑
            #5

            这个因子有计算解释么?

            1 条回复 最后回复
            -1
            • 1 离线
              1 离线
              18677570624
              编写于 最后由 编辑
              #6

              我感觉是python包计算差异, 算法差异

              1 条回复 最后回复
              0
              • X 离线
                X 离线
                xuanyuan1hao
                编写于 最后由 编辑
                #7

                from sklearn.linear_model import LinearRegression
                from sklearn.metrics import r2_score

                def calculate_R2_with_slope(close_values,K):
                n = len(close_values)
                if n < K:
                return np.nan
                # 获取最新的close_values数据
                close_values = close_values[-K:]
                n = len(close_values)
                # 取close_values窗口滑动向前的20天数据
                x = np.arange(n).reshape(-1, 1)
                model = LinearRegression()
                model.fit(x, close_values)
                # 获取斜率(回归系数)
                slope = model.coef_[0]
                #print(f"斜率(回归系数): {slope}")
                X_test = np.array(x)
                y_test= np.array(close_values)
                # 获取拟合度(R-squared值)
                y_pred = model.predict(X_test)
                r2 = r2_score(y_test, y_pred)
                return r2*slope

                @calc_by_symbol
                def trend_score(se: pd.Series,d):
                # 这里使用滑动窗口获取 斜率*拟合度
                return se.rolling(window=d).apply(lambda x: calculate_R2_with_slope(x.values, d))

                我这里的计算方式是这样的,也回测不出来公开策略的60%多倍收益,只测试出来37倍收益

                1 条回复 最后回复
                0
                • X 离线
                  X 离线
                  xuanyuan1hao
                  编写于 最后由 编辑
                  #8

                  我这里修改了一下,拟合直线的斜率改成了暴力两点 斜率

                  获取斜率(回归系数)

                  slope = model.coef_[0]

                  暴力首尾两点斜率
                  slope=(close_values[n-1]-close_values[0])/close_values[0]

                  这样计算出来总收益为50.57812057000028

                  1 条回复 最后回复
                  0
                  • D 离线
                    D 离线
                    douzi
                    编写于 最后由 编辑
                    #9

                    下面这个是星主的源码:
                    @staticmethod
                    def trend_score(series: pd.Series, period=25):
                    def _trend_score(close, period=25):
                    """
                    向量化计算趋势评分:年化收益率 × R平方
                    :param close: 收盘价序列(np.array或pd.Series)
                    :param period: 计算窗口长度,默认25天
                    :return: 趋势评分数组,长度与输入相同,前period-1位为NaN
                    """
                    if len(close) < period:
                    return np.full_like(close, np.nan)

                        y = np.log(close)
                        windows = np.lib.stride_tricks.sliding_window_view(y, window_shape=period)
                        x = np.arange(period)
                    
                        # 预计算固定值
                        n = period
                        sum_x = x.sum()
                        sum_x2 = (x ** 2).sum()
                        denominator = n * sum_x2 - sum_x ** 2
                    
                        # 滑动窗口统计量
                        sum_y = windows.sum(axis=1)
                        sum_xy = (windows * x).sum(axis=1)
                    
                        # 回归系数
                        slope = (n * sum_xy - sum_x * sum_y) / denominator
                        intercept = (sum_y - slope * sum_x) / n
                    
                        # 年化收益率
                        annualized_returns = np.exp(slope * 250) - 1
                    
                        # R平方计算
                        y_pred = slope[:, None] * x + intercept[:, None]
                        residuals = windows - y_pred
                        ss_res = np.sum(residuals ** 2, axis=1)
                    
                        sum_y2 = np.sum(windows ** 2, axis=1)
                        ss_tot = sum_y2 - (sum_y ** 2) / n
                        r_squared = 1 - (ss_res / ss_tot)
                        r_squared = np.nan_to_num(r_squared, nan=0.0)  # 处理零方差情况
                    
                        # 综合评分
                        score = annualized_returns * r_squared
                    
                        # 对齐原始序列长度
                        full_score = np.full_like(y, np.nan)
                        full_score = pd.Series(index=close.index)
                        full_score[period - 1:] = score
                        return full_score
                    
                    return series.groupby(level='symbol', group_keys=False).apply(_trend_score)
                    
                    1 条回复 最后回复
                    0
                    回复
                    • 在新帖中回复
                    登录后回复
                    • 从旧到新
                    • 从新到旧
                    • 最多赞同


                    • 登录

                    • 没有帐号? 注册

                    Powered by NodeBB Contributors
                    • 第一个帖子
                      最后一个帖子
                    0
                    • 版块
                    • 最新
                    • 标签
                    • 热门
                    • 世界
                    • 用户
                    • 群组