package rule import ( "encoding/json" "fmt" "git.apinb.com/bsm-sdk/core/utils" "git.apinb.com/quant/gostock/internal/impl" "git.apinb.com/quant/gostock/internal/models" talib "github.com/markcheno/go-talib" ) var ( offset = 3 // 偏移量 ) type StockArgConf struct { BestByDrawdown string `json:"best_by_drawdown"` BestByProfit string `json:"best_by_profit"` BestByReturn string `json:"best_by_return"` BestBySharpe string `json:"best_by_sharpe"` BestByWinRate string `json:"best_by_win_rate"` } func GetArgConfig(code string) (*models.StockArgs, *StockArgConf, error) { var args models.StockArgs err := impl.DBService.Where("ts_code = ?", code).First(&args).Error if err != nil { return nil, nil, err } var conf StockArgConf err = json.Unmarshal([]byte(args.Config), &conf) if err != nil { return nil, nil, err } return &args, &conf, nil } func (r *RuleFactory) RunRsi(code string) { args, conf, err := GetArgConfig(code) if err != nil { r.Model.ScoreRsi = -1 r.Model.AddDesc("RSI参数错误!") return } if conf.BestByProfit != "rsi" { r.Model.ScoreRsi = -1 r.Model.AddDesc("BestByProfit不是RSI") return } var close []float64 impl.DBService.Model(models.StockDaily{}).Where("ts_code = ?", code).Order("trade_date desc").Limit(args.RsiPeriod*4).Pluck("close", &close) if len(close) < args.RsiPeriod { r.Model.ScoreRsi = -1 r.Model.AddDesc("数据不足") return } newCloses := reverseSlice(close) args.RsiOversold = args.RsiOversold + offset rsiResult := talib.Rsi(newCloses, args.RsiPeriod) prveRsi := utils.FloatRound(rsiResult[len(rsiResult)-2], 2) lastRsi := utils.FloatRound(rsiResult[len(rsiResult)-1], 2) r.Model.ValRsiLast = lastRsi r.Model.ValRsiPrve = prveRsi r.Model.ValRsiOversold = args.RsiOversold prveRsiInt := int(prveRsi) lastRsiInt := int(lastRsi) // 跌破RSI下轨 if lastRsiInt > args.RsiOversold { if CheckLowest(close, lastRsiInt, 14) { r.Model.ScoreRsi = 1 r.Model.AddDesc(fmt.Sprintf("RSI=%d 跌破下轨,14日最低", lastRsiInt)) return } if CheckLowest(close, lastRsiInt, 20) { r.Model.ScoreRsi = 1 r.Model.AddDesc(fmt.Sprintf("RSI=%d 跌破下轨,20日最低", lastRsiInt)) return } r.Model.ScoreRsi = -1 r.Model.AddDesc(fmt.Sprintf("RSI=%d 高于Oversold%d", lastRsiInt, args.RsiOversold)) return } // RSI跌破下轨后呈上涨趋势 if lastRsiInt < prveRsiInt { r.Model.ScoreRsi = -1 r.Model.AddDesc(fmt.Sprintf("Rsi=%d prveRsi=%d,突破下轨,持续下跌", lastRsiInt, prveRsiInt)) return } else if lastRsiInt == prveRsiInt { r.Model.ScoreRsi = 1 r.Model.AddDesc(fmt.Sprintf("Rsi=%d prveRsi=%d,突破下轨,与前一交易日无太大波动", lastRsiInt, prveRsiInt)) return } r.Model.ScoreRsi = 2 r.Model.AddDesc(fmt.Sprintf("Rsi=%d prveRsi=%d,突破下轨后呈上涨趋势", lastRsiInt, prveRsiInt)) return }