106 lines
3.3 KiB
Go
106 lines
3.3 KiB
Go
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)
|
||
}
|
||
},
|
||
}
|
||
}
|