Skip to content

supertrend超级趋势 #9

@anyongjin

Description

@anyongjin

From 微信:阿薛

// SuperTrend 超级趋势指标
// period: ATR周期,通常为10
// multiplier: ATR乘数,通常为3.0
// 返回 [st, upper band, lower band]
// st: 1表示看涨,-1表示看跌

func SuperTrend(high, low, close *ta.Series, period int, multiplier float64) (*ta.Series, *ta.Series, *ta.Series) {
	// Create result series with cache key based on period and multiplier
	res := close.To("supertrend", period*10+int(multiplier))
	if res.Cached() {
		return res, res.Cols[0], res.Cols[1]
	}

	res.LockData.Lock()

	if !res.Cached() {
		// Calculate ATR (Average True Range)
		atr := ta.ATR(high, low, close, period)

		// Calculate mid price (High + Low) / 2
		midPrice := ta.HL2(high, low)

		// Calculate basic upper and lower bands
		upperBasic := midPrice.Add(atr.Mul(multiplier))
		lowerBasic := midPrice.Sub(atr.Mul(multiplier))

		// Create state storage struct to save previous period's bands and trend
		type state struct {
			prevUpper float64
			prevLower float64
			trend     int
		}

		// Initialize state
		var s state
		if m, ok := res.More.(state); ok {
			s = m
		} else {
			// Initial state with NaN and trend 0
			s = state{math.NaN(), math.NaN(), 0}
		}

		// Get current close price
		currentClose := close.Get(0)

		// Calculate current upper and lower bands
		var currentUpper, currentLower float64

		// Update bands based on trend and close price
		if math.IsNaN(s.prevUpper) || math.IsNaN(s.prevLower) {
			// Initial period, use basic bands directly
			currentUpper = upperBasic.Get(0)
			currentLower = lowerBasic.Get(0)
			s.trend = 1 // No initial trend
		} else {
			var adjustedUpper, adjustedLower float64
			if res.Get(0) == -1 { // 这里因为还有没走append,所以0就是上一个
				adjustedUpper = math.Min(upperBasic.Get(0), s.prevUpper)
				adjustedLower = lowerBasic.Get(0)
			} else {
				adjustedUpper = upperBasic.Get(0)
				adjustedLower = math.Max(lowerBasic.Get(0), s.prevLower)
			}

			currentLower = adjustedLower
			currentUpper = adjustedUpper

			if currentClose > adjustedUpper {
				// Close breaks above upper band, bullish trend
				s.trend = 1
			} else if currentClose < adjustedLower {
				// Close breaks below lower band, bearish trend
				s.trend = -1
			} else {
				// Maintain previous trend
				s.trend = int(res.Get(0))
			}
		}

		// Update state with current values
		s.prevUpper = currentUpper
		s.prevLower = currentLower

		res.More = s

		// Append results: trend, upper band, lower band
		res.Append([]float64{float64(s.trend), currentUpper, currentLower})
	}
	res.LockData.Unlock()
	return res, res.Cols[0], res.Cols[1]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions