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
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
270
llmjob/his/3782.go
Normal file
270
llmjob/his/3782.go
Normal file
@@ -0,0 +1,270 @@
|
||||
package his
|
||||
|
||||
import (
|
||||
"github.com/banbox/banbot/config"
|
||||
"github.com/banbox/banbot/core"
|
||||
"github.com/banbox/banbot/strat"
|
||||
ta "github.com/banbox/banta"
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
需要多品种综合市场信息,品种数不可少于30
|
||||
*/
|
||||
|
||||
// ZoneTradeState 用于存储每个交易区间的状态信息
|
||||
type ZoneTradeState struct {
|
||||
LastTradeTime2 int64 // 买入区间2的最后交易时间
|
||||
LastTradeTime3 int64 // 买入区间3的最后交易时间
|
||||
LastTradeTime4 int64 // 买入区间4的最后交易时间
|
||||
LastSellTime int64 // 最后卖出时间
|
||||
atrBase float64
|
||||
score float64
|
||||
upFlag float64
|
||||
}
|
||||
|
||||
func J3782(pol *config.RunPolicyConfig) *strat.TradeStrat {
|
||||
// 定义可调超参数
|
||||
maPeriod := pol.DefInt("maPeriod", 100, core.PNorm(20, 200))
|
||||
baseRetracement := pol.Def("baseRetracement", 0.08, core.PNorm(0.05, 0.2))
|
||||
retracementRate := pol.Def("retracementRate", 1.8, core.PNorm(1.5, 2.5))
|
||||
profitRate := pol.Def("profitRate", 0.03, core.PNorm(0.015, 0.06))
|
||||
tradeDelay := pol.Def("tradeDelay", 40, core.PNorm(10, 100))
|
||||
slRate := pol.Def("slRate", 63, core.PNorm(5, 35))
|
||||
|
||||
// 计算各回撤比例
|
||||
retracement2 := baseRetracement
|
||||
retracement3 := baseRetracement * retracementRate
|
||||
retracement4 := baseRetracement * retracementRate * 1.33
|
||||
|
||||
lenAtr := 20
|
||||
baseAtrLen := int(math.Round(float64(lenAtr) * 4.3))
|
||||
rates := make([]float64, 0, 10)
|
||||
|
||||
// 最大交易数量
|
||||
maxTrades2 := 2
|
||||
maxTrades3 := 3
|
||||
maxTrades4 := 4
|
||||
|
||||
openPairs := 0.0
|
||||
var pairLock deadlock.Mutex
|
||||
addThres, firstRate := 1.0, 1.0
|
||||
avgAtrBase := 2.5
|
||||
maxPair := 3.0
|
||||
return &strat.TradeStrat{
|
||||
WarmupNum: maPeriod,
|
||||
BatchInfo: true,
|
||||
BatchInOut: true,
|
||||
RunTimeFrames: []string{"15m"},
|
||||
OnStartUp: func(s *strat.StratJob) {
|
||||
// 初始化状态信息
|
||||
s.More = &ZoneTradeState{}
|
||||
},
|
||||
OnPairInfos: func(s *strat.StratJob) []*strat.PairSub {
|
||||
return []*strat.PairSub{
|
||||
{"_cur_", "4h", baseAtrLen * 2},
|
||||
}
|
||||
},
|
||||
OnBar: func(s *strat.StratJob) {
|
||||
e := s.Env
|
||||
state, _ := s.More.(*ZoneTradeState)
|
||||
|
||||
// 计算MA100
|
||||
ma100 := ta.SMA(e.Close, maPeriod)
|
||||
ma100Val := ma100.Get(0)
|
||||
|
||||
// 计算交易价格水平
|
||||
curRate := max(addThres, 1+state.score/10)
|
||||
itemRate := max(0.7, min(math.Sqrt(state.atrBase/avgAtrBase), 1.4))
|
||||
buyPrice2 := ma100Val * (1 - retracement2*curRate*itemRate*firstRate)
|
||||
buyPrice3 := ma100Val * (1 - retracement3*curRate*itemRate)
|
||||
buyPrice4 := ma100Val * (1 - retracement4*curRate*itemRate)
|
||||
sellPrice := ma100Val * (1 + profitRate)
|
||||
|
||||
// 获取当前价格
|
||||
lowPrice := e.Low.Get(0)
|
||||
highPrice := e.High.Get(0)
|
||||
|
||||
// 检查交易间隔条件
|
||||
currentBarTime := e.TimeStop
|
||||
|
||||
lastEnt := max(state.LastTradeTime2, state.LastTradeTime3, state.LastTradeTime4)
|
||||
canTrade := e.BarCount(lastEnt) >= 10
|
||||
canTrade2 := canTrade && e.BarCount(state.LastTradeTime2) >= tradeDelay
|
||||
canTrade3 := canTrade && e.BarCount(state.LastTradeTime3) >= tradeDelay
|
||||
canTrade4 := canTrade && e.BarCount(state.LastTradeTime4) >= tradeDelay
|
||||
canSell := e.BarCount(state.LastSellTime) >= tradeDelay
|
||||
|
||||
// 获取当前总开仓数量,与原始策略的strategy.opentrades保持一致
|
||||
openTrades := len(s.LongOrders) + len(s.ShortOrders)
|
||||
|
||||
if lowPrice <= buyPrice4 && openTrades < maxTrades4 && canTrade4 {
|
||||
pairLock.Lock()
|
||||
allow := false
|
||||
if openPairs < maxPair {
|
||||
openPairs += 3
|
||||
allow = true
|
||||
}
|
||||
pairLock.Unlock()
|
||||
if allow {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "BuyZone4",
|
||||
CostRate: 3,
|
||||
Log: true,
|
||||
})
|
||||
state.LastTradeTime4 = currentBarTime
|
||||
}
|
||||
}
|
||||
if lowPrice <= buyPrice3 && openTrades < maxTrades3 && canTrade3 {
|
||||
pairLock.Lock()
|
||||
allow := false
|
||||
if openPairs < maxPair {
|
||||
openPairs += 1.5
|
||||
allow = true
|
||||
}
|
||||
pairLock.Unlock()
|
||||
if allow {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "BuyZone3",
|
||||
CostRate: 1.5,
|
||||
Log: true,
|
||||
})
|
||||
state.LastTradeTime3 = currentBarTime
|
||||
}
|
||||
}
|
||||
if lowPrice <= buyPrice2 && openTrades < maxTrades2 && canTrade2 {
|
||||
pairLock.Lock()
|
||||
allow := false
|
||||
if openPairs < maxPair {
|
||||
openPairs += 1
|
||||
allow = true
|
||||
}
|
||||
pairLock.Unlock()
|
||||
if allow {
|
||||
s.OpenOrder(&strat.EnterReq{
|
||||
Tag: "BuyZone2",
|
||||
CostRate: 1,
|
||||
Log: true,
|
||||
})
|
||||
state.LastTradeTime2 = currentBarTime
|
||||
}
|
||||
}
|
||||
|
||||
// 检查卖出条件
|
||||
if s.OrderNum > 0 {
|
||||
curPrice := e.Close.Get(0)
|
||||
slRange := slRate * itemRate * curPrice / 100
|
||||
avgPrice := s.PositionAvgPrice(core.OdDirtLong, "")
|
||||
if curPrice+slRange <= avgPrice {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "StopLoss",
|
||||
Log: true,
|
||||
})
|
||||
state.LastSellTime = currentBarTime
|
||||
} else {
|
||||
exitPrice := avgPrice*(1+profitRate)*0.4 + sellPrice*0.6
|
||||
if openTrades > 0 && highPrice >= exitPrice && canSell {
|
||||
s.CloseOrders(&strat.ExitReq{
|
||||
Tag: "SellAll",
|
||||
Log: true,
|
||||
})
|
||||
state.LastSellTime = currentBarTime
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
OnInfoBar: func(s *strat.StratJob, e *ta.BarEnv, pair, tf string) {
|
||||
score := float64(0)
|
||||
if ta.RSI(e.Close, 14).Get(0) < 30 {
|
||||
score += 1
|
||||
}
|
||||
roc := ta.ROC(e.Close, 20).Get(0)
|
||||
if roc < -20 {
|
||||
score += 2
|
||||
} else if roc < -10 {
|
||||
score += 1
|
||||
}
|
||||
plusDi, minusDi := ta.PluMinDI(e.High, e.Low, e.Close, 14)
|
||||
adx := ta.ADX(e.High, e.Low, e.Close, 14).Get(0)
|
||||
if minusDi.Get(0) > plusDi.Get(0) {
|
||||
if adx > 40 {
|
||||
score += 2
|
||||
} else if adx > 25 {
|
||||
score += 1
|
||||
}
|
||||
}
|
||||
atr := ta.ATR(e.High, e.Low, e.Close, lenAtr)
|
||||
atrBase := ta.Lowest(ta.Highest(atr, lenAtr), baseAtrLen).Get(0)
|
||||
rates = append(rates, atrBase/(e.Close.Get(0)*0.01))
|
||||
//openRate := 0.006 * closePrice / atrBase
|
||||
//if openRate < 1 {
|
||||
// openRate = math.Sqrt(openRate)
|
||||
//}
|
||||
//openRate = max(0.7, min(1.5, openRate))
|
||||
ma7 := ta.SMA(e.Close, 7).Get(0)
|
||||
ma20 := ta.SMA(e.Close, 20)
|
||||
ma20V := ma20.Get(0)
|
||||
ma99 := ta.SMA(e.Close, 99).Get(0)
|
||||
if ma99 > ma20V {
|
||||
score += 1
|
||||
}
|
||||
state, _ := s.More.(*ZoneTradeState)
|
||||
state.score = score
|
||||
state.upFlag = 0
|
||||
state.atrBase = atrBase / (e.Close.Get(0) * 0.01)
|
||||
if ma20V > ma99 && ma20V > ma20.Get(2) {
|
||||
state.upFlag = 1
|
||||
} else if ma7 < min(ma20V, ma99) {
|
||||
state.upFlag = -1
|
||||
}
|
||||
},
|
||||
OnBatchJobs: func(jobs []*strat.StratJob) {
|
||||
pairLock.Lock()
|
||||
openPairs = 0
|
||||
pairLock.Unlock()
|
||||
},
|
||||
OnBatchInfos: func(tf string, jobs map[string]*strat.JobEnv) {
|
||||
if len(jobs) < 3 {
|
||||
return
|
||||
}
|
||||
downNum, downHeavyNum := float64(0), float64(0)
|
||||
atrRates := make([]float64, 0, len(jobs))
|
||||
for _, j := range jobs {
|
||||
state, _ := j.Job.More.(*ZoneTradeState)
|
||||
if state.score >= 5 {
|
||||
downHeavyNum += 1
|
||||
}
|
||||
if state.score >= 3 {
|
||||
downNum += 1
|
||||
}
|
||||
atrRates = append(atrRates, state.atrBase)
|
||||
}
|
||||
jobNum := float64(len(jobs))
|
||||
downRate := downNum / jobNum
|
||||
downHeavyRate := downHeavyNum / jobNum
|
||||
avgAtrBase = atrRates[len(jobs)/2]
|
||||
if downHeavyRate >= 0.8 {
|
||||
// 极端下跌
|
||||
addThres, firstRate = 1.6, 1.2
|
||||
maxPair = jobNum * 0.5
|
||||
} else if downRate >= 0.85 && downHeavyRate >= 0.6 {
|
||||
// 严重下跌
|
||||
addThres, firstRate = 1.45, 1.15
|
||||
maxPair = jobNum * 0.55
|
||||
} else if downRate >= 0.7 && downRate <= 0.85 {
|
||||
// 市场中度下跌
|
||||
addThres, firstRate = 1.3, 1.1
|
||||
maxPair = jobNum * 0.6
|
||||
} else if downRate >= 0.5 && downRate <= 0.7 {
|
||||
// 轻度下跌
|
||||
addThres, firstRate = 1.15, 1.05
|
||||
maxPair = jobNum * 0.7
|
||||
} else {
|
||||
// 轻度或未下跌
|
||||
maxPair = jobNum
|
||||
addThres, firstRate = 1, 1
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
66
llmjob/his/3782.yml
Normal file
66
llmjob/his/3782.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
env: dry_run
|
||||
market_type: linear
|
||||
leverage: 10
|
||||
time_start: "20250101"
|
||||
time_end: "20251112"
|
||||
stake_amount: 30
|
||||
concur_num: 3
|
||||
# stake_pct: 30
|
||||
max_stake_amt: 5000
|
||||
pairs: []
|
||||
relay_sim_unfinish: false
|
||||
stake_currency: [USDT]
|
||||
wallet_amounts:
|
||||
USDT: 1400
|
||||
run_policy:
|
||||
- name: llmjob:H3762
|
||||
stake_rate: 5
|
||||
refine_tf: 1m
|
||||
- name: llmjob:845
|
||||
stake_rate: 5
|
||||
refine_tf: 1m
|
||||
- name: llmjob:H3782
|
||||
stake_rate: 1
|
||||
refine_tf: 1m
|
||||
# - name: llmjob:1525
|
||||
# run_timeframes: [5m]
|
||||
# stake_rate: 0.4
|
||||
# params:
|
||||
# max_open_pair: 5
|
||||
# max_pair: 30
|
||||
# - name: llmjob:2523
|
||||
# stake_rate: 20
|
||||
pairmgr:
|
||||
cron: '0 0 0 1 */2 *' # 秒 分钟 小时 日 月 星期
|
||||
offset: 0
|
||||
limit: 999
|
||||
force_filters: false
|
||||
pos_on_rotation: close
|
||||
pairlists:
|
||||
- name: VolumePairList
|
||||
limit_rate: 0.7
|
||||
limit: 360
|
||||
min_value: 100000
|
||||
cache_secs: 7200
|
||||
back_period: 30d
|
||||
- name: PriceFilter # 价格过滤器
|
||||
max_unit_value: 200 # 最大允许的单位价格变动对应的价值(针对定价货币,一般是USDT)。
|
||||
precision: 0.0015 # 按价格精度过滤交易对,默认要求价格变动最小单位是0.1%
|
||||
min: 0.0001 # 最低价格
|
||||
max: 500000 # 最高价格
|
||||
- name: RateOfChangeFilter # 波动性过滤器
|
||||
back_days: 10 # 回顾的K线天数
|
||||
min: 0.03 # 最小价格变动比率
|
||||
max: 3 # 最大价格变动比率
|
||||
cache_secs: 1440 # 缓存时间,秒
|
||||
- name: SpreadFilter # 流动性过滤器
|
||||
max_ratio: 0.005 # 公式:1-bid/ask,买卖价差占价格的最大比率
|
||||
- name: AgeFilter # 按标的的上市天数过滤
|
||||
min: 180
|
||||
- name: VolatilityFilter # 波动性过滤器,公式:std(log(c/c1)) * sqrt(back_days)
|
||||
back_days: 10 # 回顾的K线天数
|
||||
max: 1 # 波动分数最大值,此值越大,允许一些在1d级别上变化非常剧烈的标的
|
||||
min: 0.03 # 波动分数最小值,此值越小,允许一些在1d级别上变化非常小的标的
|
||||
- name: OffsetFilter
|
||||
rate: 0.5
|
||||
limit: 30
|
||||
Reference in New Issue
Block a user