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

219 lines
5.8 KiB
Go
Raw 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 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"
)
// SupertrendState 存储每个品种的策略状态
type SupertrendState struct {
trend int // 趋势状态,1表示上升趋势,-1表示下降趋势
prevTrend int // 前一期的趋势状态
up float64 // 上轨
dn float64 // 下轨
tp float64 // 止盈价格
}
func J3644(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调参数
atrPeriod := pol.DefInt("atrPeriod", 5, core.PNorm(2, 20))
atrMultiplier := pol.Def("atrMultiplier", 4.7, core.PNorm(2.0, 8.0))
profitRatio := pol.Def("profitRatio", 0.382, core.PNorm(0.2, 1.0))
useSmaATR := pol.DefInt("useSmaATR", 1, core.PUniform(0, 1)) // 1=true, 0=false
srcType := pol.DefInt("srcType", 0, core.PUniform(0, 7)) // 0=hlc3, 1=high, 2=low, 3=open, 4=hl2, 5=close, 6=hlcc4, 7=ohlc4
return &strat.TradeStrat{
WarmupNum: atrPeriod * 3, // 预热期设置为ATR周期的3倍,确保有足够数据
HedgeOff: true, // 单向持仓模式
EachMaxLong: 1, // 最多开1个多单
EachMaxShort: 1, // 最多开1个空单
RunTimeFrames: []string{"8h"},
OnStartUp: func(s *strat.StratJob) {
// 初始化策略状态
s.More = &SupertrendState{
trend: 1, // 初始趋势状态为上升趋势
prevTrend: 1, // 前一期趋势状态也为上升趋势
tp: 0, // 初始止盈价格
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
state, _ := s.More.(*SupertrendState)
// 获取数据源
var src *ta.Series
switch srcType {
case 0:
src = ta.HLC3(e.High, e.Low, e.Close)
case 1:
src = e.High
case 2:
src = e.Low
case 3:
src = e.Open
case 4:
src = ta.HL2(e.High, e.Low)
case 5:
src = e.Close
case 6:
// HLCC4: (high + low + close + close) / 4
src = e.High.Add(e.Low).Add(e.Close).Add(e.Close).Div(4)
case 7:
// OHLC4: (open + high + low + close) / 4
src = e.Open.Add(e.High).Add(e.Low).Add(e.Close).Div(4)
default:
src = ta.HLC3(e.High, e.Low, e.Close)
}
// 计算ATR
var atr *ta.Series
if useSmaATR == 1 {
// 使用标准ATR计算
atr = ta.ATR(e.High, e.Low, e.Close, atrPeriod)
} else {
// 使用SMA(TR)计算ATR
trueRange := ta.TR(e.High, e.Low, e.Close)
atr = ta.SMA(trueRange, atrPeriod)
}
// 计算超级趋势通道
closePrice := e.Close.Get(0)
prevClose := e.Close.Get(1)
atrVal := atr.Get(0)
srcVal := src.Get(0)
// 计算上下轨
up := srcVal - (atrMultiplier * atrVal)
dn := srcVal + (atrMultiplier * atrVal)
// 获取前一期上下轨
prevUp := state.up
prevDn := state.dn
// 如果是第一期或前一期值无效,使用当前值
if math.IsNaN(prevUp) {
prevUp = up
}
if math.IsNaN(prevDn) {
prevDn = dn
}
// 趋势跟踪逻辑
if !math.IsNaN(prevClose) && prevClose > prevUp {
up = math.Max(up, prevUp)
}
if !math.IsNaN(prevClose) && prevClose < prevDn {
dn = math.Min(dn, prevDn)
}
// 更新趋势状态
state.prevTrend = state.trend
if state.trend == -1 && closePrice > prevDn {
state.trend = 1
} else if state.trend == 1 && closePrice < prevUp {
state.trend = -1
}
// 保存当前上下轨值
state.up = up
state.dn = dn
// 生成交易信号
buySignal := state.trend == 1 && state.prevTrend == -1
sellSignal := state.trend == -1 && state.prevTrend == 1
// 获取当前订单
longOrders := s.LongOrders
shortOrders := s.ShortOrders
// 更新多头订单的止损
if len(longOrders) > 0 {
for _, od := range longOrders {
if od.Status >= ormo.InOutStatusFullEnter {
// 保持之前的止盈价
tp := state.tp
if math.IsNaN(tp) || tp <= 0 {
tp = od.InitPrice + (od.InitPrice-up)*profitRatio
}
// 更新止损价为上轨
od.SetStopLoss(&ormo.ExitTrigger{
Price: up,
Tag: "super_trend_sl",
})
// 更新止盈价
od.SetTakeProfit(&ormo.ExitTrigger{
Price: tp,
Tag: "super_trend_tp",
})
state.tp = tp
}
}
}
// 更新空头订单的止损
if len(shortOrders) > 0 {
for _, od := range shortOrders {
if od.Status >= ormo.InOutStatusFullEnter {
// 保持之前的止盈价
tp := state.tp
if math.IsNaN(tp) || tp <= 0 {
tp = od.InitPrice - (dn-od.InitPrice)*profitRatio
}
// 更新止损价为下轨
od.SetStopLoss(&ormo.ExitTrigger{
Price: dn,
Tag: "super_trend_sl",
})
// 更新止盈价
od.SetTakeProfit(&ormo.ExitTrigger{
Price: tp,
Tag: "super_trend_tp",
})
state.tp = tp
}
}
}
// 买入信号
if buySignal && len(longOrders) == 0 {
// 计算止盈价
tp := closePrice + (closePrice-up)*profitRatio
state.tp = tp
// 开多单,使用限价单
s.OpenOrder(&strat.EnterReq{
Tag: "super_trend_long",
Short: false,
OrderType: core.OrderTypeLimit,
Limit: tp,
StopLoss: up,
StopLossTag: "super_trend_sl",
TakeProfit: tp,
TakeProfitTag: "super_trend_tp",
})
}
// 卖出信号
if sellSignal && len(shortOrders) == 0 {
// 计算止盈价
tp := closePrice - (dn-closePrice)*profitRatio
state.tp = tp
// 开空单,使用限价单
s.OpenOrder(&strat.EnterReq{
Tag: "super_trend_short",
Short: true,
OrderType: core.OrderTypeLimit,
Limit: tp,
StopLoss: dn,
StopLossTag: "super_trend_sl",
TakeProfit: tp,
TakeProfitTag: "super_trend_tp",
})
}
},
}
}