Files
banstagy/llmjob/1662.go
2026-08-24 20:53:21 +08:00

198 lines
5.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 修复后的完整策略代码
// 请勿修改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",
})
}
}
}
}
},
}
}