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

106 lines
3.3 KiB
Go
Raw 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 (
"fmt"
"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: 300,
RunTimeFrames: []string{"4h"},
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
return []*strat.PairSub{
{"_cur_", "1d", 150},
}
},
OnStartUp: func(s *strat.StratJob) {
s.More = 0
},
OnBar: func(s *strat.StratJob) {
e := s.Env
dirt := s.More.(int)
macd, signal := ta.MACD(e.Close, 26, 56, 20)
macdX := macd.Cross(signal)
macdX2 := macd.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, Log: true})
}
} else if dirt > 0 && openRate > 0 {
if macdX == 1 {
s.OpenOrder(&strat.EnterReq{Tag: "long", CostRate: openRate, Log: true})
} else if macdX2 == 1 {
s.OpenOrder(&strat.EnterReq{Tag: "long2", CostRate: openRate, Log: true})
}
}
if len(s.ShortOrders) > 0 {
if macdX == 1 {
s.CloseOrders(&strat.ExitReq{Tag: "closeS", Dirt: core.OdDirtShort, Log: true})
}
} else if dirt < 0 && openRate > 0 {
if macdX == -1 {
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, CostRate: openRate, Log: true})
} else if macdX2 == -1 {
s.OpenOrder(&strat.EnterReq{Tag: "short2", Short: true, CostRate: openRate, Log: true})
}
}
if !s.IsWarmUp {
line := fmt.Sprintf("%s %s %s %d %d %f %f %f %f %f macd:%f signal:%f atr:%f er:%f x1:%v x2:%v dirt:%v rate:%f",
s.Account, s.Symbol.Symbol, s.TimeFrame, len(s.LongOrders), len(s.ShortOrders),
e.Open.Get(0), e.High.Get(0), e.Low.Get(0), e.Close.Get(0), e.Volume.Get(0),
macd.Get(0), signal.Get(0), atr.Get(0), er.Get(0), macdX, macdX2, dirt, openRate)
s.Strat.WriteOutput(line, true)
}
},
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
macdS, signalS := ta.MACD(e.Close, 12, 26, 9)
macd := macdS.Get(0)
signal := signalS.Get(0)
if macd > 0 && signal > 0 {
s.More = 1
} else if macd < 0 && signal < 0 {
s.More = -1
} else {
s.More = 0
}
if !s.IsWarmUp {
line := fmt.Sprintf("%s %s %f %f %f %f %f macd:%f signal:%f",
pair, tf, e.Open.Get(0), e.High.Get(0), e.Low.Get(0), e.Close.Get(0), e.Volume.Get(0),
macd, signal)
s.Strat.WriteOutput(line, true)
}
},
}
}