init
This commit is contained in:
177
llmjob/4009.go
Normal file
177
llmjob/4009.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package llmjob
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
// Sta4009 存储每个品种的策略状态
|
||||
type Sta4009 struct {
|
||||
atrTrailingStop float64 // ATR跟踪止损值
|
||||
position int // 当前持仓方向(1=多头,-1=空头,0=无持仓)
|
||||
entryPrice float64 // 入场价格
|
||||
buyTarget float64 // 多头目标价格
|
||||
sellTarget float64 // 空头目标价格
|
||||
}
|
||||
|
||||
func J4009(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// 定义可调参数
|
||||
keyValue := pol.Def("keyValue", 1, core.PNorm(0.1, 5))
|
||||
atrPeriod := pol.DefInt("atrPeriod", 14, core.PNorm(5, 30))
|
||||
useHeikinAshi := pol.DefInt("useHeikinAshi", 0, core.PNorm(0, 1)) // 0=false, 1=true
|
||||
exitPercentage := pol.Def("exitPercentage", 0.002, core.PNorm(0.001, 0.01))
|
||||
rsiPeriod := pol.DefInt("rsiPeriod", 14, core.PNorm(7, 30))
|
||||
donchianLength := pol.DefInt("donchianLength", 20, core.PNorm(10, 50))
|
||||
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: donchianLength + 20, // 确保有足够数据计算所有指标
|
||||
HedgeOff: true, // 单向持仓模式
|
||||
TimeFrames: "1d",
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
// 初始化策略状态
|
||||
s.More = &Sta4009{
|
||||
atrTrailingStop: math.NaN(),
|
||||
position: 0,
|
||||
entryPrice: math.NaN(),
|
||||
buyTarget: math.NaN(),
|
||||
sellTarget: math.NaN(),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
state, _ := s.More.(*Sta4009)
|
||||
|
||||
// 计算基础指标
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, atrPeriod)
|
||||
lossDistance := keyValue * atr.Get(0)
|
||||
rsiValue := ta.RSI(e.Close, rsiPeriod).Get(0)
|
||||
|
||||
// 计算价格源(普通收盘价或惠金-阿希收盘价)
|
||||
var priceSource *ta.Series
|
||||
if useHeikinAshi > 0 {
|
||||
haOpen, haHigh, haLow, haClose := ta.HeikinAshi(e)
|
||||
haCloseSeries := haOpen.Add(haHigh).Add(haLow).Add(haClose).Div(4)
|
||||
priceSource = haCloseSeries
|
||||
} else {
|
||||
priceSource = e.Close
|
||||
}
|
||||
currentPrice := priceSource.Get(0)
|
||||
prevPrice := priceSource.Get(1)
|
||||
|
||||
// 计算ATR跟踪止损
|
||||
if !math.IsNaN(lossDistance) && !math.IsNaN(currentPrice) && !math.IsNaN(prevPrice) {
|
||||
prevStop := state.atrTrailingStop
|
||||
if math.IsNaN(prevStop) {
|
||||
prevStop = 0
|
||||
}
|
||||
|
||||
if currentPrice > prevStop && prevPrice > prevStop {
|
||||
// 价格在止损线上方且前一价格也在止损线上方,止损线上移
|
||||
state.atrTrailingStop = math.Max(prevStop, currentPrice-lossDistance)
|
||||
} else if currentPrice < prevStop && prevPrice < prevStop {
|
||||
// 价格在止损线下方且前一价格也在止损线下方,止损线下移
|
||||
state.atrTrailingStop = math.Min(prevStop, currentPrice+lossDistance)
|
||||
} else if currentPrice > prevStop {
|
||||
// 价格上穿止损线,设置新的止损线
|
||||
state.atrTrailingStop = currentPrice - lossDistance
|
||||
} else {
|
||||
// 价格下穿止损线,设置新的止损线
|
||||
state.atrTrailingStop = currentPrice + lossDistance
|
||||
}
|
||||
}
|
||||
|
||||
// 计算持仓方向
|
||||
if !math.IsNaN(prevPrice) && !math.IsNaN(state.atrTrailingStop) {
|
||||
if prevPrice < state.atrTrailingStop && currentPrice > state.atrTrailingStop {
|
||||
state.position = 1 // 多头信号
|
||||
} else if prevPrice > state.atrTrailingStop && currentPrice < state.atrTrailingStop {
|
||||
state.position = -1 // 空头信号
|
||||
}
|
||||
// 否则保持原有方向
|
||||
}
|
||||
|
||||
// 计算唐奇安通道
|
||||
donchianUpper := ta.Highest(e.High, donchianLength)
|
||||
donchianLower := ta.Lowest(e.Low, donchianLength)
|
||||
donchianBasis := donchianUpper.Add(donchianLower).Div(2).Get(0)
|
||||
|
||||
// 计算交叉信号
|
||||
above := currentPrice > state.atrTrailingStop && prevPrice <= state.atrTrailingStop
|
||||
below := currentPrice < state.atrTrailingStop && prevPrice >= state.atrTrailingStop
|
||||
|
||||
// 生成交易信号
|
||||
buySignal := currentPrice > state.atrTrailingStop && above && rsiValue > 50 && currentPrice > donchianBasis
|
||||
sellSignal := currentPrice < state.atrTrailingStop && below && rsiValue < 50 && currentPrice < donchianBasis
|
||||
|
||||
// 执行交易
|
||||
if buySignal && s.OrderNum == 0 {
|
||||
state.entryPrice = currentPrice
|
||||
state.buyTarget = state.entryPrice * (1 + exitPercentage)
|
||||
state.sellTarget = state.entryPrice * (1 - exitPercentage)
|
||||
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "Buy",
|
||||
OrderType: core.OrderTypeMarket,
|
||||
})
|
||||
} else if sellSignal && s.OrderNum == 0 {
|
||||
state.entryPrice = currentPrice
|
||||
state.buyTarget = state.entryPrice * (1 + exitPercentage)
|
||||
state.sellTarget = state.entryPrice * (1 - exitPercentage)
|
||||
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "Sell",
|
||||
Short: true,
|
||||
OrderType: core.OrderTypeMarket,
|
||||
})
|
||||
}
|
||||
|
||||
// 退出条件检查
|
||||
if len(s.LongOrders) > 0 {
|
||||
od := s.LongOrders[0]
|
||||
if od.Status >= ormo.InOutStatusFullEnter {
|
||||
if currentPrice >= state.buyTarget {
|
||||
// 达到止盈目标
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Take Profit",
|
||||
Dirt: core.OdDirtLong,
|
||||
Limit: state.buyTarget,
|
||||
})
|
||||
} else if currentPrice <= state.sellTarget {
|
||||
// 触发止损
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Stop Loss",
|
||||
Dirt: core.OdDirtLong,
|
||||
Limit: state.sellTarget,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(s.ShortOrders) > 0 {
|
||||
od := s.ShortOrders[0]
|
||||
if od.Status >= ormo.InOutStatusFullEnter {
|
||||
if currentPrice <= state.sellTarget {
|
||||
// 达到止盈目标
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Take Profit",
|
||||
Dirt: core.OdDirtShort,
|
||||
Limit: state.sellTarget,
|
||||
})
|
||||
} else if currentPrice >= state.buyTarget {
|
||||
// 触发止损
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Stop Loss",
|
||||
Dirt: core.OdDirtShort,
|
||||
Limit: state.buyTarget,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user