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

226
llmjob/845.go Normal file
View File

@@ -0,0 +1,226 @@
package llmjob
import (
"fmt"
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
"github.com/banbox/banexg/utils"
ta "github.com/banbox/banta"
"math"
)
/*
需要多品种综合信息,品种数不得少于30
做多:RSI超卖、RSI轻度超买跟随
做空:全市场超卖动能枯竭做空
*/
// State845 存储每个品种的RSI动态区间策略状态
type State845 struct {
position int // 当前持仓状态: 0=无持仓, 1=多头, -1=空头
overBoughtDyn float64 // 动态超买水平
overSoldDyn float64 // 动态超卖水平
rsi float64
maSub float64
atr float64
}
// RsiDynamic RSI动态区间反转策略
func J845(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调超参数
rsiPeriod := pol.DefInt("rsiPeriod", 12, core.PNorm(7, 21))
overBought := pol.Def("overBought", 76, core.PNorm(70, 90))
overSold := pol.Def("overSold", 26, core.PNorm(20, 40))
sensitivity := pol.Def("sensitivity", 2.5, core.PNorm(1.0, 5.0))
openRate, closeRate := float64(1), float64(0)
prevRsiAvg, prevRsiBig, rsiDelta := float64(0), float64(0), float64(0)
prevOverBuy, prevStamp, prevOpenRate := 0, int64(0), float64(0)
stopLongUntil := int64(0)
dayMS := int64(utils.TFToSecs("1d") * 1000)
return &strat.TradeStrat{
WarmupNum: 91, // 预热K线数量
EachMaxLong: 1, // 最多开1个多单
EachMaxShort: 1, // 最多开1个空单
RunTimeFrames: []string{"1d"},
BatchInOut: true,
OnStartUp: func(s *strat.StratJob) {
// 初始化每个品种的状态
s.More = &State845{
position: 0,
overBoughtDyn: overBought,
overSoldDyn: overSold,
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
state, _ := s.More.(*State845)
rsi := ta.RSI(e.Close, rsiPeriod)
rsiValue := rsi.Get(0)
state.rsi = rsiValue
state.atr = ta.ATR(e.High, e.Low, e.Close, 14).Get(0)
ma20 := ta.SMA(e.Close, 20).Get(0)
ma90 := ta.SMA(e.Close, 90).Get(0)
state.maSub = ma20 - ma90
// 计算动态超买超卖水平
calculateDynamicLevels(rsi, sensitivity, overBought, overSold, state)
// 生成交易信号
if state.position == 0 && openRate > 0 && e.TimeStop >= stopLongUntil { // 无持仓
if rsiValue < state.overSoldDyn {
// RSI跌破超卖水平,建立多头仓位
s.OpenOrder(&strat.EnterReq{
Tag: "long",
CostRate: openRate,
Log: true,
})
state.position = 1
}
} else if state.position == -1 { // 持有空头仓位
if rsiValue <= state.overBoughtDyn {
// RSI从超买区域回落,平掉多头仓位
s.CloseOrders(&strat.ExitReq{
Tag: "exit2",
Dirt: core.OdDirtLong,
EnterTag: "long2",
Log: true,
})
state.position = 0
}
} else if state.position == 1 { // 持有多头仓位
if rsiValue >= state.overSoldDyn {
// RSI从超卖区域回升,平掉多头仓位
s.CloseOrders(&strat.ExitReq{
Tag: "exit1",
Dirt: core.OdDirtLong,
EnterTag: "long",
Log: true,
})
state.position = 0
}
}
},
OnBatchJobs: func(jobs []*strat.StratJob) {
rsiAvg, rsiBig := float64(0), float64(0)
overBuyNum, curStamp := 0, int64(0)
var st *strat.TradeStrat
for _, s := range jobs {
state, _ := s.More.(*State845)
rsiAvg += state.rsi
if state.rsi >= 68 {
rsiBig += 1
}
if state.rsi > state.overBoughtDyn {
overBuyNum += 1
}
curStamp = s.Env.TimeStop
st = s.Strat
}
numFlt := float64(len(jobs))
rsiAvg /= numFlt
rsiBig /= numFlt
if prevRsiAvg >= 70 && rsiAvg < prevRsiAvg && prevRsiBig > 0.5 {
// 极端过热转向,平仓,禁止做多2周
openRate, closeRate = -2, 1
if prevRsiBig > 0.65 && prevOpenRate < 0 {
openRate = -3
stopLongUntil = curStamp + dayMS*14
}
} else if rsiAvg > 77 && rsiBig > 0.75 || rsiAvg > 70 && rsiBig > 0.5 && (rsiAvg-prevRsiAvg)*5 < rsiDelta {
// 严重过热,平仓一半,禁止开仓
openRate, closeRate = -1, 0.5
if curStamp < stopLongUntil {
stopLongUntil = max(stopLongUntil, curStamp+dayMS*10)
}
} else if rsiAvg > 70 && rsiBig > 0.5 {
// 中度过热
openRate, closeRate = 0.6, 0
if curStamp < stopLongUntil {
stopLongUntil = max(stopLongUntil, curStamp+dayMS*6)
}
} else if rsiAvg > 60 && rsiBig > 0.3 {
// 轻度过热
openRate, closeRate = 0.8, 0
} else {
openRate, closeRate = 1, 0
}
if closeRate > 0 {
for _, s := range jobs {
if s.OrderNum > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "cut",
Dirt: core.OdDirtLong,
ExitRate: closeRate,
Log: true,
})
}
}
}
if overBuyNum >= 2 || overBuyNum+prevOverBuy >= 3 {
// 超买跟随,仅适用于多数品种一同上涨,所以要限制数量
for _, s := range jobs {
state, _ := s.More.(*State845)
if state.rsi > state.overBoughtDyn {
// RSI突破超买水平,追涨买入
s.OpenOrder(&strat.EnterReq{
Tag: "long2",
CostRate: openRate,
Log: true,
})
state.position = -1
}
}
}
// 超买做空机制,仅对特定品种表现良好,对于动态品种表现更差
//if openRate <= -3 {
// for _, s := range jobs {
// state, _ := s.More.(*State845)
// if state.maSub < 0 || state.rsi < 76 || len(s.ShortOrders) > 0 {
// continue
// }
// // 牛市中全市场超买时做空;不可在ObBatchJobs中开单,会变差
// s.OpenOrder(&strat.EnterReq{
// Tag: "short1",
// //Short: true,
// TakeProfitVal: state.atr * 2,
// StopLossVal: state.atr * 2,
// Log: true,
// })
// }
//}
if openRate < 1 {
st.WriteOutput(fmt.Sprintf("num: %d, rate: %.3f, rsi: %.3f, rsiBig: %.3f",
len(jobs), openRate, rsiAvg, rsiBig), true)
}
if curStamp > prevStamp {
rsiDelta = rsiAvg - prevRsiAvg
prevRsiAvg = rsiAvg
prevRsiBig = rsiBig
prevStamp = curStamp
prevOpenRate = openRate
prevOverBuy = overBuyNum
}
},
}
}
// calculateDynamicLevels 计算动态超买超卖水平
func calculateDynamicLevels(rsi *ta.Series, sensitivity, overBought, overSold float64, state *State845) {
// 计算近期RSI波动率(标准差)
stdDev, _ := ta.StdDevBy(rsi, 14, 1)
rsiVolatility := stdDev.Get(0)
// 计算动态调整因子
adjustmentFactor := sensitivity * rsiVolatility / 10
// 计算动态超买超卖水平
state.overBoughtDyn = overBought + adjustmentFactor*(100-overBought)/100
state.overSoldDyn = overSold - adjustmentFactor*overSold/100
// 确保动态水平在合理范围内
state.overBoughtDyn = math.Max(70, math.Min(95, state.overBoughtDyn))
state.overSoldDyn = math.Max(5, math.Min(40, state.overSoldDyn))
}