fix bug
This commit is contained in:
@@ -19,8 +19,7 @@ func (r *RuleFactory) RunRoe(code string) {
|
||||
var data models.StockFinaIndicator
|
||||
err := impl.DBService.Where("ts_code = ?", code).Order("period desc").Limit(1).First(&data).Error
|
||||
if err != nil {
|
||||
r.Model.GtRoe = -1
|
||||
r.Model.ValRoe = -1
|
||||
r.Model.RoeScore = -1
|
||||
r.Model.AddDesc("最近无财报,无ROE值!")
|
||||
return
|
||||
}
|
||||
@@ -29,12 +28,13 @@ func (r *RuleFactory) RunRoe(code string) {
|
||||
r.Model.ValRoe = data.Roe
|
||||
|
||||
if data.Roe < MinRoe {
|
||||
r.Model.GtRoe = -1
|
||||
r.Model.RoeScore = -1
|
||||
r.Model.AddDesc(fmt.Sprintf("ROE=%.2f 低于%.2f", data.Roe, MinRoe))
|
||||
return
|
||||
}
|
||||
|
||||
r.Model.GtRoe = 1
|
||||
r.Model.RoeScore = 1
|
||||
r.Model.ValRoe = data.Roe
|
||||
r.Model.AddDesc(fmt.Sprintf("ROE=%.2f 高于%.2f", data.Roe, MinRoe))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
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 = 1 // 偏移量
|
||||
)
|
||||
|
||||
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 args.RsiOversold == 0 {
|
||||
r.Model.ScoreRsi = -1
|
||||
r.Model.AddDesc("RSI RsiOversold=0,参数错误!")
|
||||
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)
|
||||
|
||||
if lastRsiInt == 0 {
|
||||
r.Model.ScoreRsi = -1
|
||||
r.Model.AddDesc("RSI lastRsiInt=0,计算错误!")
|
||||
return
|
||||
}
|
||||
|
||||
// 跌破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
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package rule
|
||||
|
||||
// 如果数据是降序(最新在前),需要反转
|
||||
func reverseSlice(s []float64) []float64 {
|
||||
result := make([]float64, len(s))
|
||||
for i, j := 0, len(s)-1; i < len(s); i, j = i+1, j-1 {
|
||||
result[i] = s[j]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 检查值是否为数组最后N个元素中的最小值
|
||||
func CheckLowest(prices []float64, target int, n int) bool {
|
||||
if len(prices) == 0 || n <= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// 如果n大于数组长度,使用整个数组
|
||||
if n > len(prices) {
|
||||
n = len(prices)
|
||||
}
|
||||
|
||||
// 获取最后n个元素
|
||||
slice := prices[len(prices)-n:]
|
||||
|
||||
// 查找最小值
|
||||
minVal := slice[0]
|
||||
for _, val := range slice[1:] {
|
||||
if val < minVal {
|
||||
minVal = val
|
||||
}
|
||||
}
|
||||
|
||||
return target == int(minVal)
|
||||
}
|
||||
Reference in New Issue
Block a user