package strategy import ( "sig-pub/pkg/types" ) // Grid 网格策略 // 基于均线和ATR构建动态网格 // 当价格下穿下方网格线时做多 // 当价格上穿上方网格线时做空 type Grid struct { period int16 // 均线和ATR周期 gridStep float64 // 网格间距(ATR倍数) gridSize int16 // 单侧网格数量 } func (s *Grid) New() ISigStrategy { return &Grid{} } func (s *Grid) Meta() StrategyMeta { return StrategyMeta{ Name: "Grid", Desc: "基于ATR的动态网格策略", Input: []types.InputArg{ {Name: "period", Type: types.InputTypeUInt, Desc: "EMA和ATR周期", Default: 20}, {Name: "gridStep", Type: types.InputTypeUFloat, Desc: "网格间距(ATR倍数)", Default: 1.0}, {Name: "gridSize", Type: types.InputTypeUInt, Desc: "单侧网格数量", Default: 5}, }, } } func (s *Grid) Init(input types.Input) (err error) { s.period = input.Int16("period") s.gridStep = input.Float("gridStep") s.gridSize = input.Int16("gridSize") return } func (s *Grid) CandlePeriods(ctx ISingleSigStrategyContext) int16 { return max( ctx.Indicator("EMA", s.period).CandlePeriods(), ctx.Indicator("ATR", s.period).CandlePeriods(), 2, // 需要前一根K线判断交叉 ) } func (s *Grid) Update(ctx ISingleSigStrategyContext) (side types.Side) { // 获取指标数据 ema := ctx.Indicator("EMA", s.period).Get(0) atr := ctx.Indicator("ATR", s.period).Get(0) // 获取前一根指标数据用于判断交叉 emaPrev := ctx.Indicator("EMA", s.period).Get(1) atrPrev := ctx.Indicator("ATR", s.period).Get(1) // 获取K线收盘价 closeP := ctx.Get(0).CloseF64() closePrev := ctx.Get(1).CloseF64() // 遍历网格层级 for i := int16(1); i <= s.gridSize; i++ { step := float64(i) * s.gridStep // 下方网格线 lower := ema - atr*step lowerPrev := emaPrev - atrPrev*step // 价格下穿下方网格线 -> 买入信号 // Close[1] >= Lower[1] && Close[0] < Lower[0] if closePrev >= lowerPrev && closeP < lower { return types.SideLong } // 上方网格线 upper := ema + atr*step upperPrev := emaPrev + atrPrev*step // 价格上穿上方网格线 -> 卖出信号 // Close[1] <= Upper[1] && Close[0] > Upper[0] if closePrev <= upperPrev && closeP > upper { return types.SideShort } } return }