package llmjob import ( "math" "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ta "github.com/banbox/banta" ) type FLIData struct { trendLine float64 iTrend float64 } func J419(pol *config.RunPolicyConfig) *strat.TradeStrat { bbPeriod := pol.DefInt("bbPeriod", 38, core.PNorm(10, 50)) bbDeviations := pol.Def("bbDeviations", 0.65, core.PNorm(0.5, 3.0)) useATRFilter := pol.Def("useATRFilter", 0.0, core.PUniform(0, 1)) // 0=false, 1=true atrPeriod := pol.DefInt("atrPeriod", 5, core.PNorm(3, 20)) return &strat.TradeStrat{ WarmupNum: bbPeriod + 5, // 确保有足够数据计算指标 HedgeOff: true, // 单向持仓模式 TimeFrames: "4h", OnStartUp: func(s *strat.StratJob) { // 初始化每个品种的数据 s.More = &FLIData{ trendLine: 0.0, iTrend: 0.0, } }, OnBar: func(s *strat.StratJob) { e := s.Env data, _ := s.More.(*FLIData) // 计算布林带 bbMiddle := ta.SMA(e.Close, bbPeriod) stdDev := ta.StdDev(e.Close, bbPeriod) bbUpper := bbMiddle.Add(stdDev.Mul(bbDeviations)) bbLower := bbMiddle.Sub(stdDev.Mul(bbDeviations)) // 获取当前价格 closePrice := e.Close.Get(0) highPrice := e.High.Get(0) lowPrice := e.Low.Get(0) // 检查数据有效性 if math.IsNaN(closePrice) || math.IsNaN(highPrice) || math.IsNaN(lowPrice) { return } // 确定布林带信号 bbSignal := 0 if closePrice > bbUpper.Get(0) { bbSignal = 1 // 看涨信号 } else if closePrice < bbLower.Get(0) { bbSignal = -1 // 看跌信号 } // 计算趋势线 prevTrendLine := data.trendLine var newTrendLine float64 if useATRFilter > 0.5 { // 启用ATR过滤器 atr := ta.ATR(e.High, e.Low, e.Close, atrPeriod) atrValue := atr.Get(0) switch bbSignal { case 1: // 看涨信号 newTrendLine = lowPrice - atrValue if newTrendLine < prevTrendLine { newTrendLine = prevTrendLine } case -1: // 看跌信号 newTrendLine = highPrice + atrValue if newTrendLine > prevTrendLine { newTrendLine = prevTrendLine } default: // 无信号 newTrendLine = prevTrendLine } } else { // 不启用ATR过滤器 switch bbSignal { case 1: // 看涨信号 newTrendLine = lowPrice if newTrendLine < prevTrendLine { newTrendLine = prevTrendLine } case -1: // 看跌信号 newTrendLine = highPrice if newTrendLine > prevTrendLine { newTrendLine = prevTrendLine } default: // 无信号 newTrendLine = prevTrendLine } } // 更新趋势线 data.trendLine = newTrendLine // 确定趋势方向 prevITrend := data.iTrend var newITrend float64 if newTrendLine > prevTrendLine { newITrend = 1 // 上升趋势 } else if newTrendLine < prevTrendLine { newITrend = -1 // 下降趋势 } else { newITrend = prevITrend // 保持原趋势 } // 生成交易信号 if prevITrend == -1 && newITrend == 1 { // 趋势从下跌转为上涨,产生买入信号 s.OpenOrder(&strat.EnterReq{ Tag: "buy", }) } else if prevITrend == 1 && newITrend == -1 { // 趋势从上涨转为下跌,产生卖出信号 s.OpenOrder(&strat.EnterReq{ Tag: "sell", Short: true, }) } // 更新趋势方向 data.iTrend = newITrend }, } }