package llmjob import ( "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ta "github.com/banbox/banta" ) func J4994(pol *config.RunPolicyConfig) *strat.TradeStrat { // 定义可调参数 rsiLength := pol.DefInt("RSIlength", 14, core.PNorm(5, 50)) rsiTop := pol.Def("RSItop", 70.0, core.PNorm(69, 90)) rsiBottom := pol.Def("RSIbottom", 35.0, core.PNorm(20, 40)) rvolLenRatio := pol.Def("rvolLenRatio", 1.0, core.PNorm(0.5, 3.0)) rvolThreshold := pol.Def("RVOLthreshold", 1.5, core.PNorm(1.2, 3.0)) // 计算实际成交量周期 rvolLen := int(float64(rsiLength) * rvolLenRatio) return &strat.TradeStrat{ Name: "RelativeVolumeStrategy", WarmupNum: rsiLength + rvolLen + 1, HedgeOff: true, // 单向持仓模式 EachMaxLong: 1, // 最多1个多头仓位 EachMaxShort: 1, // 最多1个空头仓位 RunTimeFrames: []string{"4h"}, OnBar: func(s *strat.StratJob) { e := s.Env volume := e.Volume.Get(0) // 计算RSI指标 rsiVal := ta.RSI(e.Close, rsiLength) currentRSI := rsiVal.Get(0) // 计算相对成交量 avgVolume := ta.SMA(e.Volume, rvolLen) rvolVal := volume / avgVolume.Get(0) // 检测RSI交叉信号 rsiCrossTop := rsiVal.Cross(rsiTop) rsiCrossBottom := rsiVal.Cross(rsiBottom) // 多头条件:RSI上穿阈值且成交量放大 longCondition := rsiCrossTop == 1 && rvolVal > rvolThreshold // 空头条件:RSI下穿阈值且成交量放大 shortCondition := rsiCrossBottom == -1 && rvolVal > rvolThreshold // 平多条件:RSI回落 closeLong := currentRSI < 69 // 平空条件:RSI反弹 closeShort := currentRSI > 35 // 执行交易逻辑 hasLong := len(s.LongOrders) > 0 hasShort := len(s.ShortOrders) > 0 // 多头开仓 if longCondition && !hasLong { s.OpenOrder(&strat.EnterReq{ Tag: "Long", Short: false, }) } // 多头平仓 if closeLong && hasLong { s.CloseOrders(&strat.ExitReq{ Tag: "CloseLong", Dirt: core.OdDirtLong, }) } // 空头开仓 if shortCondition && !hasShort { s.OpenOrder(&strat.EnterReq{ Tag: "Short", Short: true, }) } // 空头平仓 if closeShort && hasShort { s.CloseOrders(&strat.ExitReq{ Tag: "CloseShort", Dirt: core.OdDirtShort, }) } }, } }