package trend import ( "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ta "github.com/banbox/banta" "math" ) /* https://www.forexfactory.com/thread/291622-trading-made-simple 在1d周期,大多数品种上长期较好;稳定性一般 */ func eelfranzTDI(p *config.RunPolicyConfig) *strat.TradeStrat { var rsiLen = p.DefInt("rsiLen", 13, core.PNorm(8, 25)) var rsiMaLen = p.DefInt("rsiMa", 34, core.PNorm(20, 40)) var fastLen = p.DefInt("fast", 2, core.PNorm(2, 5)) var slowLen = p.DefInt("slow", 7, core.PNorm(4, 15)) return &strat.TradeStrat{ WarmupNum: 50, OnBar: func(s *strat.StratJob) { e := s.Env rsi := ta.RSI(e.Close, rsiLen) rsiMa := ta.SMA(rsi, rsiMaLen).Get(0) stDev := StDev(rsi, rsiMaLen).Get(0) upZone := rsiMa + 1.6185*stDev dnZone := rsiMa - 1.6185*stDev // market base line marketBase := (upZone + dnZone) / 2 // rsi price line: green fast := ta.SMA(rsi, fastLen).Get(0) // trade signal line: red slow := ta.SMA(rsi, slowLen).Get(0) if len(s.LongOrders) > 0 { if fast < slow { s.CloseOrders(&strat.ExitReq{ Tag: "exitL", Dirt: core.OdDirtLong, }) } } else if fast > max(slow, marketBase) { s.OpenOrder(&strat.EnterReq{ Tag: "long", }) } if len(s.ShortOrders) > 0 { if fast > slow { s.CloseOrders(&strat.ExitReq{ Tag: "exitS", Dirt: core.OdDirtShort, }) } } else if slow > max(fast, marketBase) { s.OpenOrder(&strat.EnterReq{ Tag: "short", Short: true, }) } }, } } func StDev(obj *ta.Series, period int) *ta.Series { res := obj.To("stDev", period) if res.Cached() { return res } arr := ta.WrapFloatArr(res, period, obj.Get(0)) if len(arr) < period { return res.Append(math.NaN()) } else { var sum, ssum float64 for _, v := range arr { sum += v ssum += v * v } var lenFlt = float64(period) variance := (ssum*lenFlt - sum*sum) / (lenFlt * (lenFlt - 1)) return res.Append(math.Sqrt(variance)) } }