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

154
llmjob/3087.go Normal file
View File

@@ -0,0 +1,154 @@
package llmjob
import (
"fmt"
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"gonum.org/v1/gonum/floats"
"math"
"sort"
)
/*
基于初始的3087进行了简化,只保留盈利较好的14-26
*/
// DCAStrategyState 存储每个品种的策略状态
type DCAStrategyState struct {
currentSO int // 当前安全订单计数器
firstPrice float64 // 初始订单价格
totalQtys float64 // 总交易数量
totalCost float64 // 累计花费
realTotQtys float64 // 总交易数量
realTotCost float64 // 累计花费
}
// calculateSafetyOrderThreshold 计算安全订单触发价格阈值
func calculateSafetyOrderThreshold(initPrice, priceDeviation, stepScale float64, currentSO int) float64 {
curSO := float64(currentSO)
if stepScale == 1.0 {
return initPrice - initPrice*priceDeviation*stepScale*curSO
}
rate := priceDeviation*math.Pow(stepScale, curSO) - priceDeviation
return initPrice - initPrice*(rate/(stepScale-1))
}
// DynamicDCA 动态DCA策略
func J3087(pol *config.RunPolicyConfig) *strat.TradeStrat {
// 定义可调参数
priceDeviation := pol.Def("priceDeviation", 0.82, core.PNorm(0.5, 3.0))
volumeScale := pol.Def("volumeScale", 1.16, core.PNorm(1.05, 1.5))
stepScale := pol.Def("stepScale", 1.06, core.PNorm(1.05, 1.3))
takeProfit := pol.Def("takeProfit", 1.15, core.PNorm(0.5, 2.5))
baseOrder := pol.Def("baseOrder", 10.0, core.PNorm(5, 20))
startLvl := pol.DefInt("startLvl", 14.0, core.PNorm(1, 20))
endLvl := pol.DefInt("endLvl", 26.0, core.PNorm(3, 30))
maxSafeOrders := pol.DefInt("maxSafeOrders", 30, core.PNorm(5, 50))
lenAtr := 20
baseAtrLen := int(math.Round(float64(lenAtr) * 4.3))
var rates []float64
// 14/15/16/17/18/19/20/21/22/23/24/25/26
return &strat.TradeStrat{
WarmupNum: 1,
HedgeOff: true, // 单向持仓
RunTimeFrames: []string{"15m"},
OnStartUp: func(s *strat.StratJob) {
// 初始化策略状态
s.More = &DCAStrategyState{}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
state, _ := s.More.(*DCAStrategyState)
// 计算OHLC4加权均价
price := (e.High.Get(0) + e.Low.Get(0) + e.Close.Get(0) + e.Open.Get(0)) / 4
closeP := e.Close.Get(0)
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
atrBase := ta.Lowest(ta.Highest(atr, lenAtr), baseAtrLen).Get(0)
openRate := 0.004 * closeP / atrBase
if openRate < 1 {
openRate = math.Sqrt(openRate)
}
openRate = max(0.7, min(1.5, openRate))
// 计算止盈水平
hasOrders := state.currentSO > 0
var avgPrice, realAvgPrice float64
if hasOrders && state.totalQtys > 0 {
avgPrice = state.totalCost / state.totalQtys
realAvgPrice = state.realTotCost / state.realTotQtys
}
takeProfitLevel := avgPrice * (1 + takeProfit/100)
// 初始建仓逻辑
if state.currentSO == 0 && price > 0 {
// 计算买入数量
qty := baseOrder / price
// 首次买入表现不佳,禁止实际买入
state.totalQtys += qty
state.totalCost += qty * closeP
state.firstPrice = price
state.currentSO = 1
}
// 计算安全订单触发价格阈值
priceRate := priceDeviation / 100
threshold := calculateSafetyOrderThreshold(state.firstPrice, priceRate, stepScale, state.currentSO)
// 动态补仓逻辑
if hasOrders && price <= threshold && state.currentSO <= maxSafeOrders {
// 计算补仓数量
orderQty := baseOrder * openRate * math.Pow(volumeScale, float64(state.currentSO-1)) / price
// endLvl用于实际下单。maxSafeOrders用于止盈价格
if state.currentSO >= startLvl && state.currentSO <= endLvl {
s.OpenOrder(&strat.EnterReq{
Tag: fmt.Sprintf("%v", state.currentSO),
Amount: orderQty,
Log: true,
})
state.realTotQtys += orderQty
state.realTotCost += orderQty * closeP
}
state.totalQtys += orderQty
state.totalCost += orderQty * closeP
state.currentSO += 1
}
// 止盈平仓逻辑
if price >= takeProfitLevel && hasOrders {
s.CloseOrders(&strat.ExitReq{
Tag: "TakeProfit",
})
if realAvgPrice > 0 {
rates = append(rates, takeProfitLevel/realAvgPrice)
}
// 重置状态变量
state.currentSO = 0
state.totalQtys = 0.0
state.totalCost = 0
state.realTotQtys = 0
state.realTotCost = 0
state.firstPrice = 0
}
},
OnShutDown: func(s *strat.StratJob) {
if len(rates) == 0 {
return
}
sort.Float64s(rates)
step := len(rates) / 7
for i := 0; i < len(rates); i += step {
block := rates[i:min(len(rates), i+step)]
avg := floats.Sum(block) / float64(len(block))
fmt.Printf("rate: %v: %v\n", i, avg)
}
rates = nil
},
}
}