init
This commit is contained in:
111
trend/20250225/SuperFollow.go
Normal file
111
trend/20250225/SuperFollow.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package trend
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
/*
|
||||
原始灵感:https://www.fmz.com/strategy/442547
|
||||
已改动了大部分
|
||||
|
||||
测试在4h上表现最佳;210101-241101,48个品种
|
||||
收益1919%,回撤23%,夏普5.5
|
||||
添加adx过滤,收益增加
|
||||
测试使用ATRBase显著收益下降
|
||||
添加跟踪止损收益下降
|
||||
2025/02/24添加大周期方向开单权重,15品种夏普从9.43增长到10.48;最大回撤14.7%变为12.4%
|
||||
*/
|
||||
type supFlwMore struct {
|
||||
enter *strat.EnterReq
|
||||
exitIds []int64
|
||||
}
|
||||
|
||||
func SuperFollow(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
atrLen := 14 // 默认12
|
||||
mult := p.Def("mult", 1.4, core.PNorm(0.7, 2.5))
|
||||
sRate := p.Def("sRate", 1.1, core.PNorm(0.7, 1.8))
|
||||
slAtr := p.Def("slAtr", 1.6, core.PNorm(1, 2.5))
|
||||
tpRate := p.Def("tpRate", 3, core.PNorm(1.7, 5.5))
|
||||
shortMult := -mult * sRate
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 200,
|
||||
EachMaxShort: 1,
|
||||
EachMaxLong: 1,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = 0
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", 100},
|
||||
}
|
||||
},
|
||||
//OnBar: func(s *strat.StratJob) {
|
||||
// m, _ := s.More.(*supFlwMore)
|
||||
// if m.enter != nil {
|
||||
// s.OpenOrder(m.enter)
|
||||
// m.enter = nil
|
||||
// } else if len(m.exitIds) > 0 {
|
||||
// for _, id := range m.exitIds {
|
||||
// s.CloseOrders(&strat.ExitReq{Tag: "tooLong", OrderID: id})
|
||||
// }
|
||||
// m.exitIds = nil
|
||||
// }
|
||||
//},
|
||||
//OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
// m, _ := s.More.(*supFlwMore)
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
o, c := e.Open.Get(0), e.Close.Get(0)
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, atrLen).Get(0)
|
||||
dist := (c - o) / atr
|
||||
|
||||
adx := ta.ADX(e.High, e.Low, e.Close, 30).Get(0)
|
||||
//bigDirt := s.More.(int)
|
||||
|
||||
openDirt := 0
|
||||
overRate := 0.0
|
||||
if dist < shortMult && adx < 20 {
|
||||
if len(s.ShortOrders) == 0 {
|
||||
openDirt = -1
|
||||
}
|
||||
overRate = dist / shortMult
|
||||
} else if dist > mult {
|
||||
if len(s.LongOrders) == 0 {
|
||||
openDirt = 1
|
||||
}
|
||||
overRate = dist / mult
|
||||
}
|
||||
if openDirt != 0 {
|
||||
costRate := overRate * 1.1
|
||||
//if openDirt*bigDirt < 0 {
|
||||
// costRate *= 0.5
|
||||
//}
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: strconv.Itoa(openDirt),
|
||||
Short: openDirt < 0,
|
||||
TakeProfitVal: atr * slAtr * tpRate * overRate,
|
||||
StopLossVal: atr * slAtr * overRate,
|
||||
CostRate: costRate,
|
||||
})
|
||||
} else {
|
||||
// 长期未关闭的,超过200个平仓
|
||||
odList := s.GetOrders(core.OdDirtBoth)
|
||||
for _, od := range odList {
|
||||
holdNum := e.BarCount(od.EnterAt)
|
||||
if holdNum > 200 {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "tooLong", OrderID: od.ID})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
maSml := ta.SMA(e.Close, 15)
|
||||
maBig := ta.SMA(e.Close, 70)
|
||||
s.More = maSml.Cross(maBig)
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user