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