init
This commit is contained in:
74
org/sf/01.go
Normal file
74
org/sf/01.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
/*
|
||||
此策略核心是同时突破均线和n周期最高/低价时入场。然后跟踪止损出场。
|
||||
适合品种:['AG888', 'RB888', 'I888', 'J888', 'A888', 'Y888', 'JM888', 'PP888', 'C888', 'V888', 'JD888', 'SS888',
|
||||
|
||||
'EB888', 'BC888', 'SC888', 'PG888', 'EG888', 'LH888', 'SI888', 'BR888', 'EC888', 'LC888']
|
||||
*/
|
||||
|
||||
func SF01V2(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa2 = int(pol.Def("ma2", 130, core.PNorm(50, 200)))
|
||||
lenExtrm = int(pol.Def("extrm", 240, core.PNorm(100, 400)))
|
||||
lenAtr = int(pol.Def("atr", 14, core.PNorm(7, 40)))
|
||||
initSl := pol.Def("initSl", 100, core.PNorm(50, 150))
|
||||
baseAtrLen := int(float64(lenAtr) * 4.3)
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenMa2, lenExtrm, baseAtrLen),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
//date := btime.ToDateStrLoc(e.TimeStop, "")
|
||||
maVal := ta.SMA(e.Close, lenMa2).Get(1)
|
||||
|
||||
openUp := e.High.Back(1).Sub(e.Close.Back(1)).Add(e.Open)
|
||||
openDn := e.Low.Back(1).Sub(e.Close.Back(1)).Add(e.Open)
|
||||
hh1 := ta.Highest(openUp, lenExtrm).Get(1)
|
||||
ll1 := ta.Lowest(openDn, lenExtrm).Get(1)
|
||||
c := e.Close.Get(1)
|
||||
midPrice := (e.High.Get(1) + e.Low.Get(1)) * 0.5
|
||||
|
||||
width := e.High.Sub(e.Low)
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
|
||||
var openDirt = 0.0
|
||||
if width.Get(1) > width.Get(2) {
|
||||
// 价差是否增大
|
||||
if len(s.LongOrders) == 0 && c > max(maVal, hh1) && midPrice > e.High.Get(2) {
|
||||
// 价格突破均线、周期内最高价;中间价>前bar最高
|
||||
openDirt = 1
|
||||
m.TrialLong(e.Close.Get(0))
|
||||
} else if len(s.ShortOrders) == 0 && c < min(maVal, ll1) && midPrice < e.Low.Get(2) {
|
||||
// 价格跌破均线、周期内最低价;中间价<前bar最低
|
||||
openDirt = -1
|
||||
m.TrialShort(e.Close.Get(0))
|
||||
}
|
||||
}
|
||||
|
||||
stopLong, stopShort := m.CalcSL2(s, lenAtr, baseAtrLen, slPow, slRate)
|
||||
if s.IsWarmUp {
|
||||
return
|
||||
}
|
||||
if openDirt != 0 {
|
||||
//log.Info(fmt.Sprintf("%s, open, slVal: %.1f%% slUnit: %.2f%%",
|
||||
// s.Symbols.Symbols, slUnit*m.InitSLTR*100/c, slUnit*100/c))
|
||||
com.FastOpen(s, openDirt, stopLong, stopShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, stopLong, stopShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
87
org/sf/02.go
Normal file
87
org/sf/02.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg/log"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
/*
|
||||
AROON_UP和AROON_DN,反映了一段时间内出现最高价和最低价距离当前时间的远近。
|
||||
数值越大,说明发生的时间越近;反之,数值越小,说明发生的时间越远。
|
||||
AROON为二者的差值,大于0,说明最高价出现在最低价之后,离现在更近;
|
||||
反之,则说明最高价出现在最低价之前,离现在更远。
|
||||
|
||||
使用方法
|
||||
(1) 当 AROON_UP 上穿 70,并且 AROON>0,说明上涨趋势形成,产生买入信号;
|
||||
(2) 当 AROON_DOWN 上穿 70,并且 AROON<0,说明下跌趋势形成,产生卖出信号;
|
||||
(3) 当 AROON_UP 下穿 30,并且 AROON<0,说明上涨趋势减弱,可能反转下跌,产生卖出信号;
|
||||
(4) 当 AROON_DOWN 下穿 30,并且 AROON>0,说明下跌趋势减弱,可能反转上涨,产生买入信号。
|
||||
|
||||
在币圈市场15m/1h/4h上均不稳定,且交易次数太少
|
||||
*/
|
||||
|
||||
func SF02V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 250
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: lenMa1 + 1,
|
||||
MinTfScore: 0.75,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
cXMa := e.Close.Get(0) - ta.EMA(e.Close, lenMa1).Get(0)
|
||||
arnUp, arnOsc, arnDn := ta.Aroon(e.High, e.Low, lenMa1)
|
||||
upX70 := arnUp.Cross(70)
|
||||
upX30 := arnUp.Cross(30)
|
||||
upX50 := arnUp.Cross(50)
|
||||
dnX70 := arnDn.Cross(70)
|
||||
dnX30 := arnDn.Cross(30)
|
||||
dnX50 := arnDn.Cross(50)
|
||||
oscVal := arnOsc.Get(0)
|
||||
|
||||
openDirt := 0.0
|
||||
if len(s.LongOrders) == 0 && cXMa > 0 && oscVal > 0 {
|
||||
if upX70 == 1 || dnX30 == -1 {
|
||||
// (1) 当 AROON_UP 上穿 70,并且 AROON>0,说明上涨趋势形成,产生买入信号;
|
||||
// (4) 当 AROON_DOWN 下穿 30,并且 AROON>0,说明下跌趋势减弱,可能反转上涨,产生买入信号。
|
||||
openDirt = 1
|
||||
}
|
||||
} else if len(s.ShortOrders) == 0 && cXMa < 0 && oscVal < 0 {
|
||||
if dnX70 == 1 || upX30 == -1 {
|
||||
//if upX30 == -1 {
|
||||
//(2) 当 AROON_DOWN 上穿 70,并且 AROON<0,说明下跌趋势形成,产生卖出信号;
|
||||
//(3) 当 AROON_UP 下穿 30,并且 AROON<0,说明上涨趋势减弱,可能反转下跌,产生卖出信号;
|
||||
openDirt = -1
|
||||
}
|
||||
}
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, 0, 0, 0)
|
||||
}
|
||||
closeDirt := 0
|
||||
if len(s.LongOrders) > 0 && oscVal > 0 && upX50 == -1 {
|
||||
// 当AROON大于0且AROON_UP死叉50,平多;
|
||||
closeDirt = 1
|
||||
}
|
||||
if len(s.LongOrders) > 0 && oscVal < 0 && dnX50 == -1 {
|
||||
// 当AROON小于0且AROON_DN死叉50,平空;
|
||||
closeDirt = -1
|
||||
}
|
||||
if closeDirt != 0 {
|
||||
tag := "xlong"
|
||||
if closeDirt < 0 {
|
||||
tag = "xshort"
|
||||
}
|
||||
err := s.CloseOrders(&strat.ExitReq{
|
||||
Tag: tag,
|
||||
Dirt: closeDirt,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("close fail", zap.Error(err))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
85
org/sf/03.go
Normal file
85
org/sf/03.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
使用一定周期的变化率均线+价格均线突破作为信号。
|
||||
原版只有盈利卖出信号。没有止损。
|
||||
tb测试未复现文章中的净值曲线
|
||||
*/
|
||||
|
||||
func SF03V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 100
|
||||
lenMa2 = 800
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: lenMa1 + lenMa2,
|
||||
MinTfScore: 0.75,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
ma1 := ta.SMA(e.Close, lenMa2)
|
||||
ma2 := ta.SMA(ma1, lenMa1)
|
||||
maSub := ma1.Get(0) - ma2.Get(0)
|
||||
|
||||
chg := e.High.To("chg", 0)
|
||||
if !chg.Cached() {
|
||||
h, l := e.High.Get(0), e.Low.Get(0)
|
||||
h1, l1 := e.High.Get(1), e.Low.Get(1)
|
||||
tr := max(math.Abs(h-h1), math.Abs(l-l1))
|
||||
dbf, kbf := 0.0, 0.0
|
||||
if h+l > h1+l1 {
|
||||
dbf = tr
|
||||
} else {
|
||||
kbf = tr
|
||||
}
|
||||
chgVal := (dbf - kbf) / (dbf + kbf + float64(lenMa1)*2)
|
||||
chg.Set(chgVal)
|
||||
}
|
||||
maChg := ta.SMA(chg, lenMa1)
|
||||
maChg2 := ta.EMA(chg, lenMa1)
|
||||
chgVal := chg.Get(0)
|
||||
maChgSub := maChg.Get(0) - maChg2.Get(0)
|
||||
|
||||
c := e.Close.Get(0)
|
||||
cSubMa := c - ma1.Get(0)
|
||||
openDirt := 0.0
|
||||
stopLoss := 0.0
|
||||
if len(s.LongOrders) == 0 && cSubMa > 0 && maSub > 0 && chgVal > 0 && maChgSub > 0 {
|
||||
openDirt = 1
|
||||
stopLoss = c * 0.95
|
||||
} else if len(s.ShortOrders) == 0 && cSubMa < 0 && maSub < 0 && chgVal < 0 && maChgSub < 0 {
|
||||
openDirt = -1
|
||||
stopLoss = c * 1.05
|
||||
}
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, stopLoss, stopLoss, 0)
|
||||
}
|
||||
if len(s.LongOrders) > 0 && cSubMa < 0 {
|
||||
for _, od := range s.LongOrders {
|
||||
if c/od.InitPrice > 1.01 {
|
||||
_ = s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "exitL",
|
||||
OrderID: od.ID,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s.ShortOrders) > 0 && cSubMa > 0 {
|
||||
for _, od := range s.ShortOrders {
|
||||
if c/od.InitPrice < 0.99 {
|
||||
_ = s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "exitS",
|
||||
OrderID: od.ID,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
61
org/sf/04.go
Normal file
61
org/sf/04.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
最高价突破上轨,且快线高于慢线时,开多。
|
||||
使用前n个low作为止损。
|
||||
*/
|
||||
|
||||
func SF04V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 20
|
||||
lenMa2 = 230
|
||||
X := 3.0
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: lenMa1 + lenMa2,
|
||||
MinTfScore: 0.75,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenMa1)
|
||||
ma1 := ta.SMA(e.Close, lenMa1)
|
||||
ma2 := ta.SMA(e.Close, lenMa2)
|
||||
c := e.Close.Get(0)
|
||||
upperBand := c + X*atr.Get(0)
|
||||
lowerBand := c - X*atr.Get(0)
|
||||
stopLong := e.Low.Get(lenMa2)
|
||||
stopShort := e.High.Get(lenMa2)
|
||||
|
||||
maSub := ma1.Get(0) - ma2.Get(0)
|
||||
h, h1 := e.High.Get(0), e.High.Get(1)
|
||||
l, l1 := e.Low.Get(0), e.Low.Get(1)
|
||||
|
||||
openPrice := 0.0
|
||||
if len(s.LongOrders) == 0 && h >= upperBand && maSub > 0 && h >= h1 {
|
||||
openPrice = max(c, upperBand, e.High.Get(lenMa1))
|
||||
} else if len(s.ShortOrders) == 0 && l < lowerBand && maSub < 0 && l <= l1 {
|
||||
openPrice = -min(c, lowerBand, e.Low.Get(lenMa1))
|
||||
}
|
||||
if openPrice != 0 {
|
||||
com.FastOpen(s, openPrice, stopLong, stopShort, math.Abs(openPrice))
|
||||
}
|
||||
for _, od := range s.LongOrders {
|
||||
if l >= od.InitPrice && l <= stopLong {
|
||||
od.SetStopLoss(&ormo.ExitTrigger{Price: stopLong})
|
||||
}
|
||||
}
|
||||
for _, od := range s.ShortOrders {
|
||||
if h <= od.InitPrice && h >= stopShort {
|
||||
od.SetStopLoss(&ormo.ExitTrigger{Price: stopShort})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
83
org/sf/05.go
Normal file
83
org/sf/05.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banexg/log"
|
||||
ta "github.com/banbox/banta"
|
||||
"go.uber.org/zap"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
策略说明:
|
||||
|
||||
基于K线加权均值的支撑阻力线的突破系统
|
||||
|
||||
1. 支撑线 = 周期范围内的K线加权均值 - ( 最高价 - K线加权均值)
|
||||
2. 阻力线 = 周期范围内的K线加权均值 + ( K线加权均值 - 最低价)
|
||||
入场
|
||||
1. 当价格向上突破阻力线做多
|
||||
2. 当价格向下突破支撑线做空
|
||||
出场
|
||||
1. 趋势反转即反向突破时出场
|
||||
2. 基于ATR的一定倍数的止盈
|
||||
*/
|
||||
func SF05V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 250
|
||||
trs := 30.0
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: lenMa1,
|
||||
MinTfScore: 0.75,
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
h, l, c := e.High.Get(0), e.Low.Get(0), e.Close.Get(0)
|
||||
avgP := (h + l + c*2) / 4
|
||||
rsv := e.Close.To("rsv2", 0)
|
||||
rsv.Set(avgP*2 - l)
|
||||
rs := ta.Highest(rsv, lenMa1)
|
||||
stv := e.Close.To("stv", 0)
|
||||
stv.Set(avgP*2 - h)
|
||||
st := ta.Lowest(stv, lenMa1)
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenMa1).Get(0)
|
||||
|
||||
openPrice := 0.0
|
||||
if len(s.LongOrders) == 0 && h > rs.Get(0) {
|
||||
openPrice = max(c, rs.Get(0))
|
||||
} else if len(s.ShortOrders) == 0 && l < st.Get(0) {
|
||||
openPrice = -min(c, st.Get(0))
|
||||
}
|
||||
slVal := atr * trs
|
||||
takeLong, takeShort := c+slVal, c-slVal
|
||||
if openPrice != 0 {
|
||||
openTag := "long"
|
||||
takeProfit := takeLong
|
||||
if openPrice < 0 {
|
||||
openTag = "short"
|
||||
takeProfit = takeShort
|
||||
}
|
||||
err := s.OpenOrder(&strat.EnterReq{
|
||||
Tag: openTag,
|
||||
Short: openPrice < 0,
|
||||
Limit: math.Abs(openPrice),
|
||||
TakeProfit: takeProfit,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("open fail", zap.Error(err))
|
||||
}
|
||||
exitDirt := 1
|
||||
exitTag := "exitL"
|
||||
if openPrice > 0 {
|
||||
exitDirt = -1
|
||||
exitTag = "exitS"
|
||||
}
|
||||
_ = s.CloseOrders(&strat.ExitReq{
|
||||
Tag: exitTag,
|
||||
Dirt: exitDirt,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
67
org/sf/06.go
Normal file
67
org/sf/06.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
/*
|
||||
同时突破:两个周期的最高价、均线
|
||||
跟踪止损退出
|
||||
*/
|
||||
|
||||
func SF06V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 30
|
||||
lenMaRate = 3
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
lenAtr = max(15, lenMa1/2)
|
||||
baseAtrLen := lenAtr * 13 / 5
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenMa2, baseAtrLen),
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(20, 0.5, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
hh1 := ta.Highest(e.High.Back(lenMa1), lenMa1)
|
||||
hh2 := ta.Highest(e.High.Back(lenMa2), lenMa2)
|
||||
ll1 := ta.Lowest(e.Low.Back(lenMa1), lenMa1)
|
||||
ll2 := ta.Lowest(e.Low.Back(lenMa2), lenMa2)
|
||||
hh1Val, hh2Val, ll1Val, ll2Val := hh1.Get(0), hh2.Get(0), ll1.Get(0), ll2.Get(0)
|
||||
|
||||
c, c1 := e.Close.Get(0), e.Close.Get(1)
|
||||
|
||||
entLong := c > max(hh1Val, hh2Val, e.Close.Get(lenMa1))
|
||||
entShort := c < min(ll1Val, ll2Val, e.Close.Get(lenMa1))
|
||||
|
||||
fltLong := c1 > min(hh1Val, hh2Val)
|
||||
fltShort := c1 < max(ll1Val, ll2Val)
|
||||
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
|
||||
openDirt := 0.0
|
||||
if len(s.LongOrders) == 0 && hh1Val > hh2Val && entLong && fltLong {
|
||||
openDirt = 1
|
||||
m.TrialLong(c)
|
||||
} else if len(s.ShortOrders) == 0 && ll1Val < ll2Val && entShort && fltShort {
|
||||
openDirt = -1
|
||||
m.TrialShort(c)
|
||||
}
|
||||
|
||||
stopLong, stopShort := m.CalcSL2(s, lenAtr, baseAtrLen, 0.5, 0.5)
|
||||
if openDirt != 0 {
|
||||
//log.Info(fmt.Sprintf("open, slVal: %.1f%% trRate: %.2f atr: %.1f%%",
|
||||
// atrBase*atrRate*100/c, atrRate, atrBase*100/c))
|
||||
com.FastOpen(s, openDirt, stopLong, stopShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, stopLong, stopShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
75
org/sf/08.go
Normal file
75
org/sf/08.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
func SF08V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = int(pol.Def("ma1", 139, core.PNorm(10, 300)))
|
||||
lenMaRate = pol.Def("maRate", 2.47, core.PNorm(1.5, 5))
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
lenExtrm = int(pol.Def("extrm", 30, core.PNorm(10, 300)))
|
||||
|
||||
lenAtr = int(pol.Def("atr", 20, core.PNorm(7, 40)))
|
||||
baseAtrLen := int(float64(lenAtr) * 4.3)
|
||||
|
||||
initSl := pol.Def("initSl", 90, core.PNorm(30, 150))
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenMa2+lenMa1, baseAtrLen),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
ma := ta.SMA(e.Close, lenMa2).Get(0)
|
||||
kk, _, krsv := ta.KDJBy(e.High, e.Low, e.Close, lenMa2, lenMa1, lenMa1, "sma")
|
||||
kdX := krsv.Cross(kk)
|
||||
|
||||
hh := ta.Highest(e.High, lenExtrm)
|
||||
ll := ta.Lowest(e.Low, lenExtrm)
|
||||
hd := e.Close.To("hd", 0)
|
||||
ld := e.Close.To("ld", 0)
|
||||
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
|
||||
if kdX == 1 {
|
||||
hd.Set(hh.Get(0))
|
||||
} else if kdX == -1 {
|
||||
ld.Set(ll.Get(0))
|
||||
}
|
||||
|
||||
h, l, c := e.High.Get(0), e.Low.Get(0), e.Close.Get(0)
|
||||
hdVal1, ldVal1 := hd.Get(1), ld.Get(1)
|
||||
openPrice := 0.0
|
||||
if len(s.LongOrders) == 0 && kdX == 2 && h >= hdVal1 && hdVal1 > 0 && c > ma {
|
||||
openPrice = hdVal1
|
||||
m.TrialLong(hdVal1)
|
||||
} else if len(s.ShortOrders) == 0 && kdX == -2 && l < ldVal1 && ldVal1 > 0 && c < ma {
|
||||
openPrice = -ldVal1
|
||||
m.TrialShort(ldVal1)
|
||||
}
|
||||
|
||||
stopLong, stopShort := m.CalcSL2(s, lenAtr, baseAtrLen, slPow, slRate)
|
||||
if openPrice != 0 {
|
||||
entPrice := math.Abs(openPrice)
|
||||
//if (entPrice-c)*openPrice < 0 {
|
||||
// // 限价入场
|
||||
// slVal := stopShort - entPrice
|
||||
// stopLong, stopShort = entPrice-slVal, entPrice+slVal
|
||||
//}
|
||||
com.FastOpen(s, openPrice, stopLong, stopShort, entPrice)
|
||||
}
|
||||
setAllStopLoss(s, stopLong, stopShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
72
org/sf/10.go
Normal file
72
org/sf/10.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
type Band10 struct {
|
||||
Band float64
|
||||
PBand float64
|
||||
BandUp float64
|
||||
BandDn float64
|
||||
DAtr float64
|
||||
}
|
||||
|
||||
func SF10V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
var lenDayAtr = 30
|
||||
var k = 1.0
|
||||
//var slRate = 1.5
|
||||
//lenAtr = max(15, lenMa1/2)
|
||||
//baseAtrLen := int(math.Round(float64(lenAtr) * 4.3))
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: 30,
|
||||
MinTfScore: 0.75,
|
||||
DrawDownExit: true,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &Band10{}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", 30},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*Band10)
|
||||
h, l, c := e.High.Get(0), e.Low.Get(0), e.Close.Get(0)
|
||||
openDirt := 0.0
|
||||
if m.Band > m.PBand {
|
||||
l1, h1 := e.Low.Get(1), e.High.Get(1)
|
||||
if len(s.LongOrders) == 0 && h >= m.BandUp && l1 < m.BandUp {
|
||||
openDirt = 1
|
||||
} else if len(s.ShortOrders) == 0 && l <= m.BandDn && h1 > m.BandDn {
|
||||
openDirt = -1
|
||||
}
|
||||
if openDirt != 0 {
|
||||
stopLong, stopShort := c-m.Band, c+m.Band
|
||||
com.FastOpen(s, openDirt, stopLong, stopShort, 0)
|
||||
}
|
||||
}
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
m, _ := s.More.(*Band10)
|
||||
h, l, c := e.High.Get(0), e.Low.Get(0), e.Close.Get(0)
|
||||
m.PBand = m.Band
|
||||
m.Band = max(h-c, c-l) * k
|
||||
m.BandUp, m.BandDn = c+m.Band, c-m.Band
|
||||
m.DAtr = ta.ATR(e.High, e.Low, e.Close, lenDayAtr).Get(0) * 100 / c
|
||||
},
|
||||
GetDrawDownExitRate: func(s *strat.StratJob, od *ormo.InOutOrder, maxChg float64) float64 {
|
||||
m, _ := s.More.(*Band10)
|
||||
//rate := math.Sqrt(m.DAtr)
|
||||
rate := m.DAtr * 5
|
||||
return strat.CalcDrawDownExitRate(maxChg / rate)
|
||||
},
|
||||
}
|
||||
}
|
||||
80
org/sf/14.go
Normal file
80
org/sf/14.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
type More14 struct {
|
||||
*com.TRS
|
||||
dirt int
|
||||
btm float64
|
||||
top float64
|
||||
hh float64
|
||||
ll float64
|
||||
}
|
||||
|
||||
func SF14V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenAtr = 50
|
||||
atrAlpha := 20.0
|
||||
atrN := 3.0
|
||||
lenAtr2 := 15
|
||||
baseAtrLen := int(math.Round(float64(lenAtr2) * 4.3))
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: baseAtrLen,
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More14{
|
||||
TRS: com.NewTRS(30, 0.5, 5),
|
||||
dirt: 1,
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*More14)
|
||||
atrVal := ta.ATR(e.High, e.Low, e.Close, lenAtr).Get(0)
|
||||
hl2 := (e.High.Get(0) + e.Low.Get(0)) / 2
|
||||
c, o := e.Close.Get(0), e.Open.Get(0)
|
||||
h, l := e.High.Get(0), e.Low.Get(0)
|
||||
curBtm := hl2 - atrVal*atrAlpha
|
||||
curTop := hl2 + atrVal*atrAlpha
|
||||
|
||||
openDirt := 0.0
|
||||
if m.btm == 0 || math.IsNaN(m.btm) {
|
||||
m.btm = curBtm
|
||||
m.top = curTop
|
||||
} else {
|
||||
if m.dirt == 1 && len(s.LongOrders) == 0 && h >= m.hh {
|
||||
openDirt = 1
|
||||
m.TrialLong(c)
|
||||
} else if m.dirt == -1 && len(s.ShortOrders) == 0 && l <= m.ll {
|
||||
openDirt = -1
|
||||
m.TrialShort(c)
|
||||
}
|
||||
if m.dirt == -1 && c > m.top {
|
||||
m.dirt = 1
|
||||
} else if m.dirt == 1 && c < m.btm {
|
||||
m.dirt = -1
|
||||
}
|
||||
if c > m.btm {
|
||||
m.btm = max(m.btm, curBtm)
|
||||
} else {
|
||||
m.top = min(m.top, curTop)
|
||||
}
|
||||
}
|
||||
m.hh = o + atrVal*atrN
|
||||
m.ll = o - atrVal*atrN
|
||||
|
||||
slLong, slShort := m.CalcSL2(s, lenAtr2, baseAtrLen, 0.5, 0.5)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
67
org/sf/17.go
Normal file
67
org/sf/17.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
func SF17V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = int(pol.Def("ma1", 62, core.PNorm(10, 300)))
|
||||
lenMaRate = pol.Def("maRate", 4.34, core.PNorm(1.5, 5))
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
|
||||
lenAtr = int(pol.Def("atr", 20, core.PNorm(7, 40)))
|
||||
baseAtrLen := int(float64(lenAtr) * 4.3)
|
||||
|
||||
initSl := pol.Def("initSl", 101, core.PNorm(30, 150))
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenMa2*2, baseAtrLen),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
avgPrice := ta.AvgPrice(e)
|
||||
ma1 := ta.SMA(avgPrice, lenMa1)
|
||||
ma2 := ta.EMA(ma1, lenMa1)
|
||||
maLong1 := ta.SMA(avgPrice, lenMa2)
|
||||
maLong2 := ta.EMA(maLong1, lenMa2)
|
||||
|
||||
maRange := ma1.Sub(maLong2)
|
||||
maRangeE := ta.EMA(maRange, lenMa1)
|
||||
hh := ta.Highest(e.High, lenMa2)
|
||||
ll := ta.Lowest(e.Low, lenMa2)
|
||||
|
||||
maRangeVal, maRangeEVal := maRange.Get(0), maRangeE.Get(0)
|
||||
ma1Val, ma2Val, maLong1Val, maLong2Val := ma1.Get(0), ma2.Get(0), maLong1.Get(0), maLong2.Get(0)
|
||||
maSub, longSub, otherSub := ma1Val-ma2Val, maLong1Val-maLong2Val, ma2Val-maLong2Val
|
||||
rangeSub := maRangeVal - maRangeEVal
|
||||
hhSub, llSub := e.High.Get(0)-hh.Get(0), e.Low.Get(0)-ll.Get(0)
|
||||
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
|
||||
openDirt := 0.0
|
||||
if len(s.LongOrders) == 0 && hhSub >= 0 && rangeSub > 0 && maRangeVal > 0 && maSub > 0 && longSub > 0 && otherSub > 0 {
|
||||
openDirt = 1
|
||||
m.TrialLong(e.Close.Get(0))
|
||||
} else if len(s.ShortOrders) == 0 && llSub <= 0 && rangeSub < 0 && maRangeVal < 0 && maSub < 0 && longSub < 0 && otherSub < 0 {
|
||||
openDirt = -1
|
||||
m.TrialShort(e.Close.Get(0))
|
||||
}
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, 0, 0, 0)
|
||||
}
|
||||
|
||||
stopLong, stopShort := m.CalcSL2(s, lenAtr, baseAtrLen, slPow, slRate)
|
||||
setAllStopLoss(s, stopLong, stopShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
137
org/sf/18.go
Normal file
137
org/sf/18.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"slices"
|
||||
)
|
||||
|
||||
/*策略思想:
|
||||
|
||||
1.使用变量将MACD的快慢均线交叉点记录,
|
||||
然后获取上次交叉到本次交叉之间的周期数。
|
||||
计算此周期内的高低点,
|
||||
当价格突破交叉后的高低点时进场,当MACD金叉(死叉)时出场;
|
||||
2.当MACD出现顶底背离时,开多开空;
|
||||
|
||||
核心计算:1.MACD交叉状态记录
|
||||
2.构建周期内的高低点区间
|
||||
3.描述背离状态,同时保存结果;
|
||||
|
||||
多头进场:1.最近一个MACD信号是金叉,突破周期内高点;
|
||||
2. 出现底背离时,开多;
|
||||
空头进场:1.最近一个MACD信号是死叉,突破周期内低点;
|
||||
2.出现顶背离时,开空;
|
||||
|
||||
2024/05/24 anyongjin
|
||||
上面是原始逻辑,但测试发现顶底背离时按传统逻辑反而稳定亏损,改成顶背离开多,底背离开空反而盈利
|
||||
|
||||
*/
|
||||
//使用周期:1小时周期
|
||||
|
||||
type More18 struct {
|
||||
*com.TRS
|
||||
LHNum int // 上次金叉的序号
|
||||
LLNum int // 上次死叉的序号
|
||||
XHigh float64 // 上次交叉到本次交叉之间最高点,突破开多
|
||||
XLow float64 // 上次交叉到本次交叉之间最低点,突破开空
|
||||
ExmDirt int // 上次突破最高最低的方向
|
||||
|
||||
LHPrice float64 // 上次上穿时的价格
|
||||
LLPrice float64 // 上次下穿时的价格
|
||||
LHMacd float64 // 上次上穿时macd的值
|
||||
LLMacd float64 // 上次下穿时macd的值
|
||||
RevDirt int // 上次背离的方向
|
||||
}
|
||||
|
||||
func SF18V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenN := int(pol.Def("n", 8, core.PNorm(2, 30)))
|
||||
lenX := int(pol.Def("x", 10, core.PNorm(5, 50)))
|
||||
lenAtr = int(pol.Def("atr", 15, core.PNorm(7, 40)))
|
||||
lenAtrB := int(float64(lenAtr) * 4.3)
|
||||
|
||||
initSl := pol.Def("initSl", 100, core.PNorm(20, 150))
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenAtrB, lenN*9),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More18{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 8),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
macd, sig := ta.MACD(e.Close, 4*lenN, 9*lenN, 3*lenN)
|
||||
macdX := macd.Cross(sig)
|
||||
c := e.Close.Get(0)
|
||||
|
||||
m, _ := s.More.(*More18)
|
||||
openDirt := 0.0
|
||||
|
||||
if macdX == 1 {
|
||||
x2Dist := (e.BarNum - m.LHNum) * 7 / 5
|
||||
m.XHigh = slices.Max(e.High.Range(1, max(lenX, x2Dist)))
|
||||
cHMacd := sig.Get(0)
|
||||
m.LHNum = e.BarNum
|
||||
|
||||
if c < m.LHPrice && cHMacd > m.LHMacd && cHMacd < 0 {
|
||||
// 底背离,但开空
|
||||
openDirt = -1
|
||||
}
|
||||
m.LHPrice = c
|
||||
m.LHMacd = cHMacd
|
||||
} else if macdX == -1 {
|
||||
x2Dist := (e.BarNum - m.LLNum) * 7 / 5
|
||||
m.XLow = slices.Min(e.Low.Range(1, max(lenX, x2Dist)))
|
||||
cLMacd := sig.Get(0)
|
||||
m.LLNum = e.BarNum
|
||||
|
||||
if c > m.LLPrice && cLMacd < m.LLMacd && cLMacd > 0 {
|
||||
// 顶背离,但开多
|
||||
openDirt = 1
|
||||
}
|
||||
m.LLPrice = c
|
||||
m.LLMacd = cLMacd
|
||||
}
|
||||
// 这里是控制是否过滤背离重复开单的。注释掉不过滤的话,开单数增加一倍,利润增加一倍
|
||||
//if openDirt != 0 {
|
||||
// if int(openDirt) == m.RevDirt {
|
||||
// openDirt = 0
|
||||
// } else {
|
||||
// m.RevDirt = int(openDirt)
|
||||
// }
|
||||
//}
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
atrVal := atr.Get(0)
|
||||
if macdX >= 2 && c >= m.XHigh+atrVal*2 && m.XHigh > 0 && m.ExmDirt != 1 {
|
||||
// 金叉,突破两次交叉高点,开多
|
||||
openDirt = 1
|
||||
m.ExmDirt = 1
|
||||
} else if macdX <= -2 && c <= m.XLow-atrVal*2 && m.XLow > 0 && m.ExmDirt != -1 {
|
||||
// 死叉,突破两次交叉低点,开空
|
||||
openDirt = -1
|
||||
m.ExmDirt = -1
|
||||
}
|
||||
|
||||
if openDirt == 1 { //&& len(s.LongOrders) == 0 {
|
||||
m.TrialLong(e.Close.Get(0))
|
||||
} else if openDirt == -1 { //} && len(s.ShortOrders) == 0 {
|
||||
m.TrialShort(e.Close.Get(0))
|
||||
} else {
|
||||
openDirt = 0
|
||||
}
|
||||
|
||||
slLong, slShort := m.CalcSL(s, atr, lenAtr, lenAtrB, slPow, slRate)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
73
org/sf/19.go
Normal file
73
org/sf/19.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
type More19 struct {
|
||||
*com.TRS
|
||||
UpHigh float64 // 金叉时最高价
|
||||
DnLow float64 // 死叉时最低价
|
||||
}
|
||||
|
||||
func SF19V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 30
|
||||
lenMa2 = lenMa1 * 3
|
||||
lenExtrm = lenMa1
|
||||
lenAtr = 15
|
||||
baseAtrLen := lenAtr * 13 / 5
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(baseAtrLen, lenMa2),
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More19{
|
||||
TRS: com.NewTRS(30, 0.5, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
mid := ta.AvgPrice(e)
|
||||
ma1 := ta.VWMA(mid, e.Volume, lenMa1)
|
||||
ma2 := ta.VWMA(mid, e.Volume, lenMa2)
|
||||
crx := ma1.Cross(ma2)
|
||||
|
||||
hh, ll := ta.Highest(e.High, lenExtrm), ta.Lowest(e.Low, lenExtrm)
|
||||
h, l := e.High.Get(0), e.Low.Get(0)
|
||||
coSub := e.Close.Get(0) - e.Open.Get(0)
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
m, _ := s.More.(*More19)
|
||||
|
||||
if crx == 1 {
|
||||
// 上穿,金叉;
|
||||
m.UpHigh = hh.Get(0)
|
||||
} else if crx == -1 {
|
||||
// 下穿,死叉
|
||||
m.DnLow = ll.Get(0)
|
||||
}
|
||||
openDirt := 0.0
|
||||
if crx >= 1 && len(s.LongOrders) == 0 && coSub > 0 {
|
||||
// 金叉,突破最高,当前是阳线
|
||||
if h >= max(m.UpHigh, hh.Get(0)) {
|
||||
openDirt = 1
|
||||
}
|
||||
} else if crx <= -1 && len(s.ShortOrders) == 0 && coSub < 0 {
|
||||
// 死叉,突破最低,阴线
|
||||
if l <= min(m.DnLow, ll.Get(0)) {
|
||||
openDirt = -1
|
||||
}
|
||||
}
|
||||
|
||||
slLong, slShort := m.CalcSL(s, atr, lenAtr, baseAtrLen, 0.5, 0.5)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
68
org/sf/21.go
Normal file
68
org/sf/21.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
初始版本:
|
||||
本质上是简化版RSI,超买做空,超卖做多;vwma跟踪止损出场
|
||||
|
||||
修改版本:
|
||||
RSI在75~93开多;在7-25开空;同时结合ma过滤;跟踪止损出场。
|
||||
*/
|
||||
|
||||
func SF21V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = int(pol.Def("ma1", 10, core.PNorm(10, 300)))
|
||||
lenMaRate = pol.Def("maRate", 3, core.PNorm(1.5, 5))
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
lenExtrm = int(pol.Def("extrm", 15, core.PNorm(10, 400)))
|
||||
|
||||
lenAtr = int(pol.Def("atr", 15, core.PNorm(7, 40)))
|
||||
baseAtrLen := int(float64(lenAtr) * 4.3)
|
||||
|
||||
initSl := pol.Def("initSl", 60, core.PNorm(20, 200))
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(baseAtrLen, lenMa2),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
rsi := ta.RSI50(e.Close, lenExtrm).Get(0)
|
||||
rsiAbs := math.Abs(rsi)
|
||||
ma1 := ta.SMA(e.Close, lenMa1)
|
||||
ma2 := ta.SMA(e.Close, lenMa2)
|
||||
|
||||
maSub := ma1.Get(0) - ma2.Get(0)
|
||||
|
||||
c := e.Close.Get(0)
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
openDirt := 0.0
|
||||
if rsiAbs > 25 && rsiAbs < 43 && rsi*maSub > 0 && s.OrderNum == 0 {
|
||||
if rsi < 0 {
|
||||
m.TrialShort(c)
|
||||
openDirt = -1
|
||||
} else {
|
||||
m.TrialLong(c)
|
||||
openDirt = 1
|
||||
}
|
||||
}
|
||||
slLong, slShort := m.CalcSL2(s, lenAtr, baseAtrLen, slPow, slRate)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
75
org/sf/30_v0.go
Normal file
75
org/sf/30_v0.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
原始版本:止损空间TRS使用固定百分比,测试在4h上收益较好,低于4h不够稳定。
|
||||
*/
|
||||
|
||||
func SF30V0(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 100
|
||||
lenMaRate = 3
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
var trs = 0.01
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: lenMa2,
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(1, 0.301, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
p := ta.AvgPrice(e)
|
||||
ma1 := ta.SMA(p, lenMa1)
|
||||
slowMa1 := ta.EMA(ma1, lenMa1)
|
||||
ma2 := ta.SMA(p, lenMa2)
|
||||
slowMa2 := ta.EMA(ma2, lenMa2)
|
||||
dlh := slowMa1.Sub(slowMa2)
|
||||
maDlh := ta.EMA(dlh, lenMa1)
|
||||
|
||||
hh := ta.Highest(e.High, lenMa2)
|
||||
ll := ta.Lowest(e.Low, lenMa2)
|
||||
h, l, c := e.High.Get(0), e.Low.Get(0), e.Close.Get(0)
|
||||
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
|
||||
vMa1, vSlowMa1 := ma1.Get(0), slowMa1.Get(0)
|
||||
vMa2, vSlowMa2 := ma2.Get(0), slowMa2.Get(0)
|
||||
sub1, sub2, subSlow := vMa1-vSlowMa1, vMa2-vSlowMa2, vSlowMa1-vSlowMa2
|
||||
vDlh, vMaDlh := dlh.Get(0), maDlh.Get(0)
|
||||
subDlh := vDlh - vMaDlh
|
||||
curDirt := 0
|
||||
if sub1 > 0 && sub2 > 0 && subSlow > 0 && vDlh > 0 && subDlh > 0 {
|
||||
curDirt = 1
|
||||
} else if sub1 < 0 && sub2 < 0 && subSlow < 0 && vDlh < 0 && subDlh < 0 {
|
||||
curDirt = -1
|
||||
}
|
||||
|
||||
openPrice := float64(0)
|
||||
if m.dirt == 1 && h >= hh.Get(1) && len(s.LongOrders) == 0 {
|
||||
openPrice = max(e.Open.Get(0), hh.Get(1))
|
||||
m.TrialLong(min(openPrice, c))
|
||||
} else if m.dirt == -1 && l <= ll.Get(1) && len(s.ShortOrders) == 0 {
|
||||
openPrice = min(e.Open.Get(0), ll.Get(1))
|
||||
m.TrialShort(max(openPrice, c))
|
||||
openPrice = -openPrice
|
||||
}
|
||||
m.dirt = curDirt
|
||||
|
||||
stopLong, stopShort := m.Calc(s, c*trs)
|
||||
if openPrice != 0 {
|
||||
com.FastOpen(s, openPrice, stopLong, stopShort, math.Abs(openPrice))
|
||||
}
|
||||
setAllStopLoss(s, stopLong, stopShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
78
org/sf/30_v1.go
Normal file
78
org/sf/30_v1.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
func SF30V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = int(pol.Def("ma1", 54, core.PNorm(10, 300)))
|
||||
lenMaRate = pol.Def("maRate", 1.82, core.PNorm(1.5, 5))
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
|
||||
lenAtr = int(pol.Def("atr", 20, core.PNorm(7, 40)))
|
||||
baseAtrLen := int(float64(lenAtr) * 4.3)
|
||||
|
||||
initSl := pol.Def("initSl", 120, core.PNorm(20, 160))
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenMa2, baseAtrLen),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &MTRSDirt{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 5),
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
p := ta.AvgPrice(e)
|
||||
ma1 := ta.SMA(p, lenMa1)
|
||||
slowMa1 := ta.EMA(ma1, lenMa1)
|
||||
ma2 := ta.SMA(p, lenMa2)
|
||||
slowMa2 := ta.EMA(ma2, lenMa2)
|
||||
dlh := slowMa1.Sub(slowMa2)
|
||||
maDlh := ta.EMA(dlh, lenMa1)
|
||||
|
||||
hh := ta.Highest(e.High, lenMa2)
|
||||
ll := ta.Lowest(e.Low, lenMa2)
|
||||
h, l, c := e.High.Get(0), e.Low.Get(0), e.Close.Get(0)
|
||||
|
||||
m, _ := s.More.(*MTRSDirt)
|
||||
|
||||
vMa1, vSlowMa1 := ma1.Get(0), slowMa1.Get(0)
|
||||
vMa2, vSlowMa2 := ma2.Get(0), slowMa2.Get(0)
|
||||
sub1, sub2, subSlow := vMa1-vSlowMa1, vMa2-vSlowMa2, vSlowMa1-vSlowMa2
|
||||
vDlh, vMaDlh := dlh.Get(0), maDlh.Get(0)
|
||||
subDlh := vDlh - vMaDlh
|
||||
curDirt := 0
|
||||
if sub1 > 0 && sub2 > 0 && subSlow > 0 && vDlh > 0 && subDlh > 0 {
|
||||
curDirt = 1
|
||||
} else if sub1 < 0 && sub2 < 0 && subSlow < 0 && vDlh < 0 && subDlh < 0 {
|
||||
curDirt = -1
|
||||
}
|
||||
|
||||
openPrice := float64(0)
|
||||
if m.dirt == 1 && h >= hh.Get(1) && len(s.LongOrders) == 0 {
|
||||
openPrice = max(e.Open.Get(0), hh.Get(1))
|
||||
m.TrialLong(min(openPrice, c))
|
||||
} else if m.dirt == -1 && l <= ll.Get(1) && len(s.ShortOrders) == 0 {
|
||||
openPrice = min(e.Open.Get(0), ll.Get(1))
|
||||
m.TrialShort(max(openPrice, c))
|
||||
openPrice = -openPrice
|
||||
}
|
||||
m.dirt = curDirt
|
||||
|
||||
stopLong, stopShort := m.CalcSL2(s, lenAtr, baseAtrLen, slPow, slRate)
|
||||
if openPrice != 0 {
|
||||
//log.Info("open:", zap.Float64("slVal", slVal/c), zap.Float64("trRate", atrRate),
|
||||
// zap.Float64("atr", atrBase/c))
|
||||
com.FastOpen(s, openPrice, stopLong, stopShort, math.Abs(openPrice))
|
||||
}
|
||||
setAllStopLoss(s, stopLong, stopShort)
|
||||
},
|
||||
}
|
||||
}
|
||||
103
org/sf/33.go
Normal file
103
org/sf/33.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
type More33 struct {
|
||||
*com.TRS
|
||||
openD float64 // 当日开盘价
|
||||
trend int
|
||||
}
|
||||
|
||||
func SF33V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenBid := int(pol.Def("ma1", 9, core.PNorm(10, 300)))
|
||||
|
||||
lenAtr = int(pol.Def("atr", 14, core.PNorm(7, 40)))
|
||||
baseAtrLen := int(float64(lenAtr) * 4.0)
|
||||
|
||||
lenTit := int(pol.Def("tit", 5, core.PNorm(3, 30)))
|
||||
wid1 := pol.Def("wid", 1, core.PNorm(0.5, 5))
|
||||
wid2 := wid1
|
||||
|
||||
initSl := pol.Def("initSl", 60, core.PNorm(20, 150))
|
||||
slMinRate, slPow, slRate := 0.4, 0.3, 0.6
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(baseAtrLen, lenTit, lenBid),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More33{
|
||||
TRS: com.NewTRS(initSl, slMinRate, 5),
|
||||
}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", 2},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
hh := ta.Highest(e.High, lenBid)
|
||||
ll := ta.Lowest(e.Low, lenBid)
|
||||
abid := ta.EMA(hh.Sub(ll), lenBid)
|
||||
|
||||
mid := ta.EMA(e.High, lenTit).Add(ta.EMA(e.Low, lenTit)).Mul(0.5)
|
||||
bidN := abid.Mul(wid1)
|
||||
up := mid.Add(bidN)
|
||||
dn := mid.Sub(bidN)
|
||||
|
||||
m, _ := s.More.(*More33)
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
dhh := m.openD + atr.Get(0)*wid2
|
||||
dll := m.openD - atr.Get(0)*wid2
|
||||
|
||||
h, l := e.High.Get(0), e.Low.Get(0)
|
||||
xLong, xShort := false, false
|
||||
if m.trend != 1 && h >= max(up.Get(0), hh.Get(0)) {
|
||||
m.trend = 1
|
||||
xLong = true
|
||||
}
|
||||
if m.trend != -1 && l <= min(dn.Get(0), ll.Get(0)) {
|
||||
m.trend = -1
|
||||
xShort = true
|
||||
}
|
||||
|
||||
uppVal := up.Get(0)
|
||||
dnnVal := dn.Get(0)
|
||||
// 当trend=1的时候,也就是多头判定后,如果出现dn线比前一个还小情况,那么用前一个大的,不再减小dn线
|
||||
if !xLong && m.trend > 0 && dnnVal < dn.Get(1) {
|
||||
dnnVal = dn.Get(1)
|
||||
}
|
||||
// 当trend=-1的时候,也就是空头判定后,如果出现up线比前一个还大情况,那么用前一个大的,不再增加up线
|
||||
if !xShort && m.trend < 0 && uppVal > up.Get(1) {
|
||||
uppVal = up.Get(1)
|
||||
}
|
||||
|
||||
c := e.Close.Get(0)
|
||||
openDirt := 0.0
|
||||
if m.trend == 1 && c > dnnVal && h >= dhh && len(s.LongOrders) == 0 {
|
||||
openDirt = 1
|
||||
m.TrialLong(c)
|
||||
}
|
||||
if m.trend == -1 && c < uppVal && l < dll && len(s.ShortOrders) == 0 {
|
||||
openDirt = -1
|
||||
m.TrialShort(c)
|
||||
}
|
||||
slLong, slShort := m.CalcSL(s, atr, lenAtr, baseAtrLen, slPow, slRate)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
m, _ := s.More.(*More33)
|
||||
m.openD = e.Open.Get(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
112
org/sf/35.go
Normal file
112
org/sf/35.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
type More35 struct {
|
||||
yma float64 // 单边权重均线
|
||||
openD float64
|
||||
longMin float64
|
||||
shortMax float64
|
||||
dirt float64 // 1超买,-1超卖
|
||||
|
||||
*com.EFTRS
|
||||
}
|
||||
|
||||
func SF35V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenSmt := int(pol.Def("ma1", 12, core.PNorm(10, 300)))
|
||||
|
||||
lenAtr = int(pol.Def("atr", 14, core.PNorm(7, 40)))
|
||||
lenAtBig := int(float64(lenAtr) * 4)
|
||||
|
||||
mulB := pol.Def("b", 3, core.PNorm(1.2, 10))
|
||||
mulD := pol.Def("d", 2, core.PNorm(1.2, 10))
|
||||
slMul := pol.Def("sl", 3, core.PNorm(1.2, 10))
|
||||
lenEff := int(pol.Def("eff", 10, core.PNorm(3, 100)))
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: max(lenAtBig, lenSmt),
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More35{
|
||||
dirt: 1,
|
||||
EFTRS: com.NewEFTRS(lenEff),
|
||||
}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", 2},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*More35)
|
||||
// 计算均线
|
||||
closes := e.Close.Range(0, lenSmt+1)
|
||||
c := closes[0]
|
||||
if len(closes) == 1 || math.IsNaN(c) {
|
||||
m.yma = c
|
||||
} else {
|
||||
upSum, dnSum := float64(0), float64(0)
|
||||
num := len(closes) - 1
|
||||
for i, v := range closes[:num] {
|
||||
sub := v - closes[i+1]
|
||||
if sub > 0 {
|
||||
upSum += sub
|
||||
} else {
|
||||
dnSum -= sub
|
||||
}
|
||||
}
|
||||
// cmo: 度量单边系数;值域0-1;1表示单边涨或跌,0表示震荡
|
||||
cmo := math.Abs(upSum-dnSum) / (upSum + dnSum)
|
||||
weight := 2 * cmo / (1 + float64(lenSmt))
|
||||
m.yma = c*weight + m.yma*(1-weight)
|
||||
}
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
atrMx := ta.Highest(atr, lenAtBig).Get(0)
|
||||
|
||||
// 计算上下轨
|
||||
longMin, shortMax := m.yma-atrMx*mulB, m.yma+atrMx*mulB
|
||||
if m.yma > m.longMin {
|
||||
longMin = max(longMin, m.longMin)
|
||||
}
|
||||
if m.yma < m.shortMax {
|
||||
shortMax = min(shortMax, m.shortMax)
|
||||
}
|
||||
if m.dirt == -1 && m.yma > m.shortMax {
|
||||
m.dirt = 1
|
||||
} else if m.dirt == 1 && m.yma < m.longMin {
|
||||
m.dirt = -1
|
||||
}
|
||||
m.longMin = longMin
|
||||
m.shortMax = shortMax
|
||||
|
||||
hh, ll := m.openD+atrMx*mulD, m.openD-atrMx*mulD
|
||||
|
||||
openDirt := 0.0
|
||||
if m.dirt == 1 && c >= max(hh, longMin) && len(s.LongOrders) == 0 {
|
||||
openDirt = 1
|
||||
} else if m.dirt == -1 && c <= min(ll, shortMax) && len(s.ShortOrders) == 0 {
|
||||
openDirt = -1
|
||||
}
|
||||
|
||||
// 根据ER效率计算止损
|
||||
slLong, slShort := m.Calc(s, atrMx*slMul)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
m, _ := s.More.(*More35)
|
||||
m.openD = e.Open.Get(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
138
org/sf/36.go
Normal file
138
org/sf/36.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
无输出信号
|
||||
*/
|
||||
|
||||
type More36 struct {
|
||||
pdmS float64
|
||||
mdmS float64
|
||||
pdiS float64
|
||||
mdiS float64
|
||||
vma float64
|
||||
|
||||
support float64
|
||||
stress float64
|
||||
|
||||
dirt int
|
||||
openD float64
|
||||
|
||||
*com.EFTRS
|
||||
}
|
||||
|
||||
func SF36V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenAtr = 14
|
||||
lenAtBig := lenAtr * 17 / 4
|
||||
alpha := 6.0
|
||||
mulB, mulD, slMul := 2.0, 2.0, 2.0
|
||||
lenEff := 10
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: lenAtBig,
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More36{
|
||||
dirt: 1,
|
||||
EFTRS: com.NewEFTRS(lenEff),
|
||||
}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", 2},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*More36)
|
||||
k := 1 / alpha
|
||||
c, c1 := e.Close.Get(0), e.Close.Get(1)
|
||||
pdm := max(c-c1, 0)
|
||||
mdm := max(c1-c, 0)
|
||||
m.pdmS = (1-k)*m.pdmS + k*pdm
|
||||
m.mdmS = (1-k)*m.mdmS + k*mdm
|
||||
pdi := m.pdmS / (m.pdmS + m.mdmS)
|
||||
mdi := m.mdmS / (m.pdmS + m.mdmS)
|
||||
|
||||
m.pdiS = (1-k)*m.pdiS + k*pdi
|
||||
m.mdiS = (1-k)*m.mdiS + k*mdi
|
||||
|
||||
iS := e.Close.To("iS", 0)
|
||||
if !iS.Cached() {
|
||||
if iS.Len() == 0 {
|
||||
iS.Append(0)
|
||||
} else {
|
||||
val := (1-k)*iS.Get(0) + k*math.Abs(m.pdiS-m.mdiS)/(m.pdiS+m.mdiS)
|
||||
iS.Append(val)
|
||||
}
|
||||
}
|
||||
isVal := iS.Get(0)
|
||||
|
||||
hhv := ta.Highest(iS, int(alpha)).Get(0)
|
||||
llv := ta.Lowest(iS, int(alpha)).Get(0)
|
||||
vI := (isVal - llv) / (hhv - llv)
|
||||
|
||||
if m.vma == 0 {
|
||||
m.vma = c
|
||||
} else {
|
||||
m.vma = (1-k*vI)*m.vma + k*vI*c
|
||||
}
|
||||
|
||||
atr := ta.Lowest(ta.ATR(e.High, e.Low, e.Close, lenAtBig), lenAtr)
|
||||
atrV, atrV2 := atr.Get(0), atr.Get(1)
|
||||
support := m.vma - atrV*mulB
|
||||
stress := m.vma + atrV*mulB
|
||||
if m.vma > m.support {
|
||||
support = max(m.support, support)
|
||||
}
|
||||
if m.vma < m.stress {
|
||||
stress = min(m.stress, stress)
|
||||
}
|
||||
|
||||
var dirt = m.dirt
|
||||
if m.dirt == -1 && m.vma > m.stress {
|
||||
dirt = 1
|
||||
} else if m.dirt == 1 && m.vma < m.support {
|
||||
dirt = -1
|
||||
}
|
||||
hh := e.Close.To("hh", 0)
|
||||
ll := e.Close.To("ll", 0)
|
||||
if !hh.Cached() {
|
||||
hh.Append(m.openD + atrV2*mulD)
|
||||
}
|
||||
if !ll.Cached() {
|
||||
ll.Append(m.openD - atrV2*mulD)
|
||||
}
|
||||
upHH := e.Close.Cross(hh)
|
||||
dnLL := e.Close.Cross(ll)
|
||||
|
||||
openDirt := 0.0
|
||||
if m.dirt == 1 && upHH == 2 && c > m.support && len(s.LongOrders) == 0 {
|
||||
openDirt = 1
|
||||
} else if m.dirt == -1 && dnLL == -2 && c < m.stress && len(s.ShortOrders) == 0 {
|
||||
openDirt = -1
|
||||
}
|
||||
slLong, slShort := m.Calc(s, atrV2*slMul)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
|
||||
m.support = support
|
||||
m.stress = stress
|
||||
m.dirt = dirt
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
m, _ := s.More.(*More36)
|
||||
m.openD = e.Open.Get(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
97
org/sf/37.go
Normal file
97
org/sf/37.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
/*
|
||||
交易信号很少
|
||||
*/
|
||||
|
||||
type More37 struct {
|
||||
tup float64
|
||||
tdown float64
|
||||
dirt int
|
||||
|
||||
madd float64
|
||||
openD float64
|
||||
*com.EFTRS
|
||||
}
|
||||
|
||||
func SF37V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
length := 20
|
||||
lenMad := 5
|
||||
mulB, mulD, slMul := 2.0, 2.0, 2.0
|
||||
lenEff := 10
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: length,
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More37{
|
||||
dirt: 1,
|
||||
EFTRS: com.NewEFTRS(lenEff),
|
||||
}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", lenMad},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*More37)
|
||||
half := (length - 1) / 2
|
||||
c1 := e.Close.Get(1)
|
||||
ayami := ta.EMA(e.Close.Add(e.Close.Sub(e.Close.Back(half))), length)
|
||||
ayaV, ayaV1 := ayami.Get(0), ayami.Get(1)
|
||||
|
||||
atr := ta.Highest(ta.ATR(e.High, e.Low, e.Close, length), length).Get(1)
|
||||
solid := ta.Highest(ta.SMA(e.Close.Sub(e.Open).Abs(), length), length)
|
||||
up := ayami.Get(0) + mulB*solid.Get(1)
|
||||
dn := ayami.Get(0) - mulB*solid.Get(1)
|
||||
|
||||
tup, tdown, dirt := float64(0), float64(0), m.dirt
|
||||
if m.tup == 0 || ayaV1 <= m.tup || dn > m.tup {
|
||||
tup = dn
|
||||
}
|
||||
if m.tdown == 0 || ayaV1 >= m.tdown || up < m.tdown {
|
||||
tdown = up
|
||||
}
|
||||
if ayaV > m.tdown {
|
||||
dirt = 1
|
||||
} else if ayaV < m.tup {
|
||||
dirt = -1
|
||||
}
|
||||
|
||||
hh := m.openD + solid.Get(0)*mulD
|
||||
ll := m.openD - solid.Get(0)*mulD
|
||||
|
||||
openDirt := 0.0
|
||||
if m.dirt == 1 && len(s.LongOrders) == 0 && c1 > max(m.madd, hh) {
|
||||
openDirt = 1
|
||||
} else if m.dirt == -1 && len(s.ShortOrders) == 0 && c1 < min(m.madd, ll) {
|
||||
openDirt = -1
|
||||
}
|
||||
|
||||
slLong, slShort := m.Calc(s, atr*slMul)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
|
||||
m.tup = tup
|
||||
m.tdown = tdown
|
||||
m.dirt = dirt
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
m, _ := s.More.(*More37)
|
||||
m.madd = ta.SMA(e.Close, lenMad).Get(0)
|
||||
m.openD = e.Open.Get(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
98
org/sf/38.go
Normal file
98
org/sf/38.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
ta "github.com/banbox/banta"
|
||||
)
|
||||
|
||||
type More38 struct {
|
||||
upper float64
|
||||
lower float64
|
||||
dirt int
|
||||
|
||||
openD float64
|
||||
*com.EFTRS
|
||||
}
|
||||
|
||||
func SF38V1(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
lenMa1 = 4
|
||||
lenMa2 = 16
|
||||
lenC := 50
|
||||
lenMad := 5
|
||||
lenAtr = 20
|
||||
length := 20
|
||||
mulB, mulD, slMul := 2.0, 2.0, 2.0
|
||||
lenEff := 10
|
||||
|
||||
return &strat.TradeStrat{
|
||||
Version: 1,
|
||||
WarmupNum: length,
|
||||
MinTfScore: 0.75,
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &More38{
|
||||
dirt: 1,
|
||||
EFTRS: com.NewEFTRS(lenEff),
|
||||
}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "1d", lenMad},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*More38)
|
||||
c1 := e.Close.Get(1)
|
||||
ma1 := ta.SMA(e.Close, lenMa1)
|
||||
ma2 := ta.SMA(e.Close, lenMa2)
|
||||
avgMa := e.Close.To("avgMa", 0)
|
||||
if !avgMa.Cached() {
|
||||
avgMa.Append((ma1.Get(0) + ma2.Get(0)) / 2)
|
||||
}
|
||||
maVal := ta.SMA(avgMa, lenC).Get(0)
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
solid := ta.Highest(ta.SMA(e.Close.Sub(e.Open).Abs(), length), length)
|
||||
|
||||
up := maVal + solid.Get(0)*mulB
|
||||
dn := maVal - solid.Get(0)*mulB
|
||||
|
||||
upper, lower := m.upper, m.lower
|
||||
if c1 > upper && up > upper {
|
||||
upper = up
|
||||
}
|
||||
if c1 < lower && dn < lower {
|
||||
lower = dn
|
||||
}
|
||||
if c1 > lower {
|
||||
m.dirt = 1
|
||||
} else if c1 < upper {
|
||||
m.dirt = -1
|
||||
}
|
||||
|
||||
hh := m.openD + solid.Get(0)*mulD
|
||||
ll := m.openD - solid.Get(0)*mulD
|
||||
|
||||
openDirt := 0.0
|
||||
if m.dirt == 1 && c1 >= max(hh, upper) && len(s.LongOrders) == 0 {
|
||||
openDirt = 1
|
||||
} else if m.dirt == -1 && c1 <= min(ll, lower) && len(s.ShortOrders) == 0 {
|
||||
openDirt = -1
|
||||
}
|
||||
slLong, slShort := m.Calc(s, atr.Get(1)*slMul)
|
||||
if openDirt != 0 {
|
||||
com.FastOpen(s, openDirt, slLong, slShort, 0)
|
||||
}
|
||||
setAllStopLoss(s, slLong, slShort)
|
||||
|
||||
m.upper = upper
|
||||
m.lower = lower
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
m, _ := s.More.(*More38)
|
||||
m.openD = e.Open.Get(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
50
org/sf/common.go
Normal file
50
org/sf/common.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package sf
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/orm/ormo"
|
||||
"github.com/banbox/banbot/strat"
|
||||
"github.com/banbox/banstagy/com"
|
||||
)
|
||||
|
||||
var (
|
||||
lenMa1 = 10 // 快线MA的周期
|
||||
lenMaRate = 2.0 // 慢线MA相对快线的倍率
|
||||
lenMa2 = int(float64(lenMa1) * lenMaRate)
|
||||
lenAtr = 14
|
||||
lenExtrm = 50 // 查找极值点的周期
|
||||
)
|
||||
|
||||
type MTRSDirt struct {
|
||||
dirt int // 1开多 -1开空
|
||||
*com.TRS
|
||||
}
|
||||
|
||||
func init() {
|
||||
strat.AddStratGroup("sf", map[string]strat.FuncMakeStrat{
|
||||
"01": SF01V2,
|
||||
"02": SF02V1,
|
||||
"03": SF03V1,
|
||||
"04": SF04V1,
|
||||
"30": SF30V1,
|
||||
"05": SF05V1,
|
||||
"06": SF06V1,
|
||||
"08": SF08V1,
|
||||
"10": SF10V1,
|
||||
"14": SF14V1,
|
||||
"17": SF17V1,
|
||||
"18": SF18V1,
|
||||
"19": SF19V1,
|
||||
"21": SF21V1,
|
||||
"33": SF33V1,
|
||||
"35": SF35V1,
|
||||
"36": SF36V1,
|
||||
"37": SF37V1,
|
||||
"38": SF38V1,
|
||||
})
|
||||
}
|
||||
|
||||
func setAllStopLoss(s *strat.StratJob, slLong, slShort float64) {
|
||||
s.SetAllStopLoss(core.OdDirtLong, &ormo.ExitTrigger{Price: slLong})
|
||||
s.SetAllStopLoss(core.OdDirtShort, &ormo.ExitTrigger{Price: slShort})
|
||||
}
|
||||
Reference in New Issue
Block a user