浏览代码

fix:报告解析优化

wangzaijun 1 周之前
父节点
当前提交
c098c4c90b

+ 9 - 4
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/ai/AIQuarterlyReportParser.java

@@ -26,16 +26,21 @@ public class AIQuarterlyReportParser extends AbstractAIReportParser<QuarterlyRep
     @Override
     protected String prompt() {
         return """
-                识别文件中的基金基本情况、基金净值表现、主要财务指标、投资组合情况、基金份额变动情况,
-                基金净值表现、主要财务指标可能包好分级基金数据,投资组合情况包含期末基金资产组合情况、报告期末按行业分类的股票投资组合,
-                要求准确识别金额等小数的位数,去掉金额单位、英文和多余的空格,结果用json返回
+                识别文件中的基金基本情况、主要财务指标、投资组合情况、基金份额变动情况,
+                主要财务指标可能包含分级基金数据,投资组合情况包含期末基金资产组合情况、报告期末按行业分类的股票投资组合,
+                要求解析结果的中文符号转英文符号,结果用json返回
                 """;
     }
 
     @Override
     protected QuarterlyReportData parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo,
                                                          ReportFundInfoDTO fundInfo) throws ReportParseException {
-        return null;
+        QuarterlyReportData reportData = new QuarterlyReportData(reportInfo, fundInfo);
+        reportData.setAssetAllocation(null);
+        reportData.setShareChange(null);
+        reportData.setFinancialIndicators(null);
+        reportData.setInvestmentIndustry(null);
+        return reportData;
     }
 
     @Override

+ 19 - 15
mo-daq/src/main/java/com/smppw/modaq/application/task/ParseSchedulerTask.java

@@ -31,21 +31,21 @@ public class ParseSchedulerTask {
 
     @PostConstruct
     public void executeOnStartup() {
-        try {
-            // 定期报告从 我的文件夹.报告公告 文件夹获取邮件
-            this.emailParseApiService.parseEmail(
-                    DateUtil.parseDateTime("2025-04-30 10:02:00"),
-                    DateUtil.parseDateTime("2025-04-30 10:35:00"),
-                    ListUtil.of("其他文件夹/报告公告"), EmailTypeConst.REPORT_EMAIL_TYPES);
-        } catch (Exception e) {
-            logger.error(ExceptionUtil.getMessage(e));
-        }
+//        try {
+//            // 定期报告从 我的文件夹.报告公告 文件夹获取邮件
+//            this.emailParseApiService.parseEmail(
+//                    DateUtil.parseDateTime("2025-04-30 10:02:00"),
+//                    DateUtil.parseDateTime("2025-04-30 10:35:00"),
+//                    ListUtil.of("其他文件夹/报告公告"), EmailTypeConst.REPORT_EMAIL_TYPES);
+//        } catch (Exception e) {
+//            logger.error(ExceptionUtil.getMessage(e));
+//        }
     }
 
     /**
-     * 定时任务每2小时执行一次
+     * 定时任务每11分钟执行一次
      */
-    @Scheduled(cron = "0 0 */1 * * ?")
+    @Scheduled(cron = "0 */11 * * * ?")
     public void letter() {
         String taskKye = "mo_email_parse_letter_task";
         TaskRecordDO task = this.taskRecordService.getTaskRecord(taskKye);
@@ -55,8 +55,10 @@ public class ParseSchedulerTask {
         long start = System.currentTimeMillis();
         Date now = new Date();
         try {
+            // 尽可能往前找11分钟覆盖可能遗漏的邮件
+            Date startTime = DateUtil.offsetMinute(task.getStartTime(), -11);
             // 确认单从 INBOX 默认文件夹获取邮件
-            this.emailParseApiService.parseEmail(task.getStartTime(), now,
+            this.emailParseApiService.parseEmail(startTime, now,
                     null, ListUtil.of(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE));
             task.setStatus(1);
         } catch (Exception e) {
@@ -73,9 +75,9 @@ public class ParseSchedulerTask {
     }
 
     /**
-     * 定时任务每1小时执行一次
+     * 定时任务每21分钟执行一次
      */
-    @Scheduled(cron = "0 30 */2 * * ?")
+    @Scheduled(cron = "0 */21 * * * ?")
     public void report() {
         String taskKye = "mo_email_parser_report_task";
         TaskRecordDO task = this.taskRecordService.getTaskRecord(taskKye);
@@ -85,8 +87,10 @@ public class ParseSchedulerTask {
         long start = System.currentTimeMillis();
         Date now = new Date();
         try {
+            // 尽可能往前找21分钟覆盖可能遗漏的邮件
+            Date startTime = DateUtil.offsetMinute(task.getStartTime(), -21);
             // 定期报告从 我的文件夹.报告公告 文件夹获取邮件
-            this.emailParseApiService.parseEmail(task.getStartTime(), now,
+            this.emailParseApiService.parseEmail(startTime, now,
                     ListUtil.of("其他文件夹/报告公告"), EmailTypeConst.REPORT_EMAIL_TYPES);
             task.setStatus(1);
         } catch (Exception e) {

+ 10 - 3
mo-daq/src/main/java/com/smppw/modaq/common/conts/EmailTypeConst.java

@@ -39,7 +39,14 @@ public class EmailTypeConst {
     /**
      * 所有支持解析的类型
      */
-    public final static List<Integer> SUPPORT_EMAIL_TYPES = ListUtil.of(REPORT_EMAIL_TYPE, REPORT_LETTER_EMAIL_TYPE, REPORT_OTHER_TYPE, REPORT_WEEKLY_TYPE);
-
-    public final static List<Integer> REPORT_EMAIL_TYPES = ListUtil.of(REPORT_EMAIL_TYPE, REPORT_OTHER_TYPE, REPORT_WEEKLY_TYPE);
+    public final static List<Integer> SUPPORT_EMAIL_TYPES = ListUtil.of(
+            REPORT_EMAIL_TYPE,
+            REPORT_LETTER_EMAIL_TYPE,
+            REPORT_OTHER_TYPE,
+            REPORT_WEEKLY_TYPE);
+
+    public final static List<Integer> REPORT_EMAIL_TYPES = ListUtil.of(
+            REPORT_EMAIL_TYPE,
+            REPORT_OTHER_TYPE,
+            REPORT_WEEKLY_TYPE);
 }

+ 5 - 3
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/EmailFileInfoMapper.java

@@ -12,9 +12,9 @@ public interface EmailFileInfoMapper {
 
     Integer insert(@Param("itemDo") EmailFileInfoDO emailFileInfoDO);
 
-    EmailFileInfoDO getEmailFileById(@Param("id") Integer fileId);
-
-    List<EmailFileInfoDO> getEmailFileByEmailId(@Param("emailId") Integer emailId);
+//    EmailFileInfoDO getEmailFileById(@Param("id") Integer fileId);
+//
+//    List<EmailFileInfoDO> getEmailFileByEmailId(@Param("emailId") Integer emailId);
 
     List<EmailFileInfoDO> queryByEmailId(@Param("emailId") Integer emailId);
 
@@ -35,4 +35,6 @@ public interface EmailFileInfoMapper {
     int updateAiParseByFileId(@Param("fileId") Integer fileId,
                               @Param("aiParse") Boolean aiParse,
                               @Param("aiFileId") String aiFileId);
+
+    int getLetterFilenameSuccessCount(@Param("filename") String filename);
 }

+ 44 - 17
mo-daq/src/main/java/com/smppw/modaq/domain/service/EmailParseService.java

@@ -173,7 +173,7 @@ public class EmailParseService {
 
             // 保存相关信息 -> 邮件信息表,邮件文件表,邮件净值表,邮件规模表,基金净值表
             saveRelatedTable(emailEntry.getKey(), mailboxInfoDTO.getAccount(), emailZipFileMap);
-            log.info("结束邮件解析 -> 邮箱信息:{},开始时间:{},结束时间:{}", mailboxInfoDTO,
+            log.info("结束邮件解析 -> 邮箱信息:{},开始时间:{},结束时间:{}", emailEntry.getValue(),
                     DateUtil.format(startDate, DateConst.YYYY_MM_DD_HH_MM_SS), DateUtil.format(endDate, DateConst.YYYY_MM_DD_HH_MM_SS));
         }
     }
@@ -254,6 +254,44 @@ public class EmailParseService {
             if (emailContentInfoDTO.getFileName() != null && emailContentInfoDTO.getFileName().endsWith(".html")) {
                 continue;
             }
+
+            // 待解析文件数据处理,不支持已存在的文件重复解析
+            List<EmailZipFileDTO> dtos = ListUtil.list(false);
+            List<EmailZipFileDTO> zipFiles = entry.getValue();
+            if (CollUtil.isEmpty(zipFiles)) {
+                dtos.add(new EmailZipFileDTO(emailContentInfoDTO.getFilePath(), emailContentInfoDTO.getEmailType()));
+            } else {
+                dtos.addAll(zipFiles);
+            }
+
+            String emailTitle = emailContentInfoDTO.getEmailTitle();
+            // 数据库已存在的数据过滤
+            Iterator<EmailZipFileDTO> iterator = dtos.iterator();
+            while (iterator.hasNext()) {
+                EmailZipFileDTO dto = iterator.next();
+                Integer emailType = dto.getEmailType();
+                String filename = dto.getFilename();
+                if (Objects.equals(emailType, EmailTypeConst.REPORT_LETTER_EMAIL_TYPE)) {
+                    int count = this.emailFileInfoMapper.getLetterFilenameSuccessCount(filename);
+                    if (count > 0) {
+                        iterator.remove();
+                        log.info("邮件{} 附件{} 已存在解析成功的记录,不用重新解析。", emailTitle, filename);
+                    }
+                } else if (Objects.equals(emailType, EmailTypeConst.REPORT_EMAIL_TYPE)) {
+                    // todo 定期报告
+                } else if (EmailTypeConst.REPORT_EMAIL_TYPES.contains(emailType)) {
+                    // todo 其他报告
+                } else {
+                    log.info("邮件{} 类型{} 不支持解析。", emailTitle, emailType);
+                    iterator.remove();
+                }
+            }
+
+            if (CollUtil.isEmpty(dtos)) {
+                log.warn("邮件{} 所有文件都已经解析成功过,不能重复解析了", emailTitle);
+                continue;
+            }
+
             Integer emailId = emailContentInfoDTO.getEmailId();
             EmailParseInfoDO emailParseInfoDO = buildEmailParseInfo(emailId, emailAddress, emailContentInfoDTO);
             emailParseInfoDO.setEmailKey(emailKey);
@@ -262,22 +300,11 @@ public class EmailParseService {
                 continue;
             }
 
-            List<EmailZipFileDTO> zipFiles = entry.getValue();
-            if (CollUtil.isNotEmpty(zipFiles)) {
-                for (EmailZipFileDTO zipFile : zipFiles) {
-                    EmailFileInfoDO emailFile = saveEmailFileInfo(emailId, null, zipFile.getFilename(), zipFile.getFilepath(), null);
-                    // 解析并保存报告
-                    ParseResult<ReportData> parseResult = this.parseReportAndHandleResult(emailFile.getId(), zipFile.getFilename(),
-                            zipFile.getFilepath(), zipFile.getEmailType(), emailFile.getAiFileId());
-                    dataList.add(parseResult);
-                }
-            } else {
-                String fileName = emailContentInfoDTO.getFileName();
-                EmailFileInfoDO emailFile = saveEmailFileInfo(emailId, emailContentInfoDTO.getFileId(), fileName,
-                        emailContentInfoDTO.getFilePath(), emailContentInfoDTO.getAiFileId());
+            for (EmailZipFileDTO zipFile : dtos) {
+                EmailFileInfoDO emailFile = saveEmailFileInfo(emailId, null, zipFile.getFilename(), zipFile.getFilepath(), null);
                 // 解析并保存报告
-                ParseResult<ReportData> parseResult = this.parseReportAndHandleResult(emailFile.getId(), fileName,
-                        emailContentInfoDTO.getFilePath(), emailContentInfoDTO.getEmailType(), emailFile.getAiFileId());
+                ParseResult<ReportData> parseResult = this.parseReportAndHandleResult(emailFile.getId(), zipFile.getFilename(),
+                        zipFile.getFilepath(), zipFile.getEmailType(), emailFile.getAiFileId());
                 dataList.add(parseResult);
             }
 
@@ -590,7 +617,7 @@ public class EmailParseService {
                 senderEmail = getSenderEmail(message);
                 emailType = EmailUtil.getEmailTypeBySubject(emailTitle, emailTypeMap);
                 if (emailType == null) {
-                    log.warn("{} 邮件不满足解析条件 -> 邮件主题:{},邮件日期:{}", folderName,  emailTitle, emailDateStr);
+                    log.warn("{} 邮件不满足解析条件 -> 邮件主题:{},邮件日期:{}", folderName, emailTitle, emailDateStr);
                     continue;
                 }
                 log.info("{} 邮件{} 基本信息获取完成,开始下载附件!邮件日期:{}", folderName, emailTitle, emailDateStr);

+ 21 - 12
mo-daq/src/main/resources/mapper/EmailFileInfoMapper.xml

@@ -23,19 +23,19 @@
                 #{itemDo.isvalid}, #{itemDo.creatorId}, #{itemDo.createTime}, #{itemDo.updaterId}, #{itemDo.updateTime})
     </insert>
 
-    <select id="getEmailFileById" resultMap="BaseResultMap"
-            parameterType="java.lang.Integer">
-        select id ,email_id, file_name, file_path,ai_parse,ai_file_id,
-               isvalid, creatorid, createtime, updaterid, updatetime
-        from mo_email_file_info where id=#{id} and isvalid=1
-    </select>
+<!--    <select id="getEmailFileById" resultMap="BaseResultMap"-->
+<!--            parameterType="java.lang.Integer">-->
+<!--        select id ,email_id, file_name, file_path,ai_parse,ai_file_id,-->
+<!--               isvalid, creatorid, createtime, updaterid, updatetime-->
+<!--        from mo_email_file_info where id=#{id} and isvalid=1-->
+<!--    </select>-->
 
-    <select id="getEmailFileByEmailId" resultMap="BaseResultMap"
-            parameterType="java.lang.Integer">
-        select id ,email_id, file_name, file_path,ai_parse,ai_file_id,
-               isvalid, creatorid, createtime, updaterid, updatetime
-        from mo_email_file_info where email_id=#{emailId} and isvalid=1
-    </select>
+<!--    <select id="getEmailFileByEmailId" resultMap="BaseResultMap"-->
+<!--            parameterType="java.lang.Integer">-->
+<!--        select id ,email_id, file_name, file_path,ai_parse,ai_file_id,-->
+<!--               isvalid, creatorid, createtime, updaterid, updatetime-->
+<!--        from mo_email_file_info where email_id=#{emailId} and isvalid=1-->
+<!--    </select>-->
 
     <select id="queryByEmailId" resultMap="BaseResultMap">
         select id, file_name, file_path,ai_parse,ai_file_id
@@ -234,4 +234,13 @@
         where isvalid = 1
           and id = #{fileId}
     </update>
+
+    <select id="getLetterFilenameSuccessCount" resultType="int">
+        select count(1)
+        from mo_email_file_info a
+                 join mo_report_base_info b on b.file_id = a.id and b.report_type = 'LETTER'
+                 join mo_report_fund_transaction c on a.id = c.file_id and c.fund_name is not null
+                 join mo_report_investor_info d on a.id = d.file_id and d.investor_name is not null
+        where a.file_name = #{filename}
+    </select>
 </mapper>

+ 4 - 4
mo-daq/src/test/java/com/smppw/modaq/MoDaqApplicationTests.java

@@ -37,15 +37,15 @@ public class MoDaqApplicationTests {
 
     @Test
     public void reportTest() {
-        MailboxInfoDTO emailInfoDTO = this.buildMailbox("**@simuwang.com", "**");
-        Date startDate = DateUtil.parse("2025-04-29 17:00:00", DateConst.YYYY_MM_DD_HH_MM_SS);
-        Date endDate = DateUtil.parse("2025-04-29 19:42:05", DateConst.YYYY_MM_DD_HH_MM_SS);
+        MailboxInfoDTO emailInfoDTO = this.buildMailbox("wangzaijun@simuwang.com", "*");
+        Date startDate = DateUtil.parse("2025-04-30 15:20:00", DateConst.YYYY_MM_DD_HH_MM_SS);
+        Date endDate = DateUtil.parse("2025-04-30 19:42:05", DateConst.YYYY_MM_DD_HH_MM_SS);
         try {
             List<String> folderNames = ListUtil.list(false);
 //            folderNames.add("其他文件夹/报告公告");
             folderNames.add("INBOX");
             emailParseService.parseEmail(emailInfoDTO, startDate, endDate,
-                    folderNames, EmailTypeConst.REPORT_EMAIL_TYPES);
+                    folderNames, ListUtil.of(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE));
         } catch (Exception e) {
             throw new RuntimeException(e);
         }

+ 372 - 0
季报-无分级基金.json

@@ -0,0 +1,372 @@
+{
+  "基金基本情况": {
+    "基金名称": "亘曦财富5号私募证券投资基金",
+    "基金编码": "STA259",
+    "基金管理人": "上海亘曦私募基金管理有限公司",
+    "基金托管人": "国泰君安证券股份有限公司",
+    "投资顾问": "",
+    "基金运作方式": "开放式",
+    "基金成立日期": "2021年11月02日",
+    "期末基金总份额": 206.009022,
+    "投资目标": "本基金在深入研究的基础上构建投资组合,在严格控制投资风险的前提下,力求获得长期稳定的投资回报。",
+    "投资策略": "本基金将根据宏观经济分析和整体市场估值水平的变化自上而下地进行资产配置,在降低市场风险的同时追求更高收益。以上内容为私募基金管理人对于本基金全部或部分投资品种相应投资策略的阐述,不构成对于本基金投资范围、投资比例及限制或其他投资风控指标的补充。",
+    "业绩比较基准": "",
+    "风险收益特征": "本基金属于[R4]风险投资品种,适合风险识别、评估、承受能力[C4]及以上的普通合格投资者和专业投资者。"
+  },
+  "基金净值表现": {
+    "当季": {
+      "净值增长率": 0.39,
+      "净值增长率标准差": null,
+      "业绩比较基准收益率": null,
+      "业绩比较基准收益率标准差": null
+    },
+    "自基金合同生效起至今": {
+      "净值增长率": -28.12,
+      "净值增长率标准差": null,
+      "业绩比较基准收益率": null,
+      "业绩比较基准收益率标准差": null
+    }
+  },
+  "主要财务指标": {
+    "本期已实现收益": 11647.52,
+    "本期利润": 15125.97,
+    "期末基金净资产": 1480854.87,
+    "报告期期末单位净值": 0.7188
+  },
+  "投资组合情况": {
+    "期末基金资产组合情况": [
+      {
+        "项目": "银行存款",
+        "金额": 150679.97
+      },
+      {
+        "项目": "股权投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "其中:优先股",
+        "金额": 0.00
+      },
+      {
+        "项目": "其他股权类投资",
+        "金额": null
+      },
+      {
+        "项目": "上市公司定向增发股票投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "新三板挂牌企业投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "结算备付金",
+        "金额": 0.00
+      },
+      {
+        "项目": "存出保证金",
+        "金额": 0.00
+      },
+      {
+        "项目": "股票投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "债券投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "其中:银行间市场债券",
+        "金额": 0.00
+      },
+      {
+        "项目": "其中:利率债",
+        "金额": 0.00
+      },
+      {
+        "项目": "其中:信用债",
+        "金额": 0.00
+      },
+      {
+        "项目": "资产支持证券",
+        "金额": 0.00
+      },
+      {
+        "项目": "基金投资(公募基金)",
+        "金额": 1167123.67
+      },
+      {
+        "项目": "其中:货币基金",
+        "金额": 1167123.67
+      },
+      {
+        "项目": "期货及衍生品交易保证金",
+        "金额": 0.00
+      },
+      {
+        "项目": "买入返售金融资产",
+        "金额": 0.00
+      },
+      {
+        "项目": "其他证券类标的",
+        "金额": null
+      },
+      {
+        "项目": "商业银行理财产品投资",
+        "金额": null
+      },
+      {
+        "项目": "信托计划投资",
+        "金额": null
+      },
+      {
+        "项目": "基金公司及其子公司资产管理计划投资",
+        "金额": null
+      },
+      {
+        "项目": "保险资产管理计划投资",
+        "金额": null
+      },
+      {
+        "项目": "证券公司及其子公司资产管理计划投资",
+        "金额": null
+      },
+      {
+        "项目": "期货公司及其子公司资产管理计划投资",
+        "金额": null
+      },
+      {
+        "项目": "私募基金产品投资",
+        "金额": 168395.68
+      },
+      {
+        "项目": "未在协会备案的合伙企业份额",
+        "金额": null
+      },
+      {
+        "项目": "另类投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "银行委托贷款规模",
+        "金额": null
+      },
+      {
+        "项目": "信托贷款",
+        "金额": null
+      },
+      {
+        "项目": "应收账款投资",
+        "金额": null
+      },
+      {
+        "项目": "各类受(收)益权投资",
+        "金额": null
+      },
+      {
+        "项目": "票据(承兑汇票等)投资",
+        "金额": null
+      },
+      {
+        "项目": "其他债权投资",
+        "金额": null
+      },
+      {
+        "项目": "境外投资",
+        "金额": 0.00
+      },
+      {
+        "项目": "其他资产",
+        "金额": null
+      },
+      {
+        "项目": "债券回购总额",
+        "金额": 0.00
+      },
+      {
+        "项目": "融资、融券总额",
+        "金额": 0.00
+      },
+      {
+        "项目": "其中:融券总额",
+        "金额": 0.00
+      },
+      {
+        "项目": "银行借款总额",
+        "金额": 0.00
+      },
+      {
+        "项目": "其他融资总额",
+        "金额": null
+      }
+    ],
+    "报告期末按行业分类的股票投资组合": {
+      "境内股票投资组合": [
+        {
+          "行业类别": "农、林、牧、渔业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "采矿业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "制造业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "电力、热力、燃气及水生产和供应业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "建筑业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "批发和零售业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "交通运输、仓储和邮政业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "住宿和餐饮业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "信息传输、软件和信息技术服务业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "金融业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "房地产业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "租赁和商务服务业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "科学研究和技术服务业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "水利、环境和公共设施管理业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "居民服务、修理和其他服务业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "教育",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "卫生和社会工作",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "文化、体育和娱乐业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "综合",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        }
+      ],
+      "港股通投资股票投资组合": [
+        {
+          "行业类别": "基础材料",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "消费者非必需品",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "消费者常用品",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "能源",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "金融",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "医疗保健",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "工业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "信息技术",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "电信服务",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "公用事业",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "房地产",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        },
+        {
+          "行业类别": "合计",
+          "公允价值": 0.00,
+          "占基金资产净值比例": 0.00
+        }
+      ]
+    }
+  },
+  "基金份额变动情况": {
+    "报告期期初基金份额总额": 310.371368,
+    "报告期期间基金总申购份额": 0.000000,
+    "减:报告期期间基金总赎回份额": 104.362346,
+    "报告期期间基金拆分变动份额": 0.000000,
+    "期末基金总份额": 206.009022
+  }
+}

+ 0 - 0
季报-有分级基金.json


+ 67 - 0
年报.json

@@ -0,0 +1,67 @@
+```json
+{
+"基金基本情况": {
+"基金名称": "奇盛领航私募证券投资基金",
+"基金编码": "SNJ798",
+"基金运作方式": "开放式",
+"基金成立日期": "2020年12月10日",
+"基金管理人": "深圳奇盛基金管理有限公司",
+"基金托管人": "中信证券股份有限公司",
+"期末基金总份额(万份)": 5877.552724,
+"基金到期日期": "2035年12月9日"
+},
+"主要财务指标": [
+{
+"年份": "2024年",
+"本期已实现收益": 259297.13,
+"本期利润": 1128208.88,
+"期末可供分配利润": -1919612.46,
+"期末可供分配基金份额利润": -0.033,
+"期末基金净资产": 89897594.42,
+"报告期期末单位净值": 1.530,
+"基金份额累计净值增长率(%)": 61
+},
+{
+"年份": "2023年",
+"本期已实现收益": -27237.23,
+"本期利润": 7149221.85,
+"期末可供分配利润": -2382834.44,
+"期末可供分配基金份额利润": -0.039,
+"期末基金净资产": 93078807.17,
+"报告期期末单位净值": 1.509,
+"基金份额累计净值增长率(%)": 58.9
+},
+{
+"年份": "2022年",
+"本期已实现收益": -3673772.14,
+"本期利润": 120034.28,
+"期末可供分配利润": -2221501.89,
+"期末可供分配基金份额利润": -0.039,
+"期末基金净资产": 77454185.82,
+"报告期期末单位净值": 1.368,
+"基金份额累计净值增长率(%)": 44.8
+}
+],
+"投资组合情况": {
+"期末基金资产组合情况": {
+"现金类资产": {
+"银行存款": 2953.99
+},
+"私募基金产品投资": {
+"SNG851#": 90024143.72
+},
+"其他资产": 0
+},
+"报告期末按行业分类的股票投资组合": {
+"合计": 0.00
+}
+},
+"基金份额变动情况": {
+"报告期期初基金份额总额": 6169.34159,
+"报告期期间基金总申购份额": 10.141988,
+"报告期期间基金总赎回份额": 301.930854,
+"报告期期间基金拆分变动份额": 0,
+"期末基金总份额(万份)": 5877.552724
+}
+}
+```