This commit is contained in:
2026-08-24 20:53:21 +08:00
commit 6e78bba16a
287 changed files with 32443 additions and 0 deletions

113
trend/20250225/MACDEMAV2.go Normal file
View File

@@ -0,0 +1,113 @@
package trend
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
"github.com/banbox/banstagy/com"
ta "github.com/banbox/banta"
"math"
)
/*
测试加入1d的大周期过滤,对做多或做空都未获得更好效果,反而略差
20210101-20250101
只做多:1776%,回撤28.8%,夏普3.93
多空双开:1913%,回撤22%,夏普4.53
做空部分单独运行波动很大,但和做多一起运行可减少做多的回撤
参考SMACross1加入海龟资金和ErDelta过滤后:
170品种下:夏普从7.97提升到8.91,显示最大回撤从18.71%下降到17.65%;收益从718%变为707%
2025/02/25 ERChg<1时保留ATR比率开单,整体*1.15
*/
type entExitMore struct {
enter *strat.EnterReq
exit *strat.ExitReq
}
func MACDEMAV2(p *config.RunPolicyConfig) *strat.TradeStrat {
// 初始HMA 25 4
maType := com.DefMaType(p, "ma", com.MaHMA) // hma 包揽优化列表头部
maLen := p.DefInt("maLen", 25, core.PNormF(7, 100, 25, 0)) // 超过40表现不佳,20多表现最好
maRate := p.Def("maRate", 4.1, core.PNorm(1.5, 7))
emaLen := p.DefInt("emaLen", 100, core.PNormF(30, 240, 100, 0))
macdRt := p.Def("macdRt", 1, core.PNormF(0.7, 3, 1.2, 0))
maBigLen := int(math.Round(float64(maLen) * maRate))
mc1, mc2, mc3 := int(math.Round(12*macdRt)), int(math.Round(26*macdRt)), int(math.Round(9*macdRt))
p.KeepHyperOnly("ma", "maLen", "maRate")
return &strat.TradeStrat{
WarmupNum: 500,
EachMaxLong: 1,
EachMaxShort: 1,
//OnStartUp: func(s *strat.StratJob) {
// s.More = &entExitMore{}
//},
//OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
// return []*strat.PairSub{
// {"_cur_", "4h", 500},
// }
//},
//OnBar: func(s *strat.StratJob) {
// m, _ := s.More.(*entExitMore)
// if m.enter != nil {
// s.OpenOrder(m.enter)
// m.enter = nil
// }
// if m.exit != nil {
// s.CloseOrders(m.exit)
// m.exit = nil
// }
//},
//OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
// m, _ := s.More.(*entExitMore)
OnBar: func(s *strat.StratJob) {
e := s.Env
c := e.Close.Get(0)
atr := ta.ATR(e.High, e.Low, e.Close, 30)
openRate := 0.015 * c / atr.Get(0)
if openRate < 1 {
openRate = math.Sqrt(openRate)
}
openRate *= 1.15
er := ta.ER(e.Close, 50)
erDelta := min(1.3, er.Get(0)/er.Get(12))
if erDelta > 1 {
openRate *= erDelta
}
ema := ta.EMA(e.Close, emaLen).Get(0)
macdCols := ta.MACD(e.Close, mc1, mc2, mc3).Cols
macdSub := macdCols[0].Get(0) - macdCols[1].Get(0)
if c > ema && macdSub > 0 && len(s.LongOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "long",
CostRate: openRate,
})
} else if len(s.LongOrders) > 0 && (macdSub < 0 && c < ema) {
s.CloseOrders(&strat.ExitReq{
Tag: "closeL",
Dirt: core.OdDirtLong,
})
}
ma1 := com.GetMA(e.Close, e.Volume, maType, maLen)
ma2 := com.GetMA(e.Close, e.Volume, maType, maBigLen)
cross := ma1.Cross(ma2)
if cross == 1 && len(s.ShortOrders) > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "closeS",
Dirt: core.OdDirtShort,
})
} else if cross == -1 && len(s.ShortOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "short",
Short: true,
CostRate: openRate,
})
}
},
}
}

91
trend/20250225/MACDX.go Normal file
View File

@@ -0,0 +1,91 @@
package trend
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
)
/*
视频号:山居听雨楼 2025/02/19
“有没有一眼就能看清楚,而且很好用的交易方法。。。。。这里分享一个只用macd的交易方法。”
【主要思想】
大周期(1d)MACD快线和慢线都处于0轴上方看多,都处于0轴下方看空;
小周期(8h)MACD:
看多时:快线上穿0轴或金叉,做多;死叉平仓。
看空时:快线下穿0轴或死叉,做空,死叉平仓。
测试小周期金叉死叉无需要求0轴上下,略好一点。
测试小周期当前参数4h盈利最佳。大周期1d最佳。
*/
func MACDX2(p *config.RunPolicyConfig) *strat.TradeStrat {
return &strat.TradeStrat{
WarmupNum: 200,
RunTimeFrames: []string{"4h"},
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
return []*strat.PairSub{
{"_cur_", "1d", 100},
}
},
OnStartUp: func(s *strat.StratJob) {
s.More = 0
},
OnBar: func(s *strat.StratJob) {
e := s.Env
dirt := s.More.(int)
macdCols := ta.MACD(e.Close, 26, 56, 20).Cols
macdX := macdCols[0].Cross(macdCols[1])
macdX2 := macdCols[0].Cross(0)
atr := ta.ATR(e.High, e.Low, e.Close, 30)
openRate := 0.015 * e.Close.Get(0) / atr.Get(0)
if openRate < 1 {
openRate = math.Sqrt(openRate)
}
openRate *= 1.3
er := ta.ER(e.Close, 50)
erDelta := min(1.3, er.Get(0)/er.Get(12))
if erDelta > 1 {
openRate *= erDelta
}
if len(s.LongOrders) > 0 {
if macdX == -1 {
s.CloseOrders(&strat.ExitReq{Tag: "closeL", Dirt: core.OdDirtLong})
}
} else if dirt > 0 && openRate > 0 {
if macdX == 1 {
s.OpenOrder(&strat.EnterReq{Tag: "long", CostRate: openRate})
} else if macdX2 == 1 {
s.OpenOrder(&strat.EnterReq{Tag: "long2", CostRate: openRate})
}
}
if len(s.ShortOrders) > 0 {
if macdX == 1 {
s.CloseOrders(&strat.ExitReq{Tag: "closeS", Dirt: core.OdDirtShort})
}
} else if dirt < 0 && openRate > 0 {
if macdX == -1 {
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, CostRate: openRate})
} else if macdX2 == -1 {
s.OpenOrder(&strat.EnterReq{Tag: "short2", Short: true, CostRate: openRate})
}
}
},
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
macdCols := ta.MACD(e.Close, 12, 26, 9).Cols
macd := macdCols[0].Get(0)
signal := macdCols[1].Get(0)
if macd > 0 && signal > 0 {
s.More = 1
} else if macd < 0 && signal < 0 {
s.More = -1
} else {
s.More = 0
}
},
}
}

View File

@@ -0,0 +1,107 @@
package trend
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
"github.com/banbox/banstagy/com"
ta "github.com/banbox/banta"
"math"
)
/*
自研均线趋势策略,多空都开。适合1h
在15m上,需把均线周期乘以4
尝试加止损、止盈、限价入场,都会导致整体收益减少
48个品种,21年到24年11月1日,累计收益1560%,最大回撤25%,夏普5.8
总收益93%来自多头
但加入空头可使夏普从4.8提高到5.8
多空的参数独立,比同一套参数,收益更稳定些
基于连续信号的商品期货交易策略
https://mp.weixin.qq.com/s/6MS94OhGYhtjBQ1Ufa5Rag
下面基于170固定品种:
使用1.5%*Close/atr作为开仓倍数,夏普从8.12提升到9.63
增加ErDelta过滤,夏普从9.63提升到11.03;最大回撤从21.8%降低到20.8%
有效信号权重测试没有明显改善:
OnStartUp: func(s *strat.StratJob) {
s.More = []float64{0.5, 0.5} // long, short
},
probs := s.More.([]float64)
if x1 == 1{
newShort := probs[1] * 0.5
s.More = []float64{1 - newShort, newShort}
sigDelta := math.Abs(1 - newShort*2)
if sigDelta > 0.2 {
openRate *= (1 - newShort) * 1.7
s.OpenOrder(&strat.EnterReq{Tag: "long", CostRate: openRate})
}
}
if x2 == -1{
newLong := probs[0] * 0.5
s.More = []float64{newLong, 1 - newLong}
sigDelta := math.Abs(1 - newLong*2)
if sigDelta > 0.2 {
openRate *= (1 - newLong) * 1.7
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, CostRate: openRate})
}
}
*/
func SMACrossV1(p *config.RunPolicyConfig) *strat.TradeStrat {
// 初始:两个SMA 做空:SMA 15 8
maLType := com.DefMaType(p, "maL", com.MaSMA)
maSType := com.DefMaType(p, "maS", com.MaSMA)
maLLen := p.DefInt("maLLen", 20, core.PNormF(7, 70, 20, 0))
maSLen := p.DefInt("maSLen", 15, core.PNormF(5, 50, 15, 0))
maLRate := p.Def("maLRate", 9, core.PNorm(2, 15))
maSRate := p.Def("maSRate", 8, core.PNorm(2, 14))
maLBig := int(math.Round(float64(maLLen) * maLRate))
maSBig := int(math.Round(float64(maSLen) * maSRate))
p.KeepHyperOnly("maSLen", "maSRate")
return &strat.TradeStrat{
WarmupNum: 200,
EachMaxShort: 1,
EachMaxLong: 1,
OnBar: func(s *strat.StratJob) {
e := s.Env
c := e.Close.Get(0)
atr := ta.ATR(e.High, e.Low, e.Close, 30)
openRate := 0.015 * c / atr.Get(0)
if openRate < 1 {
openRate = math.Sqrt(openRate)
}
er := ta.ER(e.Close, 50)
erDelta := min(1.3, er.Get(0)/er.Get(12))
if erDelta > 1 {
openRate *= erDelta
} else {
// 过滤掉ER下降的
openRate = 0
}
// 方案一:多空SMA:略微平滑,收益略小一点
// 方案二:多空VWMA:略微波动大点,收益略好一点
price := ta.AvgPrice(e)
ma1 := com.GetMA(price, e.Volume, maLType, maLLen)
ma2 := com.GetMA(price, e.Volume, maLType, maLBig)
x1 := ma1.Cross(ma2)
if x1 == 1 && openRate > 0 {
s.OpenOrder(&strat.EnterReq{Tag: "long", CostRate: openRate})
} else if x1 == -1 {
s.CloseOrders(&strat.ExitReq{Tag: "xlong", Dirt: core.OdDirtLong})
}
ma3 := com.GetMA(price, e.Volume, maSType, maSLen)
ma4 := com.GetMA(price, e.Volume, maSType, maSBig)
x2 := ma3.Cross(ma4)
if x2 == -1 && openRate > 0 {
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, CostRate: openRate})
} else if x2 == 1 {
s.CloseOrders(&strat.ExitReq{Tag: "xshort", Dirt: core.OdDirtShort})
}
},
}
}

View 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)
},
}
}