init
This commit is contained in:
214
llmjob/his/3762.go
Normal file
214
llmjob/his/3762.go
Normal file
@@ -0,0 +1,214 @@
|
||||
package his
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/banbox/banbot/com"
|
||||
"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"
|
||||
"github.com/banbox/banexg/log"
|
||||
"github.com/banbox/banexg/utils"
|
||||
ta "github.com/banbox/banta"
|
||||
"go.uber.org/zap"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
超跌反弹策略。30个品种为宜
|
||||
做空部分没有利润,禁用
|
||||
*/
|
||||
|
||||
type State3762 struct {
|
||||
NoLongUntil int64
|
||||
NoShortUntil int64
|
||||
}
|
||||
|
||||
func J3762(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// 定义策略参数
|
||||
p := pol.DefInt("p", 20, core.PNorm(5, 50))
|
||||
d := pol.Def("d", 30.0, core.PNorm(5, 50))
|
||||
mult := pol.Def("mult", 1.5, core.PNorm(1.0, 3.0))
|
||||
slRate := pol.Def("slRate", 25, core.PNorm(0, 50))
|
||||
needlong := pol.Def("needlong", 1.0, core.PUniform(0, 1)) > 0.5
|
||||
needshort := pol.Def("needshort", 0.0, core.PUniform(0, 1)) > 0.5
|
||||
|
||||
dayMS := int64(utils.TFToSecs("1d") * 1000)
|
||||
|
||||
lenAtr := 20
|
||||
baseAtrLen := int(math.Round(float64(lenAtr) * 4.3))
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: baseAtrLen * 2, // 预热K线数量,确保有足够数据计算指标
|
||||
RunTimeFrames: []string{"15m"},
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
s.More = &State3762{}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
m, _ := s.More.(*State3762)
|
||||
// 计算基础布林带指标
|
||||
sma := ta.SMA(e.Close, p)
|
||||
ma7 := ta.SMA(e.Close, 7).Get(0)
|
||||
ma30 := ta.SMA(e.Close, 30).Get(0)
|
||||
multCur := mult
|
||||
if ma7 < ma30 {
|
||||
// 熊市下移下限
|
||||
multCur *= 1.35
|
||||
}
|
||||
stddev := ta.StdDev(e.Close, p).Get(0) * multCur
|
||||
upperBB := sma.Get(0) + stddev
|
||||
lowerBB := sma.Get(0) - stddev
|
||||
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
atrBase := ta.Lowest(ta.Highest(atr, lenAtr), baseAtrLen).Get(0)
|
||||
|
||||
// 计算百分比偏离轨道
|
||||
atrRt := d
|
||||
if ma7 < ma30 {
|
||||
// 熊市下移下限
|
||||
atrRt *= 1.35
|
||||
}
|
||||
upex2 := sma.Get(0) + atrBase*atrRt
|
||||
dnex2 := sma.Get(0) - atrBase*atrRt
|
||||
|
||||
// 计算最终轨道
|
||||
upexPrice := max(upperBB, (upex2+upperBB)/2)
|
||||
dnexPrice := min(lowerBB, (dnex2+lowerBB)/2)
|
||||
|
||||
// 获取当前价格
|
||||
closePrice := e.Close.Get(0)
|
||||
openPrice := e.Open.Get(0)
|
||||
|
||||
// 生成交易信号
|
||||
exitSignal := closePrice > openPrice // 绿色K线信号
|
||||
|
||||
if math.IsNaN(upexPrice) || math.IsNaN(dnexPrice) {
|
||||
return
|
||||
}
|
||||
slRange := min(atrBase*slRate, closePrice*0.25)
|
||||
|
||||
// 执行交易逻辑
|
||||
if !s.IsWarmUp {
|
||||
s.Strat.WriteOutput(fmt.Sprintf("%s upp: %.6f, low: %.6f upex2: %.6f, dnex2: %.6f upex: %.6f, dnex: %.6f slRange: %.6f",
|
||||
e.Symbol, upperBB, lowerBB, upex2, dnex2, upexPrice, dnexPrice, slRange), true)
|
||||
}
|
||||
if needlong {
|
||||
if len(s.LongOrders) == 0 {
|
||||
// 使用限价单在下轨价格做多,不依赖当前价格是否突破轨道
|
||||
if e.TimeStop >= m.NoLongUntil {
|
||||
curPrice := com.GetPrice(e.Symbol, banexg.OdSideBuy)
|
||||
if math.Abs(curPrice/closePrice-1) > 0.01 {
|
||||
log.Info("bad price from GetPrice", zap.String("pair", e.Symbol),
|
||||
zap.Float64("val", curPrice), zap.Float64("close", closePrice))
|
||||
}
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "Long",
|
||||
Limit: dnexPrice, // 以下轨价格作为限价单
|
||||
StopLossVal: slRange,
|
||||
Log: true,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
for _, od := range s.LongOrders {
|
||||
if od.Status == ormo.InOutStatusInit {
|
||||
err := od.SetEnterLimit(dnexPrice)
|
||||
if err != nil {
|
||||
log.Error("SetEnterLimit fail", zap.Error(err))
|
||||
} else {
|
||||
err = od.SetStopLoss(&ormo.ExitTrigger{
|
||||
Price: dnexPrice - slRange,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("SetStopLoss fail", zap.Error(err))
|
||||
}
|
||||
}
|
||||
} else if od.Status == ormo.InOutStatusFullEnter {
|
||||
barNum := e.BarCount(od.Enter.UpdateAt)
|
||||
if barNum > 2 && od.ProfitRate < 0 {
|
||||
// 持仓2个k线,出现亏损,平仓
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Exit bad Long",
|
||||
Dirt: core.OdDirtLong,
|
||||
Log: true,
|
||||
})
|
||||
m.NoLongUntil = e.TimeStop + dayMS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if needshort {
|
||||
if len(s.ShortOrders) == 0 {
|
||||
// 使用限价单在上轨价格做空,不依赖当前价格是否突破轨道
|
||||
if e.TimeStop >= m.NoShortUntil {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "Short",
|
||||
Short: true,
|
||||
Limit: upexPrice, // 以上轨价格作为限价单
|
||||
StopLossVal: slRange,
|
||||
Log: true,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
for _, od := range s.ShortOrders {
|
||||
if od.Status == ormo.InOutStatusInit {
|
||||
err := od.SetEnterLimit(upexPrice)
|
||||
if err != nil {
|
||||
log.Error("SetEnterLimit fail", zap.Error(err))
|
||||
} else {
|
||||
err = od.SetStopLoss(&ormo.ExitTrigger{
|
||||
Price: upexPrice + slRange,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("SetStopLoss fail", zap.Error(err))
|
||||
}
|
||||
}
|
||||
} else if od.Status == ormo.InOutStatusFullEnter {
|
||||
barNum := e.BarCount(od.Enter.UpdateAt)
|
||||
if barNum > 2 && od.ProfitRate < 0 {
|
||||
// 持仓2个k线,出现亏损,平仓
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Exit bad short",
|
||||
Dirt: core.OdDirtShort,
|
||||
Log: true,
|
||||
})
|
||||
m.NoShortUntil = e.TimeStop + dayMS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 平仓条件:绿色K线
|
||||
if exitSignal {
|
||||
if len(s.LongOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Exit Long",
|
||||
Dirt: core.OdDirtLong,
|
||||
Log: true,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if len(s.ShortOrders) > 0 {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "Exit Short",
|
||||
Dirt: core.OdDirtShort,
|
||||
Log: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
OnOrderChange: func(s *strat.StratJob, od *ormo.InOutOrder, chgType int) {
|
||||
if chgType == core.OdChgExitFill && od.ExitTag == core.ExitTagStopLoss {
|
||||
m, _ := s.More.(*State3762)
|
||||
if od.Short {
|
||||
m.NoShortUntil = od.ExitAt + dayMS
|
||||
} else {
|
||||
m.NoLongUntil = od.ExitAt + dayMS
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user