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

177
llmjob/4009.go Normal file
View File

@@ -0,0 +1,177 @@
package llmjob
import (
"math"
"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"
)
// Sta4009 存储每个品种的策略状态
type Sta4009 struct {
atrTrailingStop float64 // ATR跟踪止损值
position int // 当前持仓方向(1=多头,-1=空头,0=无持仓)
entryPrice float64 // 入场价格
buyTarget float64 // 多头目标价格
sellTarget float64 // 空头目标价格
}
func J4009(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调参数
keyValue := pol.Def("keyValue", 1, core.PNorm(0.1, 5))
atrPeriod := pol.DefInt("atrPeriod", 14, core.PNorm(5, 30))
useHeikinAshi := pol.DefInt("useHeikinAshi", 0, core.PNorm(0, 1)) // 0=false, 1=true
exitPercentage := pol.Def("exitPercentage", 0.002, core.PNorm(0.001, 0.01))
rsiPeriod := pol.DefInt("rsiPeriod", 14, core.PNorm(7, 30))
donchianLength := pol.DefInt("donchianLength", 20, core.PNorm(10, 50))
return &strat.TradeStrat{
WarmupNum: donchianLength + 20, // 确保有足够数据计算所有指标
HedgeOff: true, // 单向持仓模式
TimeFrames: "1d",
OnStartUp: func(s *strat.StratJob) {
// 初始化策略状态
s.More = &Sta4009{
atrTrailingStop: math.NaN(),
position: 0,
entryPrice: math.NaN(),
buyTarget: math.NaN(),
sellTarget: math.NaN(),
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
state, _ := s.More.(*Sta4009)
// 计算基础指标
atr := ta.ATR(e.High, e.Low, e.Close, atrPeriod)
lossDistance := keyValue * atr.Get(0)
rsiValue := ta.RSI(e.Close, rsiPeriod).Get(0)
// 计算价格源(普通收盘价或惠金-阿希收盘价)
var priceSource *ta.Series
if useHeikinAshi > 0 {
haOpen, haHigh, haLow, haClose := ta.HeikinAshi(e)
haCloseSeries := haOpen.Add(haHigh).Add(haLow).Add(haClose).Div(4)
priceSource = haCloseSeries
} else {
priceSource = e.Close
}
currentPrice := priceSource.Get(0)
prevPrice := priceSource.Get(1)
// 计算ATR跟踪止损
if !math.IsNaN(lossDistance) && !math.IsNaN(currentPrice) && !math.IsNaN(prevPrice) {
prevStop := state.atrTrailingStop
if math.IsNaN(prevStop) {
prevStop = 0
}
if currentPrice > prevStop && prevPrice > prevStop {
// 价格在止损线上方且前一价格也在止损线上方,止损线上移
state.atrTrailingStop = math.Max(prevStop, currentPrice-lossDistance)
} else if currentPrice < prevStop && prevPrice < prevStop {
// 价格在止损线下方且前一价格也在止损线下方,止损线下移
state.atrTrailingStop = math.Min(prevStop, currentPrice+lossDistance)
} else if currentPrice > prevStop {
// 价格上穿止损线,设置新的止损线
state.atrTrailingStop = currentPrice - lossDistance
} else {
// 价格下穿止损线,设置新的止损线
state.atrTrailingStop = currentPrice + lossDistance
}
}
// 计算持仓方向
if !math.IsNaN(prevPrice) && !math.IsNaN(state.atrTrailingStop) {
if prevPrice < state.atrTrailingStop && currentPrice > state.atrTrailingStop {
state.position = 1 // 多头信号
} else if prevPrice > state.atrTrailingStop && currentPrice < state.atrTrailingStop {
state.position = -1 // 空头信号
}
// 否则保持原有方向
}
// 计算唐奇安通道
donchianUpper := ta.Highest(e.High, donchianLength)
donchianLower := ta.Lowest(e.Low, donchianLength)
donchianBasis := donchianUpper.Add(donchianLower).Div(2).Get(0)
// 计算交叉信号
above := currentPrice > state.atrTrailingStop && prevPrice <= state.atrTrailingStop
below := currentPrice < state.atrTrailingStop && prevPrice >= state.atrTrailingStop
// 生成交易信号
buySignal := currentPrice > state.atrTrailingStop && above && rsiValue > 50 && currentPrice > donchianBasis
sellSignal := currentPrice < state.atrTrailingStop && below && rsiValue < 50 && currentPrice < donchianBasis
// 执行交易
if buySignal && s.OrderNum == 0 {
state.entryPrice = currentPrice
state.buyTarget = state.entryPrice * (1 + exitPercentage)
state.sellTarget = state.entryPrice * (1 - exitPercentage)
s.OpenOrder(&strat.EnterReq{
Tag: "Buy",
OrderType: core.OrderTypeMarket,
})
} else if sellSignal && s.OrderNum == 0 {
state.entryPrice = currentPrice
state.buyTarget = state.entryPrice * (1 + exitPercentage)
state.sellTarget = state.entryPrice * (1 - exitPercentage)
s.OpenOrder(&strat.EnterReq{
Tag: "Sell",
Short: true,
OrderType: core.OrderTypeMarket,
})
}
// 退出条件检查
if len(s.LongOrders) > 0 {
od := s.LongOrders[0]
if od.Status >= ormo.InOutStatusFullEnter {
if currentPrice >= state.buyTarget {
// 达到止盈目标
s.CloseOrders(&strat.ExitReq{
Tag: "Take Profit",
Dirt: core.OdDirtLong,
Limit: state.buyTarget,
})
} else if currentPrice <= state.sellTarget {
// 触发止损
s.CloseOrders(&strat.ExitReq{
Tag: "Stop Loss",
Dirt: core.OdDirtLong,
Limit: state.sellTarget,
})
}
}
}
if len(s.ShortOrders) > 0 {
od := s.ShortOrders[0]
if od.Status >= ormo.InOutStatusFullEnter {
if currentPrice <= state.sellTarget {
// 达到止盈目标
s.CloseOrders(&strat.ExitReq{
Tag: "Take Profit",
Dirt: core.OdDirtShort,
Limit: state.sellTarget,
})
} else if currentPrice >= state.buyTarget {
// 触发止损
s.CloseOrders(&strat.ExitReq{
Tag: "Stop Loss",
Dirt: core.OdDirtShort,
Limit: state.buyTarget,
})
}
}
}
},
}
}