161 lines
5.2 KiB
Go
161 lines
5.2 KiB
Go
package llmjob
|
||
|
||
import (
|
||
"github.com/banbox/banbot/config"
|
||
"github.com/banbox/banbot/core"
|
||
"github.com/banbox/banbot/strat"
|
||
ta "github.com/banbox/banta"
|
||
)
|
||
|
||
func J3939(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||
// 定义可调超参数
|
||
lwstPeriod := pol.DefInt("lwst_period", 10, core.PNorm(5, 25))
|
||
lwstMultiplier := pol.Def("lwst_multiplier", 3.0, core.PNorm(1.5, 5.5))
|
||
lwstLength := pol.DefInt("lwst_length", 20, core.PNorm(10, 40))
|
||
trendLength := pol.DefInt("trend_length", 14, core.PNorm(7, 25))
|
||
trendThreshold := pol.Def("trend_threshold", 0.5, core.PNorm(0.1, 2.0))
|
||
wtChannelLength := pol.DefInt("wt_channel_length", 9, core.PNorm(5, 20))
|
||
wtAverageLength := pol.DefInt("wt_average_length", 12, core.PNorm(6, 24))
|
||
wtMaLength := pol.DefInt("wt_ma_length", 3, core.PNorm(2, 8))
|
||
wtOverbought := pol.Def("wt_overbought", 53, core.PNorm(40, 70))
|
||
wtOversold := pol.Def("wt_oversold", -53, core.PNorm(-70, -40)) // 修复:独立的超卖参数
|
||
slPercent := pol.Def("sl_percent", 2.0, core.PNorm(0.5, 5.0))
|
||
tpPercent := pol.Def("tp_percent", 4.0, core.PNorm(1.0, 10.0))
|
||
|
||
warmupNum := max(lwstPeriod*2, trendLength*2, wtChannelLength+wtAverageLength)
|
||
|
||
return &strat.TradeStrat{
|
||
Name: "Multi-Indicator-Consensus",
|
||
WarmupNum: warmupNum + 50,
|
||
HedgeOff: true, // 单向持仓模式
|
||
EachMaxLong: 1,
|
||
EachMaxShort: 1,
|
||
|
||
OnBar: func(s *strat.StratJob) {
|
||
e := s.Env
|
||
currentPrice := e.Close.Get(0)
|
||
|
||
// =================== Indicator 1: Liquidity Weighted Supertrend ===================
|
||
// Volume-weighted component for dynamic sensitivity
|
||
volSma := ta.SMA(e.Volume, lwstLength)
|
||
volWeight := e.Volume.Div(volSma)
|
||
|
||
// ATR-based bands with volume weighting
|
||
atr := ta.ATR(e.High, e.Low, e.Close, lwstPeriod)
|
||
hl2 := ta.HL2(e.High, e.Low)
|
||
_ = hl2.Add(atr.Mul(lwstMultiplier).Mul(volWeight)) // upperBand
|
||
_ = hl2.Sub(atr.Mul(lwstMultiplier).Mul(volWeight)) // lowerBand
|
||
|
||
// Trend determination based on price action and previous trend
|
||
// 修复:使用Series保存趋势状态
|
||
lwstTrendSeries := e.Close.To("_lwst_trend", 0)
|
||
var lwstTrend float64
|
||
if e.Close.Len() > 1 {
|
||
prevTrend := lwstTrendSeries.Get(1)
|
||
if currentPrice > prevTrend {
|
||
lwstTrend = 1
|
||
} else if currentPrice < prevTrend {
|
||
lwstTrend = -1
|
||
} else {
|
||
lwstTrend = prevTrend
|
||
}
|
||
} else {
|
||
lwstTrend = 1.0
|
||
}
|
||
lwstTrendSeries.Set(lwstTrend)
|
||
|
||
// =================== Indicator 2: Trend Signals ===================
|
||
// Dual EMA system for trend detection
|
||
fastEma := ta.EMA(e.Close, trendLength)
|
||
slowEma := ta.EMA(e.Close, trendLength*2)
|
||
trendDiff := fastEma.Sub(slowEma).Div(slowEma).Mul(100)
|
||
trendDiffVal := trendDiff.Get(0)
|
||
|
||
var trendSignal float64
|
||
if trendDiffVal > trendThreshold {
|
||
trendSignal = 1
|
||
} else if trendDiffVal < -trendThreshold {
|
||
trendSignal = -1
|
||
} else {
|
||
trendSignal = 0
|
||
}
|
||
|
||
// =================== Indicator 3: Enhanced Wavetrend ===================
|
||
// Calculate Wavetrend components
|
||
ap := ta.HLC3(e.High, e.Low, e.Close)
|
||
esa := ta.EMA(ap, wtChannelLength)
|
||
d := ta.EMA(ap.Sub(esa).Abs(), wtChannelLength)
|
||
ci := ap.Sub(esa).Div(d.Mul(0.015))
|
||
tci := ta.EMA(ci, wtAverageLength)
|
||
|
||
// Generate main and signal lines
|
||
wt1 := tci
|
||
wt2 := ta.SMA(wt1, wtMaLength)
|
||
|
||
// Generate Wavetrend Signal based on overbought/oversold conditions
|
||
wt1Val := wt1.Get(0)
|
||
wt2Val := wt2.Get(0)
|
||
|
||
// 修复:使用Series保存wt_signal状态
|
||
wtSignalSeries := e.Close.To("_wt_signal", 0)
|
||
var wtSignal float64
|
||
if wt1Val > wtOverbought && wt2Val > wtOverbought {
|
||
wtSignal = -1 // 超买信号
|
||
} else if wt1Val < wtOversold && wt2Val < wtOversold { // 修复:使用独立的wtOversold参数
|
||
wtSignal = 1 // 超卖信号
|
||
} else {
|
||
wtSignal = wtSignalSeries.Get(1)
|
||
}
|
||
wtSignalSeries.Set(wtSignal)
|
||
|
||
// =================== Consensus Signal Generation ===================
|
||
// 修复:正确计算净信号数(范围-3到3)
|
||
consensusCount := 0
|
||
if lwstTrend == 1 {
|
||
consensusCount++
|
||
} else if lwstTrend == -1 {
|
||
consensusCount--
|
||
}
|
||
if trendSignal == 1 {
|
||
consensusCount++
|
||
} else if trendSignal == -1 {
|
||
consensusCount--
|
||
}
|
||
if wtSignal == 1 {
|
||
consensusCount++
|
||
} else if wtSignal == -1 {
|
||
consensusCount--
|
||
}
|
||
|
||
// Generate trading signals when majority (2+ indicators) agree
|
||
buySignal := consensusCount >= 2
|
||
sellSignal := consensusCount <= -2
|
||
|
||
// =================== Trade Execution ===================
|
||
if buySignal && len(s.LongOrders) == 0 && len(s.ShortOrders) == 0 {
|
||
// 计算止损止盈价格
|
||
slAmount := currentPrice * slPercent / 100
|
||
tpAmount := currentPrice * tpPercent / 100
|
||
|
||
s.OpenOrder(&strat.EnterReq{
|
||
Tag: "Short",
|
||
Short: true,
|
||
StopLossVal: slAmount,
|
||
TakeProfitVal: tpAmount,
|
||
})
|
||
} else if sellSignal && len(s.ShortOrders) == 0 && len(s.LongOrders) == 0 {
|
||
// 计算做空止损止盈价格
|
||
slAmount := currentPrice * slPercent / 100
|
||
tpAmount := currentPrice * tpPercent / 100
|
||
|
||
s.OpenOrder(&strat.EnterReq{
|
||
Tag: "Long",
|
||
Short: false,
|
||
StopLossVal: slAmount,
|
||
TakeProfitVal: tpAmount,
|
||
})
|
||
}
|
||
},
|
||
}
|
||
}
|