Browse Source

vrvp strategy

main
strange 6 months ago
parent
commit
9beedad108
  1. 4
      config/exchange.toml
  2. 5
      internal/trading/sig/indicator_context.go
  3. 92
      pkg/strategy/mean_reversion_v1.go
  4. 4
      pkg/strategy/sig_strategy.go
  5. 1
      pkg/strategy/sig_strategy_registry.go

4
config/exchange.toml

@ -18,9 +18,9 @@ receiveBuffer = 4096
marketSubscribeLimit = 16 marketSubscribeLimit = 16
consumeBatch = 1024 consumeBatch = 1024
consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume
# httpProxy = "" httpProxy = ""
# httpProxy = "http://192.168.1.4:7890" # httpProxy = "http://192.168.1.4:7890"
httpProxy = "http://10.255.183.209:7890" # httpProxy = "http://10.255.183.209:7890"
# 模拟盘API交易地址如下: # 模拟盘API交易地址如下:
# REST:https://www.okx.com # REST:https://www.okx.com

5
internal/trading/sig/indicator_context.go

@ -173,6 +173,11 @@ func (c *IndicatorContext) SummaryIndicator(name string, args ...any) (summary i
} }
func matchIndicatorArgs(args ...any) (input types.Input) { func matchIndicatorArgs(args ...any) (input types.Input) {
defer func() {
if input == nil {
input = make(types.Input)
}
}()
inputLoop: inputLoop:
for _, arg := range args { for _, arg := range args {
switch v := arg.(type) { switch v := arg.(type) {

92
pkg/strategy/mean_reversion_v1.go

@ -1,16 +1,16 @@
package strategy package strategy
import ( import (
"math"
"sig-pub/pkg/types" "sig-pub/pkg/types"
"sig-pub/pkg/zlog"
) )
// MeanReversionV1 // MeanReversionV1
type MeanReversionV1 struct { type MeanReversionV1 struct {
IIntervalSigStrategy IIntervalSigStrategy
rate float64 interval types.Interval
rate2 float64 period int
threshold float64
buckets int
} }
func (s *MeanReversionV1) New() ISigStrategy { func (s *MeanReversionV1) New() ISigStrategy {
@ -20,44 +20,86 @@ func (s *MeanReversionV1) New() ISigStrategy {
func (s *MeanReversionV1) Meta() StrategyMeta { func (s *MeanReversionV1) Meta() StrategyMeta {
return StrategyMeta{ return StrategyMeta{
Name: "MeanReversionV1", Name: "MeanReversionV1",
Desc: "均值回归策略v1", Desc: "VRVP Mean Reversion Strategy",
Input: []types.InputArg{ Input: []types.InputArg{
{Name: "rate", Type: types.InputTypeUFloat, Desc: "上线影线与基线比例"}, {Name: "interval", Type: types.InputTypeString, Desc: "Target Interval (e.g., 1m, 1h)", Default: "1m"},
{Name: "rate2", Type: types.InputTypeUFloat, Desc: "上线影线之间比例"}, {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) { // 校验参数, 并根据参数初始化策略 func (s *MeanReversionV1) Init(input types.Input) (err error) {
s.rate = input.Float("rate") s.interval = types.Interval(input.String("interval"))
s.rate2 = input.Float("rate2") 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 return
} }
func (s *MeanReversionV1) CandlePeriods(ctx IIntervalSigStrategyContext) (iss *types.IntervalState[int16]) { func (s *MeanReversionV1) CandlePeriods(ctx IIntervalSigStrategyContext) (iss *types.IntervalState[int16]) {
iss = types.NewIntervalState[int16]() iss = types.NewIntervalState[int16]()
iss.Set(types.Interval5m, 1) iss.Set(s.interval, int16(s.period))
iss.Set(types.Interval15m, 2)
iss.Set(types.Interval30m, 2)
return return
} }
func (s *MeanReversionV1) Update(ctx IIntervalSigStrategyContext) (side types.Side) { func (s *MeanReversionV1) Update(ctx IIntervalSigStrategyContext) (side types.Side) {
// O 109744.8 H 110600 L 109507.5 C 109686.8 // Calculate VRVP period candles
k0 := ctx.Get("5m", 0) summaryObj := ctx.SummaryIndicator(s.interval, "VRVP", map[string]any{"buckets": s.buckets})
open, close, high, low := k0.OpenF64(), k0.CloseF64(), k0.HighF64(), k0.LowF64() summaryAny, ok := summaryObj.Summary(0, int16(s.period))
base := math.Abs(open - close) if !ok {
rup := (high - max(open, close)) / base return
rdown := (min(open, close) - low) / base }
if k0.Ts == 1761833700000 { vrvpSummary, ok := summaryAny.(*types.VRVPSummary)
zlog.Debugf("base=%.4f, rup=%.4f, rdown=%.4f", base, rup, rdown) if !ok || vrvpSummary == nil || len(vrvpSummary.Buckets) == 0 {
return
} }
if rup > s.rate && rup/rdown > s.rate2 {
return types.SideLong // 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 rdown > s.rate && rdown/rup > s.rate2 {
return types.SideShort 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 return
} }

4
pkg/strategy/sig_strategy.go

@ -58,6 +58,8 @@ type IIntervalSigStrategyContext interface {
Series(interval types.Interval, offset, count int16) (klines types.Klines) Series(interval types.Interval, offset, count int16) (klines types.Klines)
// 获取窗口类型指标 // 获取窗口类型指标
Indicator(interval types.Interval, name string, args ...any) indicator.IIndicatorSeries Indicator(interval types.Interval, name string, args ...any) indicator.IIndicatorSeries
// SummaryIndicator 获取Summary类型指标
SummaryIndicator(interval types.Interval, name string, args ...any) indicator.IIndicatorSummary
} }
// 多币种多周期策略接口 // 多币种多周期策略接口
@ -77,4 +79,6 @@ type IInstanceIntervalSigStrategyContext interface {
Series(instId string, interval types.Interval, offset, count int16) (klines types.Klines) Series(instId string, interval types.Interval, offset, count int16) (klines types.Klines)
// 获取窗口类型指标 // 获取窗口类型指标
Indicator(instId string, interval types.Interval, name string, args ...any) indicator.IIndicatorSeries Indicator(instId string, interval types.Interval, name string, args ...any) indicator.IIndicatorSeries
// SummaryIndicator 获取Summary类型指标
SummaryIndicator(instId string, interval types.Interval, name string, args ...any) indicator.IIndicatorSummary
} }

1
pkg/strategy/sig_strategy_registry.go

@ -31,6 +31,7 @@ func (r *SigStrategyRegistry) Init() (err error) {
r.MustRegistStrategy(&TrendTrackV1{}) r.MustRegistStrategy(&TrendTrackV1{})
r.MustRegistStrategy(&Grid{}) r.MustRegistStrategy(&Grid{})
r.MustRegistStrategy(&BollGrid{}) r.MustRegistStrategy(&BollGrid{})
r.MustRegistStrategy(&MeanReversionV1{})
return return
} }

Loading…
Cancel
Save