package llmjob import ( "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ta "github.com/banbox/banta" ) func J3939(pol *config.RunPolicyConfig) *strat.TradeStrat { // 定义可调超参数 lwstPeriod := pol.DefInt("lwst_period", 10, core.PNorm(5, 25)) lwstMultiplier := pol.Def("lwst_multiplier", 3.0, core.PNorm(1.5, 5.5)) lwstLength := pol.DefInt("lwst_length", 20, core.PNorm(10, 40)) trendLength := pol.DefInt("trend_length", 14, core.PNorm(7, 25)) trendThreshold := pol.Def("trend_threshold", 0.5, core.PNorm(0.1, 2.0)) wtChannelLength := pol.DefInt("wt_channel_length", 9, core.PNorm(5, 20)) wtAverageLength := pol.DefInt("wt_average_length", 12, core.PNorm(6, 24)) wtMaLength := pol.DefInt("wt_ma_length", 3, core.PNorm(2, 8)) wtOverbought := pol.Def("wt_overbought", 53, core.PNorm(40, 70)) wtOversold := pol.Def("wt_oversold", -53, core.PNorm(-70, -40)) // 修复:独立的超卖参数 slPercent := pol.Def("sl_percent", 2.0, core.PNorm(0.5, 5.0)) tpPercent := pol.Def("tp_percent", 4.0, core.PNorm(1.0, 10.0)) warmupNum := max(lwstPeriod*2, trendLength*2, wtChannelLength+wtAverageLength) return &strat.TradeStrat{ Name: "Multi-Indicator-Consensus", WarmupNum: warmupNum + 50, HedgeOff: true, // 单向持仓模式 EachMaxLong: 1, EachMaxShort: 1, OnBar: func(s *strat.StratJob) { e := s.Env currentPrice := e.Close.Get(0) // =================== Indicator 1: Liquidity Weighted Supertrend =================== // Volume-weighted component for dynamic sensitivity volSma := ta.SMA(e.Volume, lwstLength) volWeight := e.Volume.Div(volSma) // ATR-based bands with volume weighting atr := ta.ATR(e.High, e.Low, e.Close, lwstPeriod) hl2 := ta.HL2(e.High, e.Low) _ = hl2.Add(atr.Mul(lwstMultiplier).Mul(volWeight)) // upperBand _ = hl2.Sub(atr.Mul(lwstMultiplier).Mul(volWeight)) // lowerBand // Trend determination based on price action and previous trend // 修复:使用Series保存趋势状态 lwstTrendSeries := e.Close.To("_lwst_trend", 0) var lwstTrend float64 if e.Close.Len() > 1 { prevTrend := lwstTrendSeries.Get(1) if currentPrice > prevTrend { lwstTrend = 1 } else if currentPrice < prevTrend { lwstTrend = -1 } else { lwstTrend = prevTrend } } else { lwstTrend = 1.0 } lwstTrendSeries.Set(lwstTrend) // =================== Indicator 2: Trend Signals =================== // Dual EMA system for trend detection fastEma := ta.EMA(e.Close, trendLength) slowEma := ta.EMA(e.Close, trendLength*2) trendDiff := fastEma.Sub(slowEma).Div(slowEma).Mul(100) trendDiffVal := trendDiff.Get(0) var trendSignal float64 if trendDiffVal > trendThreshold { trendSignal = 1 } else if trendDiffVal < -trendThreshold { trendSignal = -1 } else { trendSignal = 0 } // =================== Indicator 3: Enhanced Wavetrend =================== // Calculate Wavetrend components ap := ta.HLC3(e.High, e.Low, e.Close) esa := ta.EMA(ap, wtChannelLength) d := ta.EMA(ap.Sub(esa).Abs(), wtChannelLength) ci := ap.Sub(esa).Div(d.Mul(0.015)) tci := ta.EMA(ci, wtAverageLength) // Generate main and signal lines wt1 := tci wt2 := ta.SMA(wt1, wtMaLength) // Generate Wavetrend Signal based on overbought/oversold conditions wt1Val := wt1.Get(0) wt2Val := wt2.Get(0) // 修复:使用Series保存wt_signal状态 wtSignalSeries := e.Close.To("_wt_signal", 0) var wtSignal float64 if wt1Val > wtOverbought && wt2Val > wtOverbought { wtSignal = -1 // 超买信号 } else if wt1Val < wtOversold && wt2Val < wtOversold { // 修复:使用独立的wtOversold参数 wtSignal = 1 // 超卖信号 } else { wtSignal = wtSignalSeries.Get(1) } wtSignalSeries.Set(wtSignal) // =================== Consensus Signal Generation =================== // 修复:正确计算净信号数(范围-3到3) consensusCount := 0 if lwstTrend == 1 { consensusCount++ } else if lwstTrend == -1 { consensusCount-- } if trendSignal == 1 { consensusCount++ } else if trendSignal == -1 { consensusCount-- } if wtSignal == 1 { consensusCount++ } else if wtSignal == -1 { consensusCount-- } // Generate trading signals when majority (2+ indicators) agree buySignal := consensusCount >= 2 sellSignal := consensusCount <= -2 // =================== Trade Execution =================== if buySignal && len(s.LongOrders) == 0 && len(s.ShortOrders) == 0 { // 计算止损止盈价格 slAmount := currentPrice * slPercent / 100 tpAmount := currentPrice * tpPercent / 100 s.OpenOrder(&strat.EnterReq{ Tag: "Short", Short: true, StopLossVal: slAmount, TakeProfitVal: tpAmount, }) } else if sellSignal && len(s.ShortOrders) == 0 && len(s.LongOrders) == 0 { // 计算做空止损止盈价格 slAmount := currentPrice * slPercent / 100 tpAmount := currentPrice * tpPercent / 100 s.OpenOrder(&strat.EnterReq{ Tag: "Long", Short: false, StopLossVal: slAmount, TakeProfitVal: tpAmount, }) } }, } }