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 }