init
This commit is contained in:
79
demo/bar_agg.go
Normal file
79
demo/bar_agg.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/banbox/banbot/btime"
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banbot/utils"
|
||||
"github.com/banbox/banexg"
|
||||
"github.com/banbox/banexg/errs"
|
||||
"github.com/banbox/banexg/log"
|
||||
ta "github.com/banbox/banta"
|
||||
"go.uber.org/zap"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AggMore struct {
|
||||
bars []*banexg.Kline
|
||||
barsBig []*banexg.Kline
|
||||
}
|
||||
|
||||
func getBar(e *ta.BarEnv) *banexg.Kline {
|
||||
return &banexg.Kline{
|
||||
Time: e.TimeStart,
|
||||
Open: e.Open.Get(0),
|
||||
High: e.High.Get(0),
|
||||
Low: e.Low.Get(0),
|
||||
Close: e.Close.Get(0),
|
||||
Volume: e.Volume.Get(0),
|
||||
}
|
||||
}
|
||||
|
||||
func dumpKline(bars []*banexg.Kline, name string) *errs.Error {
|
||||
if len(bars) == 0 {
|
||||
return nil
|
||||
}
|
||||
outDir := config.GetDataDir()
|
||||
rows := utils.KlineToStr(bars, btime.UTCLocale)
|
||||
path := filepath.Join(outDir, "tmp", fmt.Sprintf("%s.csv", name))
|
||||
return utils.WriteCsvFile(path, rows, false)
|
||||
}
|
||||
|
||||
func BarAgg(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 1,
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1h", 1},
|
||||
}
|
||||
},
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &AggMore{}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
b := getBar(s.Env)
|
||||
m, _ := s.More.(*AggMore)
|
||||
m.bars = append(m.bars, b)
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
b := getBar(e)
|
||||
m, _ := s.More.(*AggMore)
|
||||
m.barsBig = append(m.barsBig, b)
|
||||
},
|
||||
OnShutDown: func(s *strat.StratJob) {
|
||||
m, _ := s.More.(*AggMore)
|
||||
code := strings.ReplaceAll(s.Symbol.Symbol, "/", "_")
|
||||
code = strings.ReplaceAll(code, ":", "_")
|
||||
err := dumpKline(m.bars, fmt.Sprintf("%s_%s", code, s.TimeFrame))
|
||||
if err != nil {
|
||||
log.Error("dump klines fail", zap.Error(err))
|
||||
}
|
||||
err = dumpKline(m.barsBig, fmt.Sprintf("%s_1h", code))
|
||||
if err != nil {
|
||||
log.Error("dump big klines fail", zap.Error(err))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
40
demo/bar_stat.go
Normal file
40
demo/bar_stat.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg/log"
|
||||
"go.uber.org/zap"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type Stat struct {
|
||||
rates []float64
|
||||
}
|
||||
|
||||
func BarStat(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 50,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &Stat{}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
m, _ := s.More.(*Stat)
|
||||
// rate := genCurFutProbs(s.Env)[0]
|
||||
m.rates = append(m.rates, 0)
|
||||
},
|
||||
OnShutDown: func(s *strat.StratJob) {
|
||||
m, _ := s.More.(*Stat)
|
||||
slices.Sort(m.rates)
|
||||
var sum float64
|
||||
var outs []string
|
||||
for _, v := range m.rates {
|
||||
sum += v
|
||||
outs = append(outs, fmt.Sprintf("%.2f", v*100))
|
||||
}
|
||||
log.Info("", zap.Float64("avg", sum/float64(len(m.rates))),
|
||||
zap.Strings("arr", outs))
|
||||
},
|
||||
}
|
||||
}
|
||||
48
demo/dca.go
Normal file
48
demo/dca.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
)
|
||||
|
||||
type DCAState struct {
|
||||
LastInvestTime int64 // 上次定投时间
|
||||
}
|
||||
|
||||
func DCA(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// 定义可调超参数
|
||||
intvDays := pol.DefInt("intvDays", 7, core.PNorm(1, 365))
|
||||
intvMSecs := int64(intvDays) * 86400000
|
||||
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 1, // 定投策略不需要太多预热数据
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
// 初始化每个品种的状态
|
||||
s.More = &DCAState{
|
||||
LastInvestTime: 0,
|
||||
}
|
||||
},
|
||||
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
state, _ := s.More.(*DCAState)
|
||||
currentTime := s.Env.TimeStop
|
||||
|
||||
// 检查是否到了定投时间间隔
|
||||
if state.LastInvestTime > 0 && currentTime-state.LastInvestTime < intvMSecs {
|
||||
return // 还未到定投时间
|
||||
}
|
||||
|
||||
// 执行定投买入
|
||||
err := s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "buy",
|
||||
Log: true,
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
// 更新上次定投时间
|
||||
state.LastInvestTime = currentTime
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
71
demo/demo.go
Normal file
71
demo/demo.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func Demo(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// 定义可调超参数
|
||||
fastPeriod := pol.DefInt("fastPeriod", 5, core.PNorm(3, 20))
|
||||
maRate := pol.Def("maRate", 4.0, core.PNorm(1.5, 9.0))
|
||||
|
||||
// 计算慢速均线周期
|
||||
slowPeriod := int(float64(fastPeriod) * maRate)
|
||||
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: slowPeriod + 10,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
|
||||
// 计算技术指标
|
||||
maFast := ta.SMA(e.Close, fastPeriod) // 快速移动平均线
|
||||
maSlow := ta.SMA(e.Close, slowPeriod) // 慢速移动平均线
|
||||
maCrossState := maFast.Cross(maSlow) // 判断均线交叉状态
|
||||
|
||||
// 金叉:快线上穿慢线
|
||||
if maCrossState == 1 {
|
||||
// 先平掉空头持仓
|
||||
if len(s.ShortOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "golden_cross_close_short",
|
||||
Dirt: core.OdDirtShort,
|
||||
})
|
||||
}
|
||||
|
||||
// 再开多头仓位
|
||||
if len(s.LongOrders) == 0 {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "golden_cross_long",
|
||||
Short: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 死叉:快线下穿慢线
|
||||
if maCrossState == -1 {
|
||||
// 先平掉多头持仓
|
||||
if len(s.LongOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "death_cross_close_long",
|
||||
Dirt: core.OdDirtLong,
|
||||
})
|
||||
}
|
||||
|
||||
// 再开空头仓位
|
||||
if len(s.ShortOrders) == 0 {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "death_cross_short",
|
||||
Short: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
strat.StratMake["demo"] = Demo
|
||||
}
|
||||
43
demo/freqtrade/Strategy004.go
Normal file
43
demo/freqtrade/Strategy004.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package freqtrade
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
/*
|
||||
Strategy 004
|
||||
author@: Gerald Lonlas
|
||||
github@: https://github.com/freqtrade/freqtrade-strategies/blob/main/user_data/strategies/Strategy004.py
|
||||
*/
|
||||
func Strategy004(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 100,
|
||||
EachMaxLong: 1,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
adx := ta.ADX(e.High, e.Low, e.Close, 14).Get(0)
|
||||
adxSlow := ta.ADX(e.High, e.Low, e.Close, 35).Get(0)
|
||||
cci := ta.CCI(e.Close, 14).Get(0)
|
||||
fastD, _, fastK := ta.KDJBy(e.High, e.Low, e.Close, 5, 3, 3, "sma")
|
||||
fastDBig, _, fastKBig := ta.KDJBy(e.High, e.Low, e.Close, 50, 3, 3, "sma")
|
||||
ema := ta.EMA(e.Close, 5).Get(0)
|
||||
KDX := fastK.Cross(fastD)
|
||||
|
||||
adxOk := adx > 50 || adxSlow > 26
|
||||
fastKDOk := fastK.Get(1) < 20 && fastD.Get(1) < 20
|
||||
fastKDBigOk := fastKBig.Get(1) < 30 && fastDBig.Get(1) < 30
|
||||
|
||||
fastKDgt70 := fastK.Get(0) > 70 || fastD.Get(0) > 70
|
||||
if adxOk && cci < -100 && fastKDOk && fastKDBigOk && KDX == 1 {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "long",
|
||||
StopLossVal: ema * 0.1,
|
||||
})
|
||||
} else if adxSlow < 25 && fastKDgt70 && fastK.Get(1) < fastD.Get(1) && e.Close.Get(0) > ema {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exit"})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
26
demo/freqtrade/Strategy005.go
Normal file
26
demo/freqtrade/Strategy005.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package freqtrade
|
||||
|
||||
/*
|
||||
Strategy 005
|
||||
author@: Gerald Lonlas
|
||||
github@: https://github.com/freqtrade/freqtrade-strategies/blob/main/user_data/strategies/Strategy005.py
|
||||
*/
|
||||
|
||||
//func Strategy005(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// buyVolAvg := int(p.Def("buyVolAvg", 150, core.PNorm(50, 300)))
|
||||
// buyRsi := p.Def("buyRsi", 26, core.PNorm(1, 100))
|
||||
// buyFastD := p.Def("buyFastD", 1, core.PNorm(1, 100))
|
||||
// buyFishNo := p.Def("buyFishNo", 5, core.PNorm(1, 100))
|
||||
// sellRsi := p.Def("sellRsi", 74, core.PNorm(1, 100))
|
||||
// sellMiDi := p.Def("sellMiDi", 4, core.PNorm(1, 100))
|
||||
// sellFiRsiN := p.Def("sellFiRsiN", 30, core.PNorm(1, 100))
|
||||
// return &strat.TradeStrat{
|
||||
// WarmupNum: 100,
|
||||
// OnBar: func(s *strat.StratJob) {
|
||||
// e := s.Env
|
||||
// macdCols := ta.MACD(e.Close, 12, 26, 9).Cols
|
||||
// macd, macdSig := macdCols[0], macdCols[1]
|
||||
//
|
||||
// },
|
||||
// }
|
||||
//}
|
||||
11
demo/freqtrade/common.go
Normal file
11
demo/freqtrade/common.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package freqtrade
|
||||
|
||||
import "github.com/banbox/banbot/strat"
|
||||
|
||||
func init() {
|
||||
strat.AddStratGroup("freqtrade", map[string]strat.FuncMakeStrat{
|
||||
"Strategy001": Strategy001,
|
||||
"Strategy004": Strategy004,
|
||||
|
||||
})
|
||||
}
|
||||
46
demo/freqtrade/strategy001.go
Normal file
46
demo/freqtrade/strategy001.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package freqtrade
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
/*
|
||||
Strategy 001
|
||||
author@: Gerald Lonlas
|
||||
github@: https://github.com/freqtrade/freqtrade-strategies/blob/main/user_data/strategies/Strategy001.py
|
||||
*/
|
||||
|
||||
func Strategy001(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenSml := int(p.Def("lenSml", 20, core.PNorm(10, 30)))
|
||||
midRate := p.Def("midRate", 2.5, core.PNorm(1.5, 5))
|
||||
bigRate := p.Def("bigRate", 2, core.PNorm(1.5, 3))
|
||||
lenMid := int(float64(lenSml) * midRate)
|
||||
lenBig := int(float64(lenMid) * bigRate)
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 200,
|
||||
EachMaxLong: 1,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
maSml := ta.EMA(e.Close, lenSml)
|
||||
maMid := ta.EMA(e.Close, lenMid)
|
||||
maBig := ta.EMA(e.Close, lenBig)
|
||||
haO, _, _, haC := ta.HeikinAshi(e)
|
||||
haOpen := haO.Get(0)
|
||||
haClose := haC.Get(0)
|
||||
smlXmid := maSml.Cross(maMid)
|
||||
midXBig := maMid.Cross(maBig)
|
||||
|
||||
if smlXmid == 1 && haClose > maSml.Get(0) && haOpen < haClose {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "long",
|
||||
StopLossVal: haClose * 0.1,
|
||||
})
|
||||
} else if midXBig == 1 && haClose < maSml.Get(0) && haOpen > haClose {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exit"})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
3
demo/here.java
Normal file
3
demo/here.java
Normal file
@@ -0,0 +1,3 @@
|
||||
public static void main (String[] args) {
|
||||
System.out.println("Hello World2!");
|
||||
}
|
||||
43
demo/hft.go
Normal file
43
demo/hft.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/banbox/banbot/biz"
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg"
|
||||
"github.com/banbox/banexg/log"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func hft(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WsSubs: map[string]string{
|
||||
core.WsSubDepth: "",
|
||||
core.WsSubTrade: "",
|
||||
core.WsSubKLine: "",
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
log.Info(fmt.Sprintf("OnBar %v: %v", e.TimeStop, e.Close.Get(0)))
|
||||
},
|
||||
OnWsKline: func(s *strat.StratJob, pair string, k *banexg.Kline) {
|
||||
log.Info(fmt.Sprintf("OnWsKline %v: %v", k.Time, k.Close))
|
||||
s.OpenOrder(&strat.EnterReq{Tag: "long"})
|
||||
_, _, err := biz.GetOdMgr(s.Account).ProcessOrders(s)
|
||||
if err != nil {
|
||||
log.Error("process order fail", zap.Error(err))
|
||||
}
|
||||
},
|
||||
OnWsTrades: func(s *strat.StratJob, pair string, trades []*banexg.Trade) {
|
||||
last := trades[len(trades)-1]
|
||||
log.Info(fmt.Sprintf("OnWsTrades %v %v, %v", last.Timestamp, last.Price, last.Amount))
|
||||
},
|
||||
OnWsDepth: func(s *strat.StratJob, dep *banexg.OrderBook) {
|
||||
bp1, bm1 := dep.Bids.Price[0], dep.Bids.Size[0]
|
||||
ap1, am1 := dep.Asks.Price[0], dep.Asks.Size[0]
|
||||
log.Info(fmt.Sprintf("OnWsDepth %v %v, %v,, %v, %v", dep.TimeStamp, bp1, bm1, ap1, am1))
|
||||
},
|
||||
}
|
||||
}
|
||||
19
demo/hold.go
Normal file
19
demo/hold.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
)
|
||||
|
||||
func Hold(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
EachMaxLong: 1,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
if len(s.LongOrders) == 0 {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "hold",
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
37
demo/holdSl.go
Normal file
37
demo/holdSl.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package demo
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
func HoldSL(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 20,
|
||||
EachMaxLong: 1,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
ma5 := ta.VWMA(e.Close, e.Volume, 5)
|
||||
ma20 := ta.VWMA(e.Close, e.Volume, 10)
|
||||
maCrx := ma5.Cross(ma20)
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, 14).Get(0)
|
||||
|
||||
for _, od := range s.LongOrders {
|
||||
od.SetStopLoss(&ormo.ExitTrigger{
|
||||
Price: e.Close.Get(0) - atr*0.5,
|
||||
})
|
||||
}
|
||||
if maCrx == -1 && len(s.LongOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exit", Dirt: core.OdDirtLong})
|
||||
} else if maCrx == 1 || len(s.LongOrders) == 0 {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "long",
|
||||
StopLossVal: atr * 0.5,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
48
demo/limits.go
Normal file
48
demo/limits.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg/log"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func DemoV1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
dirt := -1.0
|
||||
limitRate := 0.001
|
||||
slRate := 0.005
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 30,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
if s.OrderNum == 0 {
|
||||
price := s.Env.Close.Get(0)
|
||||
limit := price * (1 - dirt*limitRate)
|
||||
stopLoss := price * (1 - dirt*slRate)
|
||||
err := s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "enter",
|
||||
Limit: limit,
|
||||
Short: dirt < 0,
|
||||
StopLoss: stopLoss,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("open fail", zap.Error(err))
|
||||
} else {
|
||||
log.Info("new order", zap.Float64("limit", limit), zap.Float64("stopLoss", stopLoss))
|
||||
}
|
||||
}
|
||||
},
|
||||
OnCheckExit: func(s *strat.StratJob, od *ormo.InOutOrder) *strat.ExitReq {
|
||||
price := s.Env.Close.Get(0)
|
||||
stopLoss := price * (1 - dirt*slRate)
|
||||
sl := od.GetStopLoss()
|
||||
if sl != nil && (stopLoss-sl.Price)*dirt > 0 {
|
||||
// 有盈利,调整跟踪止损
|
||||
log.Info("set stoploss", zap.Float64("val", stopLoss))
|
||||
sl.Price = stopLoss
|
||||
od.DirtyInfo = true
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
31
demo/ma_er.go
Normal file
31
demo/ma_er.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func DemoER(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
smlLen := int(pol.Def("smlLen", 9, core.PNorm(3, 10)))
|
||||
bigLen := int(pol.Def("bigLen", 23, core.PNorm(10, 40)))
|
||||
erUpp := pol.Def("erUpp", 0.13, core.PNorm(0.1, 0.7))
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 100,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
ma5 := ta.SMA(e.Close, smlLen)
|
||||
ma20 := ta.SMA(e.Close, bigLen)
|
||||
maCrx := ma5.Cross(ma20)
|
||||
|
||||
er := ta.ER(e.Close, 50).Get(0)
|
||||
|
||||
if maCrx == 1 && er < erUpp {
|
||||
s.OpenOrder(&strat.EnterReq{Tag: "open"})
|
||||
} else if maCrx == -1 {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exit"})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
86
demo/made.go
Normal file
86
demo/made.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func Made(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// 定义可调超参数
|
||||
fastMAPeriod := pol.DefInt("fast_ma_period", 5, core.PUniform(3, 10))
|
||||
slowMAPeriod := pol.DefInt("slow_ma_period", 20, core.PUniform(10, 40))
|
||||
atrPeriod := pol.DefInt("atr_period", 14, core.PUniform(7, 21))
|
||||
slRate := pol.Def("sl_rate", 2.0, core.PUniform(1.0, 4.0))
|
||||
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 100,
|
||||
EachMaxLong: 1,
|
||||
EachMaxShort: 1,
|
||||
DrawDownExit: true, // 启用回撤止盈
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
|
||||
// 计算技术指标
|
||||
maFast := ta.SMA(e.Close, fastMAPeriod)
|
||||
maSlow := ta.SMA(e.Close, slowMAPeriod)
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, atrPeriod)
|
||||
|
||||
// 计算均线交叉信号
|
||||
maCrossOver := maFast.Cross(maSlow) // 1 表示上穿
|
||||
maCrossUnder := maSlow.Cross(maFast) // 1 表示下穿
|
||||
|
||||
// 获取当前价格和ATR值
|
||||
currentPrice := e.Close.Get(0)
|
||||
currentATR := atr.Get(0)
|
||||
|
||||
// 多头入场信号:快线上穿慢线(金叉)
|
||||
if maCrossOver == 1 {
|
||||
if s.GetOrderNum(core.OdDirtShort) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{Dirt: core.OdDirtShort, Tag: "exit_short"})
|
||||
}
|
||||
if s.GetOrderNum(core.OdDirtLong) == 0 {
|
||||
stopLossPrice := currentPrice - currentATR*slRate
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "long",
|
||||
StopLoss: stopLossPrice,
|
||||
StopLossTag: "atr_sl_long",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 空头入场信号:快线下穿慢线(死叉)
|
||||
if maCrossUnder == 1 {
|
||||
if s.GetOrderNum(core.OdDirtLong) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{Dirt: core.OdDirtLong, Tag: "exit_long"})
|
||||
}
|
||||
if s.GetOrderNum(core.OdDirtShort) == 0 {
|
||||
stopLossPrice := currentPrice + currentATR*slRate
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "short",
|
||||
Short: true,
|
||||
StopLoss: stopLossPrice,
|
||||
StopLossTag: "atr_sl_short",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 多头出场信号:快线下穿慢线(死叉)
|
||||
if maCrossUnder == 1 && s.GetOrderNum(core.OdDirtLong) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Dirt: core.OdDirtLong,
|
||||
Tag: "exit_long",
|
||||
})
|
||||
}
|
||||
|
||||
// 空头出场信号:快线上穿慢线(金叉)
|
||||
if maCrossOver == 1 && s.GetOrderNum(core.OdDirtShort) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Dirt: core.OdDirtShort,
|
||||
Tag: "exit_short",
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
26
demo/main.go
Normal file
26
demo/main.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/strat"
|
||||
)
|
||||
|
||||
func init() {
|
||||
strat.AddStratGroup("demo", map[string]strat.FuncMakeStrat{
|
||||
"dca": DCA,
|
||||
"tmp": tmp,
|
||||
"01": DemoV1,
|
||||
"agg": BarAgg,
|
||||
"stat": BarStat,
|
||||
"demo": Demo,
|
||||
"demo_er": DemoER,
|
||||
"riskRw": fixRiskReward,
|
||||
"hold": Hold,
|
||||
"holdSL": HoldSL,
|
||||
"show": Show,
|
||||
"tmp1": Tmp1,
|
||||
"made": Made,
|
||||
"test": Test,
|
||||
"hft": hft,
|
||||
"TrailStop": TrailStop,
|
||||
})
|
||||
}
|
||||
97
demo/pairs_test.go
Normal file
97
demo/pairs_test.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/biz"
|
||||
"github.com/banbox/banbot/btime"
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/exg"
|
||||
"github.com/banbox/banbot/goods"
|
||||
"github.com/banbox/banbot/orm"
|
||||
"github.com/banbox/banexg/log"
|
||||
"go.uber.org/zap"
|
||||
"math/rand"
|
||||
"slices"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func genVolPairs(timeMS int64) []string {
|
||||
err := biz.SetupComs(&config.CmdArgs{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = orm.LoadMarkets(exg.Default, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ft := goods.VolumePairFilter{
|
||||
BaseFilter: goods.BaseFilter{Name: "VolumePairFilter"},
|
||||
BackPeriod: "3d",
|
||||
}
|
||||
core.SetRunMode(core.RunModeBackTest)
|
||||
core.SetRunEnv(core.RunEnvProd)
|
||||
btime.CurTimeMS = timeMS
|
||||
config.PairMgr.Cron = ""
|
||||
pairs, err := ft.GenSymbols(btime.UTCStamp())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res := make([]string, 0, len(pairs))
|
||||
for _, pair := range pairs {
|
||||
_, quote, _, _ := core.SplitSymbol(pair)
|
||||
if _, ok := config.StakeCurrencyMap[quote]; ok {
|
||||
res = append(res, pair)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func TestRandPairs(t *testing.T) {
|
||||
timeMS, _ := btime.ParseTimeMS("2021-11-01 00:00")
|
||||
pairs := genVolPairs(timeMS)
|
||||
total := len(pairs)
|
||||
half := pairs[:total/3]
|
||||
for i := range half {
|
||||
j := rand.Intn(i + 1)
|
||||
if i != j {
|
||||
half[i], half[j] = half[j], half[i]
|
||||
}
|
||||
}
|
||||
cutNum := 50
|
||||
if len(half) > cutNum {
|
||||
half = half[:cutNum]
|
||||
}
|
||||
log.Info("pairs", zap.Int("total", total), zap.Strings("arr", half))
|
||||
}
|
||||
|
||||
func TestPairsLocs(t *testing.T) {
|
||||
pairs := genVolPairs(time.Now().UnixMilli())
|
||||
//pairs48 := []string{"1000FLOKI/USDT:USDT", "1000LUNC/USDT:USDT", "1000PEPE/USDT:USDT", "1000SHIB/USDT:USDT", "1000XEC/USDT:USDT", "ADA/USDT:USDT", "APT/USDT:USDT", "ARB/USDT:USDT", "AVAX/USDT:USDT", "BADGER/USDT:USDT", "BCH/USDT:USDT", "BNB/USDT:USDT", "BOME/USDT:USDT", "BTC/USDT:USDT", "CFX/USDT:USDT", "DOGE/USDT:USDT", "DOT/USDT:USDT", "ETC/USDT:USDT", "ETH/USDT:USDT", "ETHFI/USDT:USDT", "FET/USDT:USDT", "FIL/USDT:USDT", "FTM/USDT:USDT", "GALA/USDT:USDT", "HIFI/USDT:USDT", "ICP/USDT:USDT", "ID/USDT:USDT", "JUP/USDT:USDT", "LINK/USDT:USDT", "LTC/USDT:USDT", "LUNA2/USDT:USDT", "MATIC/USDT:USDT", "NEAR/USDT:USDT", "ONDO/USDT:USDT", "OP/USDT:USDT", "ORDI/USDT:USDT", "PENDLE/USDT:USDT", "PIXEL/USDT:USDT", "POLYX/USDT:USDT", "RSR/USDT:USDT", "SAND/USDT:USDT", "SOL/USDT:USDT", "STX/USDT:USDT", "SUI/USDT:USDT", "TOKEN/USDT:USDT", "TON/USDT:USDT", "WIF/USDT:USDT", "WLD/USDT:USDT", "XRP/USDT:USDT", "YGG/USDT:USDT"}
|
||||
pairs170 := []string{"1000BONK/USDT:USDT", "1000FLOKI/USDT:USDT", "1000LUNC/USDT:USDT", "1000PEPE/USDT:USDT", "1000RATS/USDT:USDT", "1000XEC/USDT:USDT", "1INCH/USDT:USDT", "AAVE/USDT:USDT", "ACH/USDT:USDT", "ADA/USDT:USDT", "AGIX/USDT:USDT", "ALGO/USDT:USDT", "ANKR/USDT:USDT", "APE/USDT:USDT", "API3/USDT:USDT", "APT/USDT:USDT", "AR/USDT:USDT", "ARB/USDT:USDT", "ARPA/USDT:USDT", "ASTR/USDT:USDT", "ATOM/USDT:USDT", "AUCTION/USDT:USDT", "AVAX/USDT:USDT", "AXL/USDT:USDT", "AXS/USDT:USDT", "BADGER/USDT:USDT", "BAKE/USDT:USDT", "BCH/USDT:USDT", "BEAMX/USDT:USDT", "BEL/USDT:USDT", "BICO/USDT:USDT", "BLUR/USDT:USDT", "BNB/USDT:USDT", "BNX/USDT:USDT", "BOND/USDT:USDT", "BSV/USDT:USDT", "BTC/USDT:USDT", "CAKE/USDT:USDT", "CELO/USDT:USDT", "CFX/USDT:USDT", "CHR/USDT:USDT", "CHZ/USDT:USDT", "COMP/USDT:USDT", "CYBER/USDT:USDT", "DOGE/USDT:USDT", "DOT/USDT:USDT", "DUSK/USDT:USDT", "DYM/USDT:USDT", "EGLD/USDT:USDT", "ENA/USDT:USDT", "ENJ/USDT:USDT", "EOS/USDT:USDT", "ETC/USDT:USDT", "ETH/USDT:USDT", "ETHW/USDT:USDT", "FET/USDT:USDT", "FIL/USDT:USDT", "FLM/USDT:USDT", "FLOW/USDT:USDT", "FRONT/USDT:USDT", "FTM/USDT:USDT", "GAL/USDT:USDT", "GALA/USDT:USDT", "GAS/USDT:USDT", "GLM/USDT:USDT", "GMT/USDT:USDT", "GMX/USDT:USDT", "GRT/USDT:USDT", "HBAR/USDT:USDT", "HIFI/USDT:USDT", "HOOK/USDT:USDT", "HOT/USDT:USDT", "ICP/USDT:USDT", "ID/USDT:USDT", "ILV/USDT:USDT", "IMX/USDT:USDT", "INJ/USDT:USDT", "IOTA/USDT:USDT", "IOTX/USDT:USDT", "JASMY/USDT:USDT", "JOE/USDT:USDT", "JTO/USDT:USDT", "JUP/USDT:USDT", "KAS/USDT:USDT", "KAVA/USDT:USDT", "KEY/USDT:USDT", "KNC/USDT:USDT", "KSM/USDT:USDT", "LDO/USDT:USDT", "LEVER/USDT:USDT", "LINA/USDT:USDT", "LINK/USDT:USDT", "LPT/USDT:USDT", "LQTY/USDT:USDT", "LRC/USDT:USDT", "LTC/USDT:USDT", "LUNA2/USDT:USDT", "MAGIC/USDT:USDT", "MANA/USDT:USDT", "MANTA/USDT:USDT", "MASK/USDT:USDT", "MATIC/USDT:USDT", "MAV/USDT:USDT", "MEME/USDT:USDT", "METIS/USDT:USDT", "MINA/USDT:USDT", "MKR/USDT:USDT", "MTL/USDT:USDT", "MYRO/USDT:USDT", "NEO/USDT:USDT", "NKN/USDT:USDT", "OCEAN/USDT:USDT", "OM/USDT:USDT", "ONDO/USDT:USDT", "ONE/USDT:USDT", "OP/USDT:USDT", "ORDI/USDT:USDT", "PENDLE/USDT:USDT", "PEOPLE/USDT:USDT", "POLYX/USDT:USDT", "PYTH/USDT:USDT", "QNT/USDT:USDT", "QTUM/USDT:USDT", "RDNT/USDT:USDT", "REN/USDT:USDT", "RIF/USDT:USDT", "RLC/USDT:USDT", "RSR/USDT:USDT", "RUNE/USDT:USDT", "RVN/USDT:USDT", "SEI/USDT:USDT", "SKL/USDT:USDT", "SNX/USDT:USDT", "SPELL/USDT:USDT", "SSV/USDT:USDT", "STG/USDT:USDT", "STMX/USDT:USDT", "STORJ/USDT:USDT", "STX/USDT:USDT", "SUI/USDT:USDT", "SXP/USDT:USDT", "T/USDT:USDT", "THETA/USDT:USDT", "TIA/USDT:USDT", "TOKEN/USDT:USDT", "TON/USDT:USDT", "TRU/USDT:USDT", "TRX/USDT:USDT", "UMA/USDT:USDT", "VET/USDT:USDT", "WAVES/USDT:USDT", "WAXP/USDT:USDT", "WIF/USDT:USDT", "WOO/USDT:USDT", "XAI/USDT:USDT", "XLM/USDT:USDT", "XRP/USDT:USDT", "XTZ/USDT:USDT", "XVG/USDT:USDT", "YFI/USDT:USDT", "YGG/USDT:USDT", "ZEC/USDT:USDT", "ZEN/USDT:USDT", "ZETA/USDT:USDT", "ZIL/USDT:USDT", "ZRX/USDT:USDT"}
|
||||
fails := make([]string, 0, 10)
|
||||
idArr := make([]int, 0, 100)
|
||||
for _, p := range pairs170 {
|
||||
idx := slices.Index(pairs, p)
|
||||
if idx < 0 {
|
||||
fails = append(fails, p)
|
||||
} else {
|
||||
idArr = append(idArr, idx)
|
||||
}
|
||||
}
|
||||
log.Warn("pairs", zap.Int("total", len(pairs)), zap.Strings("unknown", fails))
|
||||
sort.Slice(idArr, func(i, j int) bool {
|
||||
return idArr[i] < idArr[j]
|
||||
})
|
||||
step := 10
|
||||
end, num := step, 0
|
||||
for _, v := range idArr {
|
||||
if v >= end {
|
||||
log.Info("range", zap.Int("to", end), zap.Int("num", num))
|
||||
num = 0
|
||||
end += step
|
||||
}
|
||||
num += 1
|
||||
}
|
||||
}
|
||||
63
demo/risk_reward.go
Normal file
63
demo/risk_reward.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func fixRiskReward(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
rewardRate := 4.0
|
||||
return &strat.TradeStrat{
|
||||
EachMaxLong: 1,
|
||||
WarmupNum: 30,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, 14).Get(0)
|
||||
rsi := ta.RSI50(e.Close, 14).Get(0)
|
||||
ma := ta.SMA(e.Close, 5).Get(0)
|
||||
maMid := ta.SMA(e.Close, 10).Get(0)
|
||||
maBig := ta.SMA(e.Close, 40).Get(0)
|
||||
c := e.Close.Get(0)
|
||||
if s.OrderNum == 0 && maMid > maBig && rsi > 15 && c < ma {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "long",
|
||||
StopLossVal: atr,
|
||||
StopLossTag: "init",
|
||||
})
|
||||
}
|
||||
},
|
||||
OnCheckExit: func(s *strat.StratJob, od *ormo.InOutOrder) *strat.ExitReq {
|
||||
sl := od.GetStopLoss()
|
||||
if sl.Tag == "take" {
|
||||
// 已设置止盈
|
||||
return nil
|
||||
}
|
||||
if sl.Tag == "init" {
|
||||
// 检查是否回本,如果是,设置止损到成本线
|
||||
if od.ProfitRate > 0 {
|
||||
// 保存初始止损空间
|
||||
od.SetInfo("initSL", sl.Range)
|
||||
feeRate := od.Enter.FeeQuote * 2 / od.EnterCost()
|
||||
slPrice := od.Enter.Average * (1 + feeRate)
|
||||
od.SetStopLoss(&ormo.ExitTrigger{
|
||||
Price: slPrice,
|
||||
Tag: "break_even",
|
||||
})
|
||||
}
|
||||
} else {
|
||||
//已设置成本止损,检查是否触发止盈
|
||||
slRange := od.GetInfoFloat64("initSL")
|
||||
if od.Profit > slRange*rewardRate {
|
||||
// 触发止盈线,设置止盈线止损
|
||||
od.SetStopLoss(&ormo.ExitTrigger{
|
||||
Price: od.Enter.Average + slRange*rewardRate,
|
||||
Tag: "take",
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
25
demo/sample.go
Normal file
25
demo/sample.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func Sample(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 100,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
ma5 := ta.SMA(e.Close, 5)
|
||||
ma20 := ta.SMA(e.Close, 20)
|
||||
maCrx := ma5.Cross(ma20)
|
||||
|
||||
if maCrx == 1 {
|
||||
s.OpenOrder(&strat.EnterReq{Tag: "open"})
|
||||
} else if maCrx == -1 {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exit"})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
45
demo/show.go
Normal file
45
demo/show.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/btime"
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg/log"
|
||||
"go.uber.org/zap"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func Show(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
pairMap := make(map[string]int)
|
||||
var copied []string
|
||||
var lastMS int64
|
||||
var lockPair sync.Mutex
|
||||
return &strat.TradeStrat{
|
||||
EachMaxLong: 1,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
lockPair.Lock()
|
||||
base, _, _, _ := core.SplitSymbol(s.Symbol.Symbol)
|
||||
pairMap[base] = 0
|
||||
lockPair.Unlock()
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
curMS := s.Env.TimeStop
|
||||
if curMS > lastMS {
|
||||
if len(copied) > 0 {
|
||||
date := btime.ToDateStr(lastMS, core.DefaultDateFmt)
|
||||
lockPair.Lock()
|
||||
totalNum := len(pairMap)
|
||||
lockPair.Unlock()
|
||||
log.Info("OnBar", zap.String("date", date), zap.Int("got", len(copied)),
|
||||
zap.Int("total", totalNum), zap.String("copied", strings.Join(copied, ",")))
|
||||
}
|
||||
lastMS = curMS
|
||||
copied = nil
|
||||
}
|
||||
base, _, _, _ := core.SplitSymbol(s.Symbol.Symbol)
|
||||
copied = append(copied, base)
|
||||
},
|
||||
}
|
||||
}
|
||||
45
demo/test.go
Normal file
45
demo/test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func Test(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
//- 超参(极简)
|
||||
highestDay := pol.DefInt("highest day", 20, core.PNorm(10, 40))
|
||||
atrN := pol.DefInt("atrn", 14, core.PNorm(10, 30))
|
||||
slNATR := pol.Def("sl natr", 2.0, core.PNorm(0.8, 4.0))
|
||||
tpNATR := pol.Def("tp natr", 2.5, core.PNorm(1.0, 5.0))
|
||||
//预热:技术指标所需长度的最大值 + 余量
|
||||
warm := max(highestDay+1, atrN+1, 20) + 2
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: warm,
|
||||
RunTimeFrames: []string{"15m"},
|
||||
HedgeOff: true,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
if e.Close.Len() <= warm {
|
||||
return
|
||||
}
|
||||
last := e.Close.Get(0)
|
||||
hhPrev := ta.Highest(e.High, highestDay).Get(1)
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, atrN).Get(0)
|
||||
//仅在没有任何多单(含未成交挂单)时考虑新挂单倮京沋塑
|
||||
if len(s.LongOrders) == 0 {
|
||||
//只在价格位于前高下方时挂“突破买入"的 stop 触发单
|
||||
if last < hhPrev && atr > 0 {
|
||||
entry := hhPrev
|
||||
_ = s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "Long",
|
||||
Stop: entry,
|
||||
StopLossVal: slNATR * atr,
|
||||
TakeProfitVal: tpNATR * atr,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
35
demo/tmp.go
Normal file
35
demo/tmp.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg/log"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func tmp(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
price := 2.236
|
||||
return &strat.TradeStrat{
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "BUY",
|
||||
OrderType: core.OrderTypeLimit,
|
||||
Limit: price,
|
||||
Amount: 4.65000,
|
||||
TakeProfit: price * 1.01,
|
||||
TakeProfitLimit: price * 1.012,
|
||||
StopLoss: price * 0.99,
|
||||
Log: true,
|
||||
})
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "all",
|
||||
})
|
||||
ods, err := strat.GetHistOrders(ormo.GetHistOrdersArgs{
|
||||
Limit: 3,
|
||||
})
|
||||
log.Info("get hist", zap.Int("num", len(ods)), zap.Error(err))
|
||||
},
|
||||
}
|
||||
}
|
||||
29
demo/tmp1.go
Normal file
29
demo/tmp1.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"math"
|
||||
)
|
||||
|
||||
func Tmp1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 100,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
flag := math.Round(math.Mod(float64(e.TimeStop/e.TFMSecs), 2))
|
||||
if flag == 1 {
|
||||
s.OpenOrder(&strat.EnterReq{Tag: "long"})
|
||||
if len(s.ShortOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exitS", Dirt: core.OdDirtShort})
|
||||
}
|
||||
} else {
|
||||
s.OpenOrder(&strat.EnterReq{Tag: "short", Short: true})
|
||||
if len(s.LongOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{Tag: "exitL", Dirt: core.OdDirtLong})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
27
demo/trailing_stop.go
Normal file
27
demo/trailing_stop.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func TrailStop(p *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: 100,
|
||||
TimeFrames: "1h",
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, 14).Get(0)
|
||||
atrPct := atr * 100 / e.Close.Get(0)
|
||||
k, d, _ := ta.KDJ(e.High, e.Low, e.Close, 9, 3, 3)
|
||||
kdCross := k.Cross(d)
|
||||
if len(s.LongOrders) == 0 && kdCross == 1 {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "long",
|
||||
CallbackPct: min(10, 5*atrPct),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user