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

197
llmjob/1662.go Normal file
View File

@@ -0,0 +1,197 @@
// 修复后的完整策略代码
// 请勿修改package包名和任意函数名
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"
)
/*
因止盈止损触发价未检查是否合理的bug导致虚假净值曲线
*/
// SuperTrendData 存储每个品种的Supertrend相关数据
type SuperTrendData struct {
trend int // 当前趋势方向,1表示上升趋势,-1表示下降趋势
longTrailStop float64 // 多头仓位的移动止损价格
shortTrailStop float64 // 空头仓位的移动止损价格
up float64 // 上轨值
dn float64 // 下轨值
}
func J1662(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调参数
atrPeriod := pol.DefInt("atrPeriod", 8, core.PNorm(5, 30))
atrMultiplier := pol.Def("atrMultiplier", 2.5, core.PNorm(1.5, 5.0))
lenAtr := 20
baseAtrLen := int(math.Round(float64(lenAtr) * 4.3))
return &strat.TradeStrat{
WarmupNum: baseAtrLen, // 预热K线数量,确保有足够数据计算指标
RunTimeFrames: []string{"8h"},
OnStartUp: func(s *strat.StratJob) {
// 初始化每个品种的Supertrend数据
s.More = &SuperTrendData{
trend: 1, // 初始趋势设为上升
longTrailStop: math.NaN(),
shortTrailStop: math.NaN(),
up: math.NaN(),
dn: math.NaN(),
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
data, _ := s.More.(*SuperTrendData)
// 计算数据源 (hl2 = (high + low) / 2)
src := ta.HL2(e.High, e.Low)
// 计算ATR值
atr := ta.ATR(e.High, e.Low, e.Close, atrPeriod)
// 计算Supertrend指标
upVal := src.Get(0) - atr.Get(0)*atrMultiplier
dnVal := src.Get(0) + atr.Get(0)*atrMultiplier
atr2 := ta.ATR(e.High, e.Low, e.Close, lenAtr)
atrBase := ta.Lowest(ta.Highest(atr2, lenAtr), baseAtrLen).Get(0)
// 获取历史值
up1 := data.up
if math.IsNaN(up1) {
up1 = upVal
}
dn1 := data.dn
if math.IsNaN(dn1) {
dn1 = dnVal
}
// 更新上轨和下轨
close1 := e.Close.Get(1)
if !math.IsNaN(close1) {
if close1 > up1 {
upVal = math.Max(upVal, up1)
}
if close1 < dn1 {
dnVal = math.Min(dnVal, dn1)
}
}
// 保存当前上下轨值
data.up = upVal
data.dn = dnVal
// 判断趋势方向
prevTrend := data.trend
closePrice := e.Close.Get(0)
if !math.IsNaN(closePrice) && !math.IsNaN(dn1) && !math.IsNaN(up1) && !math.IsNaN(atrBase) {
if data.trend == -1 && closePrice > dn1 {
data.trend = 1 // 趋势由下降转为上升
} else if data.trend == 1 && closePrice < up1 {
data.trend = -1 // 趋势由上升转为下降
}
}
// 生成交易信号
buySignal := data.trend == 1 && prevTrend == -1
sellSignal := data.trend == -1 && prevTrend == 1
// 执行交易策略
if buySignal {
// 开仓多头,使用下轨作为触发价格
s.OpenOrder(&strat.EnterReq{
Tag: "Long",
Stop: dnVal,
Log: true,
})
s.CloseOrders(&strat.ExitReq{
Tag: "XShort",
Dirt: core.OdDirtShort,
Log: true,
})
}
if sellSignal {
// 开仓空头,使用上轨作为触发价格
s.OpenOrder(&strat.EnterReq{
Tag: "Short",
Short: true,
Stop: upVal,
Log: true,
})
s.CloseOrders(&strat.ExitReq{
Tag: "XLong",
Dirt: core.OdDirtLong,
Log: true,
})
}
pipValue := atrBase * 0
trailingValue := atrBase * 0
// 移动止损逻辑
if s.OrderNum > 0 {
// 多头移动止损
if len(s.LongOrders) > 0 {
// 获取持仓均价
avgPrice := s.PositionAvgPrice(core.OdDirtLong, "")
if avgPrice > 0 {
if math.IsNaN(data.longTrailStop) || closePrice > avgPrice+trailingValue {
data.longTrailStop = e.High.Get(0) - trailingValue
}
// 计算初始止损
longStopLevel := upVal - pipValue
// 使用更严格的止损(更接近当前价格的止损)
finalStop := math.Max(data.longTrailStop, longStopLevel)
if finalStop >= closePrice {
s.CloseOrders(&strat.ExitReq{
Tag: "SLLong",
Dirt: core.OdDirtLong,
})
} else {
s.SetAllStopLoss(core.OdDirtLong, &ormo.ExitTrigger{
Price: finalStop,
Tag: "sl",
})
}
}
}
// 空头移动止损
if len(s.ShortOrders) > 0 {
// 获取持仓均价
avgPrice := s.PositionAvgPrice(core.OdDirtShort, "")
if avgPrice > 0 {
if math.IsNaN(data.shortTrailStop) || closePrice < avgPrice-trailingValue {
data.shortTrailStop = e.Low.Get(0) + trailingValue
}
// 计算初始止损
shortStopLevel := dnVal + pipValue
// 使用更严格的止损(更接近当前价格的止损)
finalStop := math.Min(data.shortTrailStop, shortStopLevel)
if finalStop < closePrice {
s.CloseOrders(&strat.ExitReq{
Tag: "SLShort",
Dirt: core.OdDirtShort,
})
} else {
s.SetAllStopLoss(core.OdDirtShort, &ormo.ExitTrigger{
Price: finalStop,
Tag: "sl",
})
}
}
}
}
},
}
}