Files
banstagy/trend/MACDEMAV3.go
2026-08-24 20:53:21 +08:00

115 lines
3.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package trend
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/orm/ormo"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
)
/*
基于MACDEMAV2,修改做空部分。做空的表现和SMACrossV1很相似,导致趋同性回撤
压力位开空,止损为atr
盈利空间超过atr,设置止损为c+atr
盈利超过3倍atr,设置止损0.6
10个bar时,小亏,直接平仓
*/
func MACDEMAV3(p *config.RunPolicyConfig) *strat.TradeStrat {
emaLen := p.DefInt("emaLen", 100, core.PNormF(30, 240, 100, 0))
macdRt := p.Def("macdRt", 1, core.PNormF(0.7, 3, 1.2, 0))
lenAtr := int(p.Def("atr", 29, core.PNorm(7, 40)))
baseAtrLen := int(float64(lenAtr) * 4.3)
mc1, mc2, mc3 := int(math.Round(12*macdRt)), int(math.Round(26*macdRt)), int(math.Round(9*macdRt))
p.KeepHyperOnly("emaLen", "macdRt")
stateKey := "state"
return &strat.TradeStrat{
WarmupNum: 500,
EachMaxLong: 1,
EachMaxShort: 1,
OnBar: func(s *strat.StratJob) {
e := s.Env
c := e.Close.Get(0)
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
atrBase := ta.Lowest(ta.Highest(atr, lenAtr), baseAtrLen).Get(0)
atrVal := atr.Get(0)
atrMa := (atrBase + atrVal) / 2
ema := ta.EMA(e.Close, emaLen).Get(0)
macd, signal := ta.MACD(e.Close, mc1, mc2, mc3)
macdSub := macd.Get(0) - signal.Get(0)
hh3 := ta.Highest(e.High, 3).Get(0)
_, kdjD, _ := ta.KDJBy(e.High, e.Low, e.Close, 13, 3, 3, "sma")
dSMA := ta.SMA(kdjD, 3)
isYaLi := dSMA.Cross(80.5) == 1 // crossover
if (c-ema)*macdSub > 0 {
if macdSub < 0 {
if len(s.LongOrders) > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "closeL",
Dirt: core.OdDirtLong,
})
}
} else {
//s.OpenOrder(&strat.EnterReq{
// Tag: "long",
//})
}
}
if len(s.ShortOrders) > 0 {
low := e.Low.Get(0)
for _, od := range s.ShortOrders {
if od.Status < ormo.InOutStatusFullEnter {
continue
}
// state: 0初始止损 1平衡止损c+atr 2盈利宽止损
state := od.GetInfoFloat64(stateKey)
bestRange := od.InitPrice - low
sl := od.GetStopLoss()
if bestRange > atrMa*2 || state == 2 {
// 处于较好盈利
newSl := c + bestRange*0.35
if newSl < sl.Price {
od.SetStopLoss(&ormo.ExitTrigger{Price: newSl, Tag: "good"})
od.SetInfo(stateKey, 2)
}
continue
}
holdNum := e.BarCount(od.EnterAt)
if holdNum > 9.5 && od.Profit < 0 {
// 超过10个bar,依然亏,直接平
s.CloseOrders(&strat.ExitReq{Tag: "exit10", OrderID: od.ID})
continue
}
if bestRange > atrMa*0.6 || state == 1 {
// 处于平衡状态
newSL := c + atrMa*0.3
if newSL < sl.Price {
od.SetStopLoss(&ormo.ExitTrigger{Price: newSL, Tag: "zero"})
od.SetInfo(stateKey, 1)
}
}
}
}
if isYaLi && len(s.ShortOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "short",
Short: true,
Limit: hh3 - atrMa*0.5,
StopLoss: hh3 + atrMa,
StopBars: 7,
})
}
},
}
}