package llmjob import ( "math" "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ta "github.com/banbox/banta" ) // fErf 实现Horner方法的误差函数 func fErf(x float64) float64 { nT := 1.0 / (1.0 + 0.5*math.Abs(x)) nAns := 1.0 - nT*math.Exp(-x*x-1.26551223+ nT*(1.00002368+nT*(0.37409196+nT*(0.09678418+ nT*(-0.18628806+nT*(0.27886807+nT*(-1.13520398+ nT*(1.48851587+nT*(-0.82215223+nT*(0.17087277)))))))))) if x >= 0 { return nAns } return -nAns } // fPSignal 计算P-Signal指标 func fPSignal(series *ta.Series, period int) *ta.Series { res := series.To("_psignal", period) if res.Cached() { return res } if series.Len() < period { return res.Append(math.NaN()) } nStDev := ta.StdDev(series, period) nSma := ta.SMA(series, period) stdevVal := nStDev.Get(0) smaVal := nSma.Get(0) var rawPSignal float64 if stdevVal > 0 { rawPSignal = fErf(smaVal / (stdevVal * math.Sqrt(2))) } else { rawPSignal = math.Copysign(1.0, smaVal) } return res.Append(rawPSignal) } func J7096(pol *config.RunPolicyConfig) *strat.TradeStrat { nPoints := pol.DefInt("nPoints", 13, core.PUniform(4, 50)) return &strat.TradeStrat{ Name: "P-Signal Strategy", WarmupNum: nPoints + 10, // 额外预留空间确保计算准确 HedgeOff: true, // 单向持仓模式 EachMaxLong: 1, // 最多一个多头仓位 TimeFrames: "8h", OnBar: func(s *strat.StratJob) { e := s.Env nIntr := nPoints - 1 // 1. 计算价格变化 (ohlc4的变化量) avgPrice := ta.AvgPrice(e) priceChange := avgPrice.Sub(avgPrice.Back(1)) // 2. 计算P-Signal原始值 rawPSignal := fPSignal(priceChange, nIntr) // 3. 计算平滑P-Signal nPSignal := ta.SMA(rawPSignal, nIntr) // 检查数据有效性 if nPSignal.Len() < 2 { return } // 4. 计算P-Signal变化方向 currentPSignal := nPSignal.Get(0) prevPSignal := nPSignal.Get(1) ndPSignal := math.Copysign(1.0, currentPSignal-prevPSignal) // 5. 生成交易信号 if currentPSignal < 0 && ndPSignal > 0 && len(s.LongOrders) == 0 { // 开多条件:nPSignal < 0 and ndPSignal > 0 s.OpenOrder(&strat.EnterReq{ Tag: "long", }) } else if currentPSignal > 0 && ndPSignal < 0 && len(s.LongOrders) > 0 { // 平多条件:nPSignal > 0 and ndPSignal < 0 s.CloseOrders(&strat.ExitReq{ Tag: "close_long", }) } }, } }