init
This commit is contained in:
113
trend/20250225/MACDEMAV2.go
Normal file
113
trend/20250225/MACDEMAV2.go
Normal 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
91
trend/20250225/MACDX.go
Normal 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
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
107
trend/20250225/SMACrossV1.go
Normal file
107
trend/20250225/SMACrossV1.go
Normal 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})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
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