169 lines
4.6 KiB
Go
169 lines
4.6 KiB
Go
package llmjob
|
||
|
||
import (
|
||
"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"
|
||
"math"
|
||
)
|
||
|
||
// AtrRsiStrategy 存储每个品种的持仓期间最高价和最低价
|
||
type AtrRsiStrategy struct {
|
||
IntraTradeHigh float64
|
||
IntraTradeLow float64
|
||
}
|
||
|
||
func J2625(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||
atrLength := pol.DefInt("atr_length", 18, core.PNorm(10, 50))
|
||
atrMaRate := pol.Def("atr_ma_rate", 1.8, core.PNorm(1.2, 3.0))
|
||
rsiLength := pol.DefInt("rsi_length", 9, core.PNorm(7, 30))
|
||
rsiEntry := pol.DefInt("rsi_entry", 7, core.PNorm(5, 20))
|
||
atrMaNormMin := pol.Def("atr_ma_norm_min", 0.3, core.PNorm(0.1, 0.5))
|
||
atrMaNormMax := pol.Def("atr_ma_norm_max", 0.7, core.PNorm(0.5, 1.0))
|
||
trailingPercent := pol.Def("trailing_percent", 1.3, core.PNorm(0.5, 3.0))
|
||
|
||
// 计算ATR移动平均线周期
|
||
atrMaLength := int(float64(atrLength) * atrMaRate)
|
||
|
||
// 计算RSI买入和卖出阈值
|
||
rsiBuy := 50 + float64(rsiEntry)
|
||
rsiSell := 50 - float64(rsiEntry)
|
||
|
||
// 确定预热数量,取最大参数值
|
||
warmupNum := atrMaLength
|
||
if rsiLength > warmupNum {
|
||
warmupNum = rsiLength
|
||
}
|
||
|
||
return &strat.TradeStrat{
|
||
WarmupNum: warmupNum,
|
||
HedgeOff: true, // 单向持仓模式
|
||
RunTimeFrames: []string{"1h"},
|
||
OnStartUp: func(s *strat.StratJob) {
|
||
// 初始化每个品种的持仓期间最高价和最低价
|
||
s.More = &AtrRsiStrategy{
|
||
IntraTradeHigh: 0,
|
||
IntraTradeLow: 0,
|
||
}
|
||
},
|
||
OnBar: func(s *strat.StratJob) {
|
||
e := s.Env
|
||
m, _ := s.More.(*AtrRsiStrategy)
|
||
|
||
// 计算技术指标
|
||
atrValue := ta.ATR(e.High, e.Low, e.Close, atrLength)
|
||
atrMa := ta.SMA(atrValue, atrMaLength)
|
||
rsiValue := ta.RSI(e.Close, rsiLength)
|
||
|
||
// 获取当前价格
|
||
closePrice := e.Close.Get(0)
|
||
highPrice := e.High.Get(0)
|
||
lowPrice := e.Low.Get(0)
|
||
|
||
// 检查数据有效性
|
||
if math.IsNaN(closePrice) || math.IsNaN(highPrice) || math.IsNaN(lowPrice) ||
|
||
math.IsNaN(atrValue.Get(0)) || math.IsNaN(atrMa.Get(0)) || math.IsNaN(rsiValue.Get(0)) {
|
||
return
|
||
}
|
||
|
||
// 计算ATR移动平均线的标准化值
|
||
atrMaNorm := atrMa.Get(0) / closePrice * 100
|
||
|
||
// 获取当前持仓状态
|
||
longOrders := s.LongOrders
|
||
shortOrders := s.ShortOrders
|
||
hasLongPosition := len(longOrders) > 0
|
||
hasShortPosition := len(shortOrders) > 0
|
||
|
||
// 无持仓状态
|
||
if !hasLongPosition && !hasShortPosition {
|
||
// 重置持仓期间最高价和最低价
|
||
m.IntraTradeHigh = highPrice
|
||
m.IntraTradeLow = lowPrice
|
||
|
||
// 检查波动率是否在适合交易范围内
|
||
if atrMaNorm >= atrMaNormMin && atrMaNorm <= atrMaNormMax {
|
||
// 检查当前波动率是否高于平均波动率
|
||
if atrValue.Get(0) > atrMa.Get(0) {
|
||
// 检查RSI信号
|
||
if rsiValue.Get(0) > rsiBuy {
|
||
// RSI超买,做多
|
||
s.OpenOrder(&strat.EnterReq{
|
||
Tag: "B1",
|
||
OrderType: core.OrderTypeLimit,
|
||
Limit: closePrice + 5,
|
||
})
|
||
} else if rsiValue.Get(0) < rsiSell {
|
||
// RSI超卖,做空
|
||
s.OpenOrder(&strat.EnterReq{
|
||
Tag: "S1",
|
||
Short: true,
|
||
OrderType: core.OrderTypeLimit,
|
||
Limit: closePrice - 5,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
} else if hasLongPosition {
|
||
// 多头持仓状态
|
||
// 更新持仓期间最高价
|
||
if highPrice > m.IntraTradeHigh {
|
||
m.IntraTradeHigh = highPrice
|
||
}
|
||
m.IntraTradeLow = lowPrice
|
||
|
||
// 计算多头追踪止损价格
|
||
longTp := m.IntraTradeHigh * (1 - trailingPercent/100)
|
||
|
||
// 获取入场价格
|
||
enterPrice := longOrders[0].InitPrice
|
||
|
||
// 设置止损和止盈
|
||
for _, od := range longOrders {
|
||
od.SetStopLoss(&ormo.ExitTrigger{
|
||
Price: longTp,
|
||
Rate: 1.0, // 全部退出
|
||
Tag: "trailing_stop",
|
||
})
|
||
|
||
od.SetTakeProfit(&ormo.ExitTrigger{
|
||
Price: enterPrice * 1.03,
|
||
Rate: 1.0, // 全部退出
|
||
Tag: "take_profit",
|
||
})
|
||
}
|
||
} else if hasShortPosition {
|
||
// 空头持仓状态
|
||
m.IntraTradeHigh = highPrice
|
||
// 更新持仓期间最低价
|
||
if lowPrice < m.IntraTradeLow {
|
||
m.IntraTradeLow = lowPrice
|
||
}
|
||
|
||
// 计算空头追踪止损价格
|
||
shortTp := m.IntraTradeLow * (1 + trailingPercent/100)
|
||
|
||
// 获取入场价格
|
||
enterPrice := shortOrders[0].InitPrice
|
||
|
||
// 设置止损和止盈
|
||
for _, od := range shortOrders {
|
||
od.SetStopLoss(&ormo.ExitTrigger{
|
||
Price: shortTp,
|
||
Rate: 1.0, // 全部退出
|
||
Tag: "trailing_stop",
|
||
})
|
||
|
||
od.SetTakeProfit(&ormo.ExitTrigger{
|
||
Price: enterPrice * 0.94,
|
||
Rate: 1.0, // 全部退出
|
||
Tag: "take_profit",
|
||
})
|
||
}
|
||
}
|
||
},
|
||
}
|
||
}
|