// 修复后的banbot完整策略代码 package llmjob import ( "math" "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/strat" ) type DDLState struct { lastbull float64 // 最后一个涨停价(连续上涨时的最高点) lastbear float64 // 最后一个跌停价(连续下跌时的最低点) lot float64 // 计算后的开仓数量 } func J3137(pol *config.RunPolicyConfig) *strat.TradeStrat { // 定义可调超参数 signalshort := pol.Def("signalshort", 5.1, core.PNorm(1.0, 10.0)) signallong := pol.Def("signallong", -5.1, core.PNorm(-10.0, -1.0)) capital := pol.Def("capital", 145.0, core.PNorm(10.0, 200.0)) needlong := pol.Def("needlong", 1.0, core.PNorm(0.0, 1.0)) needshort := pol.Def("needshort", 1.0, core.PNorm(0.0, 1.0)) return &strat.TradeStrat{ WarmupNum: 2, // 至少需要2个K线数据才能计算bull和bear HedgeOff: false, // 允许双向持仓 RunTimeFrames: []string{"15m"}, OnStartUp: func(s *strat.StratJob) { // 初始化每个品种的状态 s.More = &DDLState{ lastbull: math.NaN(), lastbear: math.NaN(), lot: 0.0, } }, OnBar: func(s *strat.StratJob) { e := s.Env state, _ := s.More.(*DDLState) // 获取当前和前一个K线的价格 closePrice := e.Close.Get(0) prevClose := e.Close.Get(1) openPrice := e.Open.Get(0) // 计算capital比例,避免重复计算 capitalRate := capital / 100 // 如果数据不足,返回 if math.IsNaN(closePrice) || math.IsNaN(prevClose) { return } // 计算价格波动方向 bull := closePrice > prevClose bear := closePrice < prevClose // 更新最后一个涨停价和跌停价 if bull { state.lastbull = closePrice } if bear { state.lastbear = closePrice } // 如果还没有初始化lastbull和lastbear,返回 if math.IsNaN(state.lastbull) || math.IsNaN(state.lastbear) { return } // 计算价格变化比例 ddl := ((closePrice / state.lastbull) - 1) * 100 dds := ((closePrice / state.lastbear) - 1) * 100 // 生成交易信号 up := ddl < signallong dn := dds > signalshort // 计算开仓数量(如果没有持仓) if s.OrderNum == 0 { // 修复:使用策略方法获取权益计算仓位 stakeAmount := s.Strat.GetStakeAmount(s) state.lot = stakeAmount / closePrice * capitalRate } // truetime条件,与原始策略保持一致 truetime := true // 执行交易 if up && needlong > 0.5 && truetime { // 修复:使用计算好的lot值作为开仓数量 s.OpenOrder(&strat.EnterReq{ Tag: "Long", Short: false, Amount: state.lot, }) } if dn && needshort > 0.5 && truetime { // 修复:使用计算好的lot值作为开仓数量 s.OpenOrder(&strat.EnterReq{ Tag: "Short", Short: true, Amount: state.lot, }) } // 平仓条件:开多仓后价格上涨就平多仓,开空仓后价格下跌就平空仓 if len(s.LongOrders) > 0 && closePrice > openPrice { // 修复:使用CloseOrders进行平仓 s.CloseOrders(&strat.ExitReq{ Tag: "CloseLong", Dirt: core.OdDirtLong, }) } if len(s.ShortOrders) > 0 && closePrice < openPrice { // 修复:使用CloseOrders进行平仓 s.CloseOrders(&strat.ExitReq{ Tag: "CloseShort", Dirt: core.OdDirtShort, }) } }, } }