init
This commit is contained in:
299
llmjob/656.go
Normal file
299
llmjob/656.go
Normal 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user