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