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

138
old/t01/common.go Normal file
View File

@@ -0,0 +1,138 @@
package t01
import (
"github.com/banbox/banbot/orm/ormo"
"github.com/banbox/banbot/strat"
"github.com/banbox/banexg/log"
"github.com/banbox/banstagy/com"
ta "github.com/banbox/banta"
"go.uber.org/zap"
"math"
)
var (
// 这里是默认参数,请尽量在MainVX()中修改,不要在这里修改
maBig = 30
maSml = 30
maParent = 50
sampleNum = 500 // 斜率采样数量
sampleStep = 2 // 斜率计算间隔
atrLen = 14
openOffRate = float64(0) // 开单时,从均线偏移基准ATR的倍数
goodRate = float64(10) // 收益超过此倍数的ATR时,将止损更新为均线
badRate = float64(5) // 损失超过此倍数的ATR时,止损退出
)
type MoreType struct {
bigSlop *com.Slop
hitGoods map[int64]bool // 触发goodRate的订单ID,允许每个bar更新止损
}
func openOrder(s *strat.StratJob, closePrice, dirt, price, stopLoss float64) {
if (stopLoss-closePrice)*dirt >= 0 {
// 当前止损立刻满足,跳过
return
}
tag := "long"
if dirt < 0 {
tag = "short"
}
err := s.OpenOrder(&strat.EnterReq{
Tag: tag,
Limit: price,
StopLoss: stopLoss,
Short: dirt < 0,
})
if err != nil {
log.Error("open order fail", zap.Error(err))
}
}
func onStartUp(s *strat.StratJob) {
s.More = &MoreType{
bigSlop: com.NewSlop(sampleNum, 0.25),
hitGoods: make(map[int64]bool),
}
}
func onInfoBar(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
sma := ta.SMA(e.Close, maParent)
prevSma := sma.Get(sampleStep)
if e.BarNum%sampleStep > 0 || math.IsNaN(prevSma) {
return
}
more, _ := s.More.(*MoreType)
curSma := sma.Get(0)
slop := (curSma - prevSma) / curSma
more.bigSlop.Update(e.BarNum, slop)
}
func onBar(s *strat.StratJob) {
e := s.Env
atr := ta.ATR(e.High, e.Low, e.Close, atrLen)
baseAtrLen := int(math.Round(float64(atrLen) * 4.3))
atrBase := ta.Lowest(ta.Highest(atr, atrLen), baseAtrLen).Get(0)
c := e.Close.Get(0)
smaBig := ta.SMA(e.Close, maBig)
smaVal := smaBig.Get(0)
// smaSml := ta.SMA(e.Close, maSml)
// maX := smaSml.Cross(smaBig)
// rsiVal := ta.RSI(e.Close, 20).Get(0)
more, _ := s.More.(*MoreType)
prevSma := smaBig.Get(sampleStep)
if e.BarNum%sampleStep == 0 && !math.IsNaN(prevSma) {
slop := (smaVal - prevSma) / smaVal
more.bigSlop.Update(e.BarNum, slop)
}
var longOd, shortOd *ormo.InOutOrder
if len(s.LongOrders) > 0 {
longOd = s.LongOrders[0]
}
if len(s.ShortOrders) > 0 {
shortOd = s.ShortOrders[0]
}
atrVal := atr.Get(0)
slRange := max(atrBase*badRate, atrVal*1.5)
// 检查是否触发盈利阈值,若触发更新止损
var orders = []*ormo.InOutOrder{longOd, shortOd}
for _, od := range orders {
if od != nil {
odDirt := 1.0
if od.Short {
odDirt = -1
}
isGood, ok := more.hitGoods[od.ID]
if !ok && (c-od.Enter.Average)*odDirt >= atrBase*goodRate {
more.hitGoods[od.ID] = true
isGood = true
}
if isGood {
// 已触发盈利阈值,每个bar更新止损
sl := od.GetStopLoss()
if sl == nil || (smaVal-sl.Price)*odDirt > 0 {
od.SetStopLoss(&ormo.ExitTrigger{Price: smaVal})
}
} else if od.Status == ormo.InOutStatusInit {
// 尚未入场,更新入场价格,更新止损
_ = od.SetEnterLimit(smaVal)
od.SetStopLoss(&ormo.ExitTrigger{Price: smaVal - odDirt*slRange})
}
}
}
if atrVal < atrBase {
// && more.bigSlop.Dirt > 0
if longOd == nil && more.bigSlop.Dirt >= 0 {
// 开多单 && c-smaVal+slRange > atrBase*0.5
openOrder(s, c, 1, 0, c-slRange)
}
// && more.bigSlop.Dirt < 0
if shortOd == nil && more.bigSlop.Dirt <= 0 {
// 开空单 && smaVal+slRange-c > atrBase*0.5
openOrder(s, c, -1, 0, c+slRange)
}
}
}