You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

87 lines
2.3 KiB

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
}