128 lines
3.4 KiB
Go
128 lines
3.4 KiB
Go
// 修复后的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,
|
||
})
|
||
}
|
||
},
|
||
}
|
||
}
|