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