task_fundPerformance.dos 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. module fundit::task_fundPerformance
  2. use fundit::fundCalculator
  3. use fundit::dataPuller
  4. use fundit::returnCalculator
  5. use fundit::indicatorCalculator
  6. /*
  7. * 通用收益计算
  8. *
  9. *
  10. */
  11. def calEntityReturns(entityType, freq, entities) {
  12. ret = null;
  13. if(freq == 'm') { ret = fundit::returnCalculator::cal_entity_monthly_returns(entityType, entities); }
  14. return ret;
  15. }
  16. /*
  17. * 通用指标计算
  18. *
  19. *
  20. *
  21. * @return <DICT TABLE>: ['PBI-INCEP', 'PBI-YTD', 'PBI-6M', 'PBI-1Y', 'PBI-2Y', 'PBI-3Y', 'PBI-4Y', 'PBI-5Y', 'PBI-10Y', 'MS-3Y', 'MS-5Y', 'MS-10Y']
  22. *
  23. */
  24. def calIndicators(entityType, monthlyReturns) {
  25. if(find(['FD', 'PF'], entityType) < 0) return null;
  26. if(monthlyReturns.isVoid() || monthlyReturns.size() < 1) return null;
  27. oldest_date = EXEC price_date.min() FROM monthlyReturns;
  28. v_entity_ids = (SELECT DISTINCT entity_id FROM monthlyReturns).entity_id;
  29. entity_info = get_entity_info(entityType, v_entity_ids);
  30. if(entity_info.isVoid() || entity_info.size() == 0) { return null };
  31. if(monthlyReturns.isVoid() || monthlyReturns.size() == 0) { return null; }
  32. end_day = today();
  33. // 取基金和基准的对照表
  34. primary_benchmark = SELECT entity_id, end_date, iif(benchmark_id.isNull(), 'IN00000008', benchmark_id) AS benchmark_id
  35. FROM get_entity_primary_benchmark(entityType, v_entity_ids, oldest_date.month().temporalFormat('yyyy-MM'), end_day.month().temporalFormat('yyyy-MM')) ;
  36. // 取所有出现的基准月收益
  37. bmk_ret = get_benchmark_return(primary_benchmark, end_day);
  38. if(bmk_ret.isVoid() || bmk_ret.size() == 0) { return null; }
  39. risk_free_rate = SELECT fund_id, temporalParse(end_date, 'yyyy-MM') AS end_date, ret FROM get_risk_free_rate(oldest_date, end_day);
  40. if(risk_free_rate.isVoid() || risk_free_rate.size() == 0) { return null; }
  41. // 标准的指标
  42. t0 = cal_trailing_indicators(entity_info, primary_benchmark, end_day, monthlyReturns, bmk_ret, risk_free_rate);
  43. // PBI stands for "Primary Benchmark Index"
  44. v_table_name = ['PBI-INCEP', 'PBI-YTD', 'PBI-6M', 'PBI-1Y', 'PBI-2Y', 'PBI-3Y', 'PBI-4Y', 'PBI-5Y', 'PBI-10Y'];
  45. // BFI指标
  46. return dict(v_table_name, t0);
  47. }
  48. /*
  49. * 基金指标计算
  50. *
  51. *
  52. */
  53. def calFundIndicators(rets) {
  54. t = calIndicators('FD', rets);
  55. return t;
  56. }
  57. /*
  58. * 定时任务:最新净值触发的业绩指标计算
  59. *
  60. * TODO: 目前收益表在MySQL中,所以需要将计算的最新收益与MySQL中的历史数据合并
  61. */
  62. def calFundPerformance(entityType, date) {
  63. very_old_date = 1990.01.01;
  64. if(find(['HF', 'MF'], entityType) < 0) return null;
  65. // 取有最新净值变动的私募基金列表
  66. tb_cal_funds = get_fund_list_by_nav_updatetime('MF', NULL, date);
  67. // 分批跑
  68. i = 0;
  69. batch_size = 1000;
  70. do {
  71. funds = tb_cal_funds[i:batch_size]
  72. funds.rename!('fund_id', 'entity_id');
  73. // 计算月收益
  74. rets = calEntityReturns(entityType, 'm', funds);
  75. // 最新更新的收益存入数据库
  76. // 取完整历史收益用于指标计算
  77. all_rets = get_fund_monthly_ret(funds.entity_id, very_old_date, today().month(), true);
  78. all_rets.rename!('fund_id', 'entity_id');
  79. // 将MySQL中的 YYYY-MM 格式改为 YYYY.MM
  80. end_dates = EXEC end_date.temporalParse('yyyy-MM') FROM all_rets;
  81. all_rets.replaceColumn!('end_date', end_dates);
  82. // 用新计算的收益覆盖旧的
  83. UPDATE all_rets
  84. SET all_rets.ret = rets.ret, all_rets.nav = rets.cumulative_nav
  85. FROM ej(all_rets, rets, ['entity_id', 'end_date']);
  86. // 用新计算的收益补充旧的, ret_ytd_a, ret_incep_a 没有用
  87. INSERT INTO all_rets
  88. SELECT entity_id, end_date, price_date, ret, cumulative_nav, null AS ret_ytd_a, null AS ret_incep_a
  89. FROM rets
  90. WHERE NOT EXISTS ( SELECT * FROM all_rets WHERE entity_id = rets.entity_id AND end_date = rets.end_date);
  91. // 计算月度指标
  92. indicators = calFundIndicators(all_rets);
  93. //INSERT INTO tb_indicators SELECT * FROM indicators;
  94. i += batch_size;
  95. } while (i < batch_size);
  96. // } while (i <= tb_cal_funds.size());
  97. return indicators;
  98. }