package strategy import ( "sig-pub/pkg/types" "sig-pub/pkg/utils/lang" ) type SupertrendBOSWaves struct { ISigStrategy atrLength int16 atrMult float64 // radiusStrength float64 // smoothness int16 prevDirection int // anchorPrice float64 // anchorBar int // velocity float64 // barCount int } func (s *SupertrendBOSWaves) New() ISigStrategy { return &SupertrendBOSWaves{} } func (s *SupertrendBOSWaves) Meta() StrategyMeta { return StrategyMeta{ Name: "SupertrendBOSWaves", Desc: "曲线半径超级趋势 [BOSWaves] https://www.tradingview.com/script/v0Fr7PAb-Curved-Radius-Supertrend-BOSWaves/", Input: []types.InputArg{ {Name: "atrLength", Type: types.InputTypeUInt, Desc: "atr指标长度,14"}, {Name: "atrMult", Type: types.InputTypeUFloat, Desc: "atr倍数,2"}, {Name: "radiusStrength", Type: types.InputTypeUFloat, Desc: ` Controls curve acceleration strength.\n\n" + "Recommended values by timeframe:\n" + "• 1-5min (Scalping): 0.08-0.12\n" + "• 15min: 0.12-0.15\n" + "• 1H: 0.15-0.18\n" + "• 4H: 0.18-0.22\n" + "• Daily: 0.20-0.25\n" + "• Weekly: 0.25-0.30\n\n" + "Lower = Tighter curves (responsive)\n" + "Higher = Wider curves (smoother) `}, {Name: "smoothness", Type: types.InputTypeUInt, Desc: "Smoothing applied to curved band. Higher = smoother curves, less noise."}, }, } } func (s *SupertrendBOSWaves) Init(input types.Input) (err error) { // 校验参数, 并根据参数初始化策略 s.atrLength = input.Int16("atrLength") s.atrMult = input.Float("atrMult") // s.radiusStrength = input.Float("radiusStrength") // s.smoothness = input.Float("smoothness") return } func (s *SupertrendBOSWaves) RequiredSeries(input types.Input) int16 { return s.atrLength + 1 } func (s *SupertrendBOSWaves) Update(ctx ISingleSigStrategyContext) (side types.Side) { k0 := ctx.Get(0) high, low, close := k0.HighF64(), k0.LowF64(), k0.CloseF64() atr := ctx.Indicator("atr", s.atrLength).Get(0) src := (high + low) / 2 // src := k0.HL2() upperBand := src + (s.atrMult * atr) lowerBand := src - (s.atrMult * atr) supertrend := lowerBand direction := 1 // Standard supertrend logic prevSupertrend := supertrend if direction == 1 { supertrend = lang.Ternary(close < prevSupertrend, upperBand, max(lowerBand, prevSupertrend)) } else { supertrend = lang.Ternary(close > prevSupertrend, lowerBand, min(upperBand, prevSupertrend)) } s.prevDirection = direction if close < supertrend { direction = -1 } if close > supertrend { direction = 1 } // ============================================================================ // Curved Radius Implementation // ============================================================================ // Detect trend change - set new anchor trendChanged := s.prevDirection != 0 && direction != s.prevDirection buySignal := trendChanged && direction == 1 sellSignal := trendChanged && direction == -1 if buySignal { return types.SideLong } if sellSignal { return types.SideShort } // if trendChanged { // s.anchorPrice = supertrend // s.anchorBar = 0 //bar_index // s.velocity = 0.0 // s.barCount = 0 // } // // Increment bar counter // s.barCount = s.barCount + 1 // // Calculate curved offset using acceleration creating a parabolic curve // // todo if not na(anchorPrice) // if trendChanged { // // Acceleration increases with each bar (quadratic growth) // s.velocity = s.velocity + (s.radiusStrength * float64(s.barCount)) // } // // Apply velocity in direction of trend // if direction == 1 { // // Uptrend - curve upward with acceleration // supertrend = s.anchorPrice + s.velocity // } else { // // Downtrend - curve downward with acceleration // supertrend = s.anchorPrice - s.velocity // } // Apply smoothing to create flowing curves // curvedBand = ta.sma(supertrend, s.smoothness) return }