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

168
llmjob/2625.go Normal file
View File

@@ -0,0 +1,168 @@
package llmjob
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/orm/ormo"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
)
// AtrRsiStrategy 存储每个品种的持仓期间最高价和最低价
type AtrRsiStrategy struct {
IntraTradeHigh float64
IntraTradeLow float64
}
func J2625(pol *config.RunPolicyConfig) *strat.TradeStrat {
atrLength := pol.DefInt("atr_length", 18, core.PNorm(10, 50))
atrMaRate := pol.Def("atr_ma_rate", 1.8, core.PNorm(1.2, 3.0))
rsiLength := pol.DefInt("rsi_length", 9, core.PNorm(7, 30))
rsiEntry := pol.DefInt("rsi_entry", 7, core.PNorm(5, 20))
atrMaNormMin := pol.Def("atr_ma_norm_min", 0.3, core.PNorm(0.1, 0.5))
atrMaNormMax := pol.Def("atr_ma_norm_max", 0.7, core.PNorm(0.5, 1.0))
trailingPercent := pol.Def("trailing_percent", 1.3, core.PNorm(0.5, 3.0))
// 计算ATR移动平均线周期
atrMaLength := int(float64(atrLength) * atrMaRate)
// 计算RSI买入和卖出阈值
rsiBuy := 50 + float64(rsiEntry)
rsiSell := 50 - float64(rsiEntry)
// 确定预热数量,取最大参数值
warmupNum := atrMaLength
if rsiLength > warmupNum {
warmupNum = rsiLength
}
return &strat.TradeStrat{
WarmupNum: warmupNum,
HedgeOff: true, // 单向持仓模式
RunTimeFrames: []string{"1h"},
OnStartUp: func(s *strat.StratJob) {
// 初始化每个品种的持仓期间最高价和最低价
s.More = &AtrRsiStrategy{
IntraTradeHigh: 0,
IntraTradeLow: 0,
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
m, _ := s.More.(*AtrRsiStrategy)
// 计算技术指标
atrValue := ta.ATR(e.High, e.Low, e.Close, atrLength)
atrMa := ta.SMA(atrValue, atrMaLength)
rsiValue := ta.RSI(e.Close, rsiLength)
// 获取当前价格
closePrice := e.Close.Get(0)
highPrice := e.High.Get(0)
lowPrice := e.Low.Get(0)
// 检查数据有效性
if math.IsNaN(closePrice) || math.IsNaN(highPrice) || math.IsNaN(lowPrice) ||
math.IsNaN(atrValue.Get(0)) || math.IsNaN(atrMa.Get(0)) || math.IsNaN(rsiValue.Get(0)) {
return
}
// 计算ATR移动平均线的标准化值
atrMaNorm := atrMa.Get(0) / closePrice * 100
// 获取当前持仓状态
longOrders := s.LongOrders
shortOrders := s.ShortOrders
hasLongPosition := len(longOrders) > 0
hasShortPosition := len(shortOrders) > 0
// 无持仓状态
if !hasLongPosition && !hasShortPosition {
// 重置持仓期间最高价和最低价
m.IntraTradeHigh = highPrice
m.IntraTradeLow = lowPrice
// 检查波动率是否在适合交易范围内
if atrMaNorm >= atrMaNormMin && atrMaNorm <= atrMaNormMax {
// 检查当前波动率是否高于平均波动率
if atrValue.Get(0) > atrMa.Get(0) {
// 检查RSI信号
if rsiValue.Get(0) > rsiBuy {
// RSI超买,做多
s.OpenOrder(&strat.EnterReq{
Tag: "B1",
OrderType: core.OrderTypeLimit,
Limit: closePrice + 5,
})
} else if rsiValue.Get(0) < rsiSell {
// RSI超卖,做空
s.OpenOrder(&strat.EnterReq{
Tag: "S1",
Short: true,
OrderType: core.OrderTypeLimit,
Limit: closePrice - 5,
})
}
}
}
} else if hasLongPosition {
// 多头持仓状态
// 更新持仓期间最高价
if highPrice > m.IntraTradeHigh {
m.IntraTradeHigh = highPrice
}
m.IntraTradeLow = lowPrice
// 计算多头追踪止损价格
longTp := m.IntraTradeHigh * (1 - trailingPercent/100)
// 获取入场价格
enterPrice := longOrders[0].InitPrice
// 设置止损和止盈
for _, od := range longOrders {
od.SetStopLoss(&ormo.ExitTrigger{
Price: longTp,
Rate: 1.0, // 全部退出
Tag: "trailing_stop",
})
od.SetTakeProfit(&ormo.ExitTrigger{
Price: enterPrice * 1.03,
Rate: 1.0, // 全部退出
Tag: "take_profit",
})
}
} else if hasShortPosition {
// 空头持仓状态
m.IntraTradeHigh = highPrice
// 更新持仓期间最低价
if lowPrice < m.IntraTradeLow {
m.IntraTradeLow = lowPrice
}
// 计算空头追踪止损价格
shortTp := m.IntraTradeLow * (1 + trailingPercent/100)
// 获取入场价格
enterPrice := shortOrders[0].InitPrice
// 设置止损和止盈
for _, od := range shortOrders {
od.SetStopLoss(&ormo.ExitTrigger{
Price: shortTp,
Rate: 1.0, // 全部退出
Tag: "trailing_stop",
})
od.SetTakeProfit(&ormo.ExitTrigger{
Price: enterPrice * 0.94,
Rate: 1.0, // 全部退出
Tag: "take_profit",
})
}
}
},
}
}