init
This commit is contained in:
173
llmjob/3464.go
Normal file
173
llmjob/3464.go
Normal 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,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user