145 lines
3.5 KiB
Go
145 lines
3.5 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"
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
type WeekendData struct {
|
|
FridayClose float64
|
|
HasLong bool
|
|
TotCost float64
|
|
TotAmt float64
|
|
}
|
|
|
|
func J2439(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
|
entryThreshold := pol.Def("entryThreshold", 0.02, core.PNorm(0.01, 0.1))
|
|
profitTakingPercentThreshold := pol.Def("profitTakingPercentThreshold", 0.06, core.PNorm(0.01, 0.08))
|
|
|
|
return &strat.TradeStrat{
|
|
WarmupNum: 7, // 需要最多7天的数据来获取周五收盘价
|
|
HedgeOff: true, // 单向持仓模式
|
|
RunTimeFrames: []string{"5m"},
|
|
OnStartUp: func(s *strat.StratJob) {
|
|
s.More = &WeekendData{FridayClose: math.NaN()}
|
|
},
|
|
OnBar: func(s *strat.StratJob) {
|
|
e := s.Env
|
|
data, _ := s.More.(*WeekendData)
|
|
currentTime := time.Unix(e.TimeStop/1000, 0)
|
|
weekday := currentTime.Weekday()
|
|
|
|
// 计算距离周五的天数
|
|
var daysSinceFriday int
|
|
switch weekday {
|
|
case time.Saturday:
|
|
daysSinceFriday = 1
|
|
case time.Sunday:
|
|
daysSinceFriday = 0
|
|
case time.Monday:
|
|
daysSinceFriday = 6
|
|
case time.Tuesday:
|
|
daysSinceFriday = 5
|
|
case time.Wednesday:
|
|
daysSinceFriday = 4
|
|
case time.Thursday:
|
|
daysSinceFriday = 3
|
|
case time.Friday:
|
|
daysSinceFriday = 2
|
|
}
|
|
|
|
// 获取周五收盘价 - 使用日线数据
|
|
if e.Close.Len() > daysSinceFriday {
|
|
data.FridayClose = e.Close.Get(daysSinceFriday)
|
|
}
|
|
|
|
// 如果没有有效的周五收盘价,不执行交易逻辑
|
|
if math.IsNaN(data.FridayClose) {
|
|
return
|
|
}
|
|
|
|
// 检查止盈条件
|
|
if s.EnteredNum > 0 {
|
|
totalProfitRate := 0.0
|
|
for _, od := range s.LongOrders {
|
|
if od.Status >= ormo.InOutStatusPartEnter {
|
|
totalProfitRate += od.ProfitRate
|
|
}
|
|
}
|
|
for _, od := range s.ShortOrders {
|
|
if od.Status >= ormo.InOutStatusPartEnter {
|
|
totalProfitRate += od.ProfitRate
|
|
}
|
|
}
|
|
|
|
if totalProfitRate > profitTakingPercentThreshold {
|
|
s.CloseOrders(&strat.ExitReq{
|
|
Tag: "profit_take",
|
|
Dirt: core.OdDirtBoth,
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
// 周末交易逻辑(周日和周一)
|
|
if weekday == time.Sunday || weekday == time.Monday {
|
|
currentPrice := e.Close.Get(0)
|
|
if math.IsNaN(currentPrice) {
|
|
return
|
|
}
|
|
|
|
upperThreshold := data.FridayClose * (1 + entryThreshold)
|
|
lowerThreshold := data.FridayClose * (1 - entryThreshold)
|
|
|
|
// 没有持仓时的入场逻辑
|
|
if s.OrderNum == 0 {
|
|
if currentPrice > upperThreshold {
|
|
s.OpenOrder(&strat.EnterReq{
|
|
Tag: "short_entry",
|
|
Short: true,
|
|
})
|
|
} else if currentPrice < lowerThreshold {
|
|
s.OpenOrder(&strat.EnterReq{
|
|
Tag: "long_entry",
|
|
})
|
|
}
|
|
} else {
|
|
// 已有持仓时的加仓逻辑
|
|
for _, od := range s.ShortOrders {
|
|
if od.Status >= ormo.InOutStatusPartEnter && currentPrice > od.InitPrice*(1+entryThreshold) {
|
|
s.OpenOrder(&strat.EnterReq{
|
|
Tag: "add_short",
|
|
Short: true,
|
|
})
|
|
break
|
|
}
|
|
}
|
|
|
|
for _, od := range s.LongOrders {
|
|
if od.Status >= ormo.InOutStatusPartEnter {
|
|
s.OpenOrder(&strat.EnterReq{
|
|
Tag: "add_long",
|
|
})
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 周二平仓逻辑
|
|
if weekday == time.Tuesday {
|
|
if s.OrderNum > 0 {
|
|
s.CloseOrders(&strat.ExitReq{
|
|
Tag: "monday_close",
|
|
Dirt: core.OdDirtBoth,
|
|
})
|
|
}
|
|
}
|
|
},
|
|
}
|
|
}
|