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
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 |
|
}
|
|
|