gitee.com/quant1x/engine@v1.8.4/factors/feature_f10.go (about)

     1  package factors
     2  
     3  import (
     4  	"context"
     5  	"gitee.com/quant1x/engine/cache"
     6  	"gitee.com/quant1x/engine/config"
     7  	"gitee.com/quant1x/engine/datasource/dfcf"
     8  	"gitee.com/quant1x/engine/datasource/tdxweb"
     9  	"gitee.com/quant1x/engine/market"
    10  	"gitee.com/quant1x/exchange"
    11  	"gitee.com/quant1x/gotdx/securities"
    12  	"gitee.com/quant1x/gox/api"
    13  	"gitee.com/quant1x/gox/logger"
    14  	"gitee.com/quant1x/num"
    15  )
    16  
    17  const (
    18  	cacheL5KeyF10 = "f10"
    19  )
    20  
    21  // F10 证券基本面
    22  type F10 struct {
    23  	cache.DataSummary    `dataframe:"-"`
    24  	Date                 string  `name:"日期" dataframe:"Date"`                      // 日期
    25  	Code                 string  `name:"代码" dataframe:"Code"`                      // 证券代码
    26  	SecurityName         string  `name:"名称" dataframe:"Name"`                      // 证券名称
    27  	SubNew               bool    `name:"次新股" dataframe:"SubNew"`                   // 是否次新股
    28  	MarginTradingTarget  bool    `name:"两融" dataframe:"MarginTradingTarget"`       // 是否两融标的
    29  	VolUnit              int     `name:"每手" dataframe:"VolUnit"`                   // 每手单位
    30  	DecimalPoint         int     `name:"小数点" dataframe:"DecimalPoint"`             // 小数点
    31  	IpoDate              string  `name:"上市日期" dataframe:"IpoDate"`                 // 上市日期
    32  	UpdateDate           string  `name:"更新日期" dataframe:"UpdateDate"`              // 更新日期
    33  	TotalCapital         float64 `name:"总股本" dataframe:"TotalCapital"`             // 总股本
    34  	Capital              float64 `name:"流通股本" dataframe:"Capital"`                 // 流通股本
    35  	FreeCapital          float64 `name:"自由流通股本" dataframe:"FreeCapital"`           // 自由流通股本
    36  	Top10Capital         float64 `name:"前十大流通股东总股本" dataframe:"Top10Capital"`      // 前十大流通股东股本
    37  	Top10Change          float64 `name:"前十大流通股东总股本变化" dataframe:"Top10Change"`     //前十大流通股东股本变化
    38  	ChangeCapital        float64 `name:"前十大流通股东持仓变化" dataframe:"ChangeCapital"`    // 前十大流通股东持仓变化
    39  	IncreaseRatio        float64 `name:"当期增持比例" dataframe:"IncreaseRatio"`         // 当期增持比例
    40  	ReductionRatio       float64 `name:"当期减持比例" dataframe:"ReductionRatio"`        // 当期减持比例
    41  	QuarterlyYearQuarter string  `name:"季报期" dataframe:"quarterly_year_quarter"`   // 当前市场处于哪个季报期, 用于比较个股的季报数据是否存在拖延的情况
    42  	QDate                string  `name:"新报告期" dataframe:"qdate"`                   // 最新报告期
    43  	AnnualReportDate     string  `name:"年报披露日期" dataframe:"annual_report_date"`    // 年报披露日期
    44  	QuarterlyReportDate  string  `name:"季报披露日期" dataframe:"quarterly_report_date"` // 最新季报披露日期
    45  	TotalOperateIncome   float64 `name:"营业总收入" dataframe:"TotalOperateIncome"`     // 当期营业总收入
    46  	BPS                  float64 `name:"每股净资产" dataframe:"BPS"`                    // 每股净资产
    47  	BasicEPS             float64 `name:"每股收益" dataframe:"BasicEPS"`                // 每股收益
    48  	DeductBasicEPS       float64 `name:"每股收益(扣除)" dataframe:"DeductBasicEPS"`      // 每股收益(扣除)
    49  	SafetyScore          int     `name:"安全分" dataframe:"SafetyScore"`              // 通达信安全分
    50  	Increases            int     `name:"增持" dataframe:"Increases"`                 // 公告-增持
    51  	Reduces              int     `name:"减持" dataframe:"Reduces"`                   // 公告-减持
    52  	Risk                 int     `name:"风险数" dataframe:"Risk"`                     // 公告-风险数
    53  	RiskKeywords         string  `name:"风险关键词" dataframe:"RiskKeywords"`           // 公告-风险关键词
    54  	UpdateTime           string  `name:"更新时间" dataframe:"update_time"`             // 更新时间
    55  	State                uint64  `name:"样本状态" dataframe:"样本状态"`
    56  }
    57  
    58  func NewF10(date, code string) *F10 {
    59  	summary := __mapFeatures[FeatureF10]
    60  	v := F10{
    61  		DataSummary:  summary,
    62  		Date:         date,
    63  		Code:         code,
    64  		SecurityName: securities.GetStockName(code),
    65  		VolUnit:      100,
    66  		DecimalPoint: 2,
    67  		SubNew:       market.IsSubNewStock(code),
    68  	}
    69  	securityInfo, ok := securities.CheckoutSecurityInfo(code)
    70  	if ok {
    71  		v.VolUnit = int(securityInfo.VolUnit)
    72  		v.DecimalPoint = int(securityInfo.DecimalPoint)
    73  		v.SecurityName = securityInfo.Name
    74  	}
    75  	// 检测是否两融标的
    76  	v.MarginTradingTarget = securities.IsMarginTradingTarget(code)
    77  	return &v
    78  }
    79  
    80  func (this *F10) GetDate() string {
    81  	return this.Date
    82  }
    83  
    84  func (this *F10) GetSecurityCode() string {
    85  	return this.Code
    86  }
    87  
    88  func (this *F10) Factory(date string, code string) Feature {
    89  	v := NewF10(date, code)
    90  	return v
    91  }
    92  
    93  func (this *F10) Init(ctx context.Context, date string) error {
    94  	loadQuarterlyReports(this.GetDate())
    95  	_ = ctx
    96  	_ = date
    97  	return nil
    98  }
    99  
   100  func (this *F10) FromHistory(history History) Feature {
   101  	_ = history
   102  	return this
   103  }
   104  
   105  func (this *F10) Update(code, cacheDate, featureDate string, complete bool) {
   106  	securityCode := this.GetSecurityCode()
   107  	logger.Warnf("update f10, code=%s", securityCode)
   108  
   109  	// 1. 基本信息
   110  	securityInfo := checkoutSecurityBasicInfo(securityCode, featureDate)
   111  	_ = api.Copy(this, &securityInfo)
   112  	// 2. 前十大流通股股东
   113  	shareHolder := checkoutShareHolder(securityCode, featureDate)
   114  	_ = api.Copy(this, shareHolder)
   115  	if this.FreeCapital == 0 {
   116  		this.FreeCapital = this.Capital
   117  	}
   118  	// 3. 上市公司公告
   119  	notice := getOneNotice(securityCode, featureDate)
   120  	_ = api.Copy(this, &notice)
   121  	// 4. 季报
   122  	this.QuarterlyYearQuarter = getQuarterlyYearQuarter(featureDate)
   123  	report := getQuarterlyReportSummary(securityCode, featureDate)
   124  	_ = api.Copy(this, &report)
   125  
   126  	// 5. 安全分
   127  	safetyScore := tdxweb.GetSafetyScore(securityCode)
   128  	this.SafetyScore = safetyScore
   129  
   130  	// 6. 年报季报披露日期
   131  	annualReportDate, quarterlyReportDate := dfcf.NoticeDateForReport(securityCode, cacheDate)
   132  	this.AnnualReportDate = annualReportDate
   133  	this.QuarterlyReportDate = quarterlyReportDate
   134  
   135  	this.UpdateTime = GetTimestamp()
   136  	this.State |= this.Kind()
   137  	logger.Warnf("update f10, code=%s, OK", securityCode)
   138  	_ = complete
   139  }
   140  
   141  func (this *F10) Repair(code, cacheDate, featureDate string, complete bool) {
   142  	securityCode := code
   143  
   144  	// 1. 基本信息
   145  	securityInfo := checkoutSecurityBasicInfo(securityCode, featureDate)
   146  	_ = api.Copy(this, &securityInfo)
   147  	// 2. 前十大流通股股东
   148  	shareHolder := checkoutShareHolder(securityCode, featureDate)
   149  	_ = api.Copy(this, shareHolder)
   150  	if this.FreeCapital == 0 {
   151  		this.FreeCapital = this.Capital
   152  	}
   153  	// 3. 上市公司公告
   154  	notice := getOneNotice(securityCode, featureDate)
   155  	_ = api.Copy(this, &notice)
   156  	// 4. 季报
   157  	report := getQuarterlyReportSummary(securityCode, featureDate)
   158  	_ = api.Copy(this, &report)
   159  
   160  	// 5. 安全分
   161  	if this.SafetyScore == 0 {
   162  		safetyScore := tdxweb.GetSafetyScore(securityCode)
   163  		this.SafetyScore = safetyScore
   164  	}
   165  
   166  	// 6. 年报季报披露日期
   167  	annualReportDate, quarterlyReportDate := dfcf.NoticeDateForReport(securityCode, cacheDate)
   168  	this.AnnualReportDate = annualReportDate
   169  	this.QuarterlyReportDate = quarterlyReportDate
   170  
   171  	this.UpdateTime = GetTimestamp()
   172  	this.State |= this.Kind()
   173  
   174  	_ = complete
   175  }
   176  
   177  func (this *F10) Increase(snapshot QuoteSnapshot) Feature {
   178  	//TODO implement me
   179  	panic("implement me")
   180  }
   181  
   182  func (this *F10) ValidateSample() error {
   183  	if this.State > 0 {
   184  		return nil
   185  	}
   186  	return ErrInvalidFeatureSample
   187  }
   188  
   189  func (this *F10) TurnZ(v any) float64 {
   190  	freeCapital := this.FreeCapital
   191  	if freeCapital == 0 {
   192  		freeCapital = this.Capital
   193  	}
   194  	if freeCapital == 0 {
   195  		return 0.00
   196  	}
   197  	n := num.AnyToFloat64(v)
   198  	turnoverRateZ := num.ChangeRate(freeCapital, n)
   199  	turnoverRateZ *= 10000
   200  	turnoverRateZ = num.Decimal(turnoverRateZ)
   201  	return turnoverRateZ
   202  }
   203  
   204  // IsReportingRiskPeriod 是否财报披露前夕
   205  func (this *F10) IsReportingRiskPeriod() bool {
   206  	if len(this.AnnualReportDate) == 0 || len(this.QuarterlyReportDate) == 0 {
   207  		// 如果年报和季报日期不确定, 判定为非风险期, 返回false
   208  		// 这种情况有可能是次新股的保护期
   209  		return false
   210  	}
   211  	f10Config := config.GetDataConfig().Feature.F10
   212  	date := this.GetDate()
   213  	ys := exchange.DateRange(date, this.AnnualReportDate)
   214  	ly := len(ys)
   215  	qs := exchange.DateRange(date, this.QuarterlyReportDate)
   216  	lq := len(qs)
   217  	if (ly > 0 && ly < f10Config.ReportingRiskPeriod) || (lq > 0 && lq < f10Config.ReportingRiskPeriod) {
   218  		return true
   219  	}
   220  	return false
   221  }