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

205 lines
5.9 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 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导致表现看起来很好,不可用
*/
type State5689 struct {
entryPrice float64
hlv3 int // 保存三重均线状态
}
func J5689(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调超参数
tpPercent := pol.Def("tpPercent", 0.33, core.PNorm(0.15, 0.5)) // 止盈百分比
length := pol.DefInt("length", 18, core.PNorm(10, 50)) // 通道计算周期
lengthChop := pol.DefInt("lengthChop", 14, core.PNorm(5, 30)) // CHOP指标周期
emaPeriod := pol.DefInt("emaPeriod", 10, core.PNorm(5, 30)) // EMA平滑周期
maPeriod := pol.DefInt("maPeriod", 50, core.PNorm(30, 100)) // 主均线周期
channelRate := pol.Def("channelRate", 0.15, core.PNorm(0.1, 0.5)) // 通道倍率
exitPeriod := pol.DefInt("exitPeriod", 12, core.PNorm(5, 30)) // 退出均线周期
return &strat.TradeStrat{
WarmupNum: maPeriod, // 预热K线数量,至少需要主均线周期
RunTimeFrames: []string{"1h"},
OnStartUp: func(s *strat.StratJob) {
// 初始化每个品种的状态变量
s.More = &State5689{
entryPrice: math.NaN(),
hlv3: 0, // 初始状态为0
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
state, _ := s.More.(*State5689)
// 计算技术指标
upper := ta.Highest(e.High, length)
lower := ta.Lowest(e.Low, length)
// 计算output值:价格在通道中的百分比位置
output := e.Close.Sub(upper).Div(upper.Sub(lower)).Mul(100)
emaOutput := ta.EMA(output, emaPeriod)
// 自定义MA函数:双重WMA平滑
maFunc := func(src *ta.Series, len int) *ta.Series {
wma1 := ta.WMA(src, len/2)
wma2 := ta.WMA(src, len)
return ta.WMA(wma1.Mul(2).Sub(wma2), int(math.Round(math.Sqrt(float64(len)))))
}
// 计算主均线和通道
BBMC := maFunc(e.Close, maPeriod)
rangema := ta.EMA(ta.TR(e.High, e.Low, e.Close), maPeriod)
upperk := BBMC.Add(rangema.Mul(channelRate))
lowerk := BBMC.Sub(rangema.Mul(channelRate))
// 计算退出均线
exitHigh := ta.WMA(e.High, exitPeriod)
exitLow := ta.WMA(e.Low, exitPeriod)
// 计算RSI指标(原始代码中计算但未使用)
_ = ta.RSI(e.Close, 14)
// 计算CHOP指标(虽然不影响交易逻辑,但为了完整性实现)
atr1 := ta.ATR(e.High, e.Low, e.Close, 1)
sumAtr := ta.Sum(atr1, lengthChop)
highestChop := ta.Highest(e.High, lengthChop)
lowestChop := ta.Lowest(e.Low, lengthChop)
chopRange := highestChop.Sub(lowestChop)
// 避免除以零
chopRangeValid := chopRange.Get(0) > 0
if chopRangeValid {
_ = sumAtr.Div(chopRange).Mul(100)
} else {
_ = ta.EMA(e.Close, 1).Mul(0) // 创建全0序列
}
// 获取当前值
closePrice := e.Close.Get(0)
upperkVal := upperk.Get(0)
lowerkVal := lowerk.Get(0)
BBMCVal := BBMC.Get(0)
outputVal := output.Get(0)
emaOutputVal := emaOutput.Get(0)
exitHighVal := exitHigh.Get(0)
exitLowVal := exitLow.Get(0)
// 检查数据有效性
if math.IsNaN(closePrice) || math.IsNaN(BBMCVal) || math.IsNaN(outputVal) || math.IsNaN(emaOutputVal) {
return
}
// 判断价格位置和颜色
colorBlue := closePrice > upperkVal
colorBarFuchsia := closePrice < lowerkVal
// 更新三重均线状态
if closePrice > exitHighVal {
state.hlv3 = 1
} else if closePrice < exitLowVal {
state.hlv3 = -1
}
// 否则保持上一个状态
// 计算退出线
_ = exitHigh
if state.hlv3 < 0 {
_ = exitLow
}
// 生成交易信号
closeXBBMC := e.Close.Cross(BBMC)
longCondition := closeXBBMC == 1 && outputVal > emaOutputVal
shortCondition := closeXBBMC == -1 && outputVal < emaOutputVal
// 执行交易逻辑
if longCondition && len(s.LongOrders) == 0 {
// 记录入场价格
state.entryPrice = closePrice
// 开多单
s.OpenOrder(&strat.EnterReq{
Tag: "ENTER-LONG",
OrderType: core.OrderTypeMarket,
TakeProfit: closePrice * (1 + tpPercent),
})
}
// 为已有订单设置动态止损
if len(s.LongOrders) > 0 && !math.IsNaN(state.entryPrice) {
od := s.LongOrders[0]
if od.Status == ormo.InOutStatusFullEnter {
// 只有当color_bar为FUCHSIA时才设置止损
if colorBarFuchsia && !math.IsNaN(BBMCVal) {
// 设置BBMC作为止损价格
od.SetStopLoss(&ormo.ExitTrigger{
Price: BBMCVal,
Rate: 1.0, // 全部退出
Tag: "dynamic_stop_loss",
})
} else {
// 不设置止损
od.SetStopLoss(nil)
}
// 更新止盈
takeProfitPrice := state.entryPrice * (1 + tpPercent)
od.SetTakeProfit(&ormo.ExitTrigger{
Price: takeProfitPrice,
Rate: 1.0, // 全部退出
Tag: "take_profit",
})
}
}
// 做空部分(原始代码中被注释,这里也注释掉)
if shortCondition && len(s.ShortOrders) == 0 {
state.entryPrice = closePrice
s.OpenOrder(&strat.EnterReq{
Tag: "ENTER-SHORT",
OrderType: core.OrderTypeMarket,
Short: true,
TakeProfit: closePrice * (1 - tpPercent),
})
}
if len(s.ShortOrders) > 0 && !math.IsNaN(state.entryPrice) {
od := s.ShortOrders[0]
if od.Status == ormo.InOutStatusFullEnter {
// 只有当color_bar为BLUE时才设置止损
if colorBlue && !math.IsNaN(BBMCVal) {
// 设置BBMC作为止损价格
od.SetStopLoss(&ormo.ExitTrigger{
Price: BBMCVal,
Rate: 1.0, // 全部退出
Tag: "dynamic_stop_loss_short",
})
} else {
// 不设置止损
od.SetStopLoss(nil)
}
// 更新止盈
takeProfitPrice := state.entryPrice * (1 - tpPercent)
od.SetTakeProfit(&ormo.ExitTrigger{
Price: takeProfitPrice,
Rate: 1.0, // 全部退出
Tag: "take_profit_short",
})
}
}
},
}
}