Browse Source

rvi indicator

main
strange 7 months ago
parent
commit
6e8bc5a7f7
  1. 12
      README.md
  2. 2
      config/exchange.toml
  3. 10
      pkg/indicator/rvi.go
  4. 63
      pkg/strategy/mean_reversion_v1.go
  5. 1
      pkg/strategy/sig_strategy_registry.go
  6. 83
      pkg/strategy/trend_track_v1.go
  7. 1
      pkg/trade/itrade_analyzer.go

12
README.md

@ -157,3 +157,15 @@ page design:
- programmer: git repository actions, golang python js..., code examples - programmer: git repository actions, golang python js..., code examples
- trader: ai strategy coder (交易员, 交易策略, 交易信号, 交易执行) - trader: ai strategy coder (交易员, 交易策略, 交易信号, 交易执行)
- 新手学习者: 引导, 普通用户(player) 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, 运行在容器中

2
config/exchange.toml

@ -19,7 +19,7 @@ marketSubscribeLimit = 16
consumeBatch = 1024 consumeBatch = 1024
consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume
# httpProxy = "" # httpProxy = ""
# httpProxy = "http://192.168.1.5:7890" # httpProxy = "http://192.168.1.4:7890"
httpProxy = "http://10.255.183.209:7890" httpProxy = "http://10.255.183.209:7890"
# 模拟盘API交易地址如下: # 模拟盘API交易地址如下:

10
pkg/indicator/rvi.go

@ -4,7 +4,7 @@ import (
"sig-pub/pkg/types" "sig-pub/pkg/types"
) )
// RVI Relative Vigor Index // RVI Relative Vigor Index 相对能量指数
// RVI = SMA(Num, N) / SMA(Denom, N) // RVI = SMA(Num, N) / SMA(Denom, N)
// Num = (Close-Open) + 2*(Close_1-Open_1) + 2*(Close_2-Open_2) + (Close_3-Open_3) // 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) // 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 rvi = numSum / denomSum
} }
ctx.State().Set("rvi", rvi) ctx.State().Set("_rvi", rvi)
// Calculate Signal // Calculate Signal
// Signal = (RVI + 2*RVI_1 + 2*RVI_2 + RVI_3) / 6 // Signal = (RVI + 2*RVI_1 + 2*RVI_2 + RVI_3) / 6
rvi1, ok1 := ctx.State().Get("rvi", 1) rvi1, ok1 := ctx.State().Get("_rvi", 1)
rvi2, ok2 := ctx.State().Get("rvi", 2) rvi2, ok2 := ctx.State().Get("_rvi", 2)
rvi3, ok3 := ctx.State().Get("rvi", 3) rvi3, ok3 := ctx.State().Get("_rvi", 3)
var sig float64 var sig float64
if ok1 && ok2 && ok3 { if ok1 && ok2 && ok3 {

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

1
pkg/strategy/sig_strategy_registry.go

@ -28,6 +28,7 @@ func (r *SigStrategyRegistry) Init() (err error) {
r.MustRegistStrategy(&SuperTrendRSI{}) r.MustRegistStrategy(&SuperTrendRSI{})
r.MustRegistStrategy(&SuperTrend2Macd{}) r.MustRegistStrategy(&SuperTrend2Macd{})
r.MustRegistStrategy(&SuperTrendMacdRSI{}) r.MustRegistStrategy(&SuperTrendMacdRSI{})
r.MustRegistStrategy(&TrendTrackV1{})
return return
} }

83
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()
}

1
pkg/trade/itrade_analyzer.go

@ -8,6 +8,7 @@ import (
) )
// ITradeAnalyzer 建仓到平仓分析器 // ITradeAnalyzer 建仓到平仓分析器
// todo stateful 状态管理,停机和恢复
type ITradeAnalyzer interface { type ITradeAnalyzer interface {
IEntryAnalyzer IEntryAnalyzer
IExitAnalyzer IExitAnalyzer

Loading…
Cancel
Save