145 lines
4.2 KiB
Go
145 lines
4.2 KiB
Go
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,
|
||
})
|
||
}
|
||
},
|
||
}
|
||
}
|