feat: add BOLL (Bollinger Bands) indicator to Strategy Studio

- Add BOLL to frontend indicator grid with period selection
- Add BOLL calculation (upper/middle/lower bands) in market data
- Add BOLL fields to TimeframeSeriesData struct
- Integrate BOLL into AI decision engine prompts
- Support multi-timeframe BOLL analysis
This commit is contained in:
tinkle-community
2025-12-20 16:17:16 +08:00
parent 8e57fb986f
commit 0009c9c3dd
6 changed files with 69 additions and 0 deletions

View File

@@ -868,6 +868,14 @@ func (e *StrategyEngine) writeAvailableIndicators(sb *strings.Builder) {
sb.WriteString("\n")
}
if indicators.EnableBOLL {
sb.WriteString("- Bollinger Bands (BOLL) - Upper/Middle/Lower bands")
if len(indicators.BOLLPeriods) > 0 {
sb.WriteString(fmt.Sprintf(" (periods: %v)", indicators.BOLLPeriods))
}
sb.WriteString("\n")
}
if indicators.EnableVolume {
sb.WriteString("- Volume data\n")
}
@@ -1193,6 +1201,12 @@ func (e *StrategyEngine) formatTimeframeSeriesData(sb *strings.Builder, data *ma
sb.WriteString(fmt.Sprintf("ATR14: %.4f\n", data.ATR14))
}
if indicators.EnableBOLL && len(data.BOLLUpper) > 0 {
sb.WriteString(fmt.Sprintf("BOLL Upper: %s\n", formatFloatSlice(data.BOLLUpper)))
sb.WriteString(fmt.Sprintf("BOLL Middle: %s\n", formatFloatSlice(data.BOLLMiddle)))
sb.WriteString(fmt.Sprintf("BOLL Lower: %s\n", formatFloatSlice(data.BOLLLower)))
}
sb.WriteString("\n")
}

View File

@@ -227,6 +227,9 @@ func calculateTimeframeSeries(klines []Kline, timeframe string, count int) *Time
RSI7Values: make([]float64, 0, count),
RSI14Values: make([]float64, 0, count),
Volume: make([]float64, 0, count),
BOLLUpper: make([]float64, 0, count),
BOLLMiddle: make([]float64, 0, count),
BOLLLower: make([]float64, 0, count),
}
// Get latest N data points based on count from config
@@ -277,6 +280,14 @@ func calculateTimeframeSeries(klines []Kline, timeframe string, count int) *Time
rsi14 := calculateRSI(klines[:i+1], 14)
data.RSI14Values = append(data.RSI14Values, rsi14)
}
// Calculate Bollinger Bands (period 20, std dev multiplier 2)
if i >= 19 {
upper, middle, lower := calculateBOLL(klines[:i+1], 20, 2.0)
data.BOLLUpper = append(data.BOLLUpper, upper)
data.BOLLMiddle = append(data.BOLLMiddle, middle)
data.BOLLLower = append(data.BOLLLower, lower)
}
}
// Calculate ATR14
@@ -466,6 +477,36 @@ func calculateATR(klines []Kline, period int) float64 {
return atr
}
// calculateBOLL calculates Bollinger Bands (upper, middle, lower)
// period: typically 20, multiplier: typically 2
func calculateBOLL(klines []Kline, period int, multiplier float64) (upper, middle, lower float64) {
if len(klines) < period {
return 0, 0, 0
}
// Calculate SMA (middle band)
sum := 0.0
for i := len(klines) - period; i < len(klines); i++ {
sum += klines[i].Close
}
sma := sum / float64(period)
// Calculate standard deviation
variance := 0.0
for i := len(klines) - period; i < len(klines); i++ {
diff := klines[i].Close - sma
variance += diff * diff
}
stdDev := math.Sqrt(variance / float64(period))
// Calculate bands
middle = sma
upper = sma + multiplier*stdDev
lower = sma - multiplier*stdDev
return upper, middle, lower
}
// calculateIntradaySeries calculates intraday series data
func calculateIntradaySeries(klines []Kline) *IntradayData {
data := &IntradayData{

View File

@@ -41,6 +41,10 @@ type TimeframeSeriesData struct {
RSI14Values []float64 `json:"rsi14_values"` // RSI14 series
Volume []float64 `json:"volume"` // Volume series (deprecated, use Klines)
ATR14 float64 `json:"atr14"` // ATR14
// Bollinger Bands (period 20, std dev multiplier 2)
BOLLUpper []float64 `json:"boll_upper"` // Upper band
BOLLMiddle []float64 `json:"boll_middle"` // Middle band (SMA)
BOLLLower []float64 `json:"boll_lower"` // Lower band
}
// OIData Open Interest data

View File

@@ -82,6 +82,7 @@ type IndicatorConfig struct {
EnableMACD bool `json:"enable_macd"`
EnableRSI bool `json:"enable_rsi"`
EnableATR bool `json:"enable_atr"`
EnableBOLL bool `json:"enable_boll"` // Bollinger Bands
EnableVolume bool `json:"enable_volume"`
EnableOI bool `json:"enable_oi"` // open interest
EnableFundingRate bool `json:"enable_funding_rate"` // funding rate
@@ -91,6 +92,8 @@ type IndicatorConfig struct {
RSIPeriods []int `json:"rsi_periods,omitempty"` // default [7, 14]
// ATR period configuration
ATRPeriods []int `json:"atr_periods,omitempty"` // default [14]
// BOLL period configuration (period, standard deviation multiplier is fixed at 2)
BOLLPeriods []int `json:"boll_periods,omitempty"` // default [20] - can select multiple timeframes
// external data sources
ExternalDataSources []ExternalDataSource `json:"external_data_sources,omitempty"`
// quantitative data sources (capital flow, position changes, price changes)
@@ -241,12 +244,14 @@ func GetDefaultStrategyConfig(lang string) StrategyConfig {
EnableMACD: false,
EnableRSI: false,
EnableATR: false,
EnableBOLL: false,
EnableVolume: true,
EnableOI: true,
EnableFundingRate: true,
EMAPeriods: []int{20, 50},
RSIPeriods: []int{7, 14},
ATRPeriods: []int{14},
BOLLPeriods: []int{20},
EnableQuantData: true,
QuantDataAPIURL: "http://nofxaios.com:30006/api/coin/{symbol}?include=netflow,oi,price&auth=cm_568c67eae410d912c54c",
EnableQuantOI: true,

View File

@@ -72,6 +72,8 @@ export function IndicatorEditor({
rsiDesc: { zh: '相对强弱指标', en: 'Relative Strength Index' },
atr: { zh: 'ATR', en: 'ATR' },
atrDesc: { zh: '真实波幅均值', en: 'Average True Range' },
boll: { zh: 'BOLL 布林带', en: 'Bollinger Bands' },
bollDesc: { zh: '布林带指标(上中下轨)', en: 'Upper/Middle/Lower Bands' },
volume: { zh: '成交量', en: 'Volume' },
volumeDesc: { zh: '交易量分析', en: 'Trading volume analysis' },
oi: { zh: '持仓量', en: 'Open Interest' },
@@ -295,6 +297,7 @@ export function IndicatorEditor({
{ key: 'enable_macd', label: 'macd', desc: 'macdDesc', color: '#a855f7' },
{ key: 'enable_rsi', label: 'rsi', desc: 'rsiDesc', color: '#F6465D', periodKey: 'rsi_periods', defaultPeriods: '7,14' },
{ key: 'enable_atr', label: 'atr', desc: 'atrDesc', color: '#60a5fa', periodKey: 'atr_periods', defaultPeriods: '14' },
{ key: 'enable_boll', label: 'boll', desc: 'bollDesc', color: '#ec4899', periodKey: 'boll_periods', defaultPeriods: '20' },
].map(({ key, label, desc, color, periodKey, defaultPeriods }) => (
<div
key={key}

View File

@@ -467,12 +467,14 @@ export interface IndicatorConfig {
enable_macd: boolean;
enable_rsi: boolean;
enable_atr: boolean;
enable_boll: boolean;
enable_volume: boolean;
enable_oi: boolean;
enable_funding_rate: boolean;
ema_periods?: number[];
rsi_periods?: number[];
atr_periods?: number[];
boll_periods?: number[];
external_data_sources?: ExternalDataSource[];
// 量化数据源(资金流向、持仓变化、价格变化)
enable_quant_data?: boolean;