package strategy import ( "sig-pub/pkg/types" ) // MeanReversionV1 type MeanReversionV1 struct { IIntervalSigStrategy interval types.Interval period int threshold float64 buckets int } func (s *MeanReversionV1) New() ISigStrategy { return &MeanReversionV1{} } func (s *MeanReversionV1) Meta() StrategyMeta { return StrategyMeta{ Name: "MeanReversionV1", Desc: "VRVP Mean Reversion Strategy", Input: []types.InputArg{ {Name: "interval", Type: types.InputTypeString, Desc: "Target Interval (e.g., 1m, 1h)", Default: "1m"}, {Name: "period", Type: types.InputTypeInt, Desc: "VRVP calculation window", Default: 100}, {Name: "threshold", Type: types.InputTypeUFloat, Desc: "Reversion Threshold Ratio (e.g. 0.01)", Default: 0.01}, {Name: "buckets", Type: types.InputTypeInt, Desc: "VRVP Buckets", Default: 24}, }, } } func (s *MeanReversionV1) Init(input types.Input) (err error) { s.interval = types.Interval(input.String("interval")) if _, ok := types.SupportedIntervals[s.interval]; !ok { s.interval = types.Interval1m } s.period = input.Int("period") if s.period <= 0 { s.period = 100 } s.threshold = input.Float("threshold") s.buckets = input.Int("buckets") if s.buckets <= 0 { s.buckets = 24 } return } func (s *MeanReversionV1) CandlePeriods(ctx IIntervalSigStrategyContext) (iss *types.IntervalState[int16]) { iss = types.NewIntervalState[int16]() iss.Set(s.interval, int16(s.period)) return } func (s *MeanReversionV1) Update(ctx IIntervalSigStrategyContext) (side types.Side) { // Calculate VRVP period candles summaryObj := ctx.SummaryIndicator(s.interval, "VRVP", map[string]any{"buckets": s.buckets}) summaryAny, ok := summaryObj.Summary(0, int16(s.period)) if !ok { return } vrvpSummary, ok := summaryAny.(*types.VRVPSummary) if !ok || vrvpSummary == nil || len(vrvpSummary.Buckets) == 0 { return } // Find POC (Point of Control) - Bucket with max volume var maxVol float64 var pocPrice float64 found := false for _, bucket := range vrvpSummary.Buckets { if bucket.Volume > maxVol { maxVol = bucket.Volume pocPrice = bucket.Price found = true } } if !found { return } // Get Current Price k := ctx.Get(s.interval, 0) currentPrice := k.CloseF64() // Deviation ratio if pocPrice <= 0 { return } deviation := (currentPrice - pocPrice) / pocPrice if deviation > s.threshold { // 当前价格高于 POC, 预期回落 side = types.SideShort } else if deviation < -s.threshold { // 当前价格低于 POC, 预期回升 side = types.SideLong } return }