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

249
llmjob/5129.go Normal file
View File

@@ -0,0 +1,249 @@
// 修复后的banbot完整策略代码
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"
"time"
)
type MfiStrategyState struct {
DayStart int64
DayLow float64
DayHigh float64
EntryTime int64
LongSlPrice float64
ShortSlPrice float64
LongTpPrice float64
ShortTpPrice float64
TrailStop float64
TrailStopShort float64
EntryHigh float64
EntryLow float64
}
func J5129(pol *config.RunPolicyConfig) *strat.TradeStrat {
mfiPeriod := pol.DefInt("mfiPeriod", 3, core.PNorm(2, 10))
barBodySize := pol.Def("barBodySize", 0.65, core.PNorm(0.3, 0.8))
maPeriod := pol.DefInt("maPeriod", 120, core.PNorm(20, 200))
useMaFilter := pol.Def("useMaFilter", 1.0, nil)
useShorts := pol.Def("useShorts", 1.0, nil)
slType := pol.Def("slType", 0, nil) // 0:Strategy Stop, 1:Swing, 2:ATR
swingLookback := pol.DefInt("swingLookback", 10, core.PNorm(5, 30))
swingPercInc := pol.Def("swingPercInc", 0.03, core.PNorm(0.01, 0.1))
atrLength := pol.DefInt("atrLength", 14, core.PNorm(7, 30))
atrMultiple := pol.Def("atrMultiple", 6.5, core.PNorm(2.0, 10.0))
rewardRatio := pol.Def("rewardRatio", 3.2, core.PNorm(1.5, 4.0))
useTpSl := pol.Def("useTpSl", 1.0, nil)
useTimedExit := pol.Def("useTimedExit", 0.0, nil)
useTrailingStop := pol.Def("useTrailingStop", 0.0, nil)
allowDirectPositionReverse := pol.Def("allowDirectPositionReverse", 1.0, nil)
return &strat.TradeStrat{
Name: "Money Flow Index 5 min Strategy",
Version: 1,
WarmupNum: 100,
HedgeOff: false,
EachMaxLong: 1,
EachMaxShort: 1,
RunTimeFrames: []string{"15m"},
OnStartUp: func(s *strat.StratJob) {
s.More = &MfiStrategyState{
DayStart: -1,
DayLow: math.Inf(1),
DayHigh: math.Inf(-1),
EntryTime: 0,
LongSlPrice: math.NaN(),
ShortSlPrice: math.NaN(),
LongTpPrice: math.NaN(),
ShortTpPrice: math.NaN(),
TrailStop: math.NaN(),
TrailStopShort: math.NaN(),
EntryHigh: math.NaN(),
EntryLow: math.NaN(),
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
now := e.TimeStop
c, h, l, o := e.Close.Get(0), e.High.Get(0), e.Low.Get(0), e.Open.Get(0)
if math.IsNaN(c) || math.IsNaN(h) || math.IsNaN(l) {
return
}
// 更新交易日状态
t := time.UnixMilli(now)
dayStartMs := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).UnixMilli()
m := s.More.(*MfiStrategyState)
if m.DayStart != dayStartMs {
m.DayStart = dayStartMs
m.DayLow = l
m.DayHigh = h
} else {
if l < m.DayLow {
m.DayLow = l
}
if h > m.DayHigh {
m.DayHigh = h
}
}
// 计算指标
mfi := ta.MFI(e, mfiPeriod)
smaVal := ta.SMA(e.Close, maPeriod)
maFilter := c > smaVal.Get(0)
atr := ta.ATR(e.High, e.Low, e.Close, atrLength).Get(0)
// K线实体判断 - 修复错误3:与原始策略保持一致
barSize := h - l
var barBodySizeVal float64
if c > o {
barBodySizeVal = (o - c) * -1
} else {
barBodySizeVal = (o - c)
}
shortWicks := barBodySizeVal > barSize*barBodySize
// 交易信号
prevMfi := mfi.Get(1)
buySignal := !math.IsNaN(prevMfi) && prevMfi == 100 && c > o && shortWicks && (useMaFilter == 0.0 || maFilter)
sellSignal := false
if useShorts == 1.0 {
sellSignal = !math.IsNaN(prevMfi) && prevMfi == 0 && c < o && shortWicks && (useMaFilter == 0.0 || !maFilter)
}
// 检查60分钟退出规则 - 修复错误2:添加60分钟退出规则
if useTimedExit == 1.0 && m.EntryTime > 0 {
timeSinceEntry := (now - m.EntryTime) / 60000 // 转换为分钟
if timeSinceEntry >= 60 {
// 60分钟后平仓
if len(s.LongOrders) > 0 || len(s.ShortOrders) > 0 {
s.CloseOrders(&strat.ExitReq{Dirt: core.OdDirtBoth})
m.EntryTime = 0
}
}
}
// 计算止损止盈 - 修复错误1和4:记录开仓时的止损价格
var longSl, shortSl, longTp, shortTp float64
if useTpSl == 1.0 {
switch int(slType) {
case 0: // Strategy Stop
longSl = m.DayLow * (1 - swingPercInc)
shortSl = m.DayHigh * (1 + swingPercInc)
case 1: // Swing Lo/Hi
ll := ta.Lowest(e.Low, swingLookback).Get(0) * (1 - swingPercInc)
hh := ta.Highest(e.High, swingLookback).Get(0) * (1 + swingPercInc)
longSl = ll
shortSl = hh
case 2: // ATR Stop
ohlc4 := (o + h + l + c) / 4
longSl = ohlc4 - atr*atrMultiple
shortSl = ohlc4 + atr*atrMultiple
}
longTp = c + (c-longSl)*rewardRatio
shortTp = c - (shortSl-c)*rewardRatio
}
// 更新追踪止损 - 修复错误5:添加追踪止损功能
if useTrailingStop == 1.0 {
if len(s.LongOrders) > 0 {
for _, pos := range s.LongOrders {
if pos.Status == ormo.InOutStatusFullEnter { // 多头仓位
if math.IsNaN(m.EntryHigh) || h > m.EntryHigh {
m.EntryHigh = h
}
trailOffset := pos.InitPrice - m.LongSlPrice
newTrailStop := m.EntryHigh - trailOffset
if math.IsNaN(m.TrailStop) || newTrailStop > m.TrailStop {
m.TrailStop = newTrailStop
}
}
}
}
if len(s.ShortOrders) > 0 {
for _, pos := range s.ShortOrders {
if pos.Status == ormo.InOutStatusFullEnter { // 空头仓位
if math.IsNaN(m.EntryLow) || l < m.EntryLow {
m.EntryLow = l
}
trailOffset := m.ShortSlPrice - pos.InitPrice
newTrailStop := m.EntryLow + trailOffset
if math.IsNaN(m.TrailStopShort) || newTrailStop < m.TrailStopShort {
m.TrailStopShort = newTrailStop
}
}
}
}
}
// 开仓 - 修复错误6:检查持仓数量和挂单数量
canOpenLong := len(s.LongOrders) == 0 && (len(s.ShortOrders) == 0 || (allowDirectPositionReverse == 1.0 && len(s.ShortOrders) > 0))
canOpenShort := len(s.ShortOrders) == 0 && (len(s.LongOrders) == 0 || (allowDirectPositionReverse == 1.0 && len(s.LongOrders) > 0))
if buySignal && canOpenLong {
// 记录开仓时的止损价格
m.LongSlPrice = longSl
m.LongTpPrice = longTp
m.EntryHigh = h
m.EntryTime = now
req := &strat.EnterReq{
Tag: "long",
StopLoss: longSl,
TakeProfit: longTp,
StopLossTag: "sl",
TakeProfitTag: "tp",
}
s.OpenOrder(req)
}
if sellSignal && canOpenShort {
// 记录开仓时的止损价格
m.ShortSlPrice = shortSl
m.ShortTpPrice = shortTp
m.EntryLow = l
m.EntryTime = now
req := &strat.EnterReq{
Tag: "short",
Short: true,
StopLoss: shortSl,
TakeProfit: shortTp,
StopLossTag: "sl",
TakeProfitTag: "tp",
}
s.OpenOrder(req)
}
// 更新现有订单的止损止盈
if len(s.LongOrders) > 0 && !math.IsNaN(m.LongSlPrice) {
for _, order := range s.LongOrders {
if order.Status == ormo.InOutStatusInit {
order.SetStopLoss(&ormo.ExitTrigger{Price: m.LongSlPrice, Tag: "sl"})
order.SetTakeProfit(&ormo.ExitTrigger{Price: m.LongTpPrice, Tag: "tp"})
if useTrailingStop == 1.0 && !math.IsNaN(m.TrailStop) {
order.SetStopLoss(&ormo.ExitTrigger{Price: m.TrailStop, Tag: "sl"})
}
}
}
}
if len(s.ShortOrders) > 0 && !math.IsNaN(m.ShortSlPrice) {
for _, order := range s.ShortOrders {
if order.Status == ormo.InOutStatusInit {
order.SetStopLoss(&ormo.ExitTrigger{Price: m.ShortSlPrice, Tag: "sl"})
order.SetTakeProfit(&ormo.ExitTrigger{Price: m.ShortTpPrice, Tag: "tp"})
if useTrailingStop == 1.0 && !math.IsNaN(m.TrailStopShort) {
order.SetStopLoss(&ormo.ExitTrigger{Price: m.TrailStopShort, Tag: "sl"})
}
}
}
}
},
}
}