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

36
org/day/01.go Normal file
View File

@@ -0,0 +1,36 @@
package day
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
"math"
)
func D01(p *config.RunPolicyConfig) *strat.TradeStrat {
return &strat.TradeStrat{
WarmupNum: 100,
OnBar: func(s *strat.StratJob) {
e := s.Env
o, c, h, l := e.Open.Get(0), e.Close.Get(0), e.High.Get(0), e.Low.Get(0)
solid := math.Abs(o - c)
solidRate := solid / math.Abs(h-l)
atr := ta.ATR(e.High, e.Low, e.Close, 15).Get(0)
ma := ta.SMA(e.Close, 20).Get(0)
if len(s.LongOrders) > 0 {
s.CloseOrders(&strat.ExitReq{Tag: "closeL", Dirt: core.OdDirtLong})
} else if len(s.ShortOrders) > 0 {
s.CloseOrders(&strat.ExitReq{Tag: "closeL", Dirt: core.OdDirtShort})
} else {
if solidRate > 0.7 && solid/atr > 1 {
if o > c && c < ma {
s.OpenOrder(&strat.EnterReq{Tag: "long"})
} else if c > ma {
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true})
}
}
}
},
}
}

62
org/day/02.go Normal file
View File

@@ -0,0 +1,62 @@
package day
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
)
/*
视频号:期市萧何:最简单的交易系统 2025/02/18
80均线向上只开多,向下只开空
当20均线和80均线多头排列,且价格上穿20均线开多;反之做空
前期压力支撑止损,价格再次触碰20均线止盈
最小8h才盈利,且21年到35年间几次回撤时间长达1年左右;
弃用
*/
func MaDirt(p *config.RunPolicyConfig) *strat.TradeStrat {
lenAtr := 20
baseAtrLen := 86
slRate := 2.0
bigThres := 0.2
return &strat.TradeStrat{
WarmupNum: 100,
OnBar: func(s *strat.StratJob) {
e := s.Env
maSml := ta.SMA(e.Close, 20)
maBig := ta.SMA(e.Close, 80)
atr := ta.ATR(e.High, e.Low, e.Close, 14)
atrBase := ta.Lowest(ta.Highest(atr, lenAtr), baseAtrLen).Get(0)
bigChg := (maBig.Get(0) - maBig.Get(3)) / atrBase
smlChg := (maSml.Get(0) - maSml.Get(3)) / atrBase
cSmlX := e.Close.Cross(maSml)
if len(s.LongOrders) > 0 {
if cSmlX == -1 {
// 价格下穿均线止盈
s.CloseOrders(&strat.ExitReq{Tag: "exitL", Dirt: core.OdDirtLong})
}
} else if len(s.ShortOrders) > 0 {
if cSmlX == 1 {
// 价格上穿均线止盈
s.CloseOrders(&strat.ExitReq{Tag: "exitS", Dirt: core.OdDirtShort})
}
} else if bigChg > bigThres {
// 大均线向上
if cSmlX == 1 && maSml.Get(0) > maBig.Get(0) && smlChg > 0 {
// 价格上穿20均线,且均线多头排列
s.OpenOrder(&strat.EnterReq{Tag: "long", StopLossVal: atr.Get(0) * slRate})
}
} else if bigChg < -bigThres {
// 大均线向下
if cSmlX == -1 && maSml.Get(0) < maBig.Get(0) && smlChg < 0 {
// 价格下穿20均线,且均线空头排列
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, StopLossVal: atr.Get(0) * slRate})
}
}
},
}
}

47
org/day/03.go Normal file
View File

@@ -0,0 +1,47 @@
package day
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/strat"
"github.com/banbox/banexg/utils"
ta "github.com/banbox/banta"
)
/*
在大周期4h的前一个小周期入场,检查是否有套利机会。
无法盈利
*/
func D03(p *config.RunPolicyConfig) *strat.TradeStrat {
tfMSecs := int64(utils.TFToSecs("4h") * 1000)
return &strat.TradeStrat{
WarmupNum: 100,
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
return []*strat.PairSub{
{"_cur_", "4h", 10},
}
},
OnStartUp: func(s *strat.StratJob) {
s.More = 0
},
OnBar: func(s *strat.StratJob) {
e := s.Env
dirt, _ := s.More.(int)
if len(s.LongOrders) > 0 {
s.CloseOrders(&strat.ExitReq{Tag: "exit"})
} else if len(s.ShortOrders) > 0 {
s.CloseOrders(&strat.ExitReq{Tag: "exit"})
} else if (e.TimeStop+e.TFMSecs)%tfMSecs == 0 {
s.OpenOrder(&strat.EnterReq{Tag: "ent", Short: dirt < 0})
}
},
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
ma := ta.SMA(e.Close, 10).Get(0)
if e.Close.Get(0) > ma {
s.More = 1
} else {
s.More = -1
}
},
}
}

73
org/day/04.go Normal file
View File

@@ -0,0 +1,73 @@
package day
import (
"fmt"
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/core"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
)
/*
视频号:山居听雨楼:渣男战法
5日和10日均线,10日均线向上向下确定方向
收盘价小均线金叉,且多头排列,做多;反之做空
效果较差
*/
func D04(p *config.RunPolicyConfig) *strat.TradeStrat {
lenAtr := 20
baseAtrLen := 86
//slRate := 2.0
bigThres := 0.2
upNum, dnNum, zeroNum := 0, 0, 0
return &strat.TradeStrat{
WarmupNum: 100,
OnBar: func(s *strat.StratJob) {
e := s.Env
maSml := ta.SMA(e.Close, 5)
maBig := ta.SMA(e.Close, 10)
atr := ta.ATR(e.High, e.Low, e.Close, 14)
atrBase := ta.Lowest(ta.Highest(atr, lenAtr), baseAtrLen).Get(0)
bigChg := (maBig.Get(0) - maBig.Get(2)) / atrBase
smlChg := (maSml.Get(0) - maSml.Get(2)) / atrBase
cSmlX := e.Close.Cross(maSml)
ph := ta.Highest(e.High, 2).Get(0)
pl := ta.Lowest(e.Low, 2).Get(0)
if len(s.LongOrders) > 0 {
if cSmlX == -1 {
// 价格下穿均线止盈
s.CloseOrders(&strat.ExitReq{Tag: "exitL", Dirt: core.OdDirtLong})
}
} else if len(s.ShortOrders) > 0 {
if cSmlX == 1 {
// 价格上穿均线止盈
s.CloseOrders(&strat.ExitReq{Tag: "exitS", Dirt: core.OdDirtShort})
}
} else if bigChg > bigThres {
// 大均线向上
if cSmlX == 1 && maSml.Get(0) > maBig.Get(0) && smlChg > 0 {
// 价格上穿20均线,且均线多头排列
s.OpenOrder(&strat.EnterReq{Tag: "long", StopLossVal: pl})
}
} else if bigChg < -bigThres {
// 大均线向下
if cSmlX == -1 && maSml.Get(0) < maBig.Get(0) && smlChg < 0 {
// 价格下穿20均线,且均线空头排列
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, StopLossVal: ph})
}
}
if bigChg > bigThres {
upNum++
} else if bigChg < -bigThres {
dnNum++
} else {
zeroNum++
}
},
OnShutDown: func(s *strat.StratJob) {
fmt.Printf("up: %d, dn: %d, zero: %d\n", upNum, dnNum, zeroNum)
},
}
}

58
org/day/05.go Normal file
View File

@@ -0,0 +1,58 @@
package day
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
)
/*
视频号:漫谈期事:高手能稳定盈利的交易系统到底有多简单?
截断亏损让利润奔跑
任意阳K第二根开多,开仓k前一根k最低点止损,反之做空
没止损就拿30根bar后平仓
无法盈利
*/
func D05(p *config.RunPolicyConfig) *strat.TradeStrat {
return &strat.TradeStrat{
WarmupNum: 100,
OnBar: func(s *strat.StratJob) {
e := s.Env
o, c := e.Open.Get(0), e.Close.Get(0)
_ = o
ma := ta.SMA(e.Close, 30).Get(0)
ph := ta.Highest(e.High, 2).Get(0)
pl := ta.Lowest(e.Low, 2).Get(0)
rsi := ta.RSI(e.Close, 4).Get(0)
if len(s.LongOrders) > 0 {
for _, od := range s.LongOrders {
sl := od.GetStopLoss()
if pl > sl.Price {
sl.Price = pl
}
num := e.BarCount(od.EnterAt)
if num > 10 {
s.CloseOrders(&strat.ExitReq{Tag: "exitL", OrderID: od.ID})
}
}
} else if len(s.ShortOrders) > 0 {
for _, od := range s.ShortOrders {
sl := od.GetStopLoss()
if ph < sl.Price {
sl.Price = ph
}
num := e.BarCount(od.EnterAt)
if num > 10 {
s.CloseOrders(&strat.ExitReq{Tag: "exitS", OrderID: od.ID})
}
}
} else if rsi < 10 && c < ma {
s.OpenOrder(&strat.EnterReq{Tag: "long", StopLoss: pl})
} else if rsi > 90 && c > ma {
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, StopLoss: ph})
}
},
}
}

40
org/day/06.go Normal file
View File

@@ -0,0 +1,40 @@
package day
import (
"github.com/banbox/banbot/config"
"github.com/banbox/banbot/strat"
ta "github.com/banbox/banta"
)
/*
bilibili 生财茶馆pro 98%胜率的5分钟终极剥头皮交易策略-测试
很差,一路向下
*/
func d06(p *config.RunPolicyConfig) *strat.TradeStrat {
return &strat.TradeStrat{
WarmupNum: 200,
EachMaxLong: 1,
EachMaxShort: 1,
OnBar: func(s *strat.StratJob) {
e := s.Env
c := e.Close.Get(0)
atr := ta.ATR(e.High, e.Low, e.Close, 6)
utBot := ta.UTBot(e.Close, atr, 2).Get(0)
stc := ta.STC(e.Close, 80, 27, 50, 0.5)
stcVal := stc.Get(0)
stcUp := stcVal > stc.Get(1)
hma := ta.HMA(e.Close, 55).Get(0)
hh := ta.Highest(e.High, 3).Get(0)
ll := ta.Lowest(e.Low, 3).Get(0)
if utBot > 0 && stcVal < 25 && stcUp && c > hma {
slVal := c - ll
s.OpenOrder(&strat.EnterReq{Tag: "long", StopLossVal: slVal, TakeProfitVal: slVal * 1.5})
} else if utBot < 0 && stcVal > 75 && !stcUp && c < hma {
slVal := hh - c
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true, StopLossVal: slVal, TakeProfitVal: slVal * 1.5})
}
},
}
}

162
org/day/07.go Normal file
View File

@@ -0,0 +1,162 @@
package day
import (
"fmt"
"github.com/banbox/banbot/btime"
"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"
"sort"
"sync"
)
func D07(p *config.RunPolicyConfig) *strat.TradeStrat {
symVols := make(map[int32]float64) // 成交量记录
allowSyms := make(map[int32]bool) // 允许交易的品种sid
timeDirts := make(map[int32]*TimeDirt) // 记录每个品种的触发时间和方向,只做顺势信号
holds := make(map[int32]int) // 各个品种持仓情况
var lock sync.Mutex
var bigTime int64
var allowConfirm bool // allowSyms是否已刷新
const volRateThs = 1.1 // 成交量最低倍数
const topNRate = 0.1 // 交易前n个品种比例
return &strat.TradeStrat{
WarmupNum: 100,
DrawDownExit: true,
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
return []*strat.PairSub{
{"_cur_", "1h", 1},
}
},
OnBar: func(s *strat.StratJob) {
e := s.Env
if !allowConfirm && e.TimeStart > bigTime {
// 确定当前小时,可交易的品种
allowConfirm = true
topNum := int(math.Round(float64(len(symVols)) * topNRate))
allowSyms = GetTopNKeys(symVols, topNum)
}
sid := s.Symbol.ID
_, allow := allowSyms[sid]
hold, hasPos := holds[sid]
if hasPos {
if hold > 0 {
if len(s.LongOrders) == 0 {
delete(holds, sid)
}
} else if len(s.ShortOrders) == 0 {
delete(holds, sid)
}
}
// 要求最近3bar成交量加速,实体颜色一致,且实体至少70%;最新成交量是平均成交量2倍
volMa := ta.SMA(e.Volume, 100).Get(0)
v0, v1, v2 := e.Volume.Get(0), e.Volume.Get(1), e.Volume.Get(2)
prevVolRate := v1 / v2
if v0 > volMa*2 && prevVolRate > volRateThs && v0/v1 > prevVolRate*volRateThs {
// 成交量爆发
flag0, solid0 := BarStat(e, 0)
flag1, solid1 := BarStat(e, 1)
flag2, solid2 := BarStat(e, 2)
if flag0 == flag1 && flag1 == flag2 && min(solid0, solid1, solid2) > 0.7 {
// 颜色一致,且实体至少70%
lock.Lock()
timeDirts[sid] = &TimeDirt{Time: e.TimeStart, Dirt: flag0}
lock.Unlock()
if allow && expDirt(timeDirts, e.TimeStart-e.TFMSecs) == flag0 {
dateStr := btime.ToDateStr(e.TimeStart, core.DefaultDateFmt)
fmt.Printf("[%s] enter %s dirt: %d\n", dateStr, s.Symbol.Symbol, flag0)
// 只交易成交量top,且顺应大趋势的
if len(s.ShortOrders) == 0 && len(s.LongOrders) == 0 && len(holds) <= 1 {
holds[sid] = flag0
s.OpenOrder(&strat.EnterReq{
Tag: "enter",
Short: flag0 < 0,
})
}
}
}
}
},
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
lock.Lock()
if e.TimeStop > bigTime {
symVols = make(map[int32]float64)
bigTime = e.TimeStop
allowConfirm = false
}
// 计算所有品种过去1小时成交量
avgPrice := ta.AvgPrice(e).Get(0)
symVols[s.Symbol.ID] = e.Volume.Get(0) * avgPrice
lock.Unlock()
},
GetDrawDownExitRate: func(s *strat.StratJob, od *ormo.InOutOrder, maxChg float64) float64 {
return 0.4
},
}
}
func expDirt(dirts map[int32]*TimeDirt, minStamp int64) int {
up, dn := 0, 0
for k, d := range dirts {
if d.Time < minStamp {
delete(dirts, k)
continue
}
if d.Dirt > 0 {
up++
} else {
dn++
}
}
if up+dn >= 3 {
if up >= dn*2 {
return 1
} else if dn >= up*2 {
return -1
}
}
return 0
}
func BarStat(e *ta.BarEnv, i int) (int, float64) {
o, h, l, c := e.Open.Get(i), e.High.Get(i), e.Low.Get(i), e.Close.Get(i)
solid := float64(0)
if h > l {
solid = math.Abs(c-o) / (h - l)
}
flag := 1
if o > c {
flag = -1
}
return flag, solid
}
type TimeDirt struct {
Time int64
Dirt int
}
type kv struct {
key int32
value float64
}
func GetTopNKeys(symVols map[int32]float64, n int) map[int32]bool {
pairs := make([]kv, 0, len(symVols))
for k, v := range symVols {
pairs = append(pairs, kv{k, v})
}
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].value > pairs[j].value
})
keys := make(map[int32]bool)
for i := 0; i < n && i < len(pairs); i++ {
keys[pairs[i].key] = true
}
return keys
}

15
org/day/main.go Normal file
View File

@@ -0,0 +1,15 @@
package day
import "github.com/banbox/banbot/strat"
func init() {
strat.AddStratGroup("day", map[string]strat.FuncMakeStrat{
"01": D01,
"02": MaDirt,
"03": D03,
"04": D04,
"05": D05,
"06": d06,
"07": D07,
})
}