103 lines
2.5 KiB
Go
103 lines
2.5 KiB
Go
package llmjob
|
||
|
||
import (
|
||
"math"
|
||
|
||
"github.com/banbox/banbot/config"
|
||
"github.com/banbox/banbot/core"
|
||
"github.com/banbox/banbot/strat"
|
||
ta "github.com/banbox/banta"
|
||
)
|
||
|
||
// COG 自定义重心振荡器指标
|
||
func COG(src *ta.Series, period int) *ta.Series {
|
||
res := src.To("_cog", period)
|
||
if res.Cached() {
|
||
return res
|
||
}
|
||
|
||
data := src.Range(0, period)
|
||
if len(data) < period {
|
||
return res.Append(math.NaN())
|
||
}
|
||
|
||
var sum1, sum2 float64
|
||
center := float64(period-1) / 2.0
|
||
|
||
for i := 0; i < period; i++ {
|
||
weight := float64(i) - center
|
||
sum1 += data[i] * weight
|
||
sum2 += weight * weight
|
||
}
|
||
|
||
if sum2 != 0 {
|
||
cogVal := -sum1 / sum2
|
||
return res.Append(cogVal)
|
||
}
|
||
return res.Append(0)
|
||
}
|
||
|
||
func J7854(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||
// 定义可调超参数
|
||
length := pol.DefInt("length", 9, core.PNorm(3, 50)) // COG计算周期
|
||
length5 := pol.DefInt("length5", 3, core.PNorm(2, 20)) // RMA平滑周期
|
||
windowsize := pol.DefInt("windowsize", 6, core.PNorm(2, 20)) // ALMA窗口周期
|
||
offset := pol.Def("offset", 0.88, core.PNorm(0.5, 0.99)) // ALMA偏移量
|
||
sigma := pol.Def("sigma", 7, core.PNorm(1, 10)) // ALMA高斯系数
|
||
|
||
return &strat.TradeStrat{
|
||
WarmupNum: length + 50, // 确保有足够的历史数据
|
||
HedgeOff: true, // 单向持仓
|
||
EachMaxLong: 1, // 最多1个多单
|
||
EachMaxShort: 0, // 禁止做空
|
||
TimeFrames: "8h",
|
||
OnBar: func(s *strat.StratJob) {
|
||
e := s.Env
|
||
|
||
// 检查数据长度是否足够
|
||
if e.Close.Len() < length {
|
||
return
|
||
}
|
||
|
||
// 计算COG指标
|
||
cog1 := COG(e.Close, length)
|
||
|
||
// 使用RMA平滑COG(对应原代码中的smooth选项,这里默认使用RMA)
|
||
cogSmoothed := ta.RMA(cog1, length5)
|
||
cog := cogSmoothed
|
||
|
||
// 计算ALMA触发线
|
||
trigger := ta.ALMA(cog, windowsize, sigma, offset)
|
||
|
||
// 获取最新值
|
||
cog1Val := cog1.Get(0)
|
||
triggerVal := trigger.Get(0)
|
||
|
||
// 检查有效数据
|
||
if math.IsNaN(cog1Val) || math.IsNaN(triggerVal) {
|
||
return
|
||
}
|
||
|
||
// 检测COG1与触发线的交叉状态,只计算一次
|
||
crossState := cog1.Cross(trigger)
|
||
|
||
// 检测COG1上穿触发线
|
||
if crossState == 1 {
|
||
// 产生买入信号
|
||
s.OpenOrder(&strat.EnterReq{
|
||
Tag: "COG_Enter",
|
||
})
|
||
}
|
||
|
||
// 可选:添加退出逻辑
|
||
// 这里可以根据需要添加退出条件,比如COG1下穿trigger线
|
||
if crossState == -1 && len(s.LongOrders) > 0 {
|
||
s.CloseOrders(&strat.ExitReq{
|
||
Tag: "COG_Exit",
|
||
Dirt: core.OdDirtLong,
|
||
})
|
||
}
|
||
},
|
||
}
|
||
}
|