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

157
surge/alldown.go Normal file
View File

@@ -0,0 +1,157 @@
package surge
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
"sort"
)
/*
全市场瞬时暴跌做空策略。适用于十分钟跌去70%的情况。
可使用下面脚本回测:surge/down_test.go
E:\trade\go\bandata\backtest\bdb35c1d91\surge_alldown.log
*/
type AllDownSta struct {
volBase float64 // 平均成交量
dirtRate float64 // K线方向倍率,范围约:[-3,3]
barRate float64 // K线比率
volRate float64 // 成交量倍率
}
func AllDown(p *config.RunPolicyConfig) *strat.TradeStrat {
//var allowLog = false
lenAtr, lenAtrS := 20, 30
baseAtrLen := int(math.Round(float64(lenAtr) * 4.3))
baseAtrLenS := baseAtrLen * 3 / 2
env, _ := ta.NewBarEnv("", "", "", "1m")
lenS := env.NewSeries(nil)
volS := env.NewSeries(nil)
var prevLen float64
var volThres = 2.8
var openDirt float64
return &strat.TradeStrat{
WarmupNum: 150,
BatchInOut: true,
TimeFrames: "1m",
OnStartUp: func(s *strat.StratJob) {
s.More = &AllDownSta{}
},
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
return []*strat.PairSub{
{"_cur_", "15m", 100},
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
m, _ := s.More.(*AllDownSta)
atr := ta.ATR(e.High, e.Low, e.Close, lenAtrS)
atrBase := ta.Lowest(ta.Highest(atr, lenAtrS), baseAtrLenS).Get(0)
o, c := e.Open.Get(0), e.Close.Get(0)
h, l := e.High.Get(0), e.Low.Get(0)
m.dirtRate = (c - o) / atrBase
m.barRate = (c - o) / (h - l)
m.volRate = ta.EMA(e.Volume, lenAtr).Get(0) / m.volBase
},
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
m, _ := s.More.(*AllDownSta)
maVol := ta.EMA(e.Volume, lenAtr)
m.volBase = ta.Lowest(ta.Highest(maVol, lenAtr), baseAtrLen).Get(0) / 3
},
OnBatchJobs: func(jobs []*strat.StratJob) {
jobNum := len(jobs)
volRates := make([]float64, 0, jobNum)
lenRates := make([]float64, 0, jobNum)
solidRates := make([]float64, 0, jobNum)
volIds := make([]*core.Int64Flt, 0, jobNum)
var timeMS int64
for i, j := range jobs {
m, _ := j.More.(*AllDownSta)
volRates = append(volRates, m.volRate)
lenRates = append(lenRates, m.dirtRate)
solidRates = append(solidRates, m.barRate)
timeMS = max(timeMS, j.Env.TimeStop)
volIds = append(volIds, &core.Int64Flt{
Int: int64(i),
Val: m.volRate,
})
}
sort.Float64s(volRates)
sort.Float64s(lenRates)
sort.Float64s(solidRates)
vol := volRates[jobNum/2]
solid := solidRates[jobNum/2]
lenMid := lenRates[jobNum/2]
//len33 := lenRates[jobNum/3]
len66 := lenRates[jobNum*2/3]
val := lenMid + vol
env.TimeStop = max(timeMS, env.TimeStop)
if math.IsNaN(val) || math.IsInf(val, 0) || lenS.Cached() {
return
}
lenS.Append(lenMid)
volS.Append(vol)
dataLen := volS.Len()
if dataLen > env.MaxCache*2 {
volS.Cut(env.MaxCache)
lenS.Cut(env.MaxCache)
}
volMa1 := ta.SMA(volS, 3).Get(1)
low5len := ta.Lowest(lenS, 30).Get(1)
if openDirt >= -1 && vol > volThres && lenMid < low5len && len66 < 0 && solid < -0.5 && prevLen < 0 {
// 成交量突破阈值,全市场大阴线,前一个也是阴线
prevRate := lenMid / prevLen
if prevRate < 3 && prevRate > 1.5 && vol/volMa1 < 2 {
// 与前一个k线比率不超过3,成交量缓慢增长
openDirt -= 1
costRate := 2.0
if vol < 4 {
costRate *= vol / 4
}
sort.Slice(volIds, func(i, j int) bool {
return volIds[i].Val < volIds[j].Val
})
// 做空成交量最大的1/3部分,获利最丰(收益45%, 55%, 66%)
items := volIds[jobNum*2/3:]
for _, it := range items {
jobs[it.Int].OpenOrder(&strat.EnterReq{
Tag: "short",
CostRate: costRate,
Short: true,
})
}
}
}
if openDirt < 0 {
// 正在做空/多
if lenMid*openDirt < 0 {
openDirt = 0
for _, job := range jobs {
job.CloseOrders(&strat.ExitReq{
Tag: "exit",
Force: true,
})
}
}
}
prevLen = lenMid
//if !allowLog && vol > 2.5 {
// allowLog = true
//}
//if !math.IsNaN(vol) {
// jobs[0].Strat.WriteOutput(fmt.Sprintf("%.2f %.2f %.2f %.2f %.2f", vol, solid, lenMid, len33, len66), true)
// if vol < 1.4 {
// allowLog = false
// }
//}
},
}
}