@@ -6,18 +6,10 @@ import (
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/quant/gostock/internal/impl"
"git.apinb.com/quant/gostock/internal/logic/types"
"git.apinb.com/quant/gostock/internal/models"
talib "github.com/markcheno/go-talib"
)
type Rsi struct {
Key string
Name string
Conf * StockArgConf
Args * models . StockArgs
}
type StockArgConf struct {
BestByDrawdown string ` json:"best_by_drawdown" `
BestByProfit string ` json:"best_by_profit" `
@@ -26,67 +18,83 @@ type StockArgConf struct {
BestByWinRate string ` json:"best_by_win_rate" `
}
func NewRsi ( args * models . StockArgs ) * Rsi {
rsi := & Rsi {
Key : "Rsi" ,
Name : "RSI指标" ,
Conf : nil ,
Args : nil ,
}
if args == nil {
return rsi
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 )
err = json . Unmarshal ( [ ] byte ( args . Config ) , & conf )
if err != nil {
return rsi
return nil , nil , err
}
rsi . Conf = & conf
rsi . Args = args
return rsi
return & args , & conf , nil
}
func ( r * Rsi ) Run ( code string ) * types . RuleResult {
if r . C onf = = nil {
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : - 1 , Desc : "参数错误!" }
func ( r * RuleFactory ) RunRsi ( code string ) {
args , c onf, err : = GetArgConfig ( code )
if err != nil {
r . Model . ScoreRsi = - 1
r . Model . AddDesc ( "RSI参数错误! " )
return
}
if r . C onf. BestByProfit != "rsi" {
return & types . RuleResult { Key : r . Key , Name : r . Name , Score: - 1, Desc : "BestByProfit!=RSI,BestByProfit=" + r . Conf . BestByProfit }
if c onf. 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 ( r . A rgs. RsiPeriod * 4 ) . Pluck ( "close" , & close )
if len ( close ) < r . A rgs. RsiPeriod {
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : - 1 , Desc : "数据不足" }
impl . DBService . Model ( models . StockDaily { } ) . Where ( "ts_code = ?" , code ) . Order ( "trade_date desc" ) . Limit ( a rgs. RsiPeriod * 4 ) . Pluck ( "close" , & close )
if len ( close ) < a rgs. RsiPeriod {
r . Model . ScoreRsi = - 1
r . Model . AddDesc ( "数据不足" )
return
}
newCloses := reverseSlice ( close )
rsiResult := talib . Rsi ( newCloses , r . A rgs. RsiPeriod )
prveRsi := rsiResult [ len ( rsiResult ) - 2 ]
lastRsi := rsiResult [ len ( rsiResult ) - 1 ]
lastRsi = utils . FloatRound ( lastRsi , 2 )
rsiResult := talib . Rsi ( newCloses , a rgs. 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 > r . A rgs. RsiOversold {
if lastRsiInt > a rgs. RsiOversold {
if CheckLowest ( close , lastRsiInt , 14 ) {
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : 1 , Result : lastRsi , Desc : fmt . Sprintf ( "RSI=%d 跌破下轨,14日最低" , lastRsiInt ) }
r . Model . ScoreRsi = 1
r . Model . AddDesc ( fmt . Sprintf ( "RSI=%d 跌破下轨,14日最低" , lastRsiInt ) )
return
}
if CheckLowest ( close , lastRsiInt , 20 ) {
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : 1 , Result : lastRsi , Desc : fmt . Sprintf ( "RSI=%d 跌破下轨,20日最低" , lastRsiInt ) }
r . Model . ScoreRsi = 1
r . Model . AddDesc ( fmt . Sprintf ( "RSI=%d 跌破下轨,20日最低" , lastRsiInt ) )
return
}
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : - 1 , Desc : fmt . Sprintf ( "RSI=%d 高于%d" , lastRsiInt , r . Args . RsiOversold ) }
r . Model . ScoreRsi = - 1
r . Model . AddDesc ( fmt . Sprintf ( "RSI=%d 高于Oversold%d" , lastRsiInt , args . RsiOversold ) )
return
}
// RSI跌破下轨后呈上涨趋势
if lastRsiInt < prveRsiInt {
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : - 1 , Desc : fmt . Sprintf ( "Rsi=%d prveRsi=%d,跌破下轨,持续下跌" , 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
}
return & types . RuleResult { Key : r . Key , Name : r . Name , Score : 1 , Result : lastRsi , Desc : fmt . Sprintf ( "RSI=%d prveRsi=%d,跌破下轨后呈上涨趋势" , lastRsiInt , prveRsiInt ) }
r . Model . ScoreRsi = 2
r . Model . AddDesc ( fmt . Sprintf ( "Rsi=%d prveRsi=%d,突破下轨后呈上涨趋势" , lastRsiInt , prveRsiInt ) )
return
}