From 6e8bc5a7f7a99c5b58da6a4dc6f2d4169817c0d1 Mon Sep 17 00:00:00 2001 From: strange Date: Sun, 8 Feb 2026 16:32:09 +0000 Subject: [PATCH] rvi indicator --- README.md | 12 ++++ config/exchange.toml | 2 +- pkg/indicator/rvi.go | 10 ++-- pkg/strategy/mean_reversion_v1.go | 63 ++++++++++++++++++++ pkg/strategy/sig_strategy_registry.go | 1 + pkg/strategy/trend_track_v1.go | 83 +++++++++++++++++++++++++++ pkg/trade/itrade_analyzer.go | 1 + 7 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 pkg/strategy/mean_reversion_v1.go create mode 100644 pkg/strategy/trend_track_v1.go diff --git a/README.md b/README.md index abde94b..b96cec8 100644 --- a/README.md +++ b/README.md @@ -157,3 +157,15 @@ page design: - programmer: git repository actions, golang python js..., code examples - trader: ai strategy coder (交易员, 交易策略, 交易信号, 交易执行) - 新手学习者: 引导, 普通用户(player) ai strategy coder + +策略构建加速: +- CICD pipeline: indicator/strategy -> git repository -> go plugin/docker image -> 入库OSS -> 回测 +- 用户系统: 注册登录, web看板参数存储, 账户管理(交易记录, 资金管理) +- websocket行情推送: 实时k线, 交易信号 +- 指标参数、策略参数组合迭代, web页面自定义参数回测 +- 交易系统: 交易执行 + +指标策略库(安全等级): +1. 系统内置 +2. go plugin 外挂, 从OSS拉取 +3. docker image, 运行在容器中 diff --git a/config/exchange.toml b/config/exchange.toml index caa8ef0..a88552b 100644 --- a/config/exchange.toml +++ b/config/exchange.toml @@ -19,7 +19,7 @@ marketSubscribeLimit = 16 consumeBatch = 1024 consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume # httpProxy = "" -# httpProxy = "http://192.168.1.5:7890" +# httpProxy = "http://192.168.1.4:7890" httpProxy = "http://10.255.183.209:7890" # 模拟盘API交易地址如下: diff --git a/pkg/indicator/rvi.go b/pkg/indicator/rvi.go index d9ccd06..95b8494 100644 --- a/pkg/indicator/rvi.go +++ b/pkg/indicator/rvi.go @@ -4,7 +4,7 @@ import ( "sig-pub/pkg/types" ) -// RVI Relative Vigor Index +// RVI Relative Vigor Index 相对能量指数 // RVI = SMA(Num, N) / SMA(Denom, N) // Num = (Close-Open) + 2*(Close_1-Open_1) + 2*(Close_2-Open_2) + (Close_3-Open_3) // Denom = (High-Low) + 2*(High_1-Low_1) + 2*(High_2-Low_2) + (High_3-Low_3) @@ -72,13 +72,13 @@ func (c *RVI) Calculate(ctx IIndicatorContext) (vector float64) { rvi = numSum / denomSum } - ctx.State().Set("rvi", rvi) + ctx.State().Set("_rvi", rvi) // Calculate Signal // Signal = (RVI + 2*RVI_1 + 2*RVI_2 + RVI_3) / 6 - rvi1, ok1 := ctx.State().Get("rvi", 1) - rvi2, ok2 := ctx.State().Get("rvi", 2) - rvi3, ok3 := ctx.State().Get("rvi", 3) + rvi1, ok1 := ctx.State().Get("_rvi", 1) + rvi2, ok2 := ctx.State().Get("_rvi", 2) + rvi3, ok3 := ctx.State().Get("_rvi", 3) var sig float64 if ok1 && ok2 && ok3 { diff --git a/pkg/strategy/mean_reversion_v1.go b/pkg/strategy/mean_reversion_v1.go new file mode 100644 index 0000000..5b58b16 --- /dev/null +++ b/pkg/strategy/mean_reversion_v1.go @@ -0,0 +1,63 @@ +package strategy + +import ( + "math" + "sig-pub/pkg/types" + "sig-pub/pkg/zlog" +) + +// MeanReversionV1 +type MeanReversionV1 struct { + IIntervalSigStrategy + rate float64 + rate2 float64 +} + +func (s *MeanReversionV1) New() ISigStrategy { + return &MeanReversionV1{} +} + +func (s *MeanReversionV1) Meta() StrategyMeta { + return StrategyMeta{ + Name: "MeanReversionV1", + Desc: "均值回归策略v1", + Input: []types.InputArg{ + {Name: "rate", Type: types.InputTypeUFloat, Desc: "上线影线与基线比例"}, + {Name: "rate2", Type: types.InputTypeUFloat, Desc: "上线影线之间比例"}, + }, + } +} + +func (s *MeanReversionV1) Init(input types.Input) (err error) { // 校验参数, 并根据参数初始化策略 + s.rate = input.Float("rate") + s.rate2 = input.Float("rate2") + return +} + +func (s *MeanReversionV1) CandlePeriods(ctx IIntervalSigStrategyContext) (iss *types.IntervalState[int16]) { + iss = types.NewIntervalState[int16]() + iss.Set(types.Interval5m, 1) + iss.Set(types.Interval15m, 2) + iss.Set(types.Interval30m, 2) + return +} + +func (s *MeanReversionV1) Update(ctx IIntervalSigStrategyContext) (side types.Side) { + // O 109744.8 H 110600 L 109507.5 C 109686.8 + k0 := ctx.Get("5m", 0) + open, close, high, low := k0.OpenF64(), k0.CloseF64(), k0.HighF64(), k0.LowF64() + base := math.Abs(open - close) + rup := (high - max(open, close)) / base + rdown := (min(open, close) - low) / base + + if k0.Ts == 1761833700000 { + zlog.Debugf("base=%.4f, rup=%.4f, rdown=%.4f", base, rup, rdown) + } + if rup > s.rate && rup/rdown > s.rate2 { + return types.SideLong + } + if rdown > s.rate && rdown/rup > s.rate2 { + return types.SideShort + } + return +} diff --git a/pkg/strategy/sig_strategy_registry.go b/pkg/strategy/sig_strategy_registry.go index 8e08c46..de1d960 100644 --- a/pkg/strategy/sig_strategy_registry.go +++ b/pkg/strategy/sig_strategy_registry.go @@ -28,6 +28,7 @@ func (r *SigStrategyRegistry) Init() (err error) { r.MustRegistStrategy(&SuperTrendRSI{}) r.MustRegistStrategy(&SuperTrend2Macd{}) r.MustRegistStrategy(&SuperTrendMacdRSI{}) + r.MustRegistStrategy(&TrendTrackV1{}) return } diff --git a/pkg/strategy/trend_track_v1.go b/pkg/strategy/trend_track_v1.go new file mode 100644 index 0000000..65898f4 --- /dev/null +++ b/pkg/strategy/trend_track_v1.go @@ -0,0 +1,83 @@ +package strategy + +import ( + "math" + "sig-pub/pkg/types" +) + +// TrendTrackV1 趋势追踪策略v1 +type TrendTrackV1 struct { +} + +func (s *TrendTrackV1) New() ISigStrategy { + return &TrendTrackV1{} +} + +func (s *TrendTrackV1) Meta() StrategyMeta { + return StrategyMeta{ + Name: "TrendTrackV1", + Desc: "趋势追踪策略v1", + Input: []types.InputArg{ + // {Name: "trend1Window", Type: types.InputTypeUInt, Desc: "SuperTrend ATR周期"}, + }, + } +} + +// Init 校验参数, 并根据参数初始化策略 +func (s *TrendTrackV1) Init(input types.Input) (err error) { + return +} + +func (s *TrendTrackV1) CandlePeriods(ctx ISingleSigStrategyContext) int16 { + return max( + ctx.Indicator("RSI", types.Input{"window": 14}).CandlePeriods(), + ctx.Indicator("ADX", types.Input{"window": 14}).CandlePeriods(), + ctx.Indicator("SuperTrend", types.Input{"window": 14, "mul": 2}).CandlePeriods(), + ) +} + +func (s *TrendTrackV1) Update(ctx ISingleSigStrategyContext) (side types.Side) { + // RSI向上强度衰减后,RSI转向下且强度增加,考虑趋势反转,发出卖出信号 + rsi := ctx.Indicator("RSI", types.Input{"window": 14}) + r0 := rsi.Get(0) + r1 := rsi.Get(1) + r2 := rsi.Get(2) + r3 := rsi.Get(3) + + d1 := r0 - r1 + d2 := r1 - r2 + d3 := r2 - r3 + + upWeakening := d3 > d2 && d2 > 0 + turnDown := d1 < 0 + downStrengthUp := math.Abs(d1) > d2 + + if upWeakening && turnDown && downStrengthUp { + return types.SideShort + } + return + + // adx := ctx.Indicator("ADX", types.Input{"window": 14}) + // superTrend := ctx.Indicator("SuperTrend", types.Input{"window": 14, "mul": 2}) + + // rsi + // adxValue := adx.Get(0) // 趋势强度 + // direction := superTrend.State("direction", 0) // 趋势方向 + + // if direction == 1 && adxValue > 25 { + // return types.SideLong + // } + + // if direction == -1 && adxValue > 25 { + // return types.SideShort + // } + + // macd := ctx.Indicator("MACD", types.Input{"fast": 12, "slow": 26, "singal": 9}) + // macdDea := macd.StateSeries("dea", 0, 2) + // macdDif := macd.StateSeries("dif", 0, 2) + // crossover := macdDif[0] > macdDea[0] && macdDif[1] < macdDea[1] // 金叉 + // crossunder := macdDif[0] < macdDea[0] && macdDif[1] > macdDea[1] // 死叉 + + // volAvg := ctx.Series(1, 20).Vol().Avg() + // vol := ctx.Get(0).VolF64() +} diff --git a/pkg/trade/itrade_analyzer.go b/pkg/trade/itrade_analyzer.go index 2e3e310..8cbce7d 100644 --- a/pkg/trade/itrade_analyzer.go +++ b/pkg/trade/itrade_analyzer.go @@ -8,6 +8,7 @@ import ( ) // ITradeAnalyzer 建仓到平仓分析器 +// todo stateful 状态管理,停机和恢复 type ITradeAnalyzer interface { IEntryAnalyzer IExitAnalyzer