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.
 
 

107 lines
2.9 KiB

package strategy
import (
"sig-pub/pkg/types"
"sig-pub/pkg/zlog"
)
// 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
ts := ctx.Get(0).Ts
if ts == 1763685000000 {
zlog.Infof("last summary: %#v", summary)
}
// 获取指标数据
// 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
}