package llmjob import ( "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ta "github.com/banbox/banta" "math" ) func J5115(pol *config.RunPolicyConfig) *strat.TradeStrat { // 定义可调超参数 fastPeriod := pol.DefInt("fastPeriod", 11, core.PNorm(3, 15)) maRate := pol.Def("maRate", 4.4, core.PNorm(2.0, 8.0)) atrPeriod := pol.DefInt("atrPeriod", 14, core.PNorm(7, 30)) slMultiplier := pol.Def("slMultiplier", 1.3, core.PNorm(1.0, 5.0)) // 计算长期均线周期 longPeriod := int(float64(fastPeriod) * maRate) // 确保预热足够长以覆盖所有指标 warmup := longPeriod + atrPeriod + 50 return &strat.TradeStrat{ Name: "Moving-Average-Convergence-Momentum-Cloud-Strategy", WarmupNum: warmup, HedgeOff: true, // 单向持仓 DrawDownExit: false, RunTimeFrames: []string{"8h"}, OnBar: func(s *strat.StratJob) { e := s.Env close := e.Close // 计算SMA maShort := ta.SMA(close, fastPeriod) maLong := ta.SMA(close, longPeriod) cross := maShort.Cross(maLong) // 计算ATR用于止损 atr := ta.ATR(e.High, e.Low, close, atrPeriod) atrVal := atr.Get(0) // RSI仅用于展示,不参与信号过滤 _ = ta.RSI(close, 14) // 保留调用但不用于条件判断 currentPrice := close.Get(0) if math.IsNaN(currentPrice) || math.IsNaN(atrVal) { return } // 买入信号:SMA上穿(无RSI过滤) if cross == 1 { s.OpenOrder(&strat.EnterReq{ Tag: "Buy", StopLossVal: atrVal * slMultiplier, StopLossTag: "atr_sl", }) s.CloseOrders(&strat.ExitReq{ Tag: "ExitShort", Dirt: core.OdDirtShort, }) } // 卖出信号:SMA下穿 if cross == -1 { s.OpenOrder(&strat.EnterReq{ Tag: "sell", Short: true, StopLossVal: atrVal * slMultiplier, StopLossTag: "atr_sl", }) s.CloseOrders(&strat.ExitReq{ Tag: "exitLong", Dirt: core.OdDirtLong, }) } // 可选:计算并保留其他指标用于分析或未来扩展 // bbU, bbM, bbL := ta.BBANDS(close, 20, 2, 2) // tenkan := ta.SMA(ta.HL2(e.High, e.Low), 9) // kijun := ta.SMA(ta.HL2(e.High, e.Low), 26) // senkouA := ta.SMA(ta.Add(tenkan, kijun).Div(2), 26) // senkouB := ta.SMA(ta.HL2(e.High, e.Low), 52) // momentum := close.Sub(close.Back(1)) // roc := close.Sub(close.Back(12)).Div(close.Back(12)).Mul(100) }, } }