Browse Source

update

main
wangshaoping 1 year ago
parent
commit
4a163f1c89
  1. 32
      io.sc.engine.mv.sample/src/main/java/io/sc/engine/mv/sample/controller/SampleWebController.java
  2. 10
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/ProgressTracker.java
  3. 80
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/RuntimeContext.java
  4. 11
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/ScaleType.java
  5. 102
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/sc/RocWebController.java
  6. 88
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/st/PsiWebController.java
  7. 188
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ResultExecutor.java
  8. 42
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ResultInitExecutor.java
  9. 83
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/SampleCountExecutor.java
  10. 522
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/SampleExecutor.java
  11. 361
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScCapExecutor.java
  12. 30
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScCapQualitativeExecutor.java
  13. 29
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScCapQuantitativeExecutor.java
  14. 280
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScKsExecutor.java
  15. 29
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScKsQualitativeExecutor.java
  16. 29
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScKsQuantitativeExecutor.java
  17. 333
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScRocExecutor.java
  18. 39
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScRocQualitativeExecutor.java
  19. 85
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScRocQuantitativeExecutor.java
  20. 50
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/support/ScVariable.java
  21. 28
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/extractor/ScoreRecordDataExtractor.java
  22. 79
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/RuntimeParameter.java
  23. 159
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/ScCapHistory.java
  24. 159
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/ScKsHistory.java
  25. 183
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/ScRocHistory.java
  26. 53
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/RuntimeParameterId.java
  27. 66
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/ScCapHistoryId.java
  28. 66
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/ScKsHistoryId.java
  29. 65
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/ScRocHistoryId.java
  30. 11
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/RuntimeParameterRepository.java
  31. 34
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/ScCapHistoryRepository.java
  32. 34
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/ScKsHistoryRepository.java
  33. 34
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/ScRocHistoryRepository.java
  34. 33
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/sc/echarts/ScValidateResult4Echarts.java
  35. 11
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/ScCapHistoryService.java
  36. 11
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/ScKsHistoryService.java
  37. 11
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/ScRocHistoryService.java
  38. 13
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/impl/ScCapHistoryServiceImpl.java
  39. 13
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/impl/ScKsHistoryServiceImpl.java
  40. 13
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/impl/ScRocHistoryServiceImpl.java
  41. 42
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/RuntimeParameterVo.java
  42. 99
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/ScCapHistoryVo.java
  43. 98
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/ScKsHistoryVo.java
  44. 116
      io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/ScRocHistoryVo.java
  45. 40
      io.sc.engine.mv/src/main/resources/io/sc/engine/mv/initializer/SampleDefaultRecord.groovy
  46. 70
      io.sc.engine.mv/src/main/resources/io/sc/engine/mv/initializer/SampleScoreRecord.groovy
  47. 11
      io.sc.platform.core/src/main/java/io/sc/platform/core/enums/RoundingMode.java
  48. 19
      io.sc.platform.data/src/main/java/io/sc/platform/data/csv/Record.java
  49. 29
      io.sc.platform.data/src/main/java/io/sc/platform/data/csv/RecordMapper.java
  50. 7
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/QueryParameter.java
  51. 33
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/QueryResult.java
  52. 7
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/QueryResultSorter.java

32
io.sc.engine.mv.sample/src/main/java/io/sc/engine/mv/sample/controller/SampleWebController.java

@ -0,0 +1,32 @@
package io.sc.engine.mv.sample.controller;
import io.sc.engine.mv.sample.service.CardGongXinImporterService;
import io.sc.engine.mv.sample.service.CardJingyingImporterService;
import io.sc.engine.mv.sample.service.DaiKuanImporterService;
import io.sc.engine.mv.sample.service.TestCaseImporterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/mv/sample")
public class SampleWebController {
@Autowired private TestCaseImporterService testCaseImporterService;
@Autowired private CardGongXinImporterService cardGongXinImporterService;
@Autowired private CardJingyingImporterService cardJingyingImporterService;
@Autowired private DaiKuanImporterService daiKuanImporterService;
@PostMapping("testCase")
public void importTestCase() throws Exception {
testCaseImporterService.load();
}
@PostMapping("sample")
public void importSample() throws Exception{
cardGongXinImporterService.load();
cardJingyingImporterService.load();
daiKuanImporterService.load();
}
}

10
io.sc.engine.mv/src/main/java/io/sc/engine/mv/ProgressTracker.java

@ -0,0 +1,10 @@
package io.sc.engine.mv;
/**
* 执行进度跟踪器
* @author wangshaoping
*
*/
public interface ProgressTracker {
public int getExecuteTimeWeight();
}

80
io.sc.engine.mv/src/main/java/io/sc/engine/mv/RuntimeContext.java

@ -0,0 +1,80 @@
package io.sc.engine.mv;
import io.sc.platform.core.support.KeyValue;
import io.sc.platform.core.util.DateUtil;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 模型验证运行时上下文
* @author wangshaoping
*
*/
public class RuntimeContext {
private ExecuteMode executeMode; //模型验证执行模式
private Date validateDate; //模型验证执行日期
private Date rateStartDateFrom; //源数据评级有效期开始日期(起始日期)
private Date rateStartDateTo; //源数据评级有效期开始日期(结束日期)
private int performPeriod; //模型表现期(月)
private double binomialSignificanceLevel; //二项检验采用的显著水平
private double chiSquareSignificanceLevel; //卡方检验采用的显著水平
/**
* 获取模型验证运行上下文参数列表
* @return 模型验证运行上下文参数列表
*/
public List<KeyValue<String, String>> getRuntimeParameters(){
List<KeyValue<String, String>> result =new ArrayList<KeyValue<String, String>>();
result.add(new KeyValue<String,String>("rateStartDateFrom", DateUtil.formatDate(rateStartDateFrom,DateUtil.yyyy_MM_dd)));
result.add(new KeyValue<String,String>("rateStartDateTo", DateUtil.formatDate(rateStartDateTo,DateUtil.yyyy_MM_dd)));
result.add(new KeyValue<String,String>("performPeriod", Integer.toString(performPeriod)));
result.add(new KeyValue<String,String>("binomialSignificanceLevel", Double.toString(binomialSignificanceLevel)));
result.add(new KeyValue<String,String>("chiSquareSignificanceLevel", Double.toString(chiSquareSignificanceLevel)));
return result;
}
public ExecuteMode getExecuteMode() {
return executeMode;
}
public void setExecuteMode(ExecuteMode executeMode) {
this.executeMode = executeMode;
}
public Date getValidateDate() {
return validateDate;
}
public void setValidateDate(Date validateDate) {
this.validateDate = validateDate;
}
public Date getRateStartDateFrom() {
return rateStartDateFrom;
}
public void setRateStartDateFrom(Date rateStartDateFrom) {
this.rateStartDateFrom = rateStartDateFrom;
}
public Date getRateStartDateTo() {
return rateStartDateTo;
}
public void setRateStartDateTo(Date rateStartDateTo) {
this.rateStartDateTo = rateStartDateTo;
}
public int getPerformPeriod() {
return performPeriod;
}
public void setPerformPeriod(int performPeriod) {
this.performPeriod = performPeriod;
}
public double getBinomialSignificanceLevel() {
return binomialSignificanceLevel;
}
public void setBinomialSignificanceLevel(double binomialSignificanceLevel) {
this.binomialSignificanceLevel = binomialSignificanceLevel;
}
public double getChiSquareSignificanceLevel() {
return chiSquareSignificanceLevel;
}
public void setChiSquareSignificanceLevel(double chiSquareSignificanceLevel) {
this.chiSquareSignificanceLevel = chiSquareSignificanceLevel;
}
}

11
io.sc.engine.mv/src/main/java/io/sc/engine/mv/ScaleType.java

@ -0,0 +1,11 @@
package io.sc.engine.mv;
/**
* 标尺枚举值
* @author wangshaoping
*
*/
public enum ScaleType {
SINGLE, //单个标尺(所有模型采用一套等级和违约概率的对应关系)
MULTIPLE; //多个标尺(每个模型采用一套等级和违约概率的对应关系)
}

102
io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/sc/RocWebController.java

@ -0,0 +1,102 @@
package io.sc.engine.mv.controller.sc;
import io.sc.engine.mv.jpa.entity.GeneralResultHistory;
import io.sc.engine.mv.jpa.entity.ScRocHistory;
import io.sc.engine.mv.jpa.entity.id.ScRocHistoryId;
import io.sc.engine.mv.jpa.repository.GeneralResultHistoryRepository;
import io.sc.engine.mv.jpa.repository.ScRocHistoryRepository;
import io.sc.engine.mv.sc.echarts.Coordinates;
import io.sc.engine.mv.service.sc.ScRocHistoryService;
import io.sc.engine.mv.vo.ScRocHistoryVo;
import io.sc.platform.core.util.CollectionUtil;
import io.sc.platform.mvc.controller.support.RestCrudController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@Controller
@RequestMapping("/mv/sc/roc")
public class RocWebController extends RestCrudController<ScRocHistoryVo, ScRocHistory, ScRocHistoryId, ScRocHistoryRepository, ScRocHistoryService> {
//模型验证结果DAO
@Autowired private GeneralResultHistoryRepository generalResultHistoryRepository;
//jdbc 模板
@Autowired private JdbcTemplate jdbcTemplate;
/**
* 查看模型区分能力验证 ROC 指标数据UI
* @param modelId 模型标识
* @param validateDate 验证日期
* @return UI视图
*/
@RequestMapping("rocDataView")
public ModelAndView rocDataView(
@RequestParam(name="modelId",required=false) String modelId,
@RequestParam(name="validateDate",required=false) String validateDate
){
ModelAndView mv =new ModelAndView("org/wsp/model/validator/view/sc/rocDataView.html");
mv.addObject("removeNavbar", true);
mv.addObject("modelId", modelId);
mv.addObject("validateDate", validateDate);
mv.addObject("distinctModelIdAndNames", CollectionUtil.arrayList2Map(service.getRepository().findDistinctModelIdAndNames()));
return mv;
}
/**
* 获取模型区分能力 ROC 曲线的 echarts Options
* @param modelId 模型标识
* @param validateDate 验证日期
* @return 模型区分能力 ROC 曲线的 echarts Options javascript
* @throws Exception 违例
*/
@RequestMapping("roc.js")
public ModelAndView roc(
@RequestParam("modelId") String modelId,
@RequestParam("validateDate") String validateDate
) throws Exception{
ModelAndView mv =new ModelAndView("org/wsp/model/validator/view/sc/echarts/roc.js");
GeneralResultHistory resultSummary =generalResultHistoryRepository.findByModelIdAndValidateDate(modelId, validateDate);
mv.addObject("resultSummary", resultSummary);
mv.addObject("coordinates",getCoordinates(modelId,validateDate));
return mv;
}
/**
* 获取 ROC 曲线图中 X,Y 坐标集
* @param modelId 模型标识
* @param validateDate 验证日期
* @return ROC 曲线图中 X,Y 坐标集
*/
private Coordinates getCoordinates(final String modelId, final String validateDate){
return jdbcTemplate.query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
String sql ="select FD_X,FD_Y from MV_SC_ROC_HIS where FD_MODEL_ID=? and FD_VALIDATE_DATE=? group by FD_X,FD_Y order by FD_X";
PreparedStatement ps =con.prepareStatement(sql);
ps.setString(1, modelId);
ps.setString(2, validateDate);
return ps;
}
}, new ResultSetExtractor<Coordinates>() {
@Override
public Coordinates extractData(ResultSet rs) throws SQLException, DataAccessException {
Coordinates coordinates =new Coordinates();
while(rs.next()){
coordinates.add(rs.getBigDecimal("FD_X"), rs.getBigDecimal("FD_Y"));
}
coordinates.setScale(6);
return coordinates;
}
});
}
}

88
io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/st/PsiWebController.java

@ -0,0 +1,88 @@
package io.sc.engine.mv.controller.st;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DecimalFormat;
import io.sc.engine.mv.jpa.entity.GeneralResultHistory;
import io.sc.engine.mv.jpa.entity.StPsiHistory;
import io.sc.engine.mv.jpa.entity.id.StPsiHistoryId;
import io.sc.engine.mv.jpa.repository.GeneralResultHistoryRepository;
import io.sc.engine.mv.jpa.repository.StPsiHistoryRepository;
import io.sc.engine.mv.sc.echarts.XyCoordinates;
import io.sc.engine.mv.service.st.StPsiHistoryService;
import io.sc.engine.mv.vo.StPsiHistoryVo;
import io.sc.platform.core.util.CollectionUtil;
import io.sc.platform.mvc.controller.support.RestCrudController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/mv/st/psi")
public class PsiWebController extends RestCrudController<StPsiHistoryVo, StPsiHistory, StPsiHistoryId, StPsiHistoryRepository, StPsiHistoryService> {
@Autowired private GeneralResultHistoryRepository generalResultHistoryRepository;
@Autowired private JdbcTemplate jdbcTemplate;
@RequestMapping("psiDataView")
public ModelAndView rocKpiDataView(
@RequestParam(name="modelId",required=false) String modelId,
@RequestParam(name="validateDate",required=false) String validateDate
){
ModelAndView mv =new ModelAndView("org/wsp/model/validator/view/st/psiDataView.html");
mv.addObject("removeNavbar", true);
mv.addObject("modelId", modelId);
mv.addObject("validateDate", validateDate);
mv.addObject("distinctModelIdAndNames", CollectionUtil.arrayList2Map(service.getRepository().findDistinctModelIdAndNames()));
return mv;
}
@RequestMapping("psi.js")
public ModelAndView cap(
@RequestParam("modelId") String modelId,
@RequestParam("validateDate") String validateDate
) throws Exception{
ModelAndView mv =new ModelAndView("org/wsp/model/validator/view/st/echarts/psi.js");
GeneralResultHistory resultSummary =generalResultHistoryRepository.findByModelIdAndValidateDate(modelId, validateDate);
mv.addObject("resultSummary", resultSummary);
mv.addObject("coordinates",getCoordinates(modelId,validateDate));
return mv;
}
private XyCoordinates<Integer> getCoordinates(final String modelId, final String validateDate){
final DecimalFormat df =new DecimalFormat("###.#");
return jdbcTemplate.query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
String sql ="select FD_SCORE_SEG_START,FD_SCORE_SEG_END,FD_COUNT_DEV,FD_COUNT_APP from MV_ST_PSI_HIS where FD_MODEL_ID=? and FD_VALIDATE_DATE=? order by FD_SCORE_SEG_START";
PreparedStatement ps =con.prepareStatement(sql);
ps.setString(1, modelId);
ps.setString(2, validateDate);
return ps;
}
}, new ResultSetExtractor<XyCoordinates<Integer>>() {
@Override
public XyCoordinates<Integer> extractData(ResultSet rs) throws SQLException, DataAccessException {
XyCoordinates<Integer> coordinates =new XyCoordinates<Integer>();
coordinates.add("0",0,0);
while(rs.next()){
coordinates.add(
"[" + df.format(rs.getBigDecimal("FD_SCORE_SEG_START")) + "," + df.format(rs.getBigDecimal("FD_SCORE_SEG_END")) + "]",
rs.getInt("FD_COUNT_DEV"),
rs.getInt("FD_COUNT_APP")
);
}
coordinates.add("",0,0);
return coordinates;
}
});
}
}

188
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ResultExecutor.java

@ -0,0 +1,188 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.RuntimeContext;
import io.sc.platform.core.support.KeyValue;
import io.sc.platform.core.support.ProgressInfo;
import io.sc.platform.core.util.DateUtil;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.stereotype.Component;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
/**
* 模型验证结果执行器
* @author wangshaoping
*
*/
@Component
public class ResultExecutor extends AbstractExecutor{
private static final int ORDER =10000;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo) {
//删除模型验证结果历史数据
deleteMV_GENERAL_RESULT_HIS(runtimeContext);
//删除模型验证执行时参数数据
deleteMV_RUNTIME_PARAMETER(runtimeContext);
//将[模型验证结果表]中的所有数据插入到[模型验证结果历史表]中
insertIntoMV_GENERAL_RESULT_HIS(runtimeContext);
//将当前运行时参数插入到[模型验证执行时参数配置表]中
insertIntoMV_RUNTIME_PARAMETER(runtimeContext);
}
/**
* 删除模型验证结果历史数据
* @param runtimeContext 运行时上下文
*/
private void deleteMV_GENERAL_RESULT_HIS(RuntimeContext runtimeContext){
final String runtimeDateString = DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
log.info("开始删除[模型验证结果历史表]中符合(模型验证日期=" + runtimeDateString + ")的记录...");
String sql ="delete from MV_GENERAL_RESULT_HIS where FD_VALIDATE_DATE=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
log.info("完成删除[模型验证结果历史表]中符合(模型验证日期=" + runtimeDateString + ")的记录.");
}
/**
* 删除模型验证执行时参数数据
* @param runtimeContext 运行时上下文
*/
private void deleteMV_RUNTIME_PARAMETER(RuntimeContext runtimeContext){
final String runtimeDateString =DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
log.info("开始删除[模型验证执行时参数配置表]中符合[模型验证日期=" + runtimeDateString + "]的记录...");
String sql ="delete from MV_RUNTIME_PARAMETER where FD_VALIDATE_DATE=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
log.info("完成删除[模型验证执行时参数配置表]中符合[模型验证日期=" + runtimeDateString + "]的记录...");
}
/**
* [模型验证结果表]中的所有数据插入到[模型验证结果历史表]
* @param runtimeContext 运行时上下文
*/
private void insertIntoMV_GENERAL_RESULT_HIS(final RuntimeContext runtimeContext){
log.info("开始将[模型验证结果表]中全部数据插入到[模型验证结果历史表]中...");
final String runtimeDateString =DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
final String executeMode =runtimeContext.getExecuteMode().toString();
String sql = ""
+ " insert into MV_GENERAL_RESULT_HIS("
+ " FD_VALIDATE_DATE,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_EXECUTE_MODE,"
+ " FD_TOTAL_SAMPLE_COUNT,"
+ " FD_DEFAULT_SAMPLE_COUNT,"
+ " FD_SC_AUC,"
+ " FD_SC_AUC_QUANTITATIVE,"
+ " FD_SC_AUC_QUALITATIVE,"
+ " FD_SC_AR,"
+ " FD_SC_AR_QUANTITATIVE,"
+ " FD_SC_AR_QUALITATIVE,"
+ " FD_SC_KS,"
+ " FD_SC_KS_QUANTITATIVE,"
+ " FD_SC_KS_QUALITATIVE,"
+ " FD_ST_SVD,"
+ " FD_ST_PSI,"
+ " FD_COE_CHI_SQUARE,"
+ " FD_COE_BINOMIAL"
+ " )"
+ " select "
+ " ?,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " ?,"
+ " FD_TOTAL_SAMPLE_COUNT,"
+ " FD_DEFAULT_SAMPLE_COUNT,"
+ " FD_SC_AUC,"
+ " FD_SC_AUC_QUANTITATIVE,"
+ " FD_SC_AUC_QUALITATIVE,"
+ " FD_SC_AR,"
+ " FD_SC_AR_QUANTITATIVE,"
+ " FD_SC_AR_QUALITATIVE,"
+ " FD_SC_KS,"
+ " FD_SC_KS_QUANTITATIVE,"
+ " FD_SC_KS_QUALITATIVE,"
+ " FD_ST_SVD,"
+ " FD_ST_PSI,"
+ " FD_COE_CHI_SQUARE,"
+ " FD_COE_BINOMIAL"
+ " from MV_GENERAL_RESULT";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
pstmt.setObject(2, executeMode);
}
});
log.info("完成将[模型验证结果表]中全部数据插入到[模型验证结果历史表]中.");
}
/**
* 将当前运行时参数插入到[模型验证执行时参数配置表]
* @param runtimeContext 运行时上下文
*/
private void insertIntoMV_RUNTIME_PARAMETER(final RuntimeContext runtimeContext){
log.info("开始将当前运行时参数插入到[模型验证执行时参数配置表]中...");
final String runtimeDateString =DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
List<KeyValue<String,String>> parameters =runtimeContext.getRuntimeParameters();
if(parameters!=null && parameters.size()>0){
for(int i=0;i<parameters.size();i++){
final KeyValue<String,String> parameter =parameters.get(i);
final int sno =i;
if(parameter!=null){
String sql = ""
+ "insert into MV_RUNTIME_PARAMETER("
+ " FD_VALIDATE_DATE,"
+ " FD_PARAM_NAME,"
+ " FD_PARAM_VALUE,"
+ " FD_SNO"
+ ") values("
+ " ?,"
+ " ?,"
+ " ?,"
+ " ?"
+ ")";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
pstmt.setObject(2, parameter.getKey());
pstmt.setObject(3, parameter.getValue());
pstmt.setObject(4, sno);
}
});
}
}
}
log.info("完成将当前运行时参数插入到[模型验证执行时参数配置表]中.");
}
}

42
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ResultInitExecutor.java

@ -0,0 +1,42 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.RuntimeContext;
import io.sc.platform.core.support.ProgressInfo;
import org.springframework.stereotype.Component;
/**
* 模型验证结果初始化执行器
* @author wangshaoping
*
*/
@Component
public class ResultInitExecutor extends AbstractExecutor{
private static final int ORDER =100;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 5;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo) {
//删除模型验证结果数据
deleteMV_GENERAL_RESULT(runtimeContext);
}
/**
* 删除模型验证结果历史数据
* @param runtimeContext 运行时上下文
*/
private void deleteMV_GENERAL_RESULT(RuntimeContext runtimeContext){
log.info("开始删除模型验证结果表的数据...");
String sql ="delete from MV_GENERAL_RESULT";
jdbcTemplate.execute(sql);
log.info("完成删除模型验证结果表的数据");
}
}

83
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/SampleCountExecutor.java

@ -0,0 +1,83 @@
package io.sc.engine.mv.executor;
import java.sql.ResultSet;
import java.sql.SQLException;
import io.sc.engine.mv.RuntimeContext;
import io.sc.platform.core.support.ProgressInfo;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Component;
/**
* 样本统计数据执行器
* @author wangshaoping
*
*/
@Component
public class SampleCountExecutor extends AbstractExecutor{
private static final int ORDER =150;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo) {
log.info("开始执行样本统计数据...");
String sql =""
+ " select "
+ " t0.FD_MODEL_ID,"
+ " t0.FD_MODEL_NAME,"
+ " t1.FD_TOTAL_SAMPLE_COUNT,"
+ " t2.FD_DEFAULT_SAMPLE_COUNT"
+ " from ("
+ " select "
+ " FD_MODEL_ID,"
+ " max(FD_MODEL_NAME) FD_MODEL_NAME"
+ " from MV_GENERAL_SAMPLE"
+ " group by FD_MODEL_ID"
+ " ) t0"
+ " left join ("
+ " select "
+ " FD_MODEL_ID,"
+ " count(*) FD_TOTAL_SAMPLE_COUNT"
+ " from MV_GENERAL_SAMPLE"
+ " group by FD_MODEL_ID"
+ " ) t1"
+ " on t0.FD_MODEL_ID=t1.FD_MODEL_ID"
+ " left join ("
+ " select"
+ " FD_MODEL_ID,"
+ " count(*) FD_DEFAULT_SAMPLE_COUNT"
+ " from MV_GENERAL_SAMPLE"
+ " where FD_DEFAULT_STATUS='D'"
+ " group by FD_MODEL_ID"
+ " ) t2"
+ " on t0.FD_MODEL_ID=t2.FD_MODEL_ID";
jdbcTemplate.query(sql, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
String modelId = rs.getString("FD_MODEL_ID");
String modelName = rs.getString("FD_MODEL_NAME");
long totalSampleCount =rs.getLong("FD_TOTAL_SAMPLE_COUNT");
long defaultSampleCount =rs.getLong("FD_DEFAULT_SAMPLE_COUNT");
//更新模型验证结果表
int updated =jdbcTemplate.update("update MV_GENERAL_RESULT set FD_TOTAL_SAMPLE_COUNT=?,FD_DEFAULT_SAMPLE_COUNT=? where FD_MODEL_ID=?", totalSampleCount,defaultSampleCount,modelId);
if(updated==0){
jdbcTemplate.update("insert into MV_GENERAL_RESULT(FD_MODEL_ID,FD_MODEL_NAME,FD_TOTAL_SAMPLE_COUNT,FD_DEFAULT_SAMPLE_COUNT) values(?,?,?,?)", modelId,modelName,totalSampleCount,defaultSampleCount);
}
}
});
jdbcTemplate.update("update MV_GENERAL_RESULT set FD_TOTAL_SAMPLE_COUNT=0 where FD_TOTAL_SAMPLE_COUNT is null");
jdbcTemplate.update("update MV_GENERAL_RESULT set FD_DEFAULT_SAMPLE_COUNT=0 where FD_DEFAULT_SAMPLE_COUNT is null");
log.info("完成执行样本统计数据.");
}
}

522
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/SampleExecutor.java

@ -0,0 +1,522 @@
package io.sc.engine.mv.executor;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import io.sc.engine.mv.RuntimeContext;
import io.sc.platform.core.support.ProgressInfo;
import io.sc.platform.core.util.DateUtil;
import io.sc.platform.jdbc.sql.dialect.DateTimePart;
import io.sc.platform.jdbc.sql.dialect.Dialect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Component;
/**
* 模型验证样本执行器
* @author wangshaoping
*
*/
@Component
public class SampleExecutor extends AbstractExecutor{
private static final int ORDER =0;
@Autowired private Dialect dialect;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo) {
info(progressInfo,"开始执行处理合格验证样本...");
//初始化合格样本表及合格样本临时表
initSample(runtimeContext,progressInfo);
//生成合格样本表
generateSample(runtimeContext,progressInfo);
//将合格样本数据保存到历史表
saveToHistory(runtimeContext,progressInfo);
info(progressInfo,"完成执行处理合格验证样本...");
}
/**
* 初始化合格样本表
* @param runtimeContext 执行上下文
* @param progressInfo 执行进度对象
*/
protected void initSample(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始执行初始化合格样本表...");
jdbcTemplate.execute("delete from MV_GENERAL_SAMPLE");
info(progressInfo,"完成执行初始化合格样本表");
}
/**
* 生成合格样本表
* @param runtimeContext 执行上下文
* @param progressInfo 执行进度对象
*/
private void generateSample(final RuntimeContext runtimeContext,ProgressInfo progressInfo) {
info(progressInfo,"开始执行生成合格样本...");
//生成好的合格样本
generateGoodSample(runtimeContext,progressInfo);
//生成坏的合格样本
generateBadSample(runtimeContext,progressInfo);
info(progressInfo,"完成执行生成合格样本");
}
/**
* 生成好的合格样本
* @param runtimeContext 执行上下文
* @param progressInfo 执行进度对象
*/
private void generateGoodSample(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始生成合格样本(好样本)...");
//删除临时表
deleteTempTables(runtimeContext);
//插入好客户的评分记录到临时表中
insertGoodRecord2TempTable(runtimeContext,progressInfo);
//生成好的合格样本
_generateGoodSample(runtimeContext,progressInfo);
info(progressInfo,"完成生成合格样本(好样本).");
}
private void generateBadSample(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始生成合格样本(坏样本)...");
//删除临时表
deleteTempTables(runtimeContext);
//将违约客户评级信息插入到合格样本临时表中
insertBadRecord2TempTable(runtimeContext,progressInfo);
//生成坏的合格样本
_generateBadSample(runtimeContext,progressInfo);
info(progressInfo,"完成生成合格样本(坏样本).");
}
/**
* 删除临时表
*/
private void deleteTempTables(final RuntimeContext runtimeContext){
jdbcTemplate.execute("delete from MV_SCORE_RECORD_TMP");
jdbcTemplate.execute("delete from MV_GENERAL_SAMPLE_TMP");
}
/**
* 将非违约客户评级信息插入到合格样本临时表中
*/
private void insertGoodRecord2TempTable(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始执行将好客户评级信息插入到评分临时表中...");
final Date from =runtimeContext.getRateStartDateFrom();
final Date to =runtimeContext.getRateStartDateTo();
String sql =""
+ " insert into MV_SCORE_RECORD_TMP("
+ " FD_CUSTOM_ID," //客户标识
+ " FD_CUSTOM_NAME," //客户名称
+ " FD_MODEL_ID," //模型标识
+ " FD_MODEL_NAME," //模型名称
+ " FD_PD," //评级结果(违约概率)
+ " FD_SCORE," //评级结果(得分)
+ " FD_SCORE_QUANTITATIVE," //评级结果(得分-定量)
+ " FD_SCORE_QUALITATIVE," //评级结果(得分-定性)
+ " FD_LEVEL," //评级结果(等级)
+ " FD_SCORE_BEGIN_DATE," //评级有效期开始日期
+ " FD_SCORE_END_DATE" //评级有效期结束日期
+ " )"
+ " select"
+ " S.FD_CUSTOM_ID,"
+ " S.FD_CUSTOM_NAME,"
+ " S.FD_MODEL_ID,"
+ " S.FD_MODEL_NAME,"
+ " S.FD_PD,"
+ " S.FD_SCORE,"
+ " S.FD_SCORE_QUANTITATIVE,"
+ " S.FD_SCORE_QUALITATIVE,"
+ " S.FD_LEVEL,"
+ " S.FD_SCORE_BEGIN_DATE,"
+ " S.FD_SCORE_END_DATE"
+ " from MV_SCORE_RECORD S"
+ " left join (select distinct FD_CUSTOM_ID from MV_DEFAULT_RECORD) T"
+ " on S.FD_CUSTOM_ID=T.FD_CUSTOM_ID"
+ " where"
+ " T.FD_CUSTOM_ID is null" //排除评分记录表中客户标识在违约认定记录表中的数据
+ " and S.FD_CUSTOM_ID is not null" //排除不正常的评分记录(无客户标识)
+ " and S.FD_MODEL_ID is not null " //排除不正常的评分记录(无模型标识)
+ " and S.FD_SCORE is not null " //排除不正常的评分记录(无总体评分)
+ " and S.FD_LEVEL is not null"; //排除不正常的评分记录(无等级)
if(from!=null){
sql +=" and FD_SCORE_BEGIN_DATE>=?"; //排除评分有效期开始日期在指定的日期范围外的评分记录
}
if(to!=null){
sql +=" and FD_SCORE_BEGIN_DATE<=?";
}
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
if(from!=null && to!=null){
pstmt.setObject(1, DateUtil.toSqlDate(from));
pstmt.setObject(2, DateUtil.toSqlDate(to));
}else if(from!=null){
pstmt.setObject(1, DateUtil.toSqlDate(from));
}else if(to!=null){
pstmt.setObject(1, DateUtil.toSqlDate(to));
}
}
});
info(progressInfo,"完成执行将好客户评级信息插入到评分临时表中.");
}
private void _generateGoodSample(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始执行生成合格的好样本...");
String sql =""
+ " insert into MV_GENERAL_SAMPLE_TMP("
+ " FD_CUSTOM_ID,"
+ " FD_MODEL_ID,"
+ " FD_SCORE_BEGIN_DATE,"
+ " FD_SCORE_END_DATE,"
+ " FD_DEL"
+ " )"
+ " select"
+ " S.FD_CUSTOM_ID,"
+ " S.FD_MODEL_ID,"
+ " S.FD_SCORE_BEGIN_DATE,"
+ " S.FD_SCORE_END_DATE,"
+ " 1"
+ " from MV_SCORE_RECORD_TMP S"
+ " join MV_SCORE_RECORD_TMP T"
+ " on "
+ " S.FD_CUSTOM_ID=T.FD_CUSTOM_ID "
+ " and S.FD_MODEL_ID=T.FD_MODEL_ID"
+ " where "
+ " T.FD_SCORE_BEGIN_DATE>S.FD_SCORE_BEGIN_DATE"
+ " and T.FD_SCORE_BEGIN_DATE<S.FD_SCORE_END_DATE";
jdbcTemplate.execute(sql);
sql =""
+ " insert into MV_GENERAL_SAMPLE("
+ " FD_CUSTOM_ID," //客户标识
+ " FD_CUSTOM_NAME," //客户名称
+ " FD_MODEL_ID," //模型标识
+ " FD_MODEL_NAME," //模型名称
+ " FD_PD," //评级结果(违约概率)
+ " FD_SCORE," //评级结果(得分)
+ " FD_SCORE_QUANTITATIVE," //评级结果(得分-定量)
+ " FD_SCORE_QUALITATIVE," //评级结果(得分-定性)
+ " FD_LEVEL," //评级结果(等级)
+ " FD_SCORE_BEGIN_DATE," //评级有效期开始日期
+ " FD_SCORE_END_DATE," //评级有效期结束日期
+ " FD_DEFAULT_STATUS" //实际违约状态
+ " )"
+ " select"
+ " S.FD_CUSTOM_ID,"
+ " S.FD_CUSTOM_NAME,"
+ " S.FD_MODEL_ID,"
+ " S.FD_MODEL_NAME,"
+ " S.FD_PD,"
+ " S.FD_SCORE,"
+ " S.FD_SCORE_QUANTITATIVE,"
+ " S.FD_SCORE_QUALITATIVE,"
+ " S.FD_LEVEL,"
+ " S.FD_SCORE_BEGIN_DATE,"
+ " S.FD_SCORE_END_DATE,"
+ " 'N'"
+ " from MV_SCORE_RECORD_TMP S"
+ " left join MV_GENERAL_SAMPLE_TMP T"
+ " on "
+ " S.FD_CUSTOM_ID=T.FD_CUSTOM_ID "
+ " and S.FD_MODEL_ID=T.FD_MODEL_ID "
+ " and S.FD_SCORE_BEGIN_DATE=T.FD_SCORE_BEGIN_DATE"
+ " where T.FD_DEL is null";
jdbcTemplate.execute(sql);
info(progressInfo,"完成执行生成合格的好样本...");
}
/**
* 将坏客户评级记录插入到临时表
*/
private void insertBadRecord2TempTable(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始执行将坏客户评级记录插入到临时表...");
final Date from =runtimeContext.getRateStartDateFrom();
final Date to =runtimeContext.getRateStartDateTo();
String sql =""
+ " insert into MV_SCORE_RECORD_TMP("
+ " FD_CUSTOM_ID," //客户标识
+ " FD_CUSTOM_NAME," //客户名称
+ " FD_MODEL_ID," //模型标识
+ " FD_MODEL_NAME," //模型名称
+ " FD_PD," //评级结果(违约概率)
+ " FD_SCORE," //评级结果(得分)
+ " FD_SCORE_QUANTITATIVE," //评级结果(得分-定量)
+ " FD_SCORE_QUALITATIVE," //评级结果(得分-定性)
+ " FD_LEVEL," //评级结果(等级)
+ " FD_SCORE_BEGIN_DATE," //评级有效期开始日期
+ " FD_SCORE_END_DATE" //评级有效期结束日期
+ " )"
+ " select"
+ " S.FD_CUSTOM_ID,"
+ " S.FD_CUSTOM_NAME,"
+ " S.FD_MODEL_ID,"
+ " S.FD_MODEL_NAME,"
+ " S.FD_PD,"
+ " S.FD_SCORE,"
+ " S.FD_SCORE_QUANTITATIVE,"
+ " S.FD_SCORE_QUALITATIVE,"
+ " S.FD_LEVEL,"
+ " S.FD_SCORE_BEGIN_DATE,"
+ " S.FD_SCORE_END_DATE"
+ " from MV_SCORE_RECORD S"
+ " left join (select distinct FD_CUSTOM_ID from MV_DEFAULT_RECORD) T"
+ " on S.FD_CUSTOM_ID=T.FD_CUSTOM_ID"
+ " where "
+ " T.FD_CUSTOM_ID is not null" //保留坏客户的评分记录
+ " and S.FD_CUSTOM_ID is not null" //排除不正常的评分记录(无客户标识)
+ " and S.FD_MODEL_ID is not null " //排除不正常的评分记录(无模型标识)
+ " and S.FD_SCORE is not null " //排除不正常的评分记录(无总体评分)
+ " and S.FD_LEVEL is not null"; //排除不正常的评分记录(无等级)
if(from!=null){
sql +=" and FD_SCORE_BEGIN_DATE>=?"; //排除评分有效期开始日期在指定的日期范围外的评分记录
}
if(to!=null){
sql +=" and FD_SCORE_BEGIN_DATE<=?";
}
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
if(from!=null && to!=null){
pstmt.setObject(1, DateUtil.toSqlDate(from));
pstmt.setObject(2, DateUtil.toSqlDate(to));
}else if(from!=null){
pstmt.setObject(1, DateUtil.toSqlDate(from));
}else if(to!=null){
pstmt.setObject(1, DateUtil.toSqlDate(to));
}
}
});
info(progressInfo,"完成执行将坏客户评级记录插入到临时表.");
}
private void _generateBadSample(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始执行生成合格的坏样本...");
String sql =""
+ " insert into MV_GENERAL_SAMPLE_TMP("
+ " FD_CUSTOM_ID,"
+ " FD_MODEL_ID,"
+ " FD_SCORE_BEGIN_DATE,"
+ " FD_SCORE_END_DATE,"
+ " FD_DEFAULT_CONFIRM_DATE"
+ " )"
+ " select "
+ " S.FD_CUSTOM_ID,"
+ " S.FD_MODEL_ID,"
+ " S.FD_SCORE_BEGIN_DATE,"
+ " S.FD_SCORE_END_DATE,"
+ " T.FD_DEFAULT_CONFIRM_DATE"
+ " from MV_SCORE_RECORD_TMP S"
+ " join MV_DEFAULT_RECORD T"
+ " on S.FD_CUSTOM_ID=T.FD_CUSTOM_ID"
+ " where"
+ " T.FD_DEFAULT_CONFIRM_DATE>=S.FD_SCORE_BEGIN_DATE"
+ " and T.FD_DEFAULT_CONFIRM_DATE<=" + dialect.dateAdd(DateTimePart.MONTH, "S.FD_SCORE_BEGIN_DATE", runtimeContext.getPerformPeriod())
+ "";
jdbcTemplate.execute(sql);
sql =""
+ " insert into MV_GENERAL_SAMPLE("
+ " FD_CUSTOM_ID," //客户标识
+ " FD_CUSTOM_NAME," //客户名称
+ " FD_MODEL_ID," //模型标识
+ " FD_MODEL_NAME," //模型名称
+ " FD_PD," //评级结果(违约概率)
+ " FD_SCORE," //评级结果(得分)
+ " FD_SCORE_QUANTITATIVE," //评级结果(得分-定量)
+ " FD_SCORE_QUALITATIVE," //评级结果(得分-定性)
+ " FD_LEVEL," //评级结果(等级)
+ " FD_SCORE_BEGIN_DATE," //评级有效期开始日期
+ " FD_SCORE_END_DATE," //评级有效期结束日期
+ " FD_DEFAULT_CONFIRM_DATE"//违约认定日期
+ " )"
+ " select"
+ " S.FD_CUSTOM_ID,"
+ " S.FD_CUSTOM_NAME,"
+ " S.FD_MODEL_ID,"
+ " S.FD_MODEL_NAME,"
+ " S.FD_PD,"
+ " S.FD_SCORE,"
+ " S.FD_SCORE_QUANTITATIVE,"
+ " S.FD_SCORE_QUALITATIVE,"
+ " S.FD_LEVEL,"
+ " S.FD_SCORE_BEGIN_DATE,"
+ " S.FD_SCORE_END_DATE,"
+ " T.FD_DEFAULT_CONFIRM_DATE"
+ " from MV_SCORE_RECORD_TMP S"
+ " left join ("
+ " select distinct"
+ " FD_CUSTOM_ID,"
+ " FD_MODEL_ID,"
+ " FD_SCORE_BEGIN_DATE,"
+ " FD_SCORE_END_DATE,"
+ " FD_DEFAULT_CONFIRM_DATE"
+ " from MV_GENERAL_SAMPLE_TMP"
+ " ) T"
+ " on "
+ " S.FD_CUSTOM_ID=T.FD_CUSTOM_ID"
+ " and S.FD_MODEL_ID=T.FD_MODEL_ID"
+ " and S.FD_SCORE_BEGIN_DATE=T.FD_SCORE_BEGIN_DATE"
+ "";
jdbcTemplate.execute(sql);
//删除
sql =""
+ " select "
+ " FD_CUSTOM_ID,"
+ " FD_MODEL_ID,"
+ " FD_SCORE_BEGIN_DATE,"
+ " FD_SCORE_END_DATE,"
+ " FD_DEFAULT_CONFIRM_DATE"
+ " from MV_GENERAL_SAMPLE_TMP"
+ " order by FD_CUSTOM_ID,FD_MODEL_ID,FD_SCORE_BEGIN_DATE";
jdbcTemplate.query(sql, new ResultSetExtractor<Object>(){
@Override
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
String updateSql =""
+ " update MV_GENERAL_SAMPLE set"
+ " FD_DEFAULT_CONFIRM_DATE=NULL"
+ " where"
+ " FD_CUSTOM_ID=?"
+ " and FD_MODEL_ID=?"
+ " and FD_SCORE_BEGIN_DATE=?";
String preCustomId =null;
String preModelId =null;
Date preScoreBeginDate =null;
Date preScoreEndDate =null;
Date preDefaultConfirmDate =null;
while(rs.next()){
String customId =rs.getString("FD_CUSTOM_ID");
String modelId =rs.getString("FD_MODEL_ID");
Date scoreBeginDate =rs.getDate("FD_SCORE_BEGIN_DATE");
Date scoreEndDate =rs.getDate("FD_SCORE_END_DATE");
Date defaultConfirmDate =rs.getDate("FD_DEFAULT_CONFIRM_DATE");
final String _preCustomId =preCustomId;
final String _preModelId =preModelId;
final Date _preScoreBeginDate =preScoreBeginDate;
if(
preCustomId!=null && preModelId!=null && preScoreBeginDate!=null && preScoreEndDate!=null && preDefaultConfirmDate!=null
&& customId!=null && modelId!=null && scoreBeginDate!=null && scoreEndDate!=null && defaultConfirmDate!=null
&& customId.equalsIgnoreCase(preCustomId) && modelId.equalsIgnoreCase(preModelId)
&& preDefaultConfirmDate.getTime()>preScoreEndDate.getTime()
&& preDefaultConfirmDate.getTime()>=scoreBeginDate.getTime()
&& preDefaultConfirmDate.getTime()<=scoreEndDate.getTime()
){
jdbcTemplate.update(updateSql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, _preCustomId);
pstmt.setObject(2, _preModelId);
pstmt.setObject(3, _preScoreBeginDate);
}
});
}
preCustomId =customId;
preModelId =modelId;
preScoreBeginDate =scoreBeginDate;
preScoreEndDate =scoreEndDate;
preDefaultConfirmDate =defaultConfirmDate;
}
return null;
}
});
//
jdbcTemplate.update("update MV_GENERAL_SAMPLE set FD_DEFAULT_STATUS='D' where FD_DEFAULT_CONFIRM_DATE is not null");
jdbcTemplate.update("update MV_GENERAL_SAMPLE set FD_DEFAULT_STATUS='N' where FD_DEFAULT_CONFIRM_DATE is null");
//移除评级有效期开始日期距今小于评级表现期的好样本
sql =""
+ " delete from MV_GENERAL_SAMPLE"
+ " where FD_DEFAULT_STATUS='N'"
+ " and " + dialect.currentDate() + "<=" + dialect.dateAdd(DateTimePart.MONTH, "FD_SCORE_BEGIN_DATE", runtimeContext.getPerformPeriod());
jdbcTemplate.update(sql);
info(progressInfo,"完成执行生成合格的坏样本...");
}
/**
* 将合格样本数据保存到历史表
* @param runtimeContext 执行上下文
* @param progressInfo 执行进度对象
*/
protected void saveToHistory(final RuntimeContext runtimeContext,ProgressInfo progressInfo){
info(progressInfo,"开始执行将合格样本数据保存到历史表...");
final String runtimeDateString =DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
String sql ="delete from MV_GENERAL_SAMPLE_HIS where FD_VALIDATE_DATE=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
sql = ""
+ " insert into MV_GENERAL_SAMPLE_HIS("
+ " FD_VALIDATE_DATE,"
+ " FD_CUSTOM_ID,"
+ " FD_CUSTOM_NAME,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_PD,"
+ " FD_SCORE,"
+ " FD_SCORE_QUANTITATIVE,"
+ " FD_SCORE_QUALITATIVE,"
+ " FD_LEVEL,"
+ " FD_SCORE_BEGIN_DATE,"
+ " FD_SCORE_END_DATE,"
+ " FD_DEFAULT_STATUS,"
+ " FD_DEFAULT_CONFIRM_DATE"
+ " )"
+ " select "
+ " ?,"
+ " FD_CUSTOM_ID,"
+ " FD_CUSTOM_NAME,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_PD,"
+ " FD_SCORE,"
+ " FD_SCORE_QUANTITATIVE,"
+ " FD_SCORE_QUALITATIVE,"
+ " FD_LEVEL,"
+ " FD_SCORE_BEGIN_DATE,"
+ " FD_SCORE_END_DATE,"
+ " FD_DEFAULT_STATUS,"
+ " FD_DEFAULT_CONFIRM_DATE"
+ " from MV_GENERAL_SAMPLE";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
info(progressInfo,"完成执行将合格样本数据保存到历史表.");
}
private void info(ProgressInfo progressInfo,String msg){
log.info(msg);
progressInfo.setMessageKey(msg);
}
}

361
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScCapExecutor.java

@ -0,0 +1,361 @@
package io.sc.engine.mv.executor;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import io.sc.engine.mv.RuntimeContext;
import io.sc.engine.mv.executor.support.CutOffPointFinder;
import io.sc.engine.mv.executor.support.ExecutorUtil;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import io.sc.platform.core.support.NumberIterator;
import io.sc.platform.core.support.ProgressInfo;
import io.sc.platform.core.util.DateUtil;
import io.sc.platform.jdbc.util.SqlBatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 CAP(总体) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScCapExecutor extends AbstractExecutor{
protected static final int ORDER =300;
@Autowired protected CutOffPointFinder cutOffPointFinder;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_AR");
result.setTableName("MV_SC_CAP");
result.setHisTableName("MV_SC_CAP_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_CAP);
return result;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo){
//获取变量
ScVariable variable =getRuntimeVariable();
//初始化指标表
initKpi(runtimeContext,variable);
//计算并生成指标表数据
generateKpi(runtimeContext,variable);
//计算 AR 值,并更新到模型验证结果表中
calAr(runtimeContext,variable);
//将计算并生成指标表数据保存到历史表中
saveToHistory(runtimeContext,variable);
}
/**
* 删除指标表历史数据
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void initKpi(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始执行初始化指标表...");
jdbcTemplate.execute("delete from " + variable.getTableName());
log.info("完成执行初始化指标表");
}
/**
* 计算并生成指标表
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void generateKpi(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始执行计算并生成指标表数据...");
final NumberIterator cutOffPointer =cutOffPointFinder.getCufOffPoint(variable.getCutOffPointName());
if(cutOffPointer==null){
throw new RuntimeException("无法获取截断点配置信息,请查看是否已经配置了截断点配置信息.");
}
initCutOffPoint(cutOffPointer,variable);
doGenerateKpi(cutOffPointer,variable);
log.info("完成执行计算并生成指标表数据");
}
/**
* 根据截断点初始化指标表
* @param cutOffPointer
* @param variable
*/
private void initCutOffPoint(final NumberIterator cutOffPointer,ScVariable variable){
log.info("开始执行初始化截断点...");
final SqlBatcher sqlBatcher =new SqlBatcher(""
+ " insert into " + variable.getTableName() + "("
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT"
+ " ) values ("
+ " ?,"
+ " ?,"
+ " ?"
+ ")"
);
Map<String,String> models = ExecutorUtil.getAllModels(jdbcTemplate);
if(models!=null && models.size()>0){
for(String key : models.keySet()){
String modelId =key;
String modelName =models.get(key);
cutOffPointer.reset();
while(cutOffPointer.hasNext()){
sqlBatcher.addArg(new Object[]{
modelId,
modelName,
cutOffPointer.next()
});
}
sqlBatcher.execute(jdbcTemplate);
}
}
log.info("完成执行初始化截断点");
}
private void doGenerateKpi(NumberIterator cutOffPointer,final ScVariable variable){
final SqlBatcher sqlBatcher =new SqlBatcher(""
+ " update " + variable.getTableName()
+ " set"
+ " FD_TS=?,"
+ " FD_TT=?,"
+ " FD_TDS=?,"
+ " FD_TDT=?,"
+ " FD_Y=?,"
+ " FD_X=?"
+ " where"
+ " FD_MODEL_ID=?"
+ " and FD_SCORE_CUT_OFF_POINT=?"
);
cutOffPointer.reset();
while(cutOffPointer.hasNext()){
final BigDecimal cutOffPointValue =cutOffPointer.next();
String sql = " select"
+ " t0.FD_MODEL_ID," //模型ID
+ " t0.CUT_OFF_POINT," //截断点
+ " t1.FD_TS," //评分小于等于截断点的客户个数
+ " t2.FD_TT," //客户总数
+ " t3.FD_TDS," //评分小于等于截断点的事实违约客户个数
+ " t4.FD_TDT" //事实违约的总客户数
+ " from "
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT from MV_GENERAL_SAMPLE group by FD_MODEL_ID) t0"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TS from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " group by FD_MODEL_ID) t1"
+ " on t0.FD_MODEL_ID=t1.FD_MODEL_ID and t0.CUT_OFF_POINT=t1.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TT from MV_GENERAL_SAMPLE group by FD_MODEL_ID) t2"
+ " on t0.FD_MODEL_ID=t2.FD_MODEL_ID and t0.CUT_OFF_POINT=t2.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TDS from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t3"
+ " on t0.FD_MODEL_ID=t3.FD_MODEL_ID and t0.CUT_OFF_POINT=t3.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TDT from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS = 'D' group by FD_MODEL_ID) t4"
+ " on t0.FD_MODEL_ID=t4.FD_MODEL_ID and t0.CUT_OFF_POINT=t4.CUT_OFF_POINT"
+ "";
jdbcTemplate.query(sql, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
sqlBatcher.addArg(new Object[]{
rs.getDouble("FD_TS"),
rs.getDouble("FD_TT"),
rs.getDouble("FD_TDS"),
rs.getDouble("FD_TDT"),
rs.getDouble("FD_TDT")==0?0:rs.getDouble("FD_TDS")/rs.getDouble("FD_TDT"),
rs.getDouble("FD_TT")==0?0:rs.getDouble("FD_TS")/rs.getDouble("FD_TT"),
rs.getString("FD_MODEL_ID"),
rs.getInt("CUT_OFF_POINT")
});
}
});
sqlBatcher.execute(jdbcTemplate);
}
}
/**
* 计算 AR 并更新到模型验证结果表中
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void calAr(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始计算 AR 值,并更新到模型验证结果表中...");
Map<String,String> models =ExecutorUtil.getAllModels(jdbcTemplate);
if(models!=null && models.size()>0){
for(String key : models.keySet()){
final String modelId =key;
final String modelName =models.get(key);
String sql =""
+ " select"
+ " FD_X,"
+ " FD_Y "
+ " from " + variable.getTableName()
+ " where FD_MODEL_ID='"+modelId+"'"
+ " group by FD_X,FD_Y"
+ " order by FD_X";
jdbcTemplate.query(sql, new ResultSetExtractor<Object>(){
@Override
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
//计算 CAP 曲线下面的面积
Double area = 0.0;
Double Yn_1 = null;
Double Xn_1 = null;
while (rs.next()) {
Double Yn = rs.getDouble("FD_Y");
Double Xn = rs.getDouble("FD_X");
if(Yn_1 != null && Xn_1 != null){
area = area + (Yn_1 + Yn)*(Xn - Xn_1);
}
Yn_1 = rs.getDouble("FD_Y");
Xn_1 = rs.getDouble("FD_X");
}
area = area/2;
//某个模型事实违约总客户个数
long defaultCount =getDefaultCustomerCount(modelId);
//某个模型总客户个数
long allCount =getAllCustomerCount(modelId);
//计算 AR 值
//计算斜率
double slope =0;
if(allCount!=0){
slope =(double)defaultCount/(double)allCount;
}
//计算 AR 值
double ar =(area-0.5)/((1-slope+1)/2-0.5);
//更新模型验证结果表
int updated =jdbcTemplate.update("update MV_GENERAL_RESULT set " + variable.getKpiFieldName() + "=? where FD_MODEL_ID=?", ar,modelId);
if(updated==0){
jdbcTemplate.update("insert into MV_GENERAL_RESULT(FD_MODEL_ID,FD_MODEL_NAME," + variable.getKpiFieldName() + ") values(?,?,?)", modelId,modelName,ar);
}
return null;
}
});
}
}
log.info("完成计算 AR 值,并更新到模型验证结果表中");
}
/**
* 将计算并生成指标表数据保存到历史表中
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void saveToHistory(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始将计算并生成指标表数据保存到历史表中...");
final String runtimeDateString = DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
String sql ="delete from " + variable.getHisTableName() + " where FD_VALIDATE_DATE=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
sql = ""
+ " insert into " + variable.getHisTableName() + "("
+ " FD_VALIDATE_DATE,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT,"
+ " FD_TS,"
+ " FD_TT,"
+ " FD_TDS,"
+ " FD_TDT,"
+ " FD_X,"
+ " FD_Y"
+ " )"
+ " select "
+ " ?,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT,"
+ " FD_TS,"
+ " FD_TT,"
+ " FD_TDS,"
+ " FD_TDT,"
+ " FD_X,"
+ " FD_Y"
+ " from " + variable.getTableName();
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
log.info("完成将计算并生成指标表数据保存到历史表中");
}
//某个模型事实违约总客户个数
protected long getDefaultCustomerCount(String modelId){
Long result =jdbcTemplate.query(
"select count(*) from MV_GENERAL_SAMPLE where FD_MODEL_ID='" + modelId + "' and FD_DEFAULT_STATUS='D'",
new ResultSetExtractor<Long>(){
public Long extractData(ResultSet rs) throws SQLException, DataAccessException{
if(rs.next()){
return rs.getLong(1);
}else{
return 0L;
}
}
}
);
if(result!=null) {
return result;
}else {
return 0L;
}
}
//某个模型总客户个数
protected long getAllCustomerCount(String modelId){
Long result =jdbcTemplate.query(
"select count(*) from MV_GENERAL_SAMPLE where FD_MODEL_ID='" + modelId + "'",
new ResultSetExtractor<Long>(){
public Long extractData(ResultSet rs) throws SQLException, DataAccessException{
if(rs.next()){
return rs.getLong(1);
}else{
return 0L;
}
}
}
);
if(result!=null) {
return result;
}else {
return 0L;
}
}
}

30
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScCapQualitativeExecutor.java

@ -0,0 +1,30 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 CAP(定性) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScCapQualitativeExecutor extends ScCapExecutor{
@Override
public int getOrder() {
return super.getOrder() + 20;
}
@Override
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_AR_QUALITATIVE");
result.setTableName("MV_SC_CAP_QUALITATIVE");
result.setHisTableName("MV_SC_CAP_QUALITATIVE_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_CAP_QUALITATIVE);
return result;
}
}

29
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScCapQuantitativeExecutor.java

@ -0,0 +1,29 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 CAP(定量) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScCapQuantitativeExecutor extends ScCapExecutor{
@Override
public int getOrder() {
return super.getOrder() + 10;
}
@Override
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_AR_QUANTITATIVE");
result.setTableName("MV_SC_CAP_QUANTITATIVE");
result.setHisTableName("MV_SC_CAP_QUANTITATIVE_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_CAP_QUANTITATIVE);
return result;
}
}

280
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScKsExecutor.java

@ -0,0 +1,280 @@
package io.sc.engine.mv.executor;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import io.sc.engine.mv.RuntimeContext;
import io.sc.engine.mv.executor.support.CutOffPointFinder;
import io.sc.engine.mv.executor.support.ExecutorUtil;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import io.sc.platform.core.support.NumberIterator;
import io.sc.platform.core.support.ProgressInfo;
import io.sc.platform.core.util.DateUtil;
import io.sc.platform.jdbc.util.SqlBatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 KS(总体) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScKsExecutor extends AbstractExecutor{
protected static final int ORDER =400;
@Autowired protected CutOffPointFinder cutOffPointFinder;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_KS");
result.setTableName("MV_SC_KS");
result.setHisTableName("MV_SC_KS_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_KS);
return result;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo) {
//获取变量
ScVariable variable =getRuntimeVariable();
//初始化指标表
initKpi(runtimeContext,variable);
//计算并生成指标表数据
generateKpi(runtimeContext,variable);
//计算 AR 值,并更新到模型验证结果表中
calKs(runtimeContext,variable);
//将计算并生成指标表数据保存到历史表中
saveToHistory(runtimeContext,variable);
}
/**
* 删除指标表历史数据
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void initKpi(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始执行初始化指标表...");
jdbcTemplate.execute("delete from " + variable.getTableName());
log.info("完成执行初始化指标表");
}
/**
* 计算并生成指标表
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void generateKpi(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始执行计算并生成指标表数据...");
final NumberIterator cutOffPointer =cutOffPointFinder.getCufOffPoint(variable.getCutOffPointName());
if(cutOffPointer==null){
throw new RuntimeException("无法获取截断点配置信息,请查看是否已经配置了截断点配置信息.");
}
initCutOffPoint(cutOffPointer,variable);
doGenerateKpi(cutOffPointer,variable);
log.info("完成执行计算并生成指标表数据");
}
/**
* 根据截断点初始化指标表
* @param cutOffPointer
* @param variable
*/
private void initCutOffPoint(final NumberIterator cutOffPointer,ScVariable variable){
log.info("开始执行初始化截断点...");
final SqlBatcher sqlBatcher =new SqlBatcher(""
+ " insert into " + variable.getTableName() + "("
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT"
+ " ) values ("
+ " ?,"
+ " ?,"
+ " ?"
+ ")"
);
Map<String,String> models = ExecutorUtil.getAllModels(jdbcTemplate);
if(models!=null && models.size()>0){
for(String key : models.keySet()){
String modelId =key;
String modelName =models.get(key);
cutOffPointer.reset();
while(cutOffPointer.hasNext()){
sqlBatcher.addArg(new Object[]{
modelId,
modelName,
cutOffPointer.next()
});
}
sqlBatcher.execute(jdbcTemplate);
}
}
log.info("完成执行初始化截断点");
}
private void doGenerateKpi(NumberIterator cutOffPointer,final ScVariable variable){
final SqlBatcher sqlBatcher =new SqlBatcher(""
+ " update " + variable.getTableName()
+ " set"
+ " FD_N=?,"
+ " FD_TN=?,"
+ " FD_D=?,"
+ " FD_TD=?,"
+ " FD_Y1=?,"
+ " FD_Y2=?"
+ " where"
+ " FD_MODEL_ID=?"
+ " and FD_SCORE_CUT_OFF_POINT=?"
);
cutOffPointer.reset();
while(cutOffPointer.hasNext()){
final BigDecimal cutOffPointValue =cutOffPointer.next();
String sql =""
+ "select"
+ " t0.FD_MODEL_ID," //模型ID
+ " t0.CUT_OFF_POINT," //截断点
+ " t1.FD_N," //评分小于等于截断点事实正常的客户个数
+ " t2.FD_TN," //事实正常的总客户个数
+ " t3.FD_D," //评分小于等于截断点事实违约客户个数
+ " t4.FD_TD" //事实违约的总客户个数
+ " from "
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT from MV_GENERAL_SAMPLE group by FD_MODEL_ID) t0"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_N from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t1"
+ " on t0.FD_MODEL_ID=t1.FD_MODEL_ID and t0.CUT_OFF_POINT=t1.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TN from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t2"
+ " on t0.FD_MODEL_ID=t2.FD_MODEL_ID and t0.CUT_OFF_POINT=t2.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_D from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t3"
+ " on t0.FD_MODEL_ID=t3.FD_MODEL_ID and t0.CUT_OFF_POINT=t3.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TD from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS = 'D' group by FD_MODEL_ID) t4"
+ " on t0.FD_MODEL_ID=t4.FD_MODEL_ID and t0.CUT_OFF_POINT=t4.CUT_OFF_POINT"
+ "";
jdbcTemplate.query(sql, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
sqlBatcher.addArg(new Object[]{
rs.getDouble("FD_N"),
rs.getDouble("FD_TN"),
rs.getDouble("FD_D"),
rs.getDouble("FD_TD"),
rs.getDouble("FD_TN")==0?0:rs.getDouble("FD_N")/rs.getDouble("FD_TN"),
rs.getDouble("FD_TD")==0?0:rs.getDouble("FD_D")/rs.getDouble("FD_TD"),
rs.getString("FD_MODEL_ID"),
rs.getInt("CUT_OFF_POINT")
});
}
});
sqlBatcher.execute(jdbcTemplate);
}
}
/**
* 计算 KS 并更新到模型验证结果表中
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void calKs(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始计算 KS 值,并更新到模型验证结果表中...");
String sql =""
+ " select"
+ " FD_MODEL_ID"
+ " ,max(FD_MODEL_NAME) as FD_MODEL_NAME"
+ " ,max(abs(FD_Y1-FD_Y2)) as KS"
+ " from " + variable.getTableName()
+ " group by FD_MODEL_ID";
jdbcTemplate.query(sql, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
final String modelId = rs.getString("FD_MODEL_ID");
final String modelName = rs.getString("FD_MODEL_NAME");
//更新模型验证结果表
//更新模型验证结果表
int updated =jdbcTemplate.update("update MV_GENERAL_RESULT set " + variable.getKpiFieldName() + "=? where FD_MODEL_ID=?", rs.getDouble("KS"),modelId);
if(updated==0){
jdbcTemplate.update("insert into MV_GENERAL_RESULT(FD_MODEL_ID,FD_MODEL_NAME," + variable.getKpiFieldName() + ") values(?,?,?)", modelId,modelName,rs.getDouble("KS"));
}
}
});
log.info("完成计算 KS 值,并更新到模型验证结果表中");
}
/**
* 将计算并生成指标表数据保存到历史表中
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void saveToHistory(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始将计算并生成指标表数据保存到历史表中...");
final String runtimeDateString = DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
String sql ="delete from " + variable.getHisTableName() + " where FD_VALIDATE_DATE=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
sql = ""
+ " insert into " + variable.getHisTableName() + "("
+ " FD_VALIDATE_DATE,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT,"
+ " FD_N,"
+ " FD_TN,"
+ " FD_D,"
+ " FD_TD,"
+ " FD_Y1,"
+ " FD_Y2"
+ " )"
+ " select "
+ " ?,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT,"
+ " FD_N,"
+ " FD_TN,"
+ " FD_D,"
+ " FD_TD,"
+ " FD_Y1,"
+ " FD_Y2"
+ " from " + variable.getTableName();
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
log.info("完成将计算并生成指标表数据保存到历史表中");
}
}

29
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScKsQualitativeExecutor.java

@ -0,0 +1,29 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 KS(定性) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScKsQualitativeExecutor extends ScKsExecutor{
@Override
public int getOrder() {
return super.getOrder() + 20;
}
@Override
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_KS_QUALITATIVE");
result.setTableName("MV_SC_KS_QUALITATIVE");
result.setHisTableName("MV_SC_KS_QUALITATIVE_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_KS_QUALITATIVE);
return result;
}
}

29
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScKsQuantitativeExecutor.java

@ -0,0 +1,29 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 KS(定量) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScKsQuantitativeExecutor extends ScKsExecutor{
@Override
public int getOrder() {
return super.getOrder() + 10;
}
@Override
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_KS_QUANTITATIVE");
result.setTableName("MV_SC_KS_QUANTITATIVE");
result.setHisTableName("MV_SC_KS_QUANTITATIVE_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_KS_QUANTITATIVE);
return result;
}
}

333
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScRocExecutor.java

@ -0,0 +1,333 @@
package io.sc.engine.mv.executor;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import io.sc.engine.mv.RuntimeContext;
import io.sc.engine.mv.executor.support.CutOffPointFinder;
import io.sc.engine.mv.executor.support.ExecutorUtil;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import io.sc.platform.core.support.NumberIterator;
import io.sc.platform.core.support.ProgressInfo;
import io.sc.platform.core.util.DateUtil;
import io.sc.platform.jdbc.util.SqlBatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 ROC 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScRocExecutor extends AbstractExecutor{
protected static final int ORDER =200;
@Autowired protected CutOffPointFinder cutOffPointFinder;
@Override
public int getOrder() {
return ORDER;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_AUC");
result.setTableName("MV_SC_ROC");
result.setHisTableName("MV_SC_ROC_HIS");
result.setCutOffPointFieldName("FD_SCORE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_ROC);
return result;
}
@Override
public void execute(RuntimeContext runtimeContext, ProgressInfo progressInfo) {
//获取变量
ScVariable variable =getRuntimeVariable();
//初始化指标表
initKpi(runtimeContext,variable);
//计算并生成指标表数据
generateKpi(runtimeContext,variable);
//计算 AUC 值,并更新到模型验证结果表中
calAuc(runtimeContext,variable);
//将计算并生成指标表数据保存到历史表中
saveToHistory(runtimeContext,variable);
}
/**
* 删除指标表历史数据
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void initKpi(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始执行初始化指标表...");
jdbcTemplate.execute("delete from " + variable.getTableName());
log.info("完成执行初始化指标表");
}
/**
* 计算并生成指标表
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void generateKpi(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始执行计算并生成指标表数据...");
final NumberIterator cutOffPointer =cutOffPointFinder.getCufOffPoint(variable.getCutOffPointName());
if(cutOffPointer==null){
throw new RuntimeException("无法获取截断点配置信息,请查看是否已经配置了截断点配置信息.");
}
initCutOffPoint(cutOffPointer,variable);
doGenerateKpi(cutOffPointer,variable);
log.info("完成执行计算并生成指标表数据");
}
/**
* 根据截断点初始化指标表
* @param cutOffPointer
* @param variable
*/
private void initCutOffPoint(final NumberIterator cutOffPointer,ScVariable variable){
log.info("开始执行初始化截断点...");
final SqlBatcher sqlBatcher =new SqlBatcher(""
+ " insert into " + variable.getTableName() + "("
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT"
+ " ) values ("
+ " ?,"
+ " ?,"
+ " ?"
+ ")"
);
Map<String,String> models = ExecutorUtil.getAllModels(jdbcTemplate);
if(models!=null && models.size()>0){
for(String key : models.keySet()){
String modelId =key;
String modelName =models.get(key);
cutOffPointer.reset();
while(cutOffPointer.hasNext()){
sqlBatcher.addArg(new Object[]{
modelId,
modelName,
cutOffPointer.next()
});
}
sqlBatcher.execute(jdbcTemplate);
}
}
log.info("完成执行初始化截断点.");
}
private void doGenerateKpi(NumberIterator cutOffPointer,ScVariable variable){
final SqlBatcher sqlBatcher =new SqlBatcher(""
+ " update " + variable.getTableName()
+ " set"
+ " FD_DD=?,"
+ " FD_DN=?,"
+ " FD_ND=?,"
+ " FD_NN=?,"
+ " FD_TD=?,"
+ " FD_TN=?,"
+ " FD_Y=?,"
+ " FD_X=?"
+ " where"
+ " FD_MODEL_ID=?"
+ " and FD_SCORE_CUT_OFF_POINT=?"
);
cutOffPointer.reset();
while(cutOffPointer.hasNext()){
final BigDecimal cutOffPointValue =cutOffPointer.next();
String sql =getGenerateKpiSql(cutOffPointValue,variable);
jdbcTemplate.query(sql, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
sqlBatcher.addArg(new Object[]{
rs.getDouble("FD_DD"),
rs.getDouble("FD_DN"),
rs.getDouble("FD_ND"),
rs.getDouble("FD_NN"),
rs.getDouble("FD_TD"),
rs.getDouble("FD_TN"),
rs.getDouble("FD_TD")==0?0:rs.getDouble("FD_DD")/rs.getDouble("FD_TD"),
rs.getDouble("FD_TN")==0?0:rs.getDouble("FD_ND")/rs.getDouble("FD_TN"),
rs.getString("FD_MODEL_ID"),
rs.getDouble("CUT_OFF_POINT")
});
}
});
sqlBatcher.execute(jdbcTemplate);
}
}
/**
* 计算 AUC 并更新到模型验证结果表中
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void calAuc(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始计算 AUC 值,并更新到模型验证结果表中...");
Map<String,String> models =ExecutorUtil.getAllModels(jdbcTemplate);
if(models!=null && models.size()>0){
for(String key : models.keySet()){
final String modelId =key;
final String modelName =models.get(key);
String sql =""
+ " select"
+ " FD_X,"
+ " FD_Y "
+ " from " + variable.getTableName()
+ " where"
+ " FD_MODEL_ID = '" + modelId + "'"
+ " group by FD_X,FD_Y"
+ " order by FD_X";
jdbcTemplate.query(sql, new ResultSetExtractor<Object>(){
@Override
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
//计算 CAP 曲线下面的面积
Double area = 0.0;
Double Yn_1 = null;
Double Xn_1 = null;
while (rs.next()) {
Double Yn = rs.getDouble("FD_Y");
Double Xn = rs.getDouble("FD_X");
if(Yn_1 != null && Xn_1 != null){
area = area + (Yn_1 + Yn)*(Xn - Xn_1);
}
Yn_1 = rs.getDouble("FD_Y");
Xn_1 = rs.getDouble("FD_X");
}
double auc = area/2;
//更新模型验证结果表
int updated =jdbcTemplate.update("update MV_GENERAL_RESULT set " + variable.getKpiFieldName() + "=? where FD_MODEL_ID=?", auc,modelId);
if(updated==0){
jdbcTemplate.update("insert into MV_GENERAL_RESULT(FD_MODEL_ID,FD_MODEL_NAME," + variable.getKpiFieldName() + ") values(?,?,?)", modelId,modelName,auc);
}
return null;
}
});
}
}
}
/**
* 将计算并生成指标表数据保存到历史表中
* @param runtimeContext 执行上下文
* @param variable 变量
*/
protected void saveToHistory(final RuntimeContext runtimeContext,final ScVariable variable){
log.info("开始将计算并生成指标表数据保存到历史表中...");
final String runtimeDateString = DateUtil.formatDate(runtimeContext.getValidateDate(), DateUtil.yyyy_MM_dd_HH_mm_ss);
String sql ="delete from " + variable.getHisTableName() + " where FD_VALIDATE_DATE=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
sql = ""
+ " insert into " + variable.getHisTableName() + "("
+ " FD_VALIDATE_DATE,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT,"
+ " FD_DD,"
+ " FD_DN,"
+ " FD_ND,"
+ " FD_NN,"
+ " FD_TD,"
+ " FD_TN,"
+ " FD_Y,"
+ " FD_X"
+ " )"
+ " select "
+ " ?,"
+ " FD_MODEL_ID,"
+ " FD_MODEL_NAME,"
+ " FD_SCORE_CUT_OFF_POINT,"
+ " FD_DD,"
+ " FD_DN,"
+ " FD_ND,"
+ " FD_NN,"
+ " FD_TD,"
+ " FD_TN,"
+ " FD_Y,"
+ " FD_X"
+ " from " + variable.getTableName();
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, runtimeDateString);
}
});
log.info("完成将计算并生成指标表数据保存到历史表中");
}
/**
* 获取构建指标表的关键 SQL 语句
* @param cutOffPointValue 截断点值
* @param variable 变量
* @return 构建指标表的关键 SQL 语句
*/
protected String getGenerateKpiSql(BigDecimal cutOffPointValue,ScVariable variable){
return " select"
+ " t0.FD_MODEL_ID," //模型ID
+ " t0.CUT_OFF_POINT," //截断点
+ " t1.FD_DD," //实际违约且预测违约样本总数
+ " t2.FD_DN," //实际违约且预测正常样本总数
+ " t3.FD_ND," //实际正常且预测违约样本总数
+ " t4.FD_NN," //实际正常且预测正常样本总数
+ " t5.FD_TD," //实际违约样本总数
+ " t6.FD_TN" //实际正常样本总数
+ " from "
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT from MV_GENERAL_SAMPLE group by FD_MODEL_ID) t0"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_DD from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t1"
+ " on t0.FD_MODEL_ID=t1.FD_MODEL_ID and t0.CUT_OFF_POINT=t1.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_DN from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + ">" + cutOffPointValue + " and FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t2"
+ " on t0.FD_MODEL_ID=t2.FD_MODEL_ID and t0.CUT_OFF_POINT=t2.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_ND from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t3"
+ " on t0.FD_MODEL_ID=t3.FD_MODEL_ID and t0.CUT_OFF_POINT=t3.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_NN from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + ">" + cutOffPointValue + " and FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t4"
+ " on t0.FD_MODEL_ID=t4.FD_MODEL_ID and t0.CUT_OFF_POINT=t4.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TD from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t5"
+ " on t0.FD_MODEL_ID=t5.FD_MODEL_ID and t0.CUT_OFF_POINT=t5.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TN from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t6"
+ " on t0.FD_MODEL_ID=t6.FD_MODEL_ID and t0.CUT_OFF_POINT=t6.CUT_OFF_POINT"
+ "";
}
}

39
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScRocQualitativeExecutor.java

@ -0,0 +1,39 @@
package io.sc.engine.mv.executor;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 ROC(定性) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScRocQualitativeExecutor extends ScRocQuantitativeExecutor{
@Override
public boolean isEnable() {
return true;
}
@Override
public int getOrder() {
return super.getOrder() + 20;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
@Override
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_AUC_QUALITATIVE");
result.setTableName("MV_SC_ROC_QUALITATIVE");
result.setHisTableName("MV_SC_ROC_QUALITATIVE_HIS");
result.setCutOffPointFieldName("FD_SCORE_QUANTITATIVE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_ROC_QUALITATIVE);
return result;
}
}

85
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/ScRocQuantitativeExecutor.java

@ -0,0 +1,85 @@
package io.sc.engine.mv.executor;
import java.math.BigDecimal;
import io.sc.engine.mv.executor.support.ScVariable;
import io.sc.engine.mv.jpa.entity.CfgCutOffPoint;
import org.springframework.stereotype.Component;
/**
* 模型区分能力 ROC(定量) 验证执行器
* @author wangshaoping
*
*/
@Component
public class ScRocQuantitativeExecutor extends ScRocExecutor{
@Override
public int getOrder() {
return super.getOrder() + 10;
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
protected ScVariable getRuntimeVariable(){
ScVariable result =new ScVariable();
result.setKpiFieldName("FD_SC_AUC_QUANTITATIVE");
result.setTableName("MV_SC_ROC_QUANTITATIVE");
result.setHisTableName("MV_SC_ROC_QUANTITATIVE_HIS");
result.setCutOffPointFieldName("FD_SCORE_QUALITATIVE");
result.setCutOffPointName(CfgCutOffPoint.CUT_OFF_ROC_QUANTITATIVE);
return result;
}
/**
* 覆盖父类的 SQL
* "&gt;=" 条件修改为 "&lt;="
* 在总体 ROC 截断点为违约概率 1 0
* 而定量 ROC 无法确定定量的违约概率只能通过分数进行( 0 100)为了跟总体 ROC 在意义上保持一致
* 原有 "违约概率&gt;=" 转化为 "定量分数&lt;="
* 类似其他几个条件依次进行转换
* @param cutOffPointValue 截断点值
* @param variable 变量
*/
@Override
protected String getGenerateKpiSql(BigDecimal cutOffPointValue,ScVariable variable){
return " select"
+ " t0.FD_MODEL_ID," //模型ID
+ " t0.CUT_OFF_POINT," //截断点
+ " t1.FD_DD," //实际违约且预测违约样本总数
+ " t2.FD_DN," //实际违约且预测正常样本总数
+ " t3.FD_ND," //实际正常且预测违约样本总数
+ " t4.FD_NN," //实际正常且预测正常样本总数
+ " t5.FD_TD," //实际违约样本总数
+ " t6.FD_TN" //实际正常样本总数
+ " from "
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT from MV_GENERAL_SAMPLE group by FD_MODEL_ID) t0"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_DD from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t1"
+ " on t0.FD_MODEL_ID=t1.FD_MODEL_ID and t0.CUT_OFF_POINT=t1.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_DN from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + ">" + cutOffPointValue + " and FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t2"
+ " on t0.FD_MODEL_ID=t2.FD_MODEL_ID and t0.CUT_OFF_POINT=t2.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_ND from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + "<=" + cutOffPointValue + " and FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t3"
+ " on t0.FD_MODEL_ID=t3.FD_MODEL_ID and t0.CUT_OFF_POINT=t3.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_NN from MV_GENERAL_SAMPLE where " + variable.getCutOffPointFieldName() + ">" + cutOffPointValue + " and FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t4"
+ " on t0.FD_MODEL_ID=t4.FD_MODEL_ID and t0.CUT_OFF_POINT=t4.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TD from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS='D' group by FD_MODEL_ID) t5"
+ " on t0.FD_MODEL_ID=t5.FD_MODEL_ID and t0.CUT_OFF_POINT=t5.CUT_OFF_POINT"
+ " left join"
+ " (select FD_MODEL_ID," + cutOffPointValue + " as CUT_OFF_POINT,count(*) as FD_TN from MV_GENERAL_SAMPLE where FD_DEFAULT_STATUS='N' group by FD_MODEL_ID) t6"
+ " on t0.FD_MODEL_ID=t6.FD_MODEL_ID and t0.CUT_OFF_POINT=t6.CUT_OFF_POINT"
+ "";
}
}

50
io.sc.engine.mv/src/main/java/io/sc/engine/mv/executor/support/ScVariable.java

@ -0,0 +1,50 @@
package io.sc.engine.mv.executor.support;
/**
* 模型区分能力验证运行时变量类
* @author wangshaoping
*
*/
public class ScVariable {
//结果字段名
private String kpiFieldName;
//表名
private String tableName;
//历史表名
private String hisTableName;
//截断点判断字段名
private String cutOffPointFieldName;
//截断点名称
private String cutOffPointName;
public String getKpiFieldName() {
return kpiFieldName;
}
public void setKpiFieldName(String kpiFieldName) {
this.kpiFieldName = kpiFieldName;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getHisTableName() {
return hisTableName;
}
public void setHisTableName(String hisTableName) {
this.hisTableName = hisTableName;
}
public String getCutOffPointName() {
return cutOffPointName;
}
public String getCutOffPointFieldName() {
return cutOffPointFieldName;
}
public void setCutOffPointFieldName(String cutOffPointFieldName) {
this.cutOffPointFieldName = cutOffPointFieldName;
}
public void setCutOffPointName(String cutOffPointName) {
this.cutOffPointName = cutOffPointName;
}
}

28
io.sc.engine.mv/src/main/java/io/sc/engine/mv/extractor/ScoreRecordDataExtractor.java

@ -0,0 +1,28 @@
package io.sc.engine.mv.extractor;
import io.sc.engine.mv.DataExtractor;
import io.sc.engine.mv.RuntimeContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 评级记录源数据抽取器
* @author wangshaoping
*
*/
@Component
public class ScoreRecordDataExtractor implements DataExtractor {
private static final Logger log =LoggerFactory.getLogger(DefaultRecordDataExtractor.class);
@Override
public void extract(RuntimeContext runtimeContext) {
log.info("开始抽取评级记录数据...");
log.info("完成抽取评级记录数据...");
}
@Override
public int getExecuteTimeWeight() {
return 10;
}
}

79
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/RuntimeParameter.java

@ -0,0 +1,79 @@
package io.sc.engine.mv.jpa.entity;
import io.sc.engine.mv.jpa.entity.id.RuntimeParameterId;
import io.sc.engine.mv.vo.RuntimeParameterVo;
import io.sc.platform.orm.entity.BaseEntity;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
/**
* 模型验证执行时参数配置
* @author wangshaoping
*
*/
@Entity
@Table(name="MV_RUNTIME_PARAMETER")
@IdClass(RuntimeParameterId.class)
public class RuntimeParameter extends BaseEntity<RuntimeParameterVo> {
//模型验证日期
@Id
@GenericGenerator(name = "MvRuntimeParamIDGenerator", strategy = "assigned")
@Column(name="FD_VALIDATE_DATE", length=19)
private String validateDate;
//运行时参数名称
@Id
@Column(name="FD_PARAM_NAME", length=254)
private String name;
//运行时参数值
@Column(name="FD_PARAM_VALUE", length=254)
private String value;
//参数显示顺序号
@Column(name="FD_SNO")
private Integer sno;
@Override
public RuntimeParameterVo toVo() {
RuntimeParameterVo vo =new RuntimeParameterVo();
vo.setValidateDate(this.getValidateDate());
vo.setName(this.getName());
vo.setValue(this.getValue());
vo.setSno(this.getSno());
return vo;
}
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Integer getSno() {
return sno;
}
public void setSno(Integer sno) {
this.sno = sno;
}
}

159
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/ScCapHistory.java

@ -0,0 +1,159 @@
package io.sc.engine.mv.jpa.entity;
import io.sc.engine.mv.jpa.entity.id.ScCapHistoryId;
import io.sc.engine.mv.vo.ScCapHistoryVo;
import io.sc.platform.orm.entity.BaseEntity;
import javax.persistence.*;
import java.math.BigDecimal;
/**
* 模型区分能力验证 CAP 曲线指标表历史数据实体类
*
* @author wangshaoping
*
*/
@Entity
@Table(name="MV_SC_CAP_HIS")
@IdClass(ScCapHistoryId.class)
public class ScCapHistory extends BaseEntity<ScCapHistoryVo> {
private static final long serialVersionUID = -2157649915130031766L;
//模型验证日期
@Id
@Column(name="FD_VALIDATE_DATE")
private String validateDate;
//模型标识
@Id
@Column(name="FD_MODEL_ID")
private String modelId;
//模型名称
@Column(name="FD_MODEL_NAME")
private String modelName;
//评分截断点
@Id
@Column(name="FD_SCORE_CUT_OFF_POINT")
private Integer scoreCutOffPoint;
//评分小于等于截断点的客户个数
@Column(name="FD_TS")
private Integer ts;
//客户总数
@Column(name="FD_TT")
private Integer tt;
//评分小于等于截断点的事实违约客户个数
@Column(name="FD_TDS")
private Integer tds;
//事实违约的总客户数
@Column(name="FD_TDT")
private Integer tdt;
//客户个数百分比
@Column(name="FD_X")
private BigDecimal x;
//违约个数百分比
@Column(name="FD_Y")
private BigDecimal y;
@Override
public ScCapHistoryVo toVo() {
ScCapHistoryVo vo =new ScCapHistoryVo();
vo.setValidateDate(this.getValidateDate());
vo.setModelId(this.getModelId());
vo.setModelName(this.getModelName());
vo.setScoreCutOffPoint(this.getScoreCutOffPoint());
vo.setTs(this.getTs());
vo.setTt(this.getTt());
vo.setTds(this.getTds());
vo.setTdt(this.getTdt());
vo.setX(this.getX());
vo.setY(this.getY());
return vo;
}
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Integer getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Integer scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
public Integer getTs() {
return ts;
}
public void setTs(Integer ts) {
this.ts = ts;
}
public Integer getTt() {
return tt;
}
public void setTt(Integer tt) {
this.tt = tt;
}
public Integer getTds() {
return tds;
}
public void setTds(Integer tds) {
this.tds = tds;
}
public Integer getTdt() {
return tdt;
}
public void setTdt(Integer tdt) {
this.tdt = tdt;
}
public BigDecimal getX() {
return x;
}
public void setX(BigDecimal x) {
this.x = x;
}
public BigDecimal getY() {
return y;
}
public void setY(BigDecimal y) {
this.y = y;
}
}

159
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/ScKsHistory.java

@ -0,0 +1,159 @@
package io.sc.engine.mv.jpa.entity;
import io.sc.engine.mv.jpa.entity.id.ScKsHistoryId;
import io.sc.engine.mv.vo.ScKsHistoryVo;
import io.sc.platform.orm.entity.BaseEntity;
import javax.persistence.*;
import java.math.BigDecimal;
/**
* 模型区分能力验证 KS 曲线指标表历史数据实体类
* @author wangshaoping
*
*/
@Entity
@Table(name="MV_SC_KS_HIS")
@IdClass(ScKsHistoryId.class)
public class ScKsHistory extends BaseEntity<ScKsHistoryVo> {
private static final long serialVersionUID = -2196414266073929052L;
//模型验证日期
@Id
@Column(name="FD_VALIDATE_DATE")
private String validateDate;
//模型标识
@Id
@Column(name="FD_MODEL_ID")
private String modelId;
//模型名称
@Column(name="FD_MODEL_NAME")
private String modelName;
//评分截断点
@Id
@Column(name="FD_SCORE_CUT_OFF_POINT")
private Integer scoreCutOffPoint;
//评分小于等于截断点事实正常的客户个数
@Column(name="FD_N")
private Integer n;
//事实正常的总客户个数
@Column(name="FD_TN")
private Integer tn;
//评分小于等于截断点事实违约客户个数
@Column(name="FD_D")
private Integer d;
//事实违约的总客户个数
@Column(name="FD_TD")
private Integer td;
//正常客户占比
@Column(name="FD_Y1")
private BigDecimal y1;
//违约客户占比
@Column(name="FD_Y2")
private BigDecimal y2;
@Override
public ScKsHistoryVo toVo() {
ScKsHistoryVo vo =new ScKsHistoryVo();
vo.setValidateDate(this.getValidateDate());
vo.setModelId(this.getModelId());
vo.setModelName(this.getModelName());
vo.setScoreCutOffPoint(this.getScoreCutOffPoint());
vo.setN(this.getN());
vo.setTn(this.getTn());
vo.setD(this.getD());
vo.setTd(this.getTd());
vo.setY1(this.getY1());
vo.setY2(this.getY2());
return vo;
}
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Integer getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Integer scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
public Integer getN() {
return n;
}
public void setN(Integer n) {
this.n = n;
}
public Integer getTn() {
return tn;
}
public void setTn(Integer tn) {
this.tn = tn;
}
public Integer getD() {
return d;
}
public void setD(Integer d) {
this.d = d;
}
public Integer getTd() {
return td;
}
public void setTd(Integer td) {
this.td = td;
}
public BigDecimal getY1() {
return y1;
}
public void setY1(BigDecimal y1) {
this.y1 = y1;
}
public BigDecimal getY2() {
return y2;
}
public void setY2(BigDecimal y2) {
this.y2 = y2;
}
}

183
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/ScRocHistory.java

@ -0,0 +1,183 @@
package io.sc.engine.mv.jpa.entity;
import io.sc.engine.mv.jpa.entity.id.ScRocHistoryId;
import io.sc.engine.mv.vo.ScRocHistoryVo;
import io.sc.platform.orm.entity.BaseEntity;
import javax.persistence.*;
import java.math.BigDecimal;
/**
* 模型区分能力验证 ROC 曲线指标表历史数据实体类
* @author wangshaoping
*
*/
@Entity
@Table(name="MV_SC_ROC_HIS")
@IdClass(ScRocHistoryId.class)
public class ScRocHistory extends BaseEntity<ScRocHistoryVo> {
//模型验证日期
@Id
@Column(name="FD_VALIDATE_DATE")
private String validateDate;
//模型标识
@Id
@Column(name="FD_MODEL_ID")
private String modelId;
//模型名称
@Column(name="FD_MODEL_NAME")
private String modelName;
//违约概率截断点
@Id
@Column(name="FD_SCORE_CUT_OFF_POINT")
private Double scoreCutOffPoint;
//实际违约且预测违约样本总数
@Column(name="FD_DD")
private Integer dd;
//实际违约且预测正常样本总数
@Column(name="FD_DN")
private Integer dn;
//实际正常且预测违约样本总数
@Column(name="FD_ND")
private Integer nd;
//实际正常且预测正常样本总数
@Column(name="FD_NN")
private Integer nn;
//实际违约样本总数
@Column(name="FD_TD")
private Integer td;
//实际正常样本总数
@Column(name="FD_TN")
private Integer tn;
//违约预测误警率
@Column(name="FD_X")
private BigDecimal x;
//违约预测命中率
@Column(name="FD_Y")
private BigDecimal y;
@Override
public ScRocHistoryVo toVo() {
ScRocHistoryVo vo =new ScRocHistoryVo();
vo.setValidateDate(this.getValidateDate());
vo.setModelId(this.getModelId());
vo.setModelName(this.getModelName());
vo.setScoreCutOffPoint(this.getScoreCutOffPoint());
vo.setDd(this.getDd());
vo.setDn(this.getDn());
vo.setNd(this.getNd());
vo.setNn(this.getNn());
vo.setTd(this.getTd());
vo.setTn(this.getTn());
vo.setX(this.getX());
vo.setY(this.getY());
return vo;
}
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Double getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Double scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
public Integer getDd() {
return dd;
}
public void setDd(Integer dd) {
this.dd = dd;
}
public Integer getDn() {
return dn;
}
public void setDn(Integer dn) {
this.dn = dn;
}
public Integer getNd() {
return nd;
}
public void setNd(Integer nd) {
this.nd = nd;
}
public Integer getNn() {
return nn;
}
public void setNn(Integer nn) {
this.nn = nn;
}
public Integer getTd() {
return td;
}
public void setTd(Integer td) {
this.td = td;
}
public Integer getTn() {
return tn;
}
public void setTn(Integer tn) {
this.tn = tn;
}
public BigDecimal getX() {
return x;
}
public void setX(BigDecimal x) {
this.x = x;
}
public BigDecimal getY() {
return y;
}
public void setY(BigDecimal y) {
this.y = y;
}
}

53
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/RuntimeParameterId.java

@ -0,0 +1,53 @@
package io.sc.engine.mv.jpa.entity.id;
import java.io.Serializable;
public class RuntimeParameterId implements Serializable{
private static final long serialVersionUID = 1367562856018529543L;
private String validateDate;
private String name;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((validateDate == null) ? 0 : validateDate.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RuntimeParameterId other = (RuntimeParameterId) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (validateDate == null) {
if (other.validateDate != null)
return false;
} else if (!validateDate.equals(other.validateDate))
return false;
return true;
}
}

66
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/ScCapHistoryId.java

@ -0,0 +1,66 @@
package io.sc.engine.mv.jpa.entity.id;
import java.io.Serializable;
public class ScCapHistoryId implements Serializable{
private static final long serialVersionUID = -269346483593245329L;
private String validateDate;
private String modelId;
private Integer scoreCutOffPoint;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public Integer getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Integer scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((modelId == null) ? 0 : modelId.hashCode());
result = prime * result + ((scoreCutOffPoint == null) ? 0 : scoreCutOffPoint.hashCode());
result = prime * result + ((validateDate == null) ? 0 : validateDate.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ScCapHistoryId other = (ScCapHistoryId) obj;
if (modelId == null) {
if (other.modelId != null)
return false;
} else if (!modelId.equals(other.modelId))
return false;
if (scoreCutOffPoint == null) {
if (other.scoreCutOffPoint != null)
return false;
} else if (!scoreCutOffPoint.equals(other.scoreCutOffPoint))
return false;
if (validateDate == null) {
if (other.validateDate != null)
return false;
} else if (!validateDate.equals(other.validateDate))
return false;
return true;
}
}

66
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/ScKsHistoryId.java

@ -0,0 +1,66 @@
package io.sc.engine.mv.jpa.entity.id;
import java.io.Serializable;
public class ScKsHistoryId implements Serializable{
private static final long serialVersionUID = 6247313483047348351L;
private String validateDate;
private String modelId;
private Integer scoreCutOffPoint;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public Integer getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Integer scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((modelId == null) ? 0 : modelId.hashCode());
result = prime * result + ((scoreCutOffPoint == null) ? 0 : scoreCutOffPoint.hashCode());
result = prime * result + ((validateDate == null) ? 0 : validateDate.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ScKsHistoryId other = (ScKsHistoryId) obj;
if (modelId == null) {
if (other.modelId != null)
return false;
} else if (!modelId.equals(other.modelId))
return false;
if (scoreCutOffPoint == null) {
if (other.scoreCutOffPoint != null)
return false;
} else if (!scoreCutOffPoint.equals(other.scoreCutOffPoint))
return false;
if (validateDate == null) {
if (other.validateDate != null)
return false;
} else if (!validateDate.equals(other.validateDate))
return false;
return true;
}
}

65
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/entity/id/ScRocHistoryId.java

@ -0,0 +1,65 @@
package io.sc.engine.mv.jpa.entity.id;
import java.io.Serializable;
public class ScRocHistoryId implements Serializable{
private static final long serialVersionUID = 4863037037512170910L;
private String validateDate;
private String modelId;
private Double scoreCutOffPoint;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public Double getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Double scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((modelId == null) ? 0 : modelId.hashCode());
result = prime * result + ((scoreCutOffPoint == null) ? 0 : scoreCutOffPoint.hashCode());
result = prime * result + ((validateDate == null) ? 0 : validateDate.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ScRocHistoryId other = (ScRocHistoryId) obj;
if (modelId == null) {
if (other.modelId != null)
return false;
} else if (!modelId.equals(other.modelId))
return false;
if (scoreCutOffPoint == null) {
if (other.scoreCutOffPoint != null)
return false;
} else if (!scoreCutOffPoint.equals(other.scoreCutOffPoint))
return false;
if (validateDate == null) {
if (other.validateDate != null)
return false;
} else if (!validateDate.equals(other.validateDate))
return false;
return true;
}
}

11
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/RuntimeParameterRepository.java

@ -0,0 +1,11 @@
package io.sc.engine.mv.jpa.repository;
import io.sc.engine.mv.jpa.entity.RuntimeParameter;
import io.sc.platform.orm.repository.DaoRepository;
import java.util.List;
public interface RuntimeParameterRepository extends DaoRepository<RuntimeParameter,String> {
public List<RuntimeParameter> findByValidateDateOrderBySno(String validateDate);
}

34
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/ScCapHistoryRepository.java

@ -0,0 +1,34 @@
package io.sc.engine.mv.jpa.repository;
import io.sc.engine.mv.jpa.entity.ScCapHistory;
import io.sc.engine.mv.jpa.entity.id.ScCapHistoryId;
import io.sc.platform.orm.repository.DaoRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface ScCapHistoryRepository extends DaoRepository<ScCapHistory, ScCapHistoryId> {
/**
* 分页查询某个验证日期的所有历史区分能力CAP曲线指标
* @param validateDate 验证日期
* @param pageable 分页信息
* @return 历史区分能力CAP曲线指标分页对象
*/
public Page<ScCapHistory> findAllByValidateDate(String validateDate,Pageable pageable);
/**
* 获取CAP指标表中包含的所有不重复的验证日期
* @return ROC指标表中包含的所有不重复的验证日期
*/
@Query("select distinct e.validateDate from ScCapHistory e order by e.validateDate desc")
public List<String> findDistinctValidateDates();
/**
* 获取CAP指标表中包含的所有不重复的模型标识和名称
* @return ROC指标表中包含的所有不重复的模型标识和名称
*/
@Query("select e.modelId,max(e.modelName) from ScCapHistory e group by e.modelId")
public List<Object[]> findDistinctModelIdAndNames();
}

34
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/ScKsHistoryRepository.java

@ -0,0 +1,34 @@
package io.sc.engine.mv.jpa.repository;
import java.util.List;
import io.sc.engine.mv.jpa.entity.ScKsHistory;
import io.sc.engine.mv.jpa.entity.id.ScKsHistoryId;
import io.sc.platform.orm.repository.DaoRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
public interface ScKsHistoryRepository extends DaoRepository<ScKsHistory, ScKsHistoryId> {
/**
* 分页查询某个验证日期的所有历史区分能力KS曲线指标
* @param validateDate 验证日期
* @param pageable 分页信息
* @return 历史区分能力KS曲线指标分页对象
*/
public Page<ScKsHistory> findAllByValidateDate(String validateDate,Pageable pageable);
/**
* 获取KS指标表中包含的所有不重复的验证日期
* @return ROC指标表中包含的所有不重复的验证日期
*/
@Query("select distinct e.validateDate from ScKsHistory e order by e.validateDate desc")
public List<String> findDistinctValidateDates();
/**
* 获取KS指标表中包含的所有不重复的模型标识和名称
* @return ROC指标表中包含的所有不重复的模型标识和名称
*/
@Query("select e.modelId,max(e.modelName) from ScKsHistory e group by e.modelId")
public List<Object[]> findDistinctModelIdAndNames();
}

34
io.sc.engine.mv/src/main/java/io/sc/engine/mv/jpa/repository/ScRocHistoryRepository.java

@ -0,0 +1,34 @@
package io.sc.engine.mv.jpa.repository;
import java.util.List;
import io.sc.engine.mv.jpa.entity.ScRocHistory;
import io.sc.engine.mv.jpa.entity.id.ScRocHistoryId;
import io.sc.platform.orm.repository.DaoRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
public interface ScRocHistoryRepository extends DaoRepository<ScRocHistory, ScRocHistoryId> {
/**
* 分页查询某个验证日期的所有历史区分能力ROC曲线指标
* @param validateDate 验证日期
* @param pageable 分页信息
* @return 历史区分能力ROC曲线指标分页对象
*/
public Page<ScRocHistory> findAllByValidateDate(String validateDate,Pageable pageable);
/**
* 获取ROC指标表中包含的所有不重复的验证日期
* @return ROC指标表中包含的所有不重复的验证日期
*/
@Query("select distinct e.validateDate from ScRocHistory e order by e.validateDate desc")
public List<String> findDistinctValidateDates();
/**
* 获取ROC指标表中包含的所有不重复的模型标识和名称
* @return ROC指标表中包含的所有不重复的模型标识和名称
*/
@Query("select e.modelId,max(e.modelName) from ScRocHistory e group by e.modelId")
public List<Object[]> findDistinctModelIdAndNames();
}

33
io.sc.engine.mv/src/main/java/io/sc/engine/mv/sc/echarts/ScValidateResult4Echarts.java

@ -0,0 +1,33 @@
package io.sc.engine.mv.sc.echarts;
public class ScValidateResult4Echarts {
private double auc;
private double ar;
private double ks;
private Coordinates coordinates;
public double getAuc() {
return auc;
}
public void setAuc(double auc) {
this.auc = auc;
}
public double getAr() {
return ar;
}
public void setAr(double ar) {
this.ar = ar;
}
public double getKs() {
return ks;
}
public void setKs(double ks) {
this.ks = ks;
}
public Coordinates getCoordinates() {
return coordinates;
}
public void setCoordinates(Coordinates coordinates) {
this.coordinates = coordinates;
}
}

11
io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/ScCapHistoryService.java

@ -0,0 +1,11 @@
package io.sc.engine.mv.service.sc;
import io.sc.engine.mv.jpa.entity.ScCapHistory;
import io.sc.engine.mv.jpa.entity.id.ScCapHistoryId;
import io.sc.engine.mv.jpa.repository.ScCapHistoryRepository;
import io.sc.platform.orm.service.DaoService;
public interface ScCapHistoryService extends DaoService<ScCapHistory, ScCapHistoryId, ScCapHistoryRepository> {
}

11
io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/ScKsHistoryService.java

@ -0,0 +1,11 @@
package io.sc.engine.mv.service.sc;
import io.sc.engine.mv.jpa.entity.ScKsHistory;
import io.sc.engine.mv.jpa.entity.id.ScKsHistoryId;
import io.sc.engine.mv.jpa.repository.ScKsHistoryRepository;
import io.sc.platform.orm.service.DaoService;
public interface ScKsHistoryService extends DaoService<ScKsHistory, ScKsHistoryId, ScKsHistoryRepository> {
}

11
io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/ScRocHistoryService.java

@ -0,0 +1,11 @@
package io.sc.engine.mv.service.sc;
import io.sc.engine.mv.jpa.entity.ScRocHistory;
import io.sc.engine.mv.jpa.entity.id.ScRocHistoryId;
import io.sc.engine.mv.jpa.repository.ScRocHistoryRepository;
import io.sc.platform.orm.service.DaoService;
public interface ScRocHistoryService extends DaoService<ScRocHistory, ScRocHistoryId, ScRocHistoryRepository> {
}

13
io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/impl/ScCapHistoryServiceImpl.java

@ -0,0 +1,13 @@
package io.sc.engine.mv.service.sc.impl;
import io.sc.engine.mv.jpa.entity.ScCapHistory;
import io.sc.engine.mv.jpa.entity.id.ScCapHistoryId;
import io.sc.engine.mv.jpa.repository.ScCapHistoryRepository;
import io.sc.engine.mv.service.sc.ScCapHistoryService;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ScCapHistoryServiceImpl extends DaoServiceImpl<ScCapHistory, ScCapHistoryId, ScCapHistoryRepository> implements ScCapHistoryService {
}

13
io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/impl/ScKsHistoryServiceImpl.java

@ -0,0 +1,13 @@
package io.sc.engine.mv.service.sc.impl;
import io.sc.engine.mv.jpa.entity.ScKsHistory;
import io.sc.engine.mv.jpa.entity.id.ScKsHistoryId;
import io.sc.engine.mv.jpa.repository.ScKsHistoryRepository;
import io.sc.engine.mv.service.sc.ScKsHistoryService;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ScKsHistoryServiceImpl extends DaoServiceImpl<ScKsHistory, ScKsHistoryId, ScKsHistoryRepository> implements ScKsHistoryService {
}

13
io.sc.engine.mv/src/main/java/io/sc/engine/mv/service/sc/impl/ScRocHistoryServiceImpl.java

@ -0,0 +1,13 @@
package io.sc.engine.mv.service.sc.impl;
import io.sc.engine.mv.jpa.entity.ScRocHistory;
import io.sc.engine.mv.jpa.entity.id.ScRocHistoryId;
import io.sc.engine.mv.jpa.repository.ScRocHistoryRepository;
import io.sc.engine.mv.service.sc.ScRocHistoryService;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ScRocHistoryServiceImpl extends DaoServiceImpl<ScRocHistory, ScRocHistoryId, ScRocHistoryRepository> implements ScRocHistoryService {
}

42
io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/RuntimeParameterVo.java

@ -0,0 +1,42 @@
package io.sc.engine.mv.vo;
import io.sc.platform.orm.api.vo.BaseVo;
public class RuntimeParameterVo extends BaseVo {
private String validateDate;
private String name;
private String value;
private Integer sno;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Integer getSno() {
return sno;
}
public void setSno(Integer sno) {
this.sno = sno;
}
}

99
io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/ScCapHistoryVo.java

@ -0,0 +1,99 @@
package io.sc.engine.mv.vo;
import io.sc.platform.orm.api.vo.BaseVo;
import java.math.BigDecimal;
public class ScCapHistoryVo extends BaseVo {
private String validateDate;
private String modelId;
private String modelName;
private Integer scoreCutOffPoint;
private Integer ts;
private Integer tt;
private Integer tds;
private Integer tdt;
private BigDecimal x;
private BigDecimal y;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Integer getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Integer scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
public Integer getTs() {
return ts;
}
public void setTs(Integer ts) {
this.ts = ts;
}
public Integer getTt() {
return tt;
}
public void setTt(Integer tt) {
this.tt = tt;
}
public Integer getTds() {
return tds;
}
public void setTds(Integer tds) {
this.tds = tds;
}
public Integer getTdt() {
return tdt;
}
public void setTdt(Integer tdt) {
this.tdt = tdt;
}
public BigDecimal getX() {
return x;
}
public void setX(BigDecimal x) {
this.x = x;
}
public BigDecimal getY() {
return y;
}
public void setY(BigDecimal y) {
this.y = y;
}
}

98
io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/ScKsHistoryVo.java

@ -0,0 +1,98 @@
package io.sc.engine.mv.vo;
import io.sc.platform.orm.api.vo.BaseVo;
import java.math.BigDecimal;
public class ScKsHistoryVo extends BaseVo {
private String validateDate;
private String modelId;
private String modelName;
private Integer scoreCutOffPoint;
private Integer n;
private Integer tn;
private Integer d;
private Integer td;
private BigDecimal y1;
private BigDecimal y2;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Integer getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Integer scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
public Integer getN() {
return n;
}
public void setN(Integer n) {
this.n = n;
}
public Integer getTn() {
return tn;
}
public void setTn(Integer tn) {
this.tn = tn;
}
public Integer getD() {
return d;
}
public void setD(Integer d) {
this.d = d;
}
public Integer getTd() {
return td;
}
public void setTd(Integer td) {
this.td = td;
}
public BigDecimal getY1() {
return y1;
}
public void setY1(BigDecimal y1) {
this.y1 = y1;
}
public BigDecimal getY2() {
return y2;
}
public void setY2(BigDecimal y2) {
this.y2 = y2;
}
}

116
io.sc.engine.mv/src/main/java/io/sc/engine/mv/vo/ScRocHistoryVo.java

@ -0,0 +1,116 @@
package io.sc.engine.mv.vo;
import io.sc.platform.orm.api.vo.BaseVo;
import java.math.BigDecimal;
public class ScRocHistoryVo extends BaseVo {
private String validateDate;
private String modelId;
private String modelName;
private Double scoreCutOffPoint;
private Integer dd;
private Integer dn;
private Integer nd;
private Integer nn;
private Integer td;
private Integer tn;
private BigDecimal x;
private BigDecimal y;
public String getValidateDate() {
return validateDate;
}
public void setValidateDate(String validateDate) {
this.validateDate = validateDate;
}
public String getModelId() {
return modelId;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Double getScoreCutOffPoint() {
return scoreCutOffPoint;
}
public void setScoreCutOffPoint(Double scoreCutOffPoint) {
this.scoreCutOffPoint = scoreCutOffPoint;
}
public Integer getDd() {
return dd;
}
public void setDd(Integer dd) {
this.dd = dd;
}
public Integer getDn() {
return dn;
}
public void setDn(Integer dn) {
this.dn = dn;
}
public Integer getNd() {
return nd;
}
public void setNd(Integer nd) {
this.nd = nd;
}
public Integer getNn() {
return nn;
}
public void setNn(Integer nn) {
this.nn = nn;
}
public Integer getTd() {
return td;
}
public void setTd(Integer td) {
this.td = td;
}
public Integer getTn() {
return tn;
}
public void setTn(Integer tn) {
this.tn = tn;
}
public BigDecimal getX() {
return x;
}
public void setX(BigDecimal x) {
this.x = x;
}
public BigDecimal getY() {
return y;
}
public void setY(BigDecimal y) {
this.y = y;
}
}

40
io.sc.engine.mv/src/main/resources/io/sc/engine/mv/initializer/SampleDefaultRecord.groovy

@ -0,0 +1,40 @@
import groovy.sql.Sql;
/**
* 使:
* 1. dataExtractor:
* 2. runtimeContext:
* 3. applicationContext: spring
* 4. defaultDataSource:
* 5. dataSource:
**/
//SQL语句
/* ----------------通常以下部分为客户定制部分---------------- */
def query ="""
select
'客户唯一标识' as FD_CUSTOM_ID, /*客户唯一标识*/
null as FD_DEFAULT_CONFIRM_DATE /*违约认定日期*/
from MV_DEFAULT_RECORD
""";
/* --------------------客户定制部分结束--------------------- */
// SQL
def insert ="""
insert into MV_DEFAULT_RECORD(
FD_CUSTOM_ID,
FD_DEFAULT_CONFIRM_DATE
) values (?,?)
""";
//
def defaultSql = new Sql(defaultDataSource);
defaultSql.execute("delete from MV_DEFAULT_RECORD");
//
def Sql =new Sql(dataSource);
defaultSql.withBatch(5000,insert){ps ->
Sql.eachRow(query){ row ->
ps.addBatch([row['FD_CUSTOM_ID'],row['FD_DEFAULT_CONFIRM_DATE']]);
}
}

70
io.sc.engine.mv/src/main/resources/io/sc/engine/mv/initializer/SampleScoreRecord.groovy

@ -0,0 +1,70 @@
import groovy.sql.Sql;
/**
* 使:
* 1. dataExtractor:
* 2. runtimeContext:
* 3. applicationContext: spring
* 4. defaultDataSource:
* 5. dataSource:
**/
//SQL语句
/* ----------------通常以下部分为客户定制部分---------------- */
def query ="""
select
'客户唯一标识' as FD_CUSTOM_ID, /*客户唯一标识*/
'客户名称' as FD_CUSTOM_NAME, /*客户名称*/
'评级模型标识' as FD_MODEL_ID, /*评级模型标识*/
'评级模型名称' as FD_MODEL_NAME, /*评级模型名称*/
0.6 as FD_PD, /*评级结果(违约概率)*/
50 as FD_SCORE, /*评级结果(总体得分)*/
30 as FD_SCORE_QUANTITATIVE, /*评级结果(定量部分得分)*/
20 as FD_SCORE_QUALITATIVE, /*评级结果(定性部分得分)*/
'8' as FD_LEVEL, /*评级结果(等级)*/
null as FD_SCORE_BEGIN_DATE, /*评级有效期开始日期*/
null as FD_SCORE_END_DATE /*评级有效期结束日期*/
from MV_SCORE_RECORD
""";
/* --------------------客户定制部分结束--------------------- */
// SQL
def insert ="""
insert into MV_SCORE_RECORD(
FD_CUSTOM_ID,
FD_CUSTOM_NAME,
FD_MODEL_ID,
FD_MODEL_NAME,
FD_PD,
FD_SCORE,
FD_SCORE_QUANTITATIVE,
FD_SCORE_QUALITATIVE,
FD_LEVEL,
FD_SCORE_BEGIN_DATE,
FD_SCORE_END_DATE
) values (?,?,?,?,?,?,?,?,?,?,?)
""";
//
def defaultSql = new Sql(defaultDataSource);
defaultSql.execute("delete from MV_SCORE_RECORD");
//
def Sql =new Sql(dataSource);
defaultSql.withBatch(5000,insert){ps ->
Sql.eachRow(query){ row ->
ps.addBatch([
row['FD_CUSTOM_ID'],
row['FD_CUSTOM_NAME'],
row['FD_MODEL_ID'],
row['FD_MODEL_NAME'],
row['FD_PD'],
row['FD_SCORE'],
row['FD_SCORE_QUANTITATIVE'],
row['FD_SCORE_QUALITATIVE'],
row['FD_LEVEL'],
row['FD_SCORE_BEGIN_DATE'],
row['FD_SCORE_END_DATE']
]);
}
}

11
io.sc.platform.core/src/main/java/io/sc/platform/core/enums/RoundingMode.java

@ -0,0 +1,11 @@
package io.sc.platform.core.enums;
public enum RoundingMode {
UP,
DOWN,
CEILING,
FLOOR,
HALF_UP,
HALF_DOWN,
HALF_EVEN;
}

19
io.sc.platform.data/src/main/java/io/sc/platform/data/csv/Record.java

@ -0,0 +1,19 @@
package io.sc.platform.data.csv;
public class Record {
private RecordMapper mapper;
private Object[] values;
public Record(RecordMapper mapper, Object[] values){
this.mapper =mapper;
this.values =values;
}
public Object get(String name){
return values[mapper.getIndex(name)];
}
public <T> T get(String name,Class<T> clazz){
return mapper.getConversionService().convert(values[mapper.getIndex(name)],clazz);
}
}

29
io.sc.platform.data/src/main/java/io/sc/platform/data/csv/RecordMapper.java

@ -0,0 +1,29 @@
package io.sc.platform.data.csv;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import java.util.HashMap;
import java.util.Map;
public class RecordMapper {
private ConversionService conversionService =DefaultConversionService.getSharedInstance();
private Map<String,Integer> mapping =new HashMap<>();
public RecordMapper addMapping(String name, int index){
mapping.put(name,index);
return this;
}
public int getIndex(String name){
return mapping.get(name);
}
public ConversionService getConversionService() {
return conversionService;
}
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
}

7
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/QueryParameter.java

@ -65,6 +65,13 @@ public class QueryParameter {
return Sort.by(orders); return Sort.by(orders);
} }
public boolean existsSortBy(){
if(this.sortBy!=null && !this.sortBy.isEmpty()){
return true;
}
return false;
}
public void addSortBy(String sortBy){ public void addSortBy(String sortBy){
if(StringUtils.hasText(sortBy)) { if(StringUtils.hasText(sortBy)) {
this.sortBy.add(sortBy); this.sortBy.add(sortBy);

33
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/QueryResult.java

@ -3,6 +3,7 @@ package io.sc.platform.orm.service.support;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -26,8 +27,33 @@ public class QueryResult {
} }
} }
public static <T> Page<T> page(List<T> list, Pageable pageable){ public static <T> Page<T> page(List<T> list, QueryParameter queryParameter){
if(list!=null && !list.isEmpty()) { return page(list,queryParameter, new DefaultQueryResultSorter());
}
public static <T> Page<T> page(List<T> list, QueryParameter queryParameter, QueryResultSorter sorter){
if(list==null && list.isEmpty()){
return emptyPage();
}
if(queryParameter==null){
return page(list);
}
Sort sort =queryParameter.getSort();
if(sort!=null){
Sort.Order order =sort.iterator().next();
if(order!=null){
String sortFieldName =order.getProperty();
boolean isAscending =order.isAscending();
list.sort(sorter.getComparator(sortFieldName,isAscending));
}
}
if(!queryParameter.getPageable()){
return page(list);
}
Pageable pageable =queryParameter.getJpaPageable();
if(pageable==null){
return page(list);
}
int page =pageable.getPageNumber(); int page =pageable.getPageNumber();
int pageSize =pageable.getPageSize(); int pageSize =pageable.getPageSize();
int total =list.size(); int total =list.size();
@ -37,8 +63,5 @@ public class QueryResult {
result.add(list.get(i)); result.add(list.get(i));
} }
return new PageImpl<T>(result,pageable,total); return new PageImpl<T>(result,pageable,total);
}else{
return new PageImpl<T>(Collections.emptyList());
}
} }
} }

7
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/support/QueryResultSorter.java

@ -0,0 +1,7 @@
package io.sc.platform.orm.service.support;
import java.util.Comparator;
public interface QueryResultSorter<T> {
public Comparator<T> getComparator(String propertyName,boolean isAscending);
}
Loading…
Cancel
Save