This commit is contained in:
2026-08-24 20:53:21 +08:00
commit 6e78bba16a
287 changed files with 32443 additions and 0 deletions

173
llmjob/3464.go Normal file
View File

@@ -0,0 +1,173 @@
package llmjob
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
)
type TrendlineData struct {
upper float64
lower float64
slopePh float64
slopePl float64
upos int
dnos int
prevUpos int
prevDnos int
}
func J3464(pol *config.RunPolicyConfig) *strat.TradeStrat {
length := pol.DefInt("length", 13, core.PNorm(5, 30))
mult := pol.Def("mult", 1.05, core.PNorm(0.5, 2.0))
calcMethod := pol.Def("calcMethod", 0, core.PUniform(0, 2)) // 0: Atr, 1: Stdev, 2: Linreg
_ = pol.Def("backpaint", 1.0, core.PUniform(0, 1)) == 1.0 // 使用下划线忽略未使用的变量
return &strat.TradeStrat{
WarmupNum: length * 2,
HedgeOff: true, // 单向持仓
RunTimeFrames: []string{"4h"},
OnStartUp: func(s *strat.StratJob) {
s.More = &TrendlineData{
upper: 0,
lower: 0,
slopePh: 0,
slopePl: 0,
upos: 0,
dnos: 0,
prevUpos: 0,
prevDnos: 0,
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
data, _ := s.More.(*TrendlineData)
// 获取当前价格
closePrice := e.Close.Get(0)
if math.IsNaN(closePrice) {
return
}
// 检测支点 - 实现与PineScript的pivothigh和pivotlow相似的功能
// 需要检查当前K线是否是过去length周期内的最高点,并且左右两侧都有length个K线
ph := false
pl := false
// 确保有足够的历史数据
if e.Close.Len() > length*2 {
// 检查当前K线是否是支点高
currentHigh := e.High.Get(length)
isPivotHigh := true
for i := 0; i < length; i++ {
if e.High.Get(i) >= currentHigh || e.High.Get(length*2-i) >= currentHigh {
isPivotHigh = false
break
}
}
// 检查当前K线是否是支点低
currentLow := e.Low.Get(length)
isPivotLow := true
for i := 0; i < length; i++ {
if e.Low.Get(i) <= currentLow || e.Low.Get(length*2-i) <= currentLow {
isPivotLow = false
break
}
}
ph = isPivotHigh && !math.IsNaN(currentHigh)
pl = isPivotLow && !math.IsNaN(currentLow)
}
// 计算斜率
var slope float64
method := int(calcMethod)
switch method {
case 0: // Atr
atr := ta.ATR(e.High, e.Low, e.Close, length)
slope = atr.Get(0) / float64(length) * mult
case 1: // Stdev
stdDev := ta.StdDev(e.Close, length)
slope = stdDev.Get(0) / float64(length) * mult
case 2: // Linreg
// 简化版的线性回归斜率计算
n := float64(length)
sumX := n * (n - 1) / 2
sumY := ta.SMA(e.Close, length).Get(0) * n
sumXY := 0.0
sumX2 := 0.0
for i := 0; i < length; i++ {
x := float64(i)
y := e.Close.Get(i)
if !math.IsNaN(y) {
sumXY += x * y
sumX2 += x * x
}
}
// 计算斜率
denominator := n*sumX2 - sumX*sumX
if denominator != 0 {
slope = (n*sumXY - sumX*sumY) / denominator * mult
} else {
slope = 0
}
}
// 更新趋势线斜率和值
if ph {
data.slopePh = slope
data.upper = e.High.Get(length)
} else {
data.upper = data.upper - data.slopePh
}
if pl {
data.slopePl = slope
data.lower = e.Low.Get(length)
} else {
data.lower = data.lower + data.slopePl
}
// 保存前一个状态
data.prevUpos = data.upos
data.prevDnos = data.dnos
// 检测突破状态
if ph {
data.upos = 0
} else if closePrice > data.upper-data.slopePh*float64(length) {
data.upos = 1
}
if pl {
data.dnos = 0
} else if closePrice < data.lower+data.slopePl*float64(length) {
data.dnos = 1
}
// 检测突破并生成交易信号
upBreakout := data.upos > data.prevUpos
dnBreakout := data.dnos > data.prevDnos
if upBreakout && len(s.LongOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "Up Breakout",
})
}
if dnBreakout && len(s.ShortOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "Down Breakout",
Short: true,
})
}
},
}
}