Files
banstagy/llmjob/3827.go
2026-08-24 20:53:21 +08:00

145 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package llmjob
import (
"math"
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
)
// FibRSIGoldenCross 用于存储每个品种的斐波那契回撤水平
type FibRSIGoldenCross struct {
FibHigh float64
FibLow float64
Fib38 float64
Fib50 float64
Fib61 float64
}
func J3827(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调超参数
short_ma_length := pol.DefInt("short_ma_length", 40, core.PNorm(20, 100))
ma_ratio := pol.Def("ma_ratio", 3.8, core.PNorm(2, 6))
rsi_length := pol.DefInt("rsi_length", 14, core.PNorm(7, 21))
rsi_overbought := pol.Def("rsi_overbought", 70, core.PNorm(60, 80))
rsi_oversold := pol.Def("rsi_oversold", 30, core.PNorm(20, 40))
fib_period := pol.DefInt("fib_period", 50, core.PNorm(20, 100))
// 计算长期均线周期
long_ma_length := int(float64(short_ma_length) * ma_ratio)
// 计算预热数量,取所有指标中最大的周期
warmup_num := int(math.Max(float64(long_ma_length), float64(fib_period)))
return &strat.TradeStrat{
WarmupNum: warmup_num,
HedgeOff: true, // 单向持仓模式
EachMaxLong: 1, // 最多一个多头订单
EachMaxShort: 1, // 最多一个空头订单
TimeFrames: "8h",
OnStartUp: func(s *strat.StratJob) {
// 初始化斐波那契回撤水平
s.More = &FibRSIGoldenCross{
FibHigh: math.NaN(),
FibLow: math.NaN(),
Fib38: math.NaN(),
Fib50: math.NaN(),
Fib61: math.NaN(),
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
fib, _ := s.More.(*FibRSIGoldenCross)
// 计算技术指标
rsi := ta.RSI(e.Close, rsi_length)
short_ma := ta.SMA(e.Close, short_ma_length)
long_ma := ta.SMA(e.Close, long_ma_length)
// 获取当前价格
close_price := e.Close.Get(0)
if math.IsNaN(close_price) {
return
}
// 更新斐波那契回撤水平
highest := ta.Highest(e.Close, fib_period).Get(0)
lowest := ta.Lowest(e.Close, fib_period).Get(0)
// 如果最高价或最低价发生变化,更新斐波那契回撤水平
if !math.IsNaN(highest) && (math.IsNaN(fib.FibHigh) || highest != fib.FibHigh) {
fib.FibHigh = highest
}
if !math.IsNaN(lowest) && (math.IsNaN(fib.FibLow) || lowest != fib.FibLow) {
fib.FibLow = lowest
}
// 计算斐波那契回撤水平
if !math.IsNaN(fib.FibHigh) && !math.IsNaN(fib.FibLow) {
fib_range := fib.FibHigh - fib.FibLow
fib.Fib38 = fib.FibHigh - fib_range*0.382
fib.Fib50 = fib.FibHigh - fib_range*0.5
fib.Fib61 = fib.FibHigh - fib_range*0.618
}
// 获取当前指标值
rsi_value := rsi.Get(0)
short_ma_value := short_ma.Get(0)
long_ma_value := long_ma.Get(0)
// 检查指标是否有效
if math.IsNaN(rsi_value) || math.IsNaN(short_ma_value) || math.IsNaN(long_ma_value) ||
math.IsNaN(fib.Fib50) {
return
}
// 检测交叉信号 - 只计算一次交叉信号
cross_signal := short_ma.Cross(long_ma)
golden_cross := cross_signal == 1 // 1表示上穿
death_cross := cross_signal == -1 // -1表示下穿
// 检查当前持仓
long_position := s.Position(1, "") > 0 // 1表示多头
short_position := s.Position(-1, "") > 0 // -1表示空头
// 多头入场条件:黄金交叉且价格在50%斐波那契水平之上且RSI未超买
long_condition := golden_cross && close_price > fib.Fib50 && rsi_value < rsi_overbought
// 空头入场条件:死亡交叉且价格在50%斐波那契水平之下且RSI未超卖
short_condition := death_cross && close_price < fib.Fib50 && rsi_value > rsi_oversold
// 执行交易
if long_condition && !long_position {
s.OpenOrder(&strat.EnterReq{
Tag: "Buy",
})
}
if short_condition && !short_position {
s.OpenOrder(&strat.EnterReq{
Tag: "Sell",
Short: true,
})
}
// 多头平仓条件:RSI超买
if long_position && rsi_value > rsi_overbought {
s.CloseOrders(&strat.ExitReq{
Tag: "Buy",
Dirt: core.OdDirtLong,
})
}
// 空头平仓条件:RSI超卖
if short_position && rsi_value < rsi_oversold {
s.CloseOrders(&strat.ExitReq{
Tag: "Sell",
Dirt: core.OdDirtShort,
})
}
},
}
}