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

299
llmjob/656.go Normal file
View File

@@ -0,0 +1,299 @@
package llmjob
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
)
func J656(pol *config.RunPolicyConfig) *strat.TradeStrat {
shortPeriod := pol.DefInt("shortPeriod", 50, core.PNorm(10, 100))
maRate := pol.Def("maRate", 2.2, core.PNorm(1.5, 4.0))
smoothMethod := pol.DefInt("smoothMethod", 1, core.PUniform(1, 4))
useCurrentRes := pol.DefInt("useCurrentRes", 1, core.PUniform(0, 1))
priceSource := pol.DefInt("priceSource", 0, core.PUniform(0, 7)) // 0=close, 1=high, 2=low, 3=open, 4=hl2, 5=hlc3, 6=hlcc4, 7=ohlc4
// 计算长期均线周期
longPeriod := int(float64(shortPeriod) * maRate)
// 确定预热数量,取长期均线周期的两倍以确保足够数据
warmupNum := longPeriod * 2
return &strat.TradeStrat{
WarmupNum: warmupNum,
HedgeOff: true, // 单向持仓模式
RunTimeFrames: []string{"1h"},
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
// 如果不使用当前时间框架,则需要添加额外的时间框架数据
if useCurrentRes == 0 {
// 使用周线作为额外时间框架,可根据需要调整
return []*strat.PairSub{{Pair: "_cur_", TimeFrame: "W", WarmupNum: warmupNum}}
}
return nil
},
OnBar: func(s *strat.StratJob) {
e := s.Env
// 获取价格数据,根据用户选择的价格源
var price *ta.Series
switch priceSource {
case 0: // close
price = e.Close
case 1: // high
price = e.High
case 2: // low
price = e.Low
case 3: // open
price = e.Open
case 4: // hl2
price = ta.HL2(e.High, e.Low)
case 5: // hlc3
price = ta.HLC3(e.High, e.Low, e.Close)
case 6: // hlcc4
// 使用基本运算实现 hlcc4 = (high + low + close + close) / 4
price = e.High.Add(e.Low).Add(e.Close).Add(e.Close).Div(4)
case 7: // ohlc4
// 使用基本运算实现 ohlc4 = (open + high + low + close) / 4
price = e.Open.Add(e.High).Add(e.Low).Add(e.Close).Div(4)
default:
price = e.Close
}
// 如果不使用当前时间框架,则从More中获取其他时间框架的数据
if useCurrentRes == 0 {
// 从More中获取其他时间框架的价格数据和移动平均线
if s.More == nil {
return
}
moreData, ok := s.More.(map[string]interface{})
if !ok {
return
}
if mtData, ok := moreData["W"]; ok {
if mtPrice, ok := mtData.(*ta.Series); ok {
price = mtPrice
}
if mtMA, ok := mtData.(map[string]interface{})["ma"]; ok {
if maData, ok := mtMA.(map[string]*ta.Series); ok {
if shortMA, ok := maData["short"]; ok {
if longMA, ok := maData["long"]; ok {
// 获取当前和前一个值
shortMA0 := shortMA.Get(0)
shortMA1 := shortMA.Get(1)
longMA0 := longMA.Get(0)
longMA1 := longMA.Get(1)
close0 := e.Close.Get(0)
close1 := e.Close.Get(1)
// 检查数据有效性
if math.IsNaN(shortMA0) || math.IsNaN(shortMA1) || math.IsNaN(longMA0) || math.IsNaN(longMA1) ||
math.IsNaN(close0) || math.IsNaN(close1) {
return
}
// 计算均线交叉信号
crossUp := shortMA1 <= longMA1 && shortMA0 > longMA0
crossDown := shortMA1 >= longMA1 && shortMA0 < longMA0
// 计算价格趋势
priceUp := close0 > close1
priceDown := close0 < close1
// 生成交易信号
buySignal := crossUp && priceUp
sellSignal := crossDown && priceDown
// 执行交易
if buySignal {
// 如果没有多头持仓,则开多单
if len(s.LongOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "Enter Long",
})
}
// 如果有空头持仓,则平空单
if len(s.ShortOrders) > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "Close Short",
Dirt: core.OdDirtShort,
})
}
} else if sellSignal {
// 如果没有空头持仓,则开空单
if len(s.ShortOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "Enter Short",
Short: true,
})
}
// 如果有多头持仓,则平多单
if len(s.LongOrders) > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "Close Long",
Dirt: core.OdDirtLong,
})
}
}
return
}
}
}
}
}
return
}
// 确保有足够的数据
if price.Len() < longPeriod {
return
}
// 根据选择的计算方法计算短期和长期移动平均线
var shortMA, longMA *ta.Series
switch smoothMethod {
case 1: // SMA
shortMA = ta.SMA(price, shortPeriod)
longMA = ta.SMA(price, longPeriod)
case 2: // EMA
shortMA = ta.EMA(price, shortPeriod)
longMA = ta.EMA(price, longPeriod)
case 3: // WMA
shortMA = ta.WMA(price, shortPeriod)
longMA = ta.WMA(price, longPeriod)
case 4: // 线性回归
shortMA = ta.LinReg(price, shortPeriod)
longMA = ta.LinReg(price, longPeriod)
default:
shortMA = ta.EMA(price, shortPeriod)
longMA = ta.EMA(price, longPeriod)
}
// 获取当前和前一个值
shortMA0 := shortMA.Get(0)
shortMA1 := shortMA.Get(1)
longMA0 := longMA.Get(0)
longMA1 := longMA.Get(1)
close0 := e.Close.Get(0)
close1 := e.Close.Get(1)
// 检查数据有效性
if math.IsNaN(shortMA0) || math.IsNaN(shortMA1) || math.IsNaN(longMA0) || math.IsNaN(longMA1) ||
math.IsNaN(close0) || math.IsNaN(close1) {
return
}
// 计算均线交叉信号
crossUp := shortMA1 <= longMA1 && shortMA0 > longMA0
crossDown := shortMA1 >= longMA1 && shortMA0 < longMA0
// 计算价格趋势
priceUp := close0 > close1
priceDown := close0 < close1
// 生成交易信号
buySignal := crossUp && priceUp
sellSignal := crossDown && priceDown
// 执行交易
if buySignal {
// 如果没有多头持仓,则开多单
if len(s.LongOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "Enter Long",
})
}
// 如果有空头持仓,则平空单
if len(s.ShortOrders) > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "Close Short",
Dirt: core.OdDirtShort,
})
}
} else if sellSignal {
// 如果没有空头持仓,则开空单
if len(s.ShortOrders) == 0 {
s.OpenOrder(&strat.EnterReq{
Tag: "Enter Short",
Short: true,
})
}
// 如果有多头持仓,则平多单
if len(s.LongOrders) > 0 {
s.CloseOrders(&strat.ExitReq{
Tag: "Close Long",
Dirt: core.OdDirtLong,
})
}
}
},
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
// 处理其他时间框架的数据
if useCurrentRes == 0 && tf == "W" {
// 根据用户选择的价格源获取价格数据
var price *ta.Series
switch priceSource {
case 0: // close
price = e.Close
case 1: // high
price = e.High
case 2: // low
price = e.Low
case 3: // open
price = e.Open
case 4: // hl2
price = ta.HL2(e.High, e.Low)
case 5: // hlc3
price = ta.HLC3(e.High, e.Low, e.Close)
case 6: // hlcc4
// 使用基本运算实现 hlcc4 = (high + low + close + close) / 4
price = e.High.Add(e.Low).Add(e.Close).Add(e.Close).Div(4)
case 7: // ohlc4
// 使用基本运算实现 ohlc4 = (open + high + low + close) / 4
price = e.Open.Add(e.High).Add(e.Low).Add(e.Close).Div(4)
default:
price = e.Close
}
// 计算移动平均线
var shortMA, longMA *ta.Series
switch smoothMethod {
case 1: // SMA
shortMA = ta.SMA(price, shortPeriod)
longMA = ta.SMA(price, longPeriod)
case 2: // EMA
shortMA = ta.EMA(price, shortPeriod)
longMA = ta.EMA(price, longPeriod)
case 3: // WMA
shortMA = ta.WMA(price, shortPeriod)
longMA = ta.WMA(price, longPeriod)
case 4: // 线性回归
shortMA = ta.LinReg(price, shortPeriod)
longMA = ta.LinReg(price, longPeriod)
default:
shortMA = ta.EMA(price, shortPeriod)
longMA = ta.EMA(price, longPeriod)
}
// 存储计算结果到s.More中
if s.More == nil {
s.More = make(map[string]interface{})
}
moreData, ok := s.More.(map[string]interface{})
if !ok {
s.More = make(map[string]interface{})
moreData = s.More.(map[string]interface{})
}
moreData["W"] = map[string]interface{}{
"price": price,
"ma": map[string]*ta.Series{
"short": shortMA,
"long": longMA,
},
}
}
},
}
}