跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 世界
  • 用户
  • 群组
皮肤
  • 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. 因子扩展及策略应用案例(Tradingview平台 Dema Adjusted ATR及Rainbow Adaptive RSI )

因子扩展及策略应用案例(Tradingview平台 Dema Adjusted ATR及Rainbow Adaptive RSI )

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

    近期,我在 TradingView 平台上探索了“彩虹波动交易法”策略,基于现有移植的c#平台,尝试扩展新的因子并设置toml策略进行应用,针对创业板 ETF(159915)进行了优化与初步回测,分享以下经验与成果。
    新因子:DEMA Adjusted ATR 和 Rainbow Adaptive RSI
    因子背景与设计
    • DEMA Adjusted ATR:通过双指数移动平均调整的平均真实波幅,衡量价格波动强度。绿色信号(上穿基线)用于买入,红色信号(下穿基线)用于卖出。
    • Rainbow Adaptive RSI:结合多周期自适应相对强弱指数,绿色线条(中间周期)确认上升趋势,红色线条(长周期)确认下降趋势。
    策略优化过程
    初始配置复刻了“做多三铁律”(DEMA ATR 绿色 + 绿线交叉 + 阳线)和“做空三要素”(DEMA ATR 红色 + 红线交叉 + 阴线),通过多次回测调整参数:
    • 买入条件从 dema_atr_14 > 1.1ma_dema_atr_20 优化至 dema_atr_14 > 1.03ma_dema_atr_20,增加信号频率。
    • RSI 阈值从 rainbow_rsi_14 > 45 放宽至 > 40,rainbow_rsi_28 < 55 调整至 < 49,提升趋势捕捉能力。
    • 卖出条件提前至 dema_atr_14 < 0.98*ma_dema_atr_20,控制回撤。
    回测成果
    • 数据范围:2019-10-25 至 2025-04-16日。
    • 结果:累计收益率:92.97% 年化收益率:16.96% 夏普比率:0.56% 最大回撤率:20.96% 风险比率:0.00% 开仓次数:97 胜率:48.45%
    心得与建议
    因子扩展的关键在于百分百复刻原有因子算法,并适配当前量化框架,平衡信号数量与质量。DEMA Adjusted ATR 提供波动过滤,Rainbow Adaptive RSI 增强趋势确认,结合 K 线形态(阳线/阴线)提高胜率。建议量化爱好者:
    • 调整 ATR 和 RSI 参数,适配不同市场特性,进一步提高回测结果指标。
    • 加入止损或动态调整,优化回撤控制。
    • 分享回测日志,验证信号有效性。
    欢迎社区交流进一步提升和优化的思路,共同提升策略表现!

    以下是c#相关的因子算法:

    public static double CalculateTvDemaAdjustedAtr(double[] high, double[] low, double[] close, int timeperiod)
    {
        // 验证输入序列有效性及长度
        if (high == null || low == null || close == null || high.Length < timeperiod * 2 + 1 || low.Length < timeperiod * 2 + 1 || close.Length < timeperiod * 2 + 1)
        {
            return double.NaN; // 无效输入返回 NaN
        }
    
        // 初始化真波幅(TR)数组
        double[] tr = new double[high.Length];
        // 遍历序列计算每日 TR
        for (int i = 0; i < high.Length; i++)
        {
            // TR1:当日高低价差
            double tr1 = high[i] - low[i];
            // TR2:高价与前日收盘价差的绝对值,首日忽略
            double tr2 = i > 0 ? Math.Abs(high[i] - close[i - 1]) : 0;
            // TR3:低价与前日收盘价差的绝对值,首日忽略
            double tr3 = i > 0 ? Math.Abs(low[i] - close[i - 1]) : 0;
            // TR:取三者最大值
            tr[i] = Math.Max(tr1, Math.Max(tr2, tr3));
        }
    
        // 对 TR 应用现有 DEMA 计算
        double demaAtr = CalculateTaDema(tr, timeperiod);
    
        // 返回最新 DEMA ATR 值
        return demaAtr;
    }
    public static double CalculateTvRainbowAdaptiveRsi(double[] close, double[] high, double[] low, int baseTimeperiod, int minTimeperiod, int maxTimeperiod)
    {
        // 验证输入序列有效性及长度
        if (close == null || high == null || low == null || close.Length < baseTimeperiod + 1 || high.Length < baseTimeperiod + 1 || low.Length < baseTimeperiod + 1)
        {
            return double.NaN; // 无效输入返回 NaN
        }
    
        // 计算基础周期的 ATR 作为波动率衡量
        double atr = CalculateTaAtr(high, low, close, baseTimeperiod);
        // 标准化波动率:ATR 相对收盘价的比例(百分比)
        double volatility = atr / close[close.Length - 1] * 100;
        // 归一化波动率到 [0,1],假设波动范围 1%~4%
        double normalizedVol = Math.Min(1, Math.Max(0, (volatility - 1) / 3));
    
        // 计算自适应周期
        int adaptiveLength = (int)(minTimeperiod + (maxTimeperiod - minTimeperiod) * normalizedVol);
    
        // 计算中间层 RSI(基于自适应周期)
        double rsi2 = CalculateTaRsi(close, adaptiveLength);
    
        // 返回最新中间层 RSI 值
        return rsi2;
    }
    public static double CalculateTaRsi(double[] input, int period)
    {
        if (input == null || input.Length < period + 1)
        {
            return double.NaN;
        }
    
        // 计算价格变化
        double[] diff = new double[input.Length - 1];
        for (int i = 1; i < input.Length; i++)
        {
            diff[i - 1] = input[i] - input[i - 1];
        }
    
        // 初始化平均增益和减益
        double gainSum = 0.0;
        double lossSum = 0.0;
        for (int i = 0; i < period; i++)
        {
            if (diff[i] > 0)
            {
                gainSum += diff[i];
            }
            else
            {
                lossSum += Math.Abs(diff[i]);
            }
        }
    
        double avgGain = gainSum / period;
        double avgLoss = lossSum / period;
    
        // 平滑 RSI 计算
        for (int i = period; i < diff.Length; i++)
        {
            double gain = diff[i] > 0 ? diff[i] : 0.0;
            double loss = diff[i] < 0 ? Math.Abs(diff[i]) : 0.0;
    
            avgGain = ((avgGain * (period - 1)) + gain) / period;
            avgLoss = ((avgLoss * (period - 1)) + loss) / period;
        }
    
        // 计算 RSI
        if (avgLoss == 0)
        {
            return 100.0;
        }
    
        double rs = avgGain / avgLoss;
        double rsi = 100.0 - (100.0 / (1.0 + rs));
    
        return rsi;
    }
    
    public static double CalculateTaDema(double[] series, int periods)
    {
        if (series.Length < periods * 2) return double.NaN;
        double[] ema1 = new double[series.Length];
        double multiplier = 2.0 / (periods + 1);
        ema1[0] = series[0];
        for (int i = 1; i < series.Length; i++)
        {
            ema1[i] = (series[i] - ema1[i - 1]) * multiplier + ema1[i - 1];
        }
        double[] ema2 = new double[series.Length];
        ema2[0] = ema1[0];
        for (int i = 1; i < series.Length; i++)
        {
            ema2[i] = (ema1[i] - ema2[i - 1]) * multiplier + ema2[i - 1];
        }
        return 2 * ema1[series.Length - 1] - ema2[series.Length - 1];
    }
    
    public static double CalculateTaAtr(double[] high, double[] low, double[] close, int window)
    {
        if (high == null || low == null || close == null || high.Length < window + 1 || low.Length < window + 1 || close.Length < window + 1)
        {
            return double.NaN;
        }
    
        // 计算真实波幅(TR)
        double[] tr = new double[high.Length];
        for (int i = 0; i < high.Length; i++)
        {
            double tr1 = high[i] - low[i];
            double tr2 = i > 0 ? Math.Abs(high[i] - close[i - 1]) : 0;
            double tr3 = i > 0 ? Math.Abs(low[i] - close[i - 1]) : 0;
            tr[i] = Math.Max(tr1, Math.Max(tr2, tr3));
        }
    
        // 计算 ATR(简单移动平均)
        double sum = 0.0;
        for (int i = high.Length - window; i < high.Length; i++)
        {
            sum += tr[i];
        }
        double atr = sum / window;
    
        return atr;
    }
    

    TOML文件内容

    name = "彩虹波动交易法"
    symbols = [ "159915.SZ",]
    benchmark = "510300.SH"
    
    [date]
    start_date = "20191025"
    end_date = "20250416"
    
    [factors]
    exprs = [ "tv_dema_atr(high,low,close,14)","tv_rainbow_rsi(close,high,low,14,7,28)","tv_rainbow_rsi(close,high,low,28,7,28)","tv_dema_atr(high,low,close,20)","ma(tv_dema_atr(high,low,close,20),20)","close - open","open - close"]
    names = [ "dema_atr_14","rainbow_rsi_14","rainbow_rsi_28","dema_atr_20","ma_dema_atr_20","kma_positive","kma_negative"]
    
    [period]
    algo = "RunDaily"
    
    [selection]
    algo = "SelectAll"
    buy_rules = ['dema_atr_14 > 1.08*ma_dema_atr_20 and rainbow_rsi_14 > 42 and kma_positive > 0']
    buy_at_least_count = 1
    sell_rules = ['dema_atr_14 < 0.92*ma_dema_atr_20 or rainbow_rsi_28 < 52 or kma_negative > 0']
    sell_at_least_count = 1
    
    [order]
    factor = ""
    topK = 1
    dropN = 0
    is_desc = true
    
    [weight]
    algo = "WeighEqually"
    
    [weight.fixed_weights]
    
    

    人生无处不量化

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

      大神学习了,实验中

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

        感谢无私分享,逻辑和代码都很清晰,可以作为以后其他大神分享模版

        做有价值的事情

        1 条回复 最后回复
        0
        回复
        • 在新帖中回复
        登录后回复
        • 从旧到新
        • 从新到旧
        • 最多赞同


        • 登录

        • 没有帐号? 注册

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