gitee.com/quant1x/engine@v1.8.4/datasource/dfcf/financial_reports.go (about)

     1  package dfcf
     2  
     3  import (
     4  	"fmt"
     5  	"gitee.com/quant1x/engine/cache"
     6  	"gitee.com/quant1x/exchange"
     7  	"gitee.com/quant1x/gox/api"
     8  	"gitee.com/quant1x/gox/http"
     9  	"gitee.com/quant1x/gox/logger"
    10  	"gitee.com/quant1x/pkg/fastjson"
    11  	urlpkg "net/url"
    12  	"sync"
    13  )
    14  
    15  // QuarterlyReports 分页获取季报数据
    16  func QuarterlyReports(featureDate string, pageNumber ...int) (reports []QuarterlyReport, pages int, err error) {
    17  	pageNo := 1
    18  	if len(pageNumber) > 0 {
    19  		pageNo = pageNumber[0]
    20  	}
    21  	qBegin, qEnd := api.GetQuarterDayByDate(featureDate)
    22  	quarterBeginDate := exchange.FixTradeDate(qBegin)
    23  	quarterEndDate := exchange.FixTradeDate(qEnd)
    24  	params := urlpkg.Values{
    25  		//"callback":    {"jQuery1123043614175387302234_1685785566671"},
    26  		//"sortColumns": {"UPDATE_DATE,SECURITY_CODE"},
    27  		"sortColumns": {"REPORTDATE,SECURITY_CODE"},
    28  		"sortTypes":   {"-1,1"},
    29  		"pageSize":    {fmt.Sprint(EastmoneyQuarterlyReportAllPageSize)},
    30  		"pageNumber":  {fmt.Sprintf("%d", pageNo)},
    31  		"reportName":  {"RPT_LICO_FN_CPD"},
    32  		"columns":     {"ALL"},
    33  		"filter":      {fmt.Sprintf("(REPORTDATE='%s')", quarterEndDate)},
    34  	}
    35  	_ = quarterBeginDate
    36  	_ = quarterEndDate
    37  
    38  	url := urlQuarterlyReportAll + "?" + params.Encode()
    39  	data, err := http.Get(url)
    40  	//fmt.Println(api.Bytes2String(data))
    41  	obj, err := fastjson.ParseBytes(data)
    42  	if err != nil {
    43  		logger.Errorf("%+v\n", err)
    44  		return
    45  	}
    46  
    47  	result := obj.Get("result")
    48  	list := result.GetArray("data")
    49  	pages = result.GetInt("pages")
    50  	if len(list) > 0 {
    51  		for _, v := range list {
    52  			report := QuarterlyReport{
    53  				SecuCode:           v.GetString("SECUCODE"),
    54  				UpdateDate:         v.GetString("UPDATE_DATE"),
    55  				ReportDate:         v.GetString("REPORTDATE"),
    56  				BasicEPS:           v.GetFloat64("BASIC_EPS"),
    57  				DeductBasicEPS:     v.GetFloat64("DEDUCT_BASIC_EPS"),
    58  				BPS:                v.GetFloat64("BPS"),
    59  				NoticeDate:         v.GetString("NOTICE_DATE"),
    60  				IsNew:              v.GetString("ISNEW"),
    61  				ORGCODE:            v.GetString("ORG_CODE"),
    62  				TRADEMARKETZJG:     v.GetString("TRADE_MARKET_ZJG"),
    63  				QDATE:              v.GetString("QDATE"),
    64  				DATATYPE:           v.GetString("DATATYPE"),
    65  				DATAYEAR:           v.GetString("DATAYEAR"),
    66  				DATEMMDD:           v.GetString("DATEMMDD"),
    67  				EITIME:             v.GetString("EITIME"),
    68  				SECURITYCODE:       v.GetString("SECURITY_CODE"),
    69  				SECURITYNAMEABBR:   v.GetString("SECURITY_NAME_ABBR"),
    70  				TRADEMARKETCODE:    v.GetString("TRADE_MARKET_CODE"),
    71  				TRADEMARKET:        v.GetString("TRADE_MARKET"),
    72  				SECURITYTYPECODE:   v.GetString("SECURITY_TYPE_CODE"),
    73  				SECURITYTYPE:       v.GetString("SECURITY_TYPE"),
    74  				TotalOperateIncome: v.GetFloat64("TOTAL_OPERATE_INCOME"),
    75  				ParentNetprofit:    v.GetFloat64("PARENT_NETPROFIT"),
    76  				WeightAvgRoe:       v.GetFloat64("WEIGHTAVG_ROE"),
    77  				YSTZ:               v.GetFloat64("YSTZ"),
    78  				SJLTZ:              v.GetFloat64("SJLTZ"),
    79  				MGJYXJJE:           v.GetFloat64("MGJYXJJE"),
    80  				XSMLL:              v.GetFloat64("XSMLL"),
    81  				YSHZ:               v.GetFloat64("YSHZ"),
    82  				SJLHZ:              v.GetFloat64("SJLHZ"),
    83  				ASSIGNDSCRPT:       v.GetFloat64("ASSIGNDSCRPT"),
    84  				PAYYEAR:            v.GetFloat64("PAYYEAR"),
    85  				PUBLISHNAME:        v.GetFloat64("PUBLISHNAME"),
    86  				ZXGXL:              v.GetFloat64("ZXGXL"),
    87  			}
    88  			// 截取市场编码,截取股票编码,市场编码+股票编码拼接作为主键
    89  			securityCode := exchange.CorrectSecurityCode(report.SecuCode)
    90  			report.SecurityCode = securityCode
    91  			reports = append(reports, report)
    92  		}
    93  	}
    94  	return
    95  }
    96  
    97  // QuarterlyReportsBySecurityCode 分页获取季报数据
    98  func QuarterlyReportsBySecurityCode(securityCode, date string, diffQuarters int, pageNumber ...int) (reports []QuarterlyReport) {
    99  	pageNo := 1
   100  	if len(pageNumber) > 0 {
   101  		pageNo = pageNumber[0]
   102  	}
   103  	_, _, code := exchange.DetectMarket(securityCode)
   104  	quarterEndDate := exchange.FixTradeDate(date)
   105  	//_, _, qEnd := api.GetQuarterByDate(date, diffQuarters)
   106  	//quarterEndDate = trading.FixTradeDate(qEnd)
   107  	params := urlpkg.Values{
   108  		"sortColumns": {"REPORTDATE,SECURITY_CODE"},
   109  		"sortTypes":   {"-1,1"},
   110  		"pageSize":    {fmt.Sprint(EastmoneyQuarterlyReportAllPageSize)},
   111  		"pageNumber":  {fmt.Sprintf("%d", pageNo)},
   112  		"reportName":  {"RPT_LICO_FN_CPD"},
   113  		"columns":     {"ALL"},
   114  		"filter":      {fmt.Sprintf("(SECURITY_CODE=\"%s\")(REPORTDATE='%s')", code, quarterEndDate)},
   115  	}
   116  
   117  	url := urlQuarterlyReportAll + "?" + params.Encode()
   118  	data, err := http.Get(url)
   119  	//fmt.Println(api.Bytes2String(data))
   120  	obj, err := fastjson.ParseBytes(data)
   121  	if err != nil {
   122  		logger.Errorf("%+v\n", err)
   123  		return
   124  	}
   125  
   126  	result := obj.Get("result")
   127  	list := result.GetArray("data")
   128  	pages := result.GetInt("pages")
   129  	_ = pages
   130  	if len(list) > 0 {
   131  		for _, v := range list {
   132  			report := QuarterlyReport{
   133  				SecuCode:           v.GetString("SECUCODE"),
   134  				UpdateDate:         v.GetString("UPDATE_DATE"),
   135  				ReportDate:         v.GetString("REPORTDATE"),
   136  				BasicEPS:           v.GetFloat64("BASIC_EPS"),
   137  				DeductBasicEPS:     v.GetFloat64("DEDUCT_BASIC_EPS"),
   138  				BPS:                v.GetFloat64("BPS"),
   139  				NoticeDate:         v.GetString("NOTICE_DATE"),
   140  				IsNew:              v.GetString("ISNEW"),
   141  				ORGCODE:            v.GetString("ORG_CODE"),
   142  				TRADEMARKETZJG:     v.GetString("TRADE_MARKET_ZJG"),
   143  				QDATE:              v.GetString("QDATE"),
   144  				DATATYPE:           v.GetString("DATATYPE"),
   145  				DATAYEAR:           v.GetString("DATAYEAR"),
   146  				DATEMMDD:           v.GetString("DATEMMDD"),
   147  				EITIME:             v.GetString("EITIME"),
   148  				SECURITYCODE:       v.GetString("SECURITY_CODE"),
   149  				SECURITYNAMEABBR:   v.GetString("SECURITY_NAME_ABBR"),
   150  				TRADEMARKETCODE:    v.GetString("TRADE_MARKET_CODE"),
   151  				TRADEMARKET:        v.GetString("TRADE_MARKET"),
   152  				SECURITYTYPECODE:   v.GetString("SECURITY_TYPE_CODE"),
   153  				SECURITYTYPE:       v.GetString("SECURITY_TYPE"),
   154  				TotalOperateIncome: v.GetFloat64("TOTAL_OPERATE_INCOME"),
   155  				ParentNetprofit:    v.GetFloat64("PARENT_NETPROFIT"),
   156  				WeightAvgRoe:       v.GetFloat64("WEIGHTAVG_ROE"),
   157  				YSTZ:               v.GetFloat64("YSTZ"),
   158  				SJLTZ:              v.GetFloat64("SJLTZ"),
   159  				MGJYXJJE:           v.GetFloat64("MGJYXJJE"),
   160  				XSMLL:              v.GetFloat64("XSMLL"),
   161  				YSHZ:               v.GetFloat64("YSHZ"),
   162  				SJLHZ:              v.GetFloat64("SJLHZ"),
   163  				ASSIGNDSCRPT:       v.GetFloat64("ASSIGNDSCRPT"),
   164  				PAYYEAR:            v.GetFloat64("PAYYEAR"),
   165  				PUBLISHNAME:        v.GetFloat64("PUBLISHNAME"),
   166  				ZXGXL:              v.GetFloat64("ZXGXL"),
   167  			}
   168  			// 截取市场编码,截取股票编码,市场编码+股票编码拼接作为主键
   169  			securityCode := exchange.CorrectSecurityCode(report.SecuCode)
   170  			report.SecurityCode = securityCode
   171  			reports = append(reports, report)
   172  		}
   173  	}
   174  	return
   175  }
   176  
   177  var (
   178  	mutexReports sync.RWMutex
   179  	mapReports   = map[string][]QuarterlyReport{}
   180  	chanReports  = make(chan int, 1)
   181  )
   182  
   183  // 获取指定个股和周期的季报
   184  func cacheQuarterlyReportsBySecurityCode(securityCode, date string, diffQuarters ...int) *QuarterlyReport {
   185  	diff := 1
   186  	if len(diffQuarters) > 0 {
   187  		diff = diffQuarters[0]
   188  	}
   189  	_, _, last := api.GetQuarterByDate(date, diff)
   190  	filename := cache.ReportsFilename(last)
   191  	var allReports []QuarterlyReport
   192  
   193  	mutexReports.Lock()
   194  	defer mutexReports.Unlock()
   195  	allReports, ok := mapReports[filename]
   196  	if !ok && api.FileExist(filename) {
   197  		_ = api.CsvToSlices(filename, &allReports)
   198  		if len(allReports) > 0 {
   199  			mapReports[filename] = allReports
   200  		}
   201  	}
   202  
   203  	//chanReports <- 1
   204  	if len(allReports) == 0 {
   205  		if diff > 1 {
   206  			_, _, date = api.GetQuarterByDate(date, diff-1)
   207  		}
   208  		reports, pages, _ := QuarterlyReports(date)
   209  		if pages < 2 || len(reports) == 0 {
   210  			return nil
   211  		}
   212  		allReports = append(allReports, reports...)
   213  		for pageNo := 2; pageNo < pages+1; pageNo++ {
   214  			list, pages, err := QuarterlyReports(date, pageNo)
   215  			if err != nil || pages < 1 {
   216  				logger.Error(err)
   217  				break
   218  			}
   219  			count := len(list)
   220  			if count == 0 {
   221  				break
   222  			}
   223  			allReports = append(allReports, list...)
   224  			if count < EastmoneyQuarterlyReportAllPageSize {
   225  				break
   226  			}
   227  		}
   228  		if len(allReports) > 0 {
   229  			mapReports[filename] = allReports
   230  			err := api.SlicesToCsv(filename, allReports)
   231  			if err != nil {
   232  				logger.Errorf("cache %s failed, error: %+v", filename, err)
   233  			}
   234  		}
   235  	}
   236  
   237  	for _, v := range allReports {
   238  		if v.SecurityCode == securityCode {
   239  			return &v
   240  		}
   241  	}
   242  
   243  	return nil
   244  }
   245  
   246  // GetCacheQuarterlyReportsBySecurityCode 获取上市公司财务季报 Quarterly Reports
   247  func GetCacheQuarterlyReportsBySecurityCode(securityCode, date string, diffQuarters ...int) *QuarterlyReport {
   248  	diff := 1
   249  	if len(diffQuarters) > 0 {
   250  		diff = diffQuarters[0]
   251  	}
   252  	for ; diff < 4; diff++ {
   253  		report := cacheQuarterlyReportsBySecurityCode(securityCode, date, diff)
   254  		if report == nil {
   255  			continue
   256  		}
   257  		return report
   258  	}
   259  	return nil
   260  }