package strategy import ( "sig-pub/pkg/types" ) // BollGrid 布林带网格策略 // 基于布林带中轨(SMA)和标准差(StdDev)构建动态网格 // 利用布林带指标计算出的中轨和上轨反推标准差 // 当价格下穿下方网格线时做多 // 当价格上穿上方网格线时做空 type BollGrid struct { period int16 // 布林带周期 gridStep float64 // 网格间距(标准差倍数) gridSize int16 // 单侧网格数量 } func (s *BollGrid) New() ISigStrategy { return &BollGrid{} } func (s *BollGrid) Meta() StrategyMeta { return StrategyMeta{ Name: "BollGrid", Desc: "基于布林带标准差的动态网格策略", Input: []types.InputArg{ {Name: "period", Type: types.InputTypeUInt, Desc: "布林带周期", Default: 20}, {Name: "gridStep", Type: types.InputTypeUFloat, Desc: "网格间距(标准差倍数)", Default: 1.0}, {Name: "gridSize", Type: types.InputTypeUInt, Desc: "单侧网格数量", Default: 3}, }, } } func (s *BollGrid) Init(input types.Input) (err error) { s.period = input.Int16("period") s.gridStep = input.Float("gridStep") s.gridSize = input.Int16("gridSize") return } func (s *BollGrid) CandlePeriods(ctx ISingleSigStrategyContext) int16 { return max( ctx.Indicator("BOLL", s.period).CandlePeriods(), 2, // 需要前一根K线判断交叉 128, ) } func (s *BollGrid) Update(ctx ISingleSigStrategyContext) (side types.Side) { // 128 根k线的成交量分布图 summary, ok := ctx.SummaryIndicator("VRVP", types.Input{"buckets": 48}).Summary(0, 128) _, _ = summary, ok // 获取指标数据 // BOLL指标 Calculate 返回值为 mb (中轨) bollInd := ctx.Indicator("BOLL", s.period) mb := bollInd.Get(0) ub := bollInd.State("ub", 0) // 上轨 (mb + 2*sigma) // 计算标准差 sigma // 默认 BOLL 实现中,ub = mb + 2 * sigma sigma := (ub - mb) / 2.0 if sigma == 0 { return types.SideNone } // 获取前一根指标数据用于判断交叉 mbPrev := bollInd.Get(1) ubPrev := bollInd.State("ub", 1) sigmaPrev := (ubPrev - mbPrev) / 2.0 // 获取K线收盘价 closeP := ctx.Get(0).CloseF64() closePrev := ctx.Get(1).CloseF64() // 遍历网格层级 for i := int16(1); i <= s.gridSize; i++ { stepMul := float64(i) * s.gridStep // 下方网格线: MB - i * step * sigma lower := mb - sigma*stepMul lowerPrev := mbPrev - sigmaPrev*stepMul // 价格下穿下方网格线 -> 买入信号 // Close[1] >= Lower[1] && Close[0] < Lower[0] if closePrev >= lowerPrev && closeP < lower { return types.SideLong } // 上方网格线: MB + i * step * sigma upper := mb + sigma*stepMul upperPrev := mbPrev + sigmaPrev*stepMul // 价格上穿上方网格线 -> 卖出信号 // Close[1] <= Upper[1] && Close[0] > Upper[0] if closePrev <= upperPrev && closeP > upper { return types.SideShort } } return }