task_fundPerformance.dos 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. module fundit::task_fundPerformance
  2. use fundit::sqlUtilities
  3. use fundit::dataPuller
  4. use fundit::returnCalculator
  5. use fundit::indicatorCalculator
  6. use fundit::fundCalculator
  7. /*
  8. * 按照 fund_performance 表结构准备数据记录
  9. *
  10. *
  11. */
  12. def generate_fund_performance(fund_info, indicators, isToMySQL, mutable fund_performance) {
  13. t = null;
  14. if(isToMySQL) {
  15. t = SELECT entity_id, end_date, price_date, nav AS cumulative_nav, ret AS ret_1m, ret AS ret_1m_a, trailing_ret AS ret_3m, trailing_ret_a AS ret_3m_a
  16. FROM indicators['PBI-3M'] AS ind
  17. INNER JOIN fund_info fi ON ind.entity_id = fi.entity_id
  18. WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
  19. UPDATE t
  20. SET ret_6m = trailing_ret, ret_6m_a = trailing_ret_a
  21. FROM ej(t, indicators['PBI-6M'], ['entity_id', 'end_date']);
  22. UPDATE t
  23. SET ret_1y = trailing_ret, ret_1y_a = trailing_ret_a
  24. FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
  25. UPDATE t
  26. SET ret_2y = trailing_ret, ret_2y_a = trailing_ret_a
  27. FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
  28. UPDATE t
  29. SET ret_3y = trailing_ret, ret_3y_a = trailing_ret_a
  30. FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
  31. UPDATE t
  32. SET ret_4y = trailing_ret, ret_4y_a = trailing_ret_a
  33. FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
  34. UPDATE t
  35. SET ret_5y = trailing_ret, ret_5y_a = trailing_ret_a
  36. FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
  37. UPDATE t
  38. SET ret_10y = trailing_ret, ret_10y_a = trailing_ret_a
  39. FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
  40. UPDATE t
  41. SET ret_ytd = trailing_ret, ret_ytd_a = trailing_ret_a
  42. FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
  43. // 取消了 ret_incep_a_all (没意义) 和 ret_incep_a_gips (ret_incep_a 与之相等)
  44. UPDATE t
  45. SET ret_incep = trailing_ret, ret_incep_a = trailing_ret_a
  46. FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
  47. INSERT INTO fund_performance SELECT * FROM t;
  48. } else {
  49. }
  50. }
  51. /*
  52. * 按照 fund_risk_stats 表结构准备数据记录
  53. *
  54. *
  55. */
  56. def generate_fund_risk_stats(fund_info, indicators, isToMySQL, mutable fund_risk_stats) {
  57. t = null;
  58. if(isToMySQL) {
  59. t = SELECT entity_id, end_date, std_dev_a AS stddev_6m, ds_dev_a AS downsidedev_6m, alpha_a AS alpha_6m, winrate AS winrate_6m, beta AS beta_6m,
  60. skewness AS skewness_6m, kurtosis AS kurtosis_6m, wrst_month AS worstmonth_6m, drawdown AS maxdrawdown_6m
  61. FROM indicators['PBI-6M'] AS ind
  62. INNER JOIN fund_info fi ON ind.entity_id = fi.entity_id
  63. WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
  64. UPDATE t
  65. SET stddev_1y = std_dev_a, downsidedev_1y = ds_dev_a, alpha_1y = alpha_a, winrate_1y = winrate, beta_1y = beta,
  66. skewness_1y = skewness, kurtosis_1y = kurtosis, worstmonth_1y = wrst_month, maxdrawdown_1y = drawdown
  67. FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
  68. UPDATE t
  69. SET stddev_2y = std_dev_a, downsidedev_2y = ds_dev_a, alpha_2y = alpha_a, winrate_2y = winrate, beta_2y = beta,
  70. skewness_2y = skewness, kurtosis_2y = kurtosis, worstmonth_2y = wrst_month, maxdrawdown_2y = drawdown
  71. FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
  72. UPDATE t
  73. SET stddev_3y = std_dev_a, downsidedev_3y = ds_dev_a, alpha_3y = alpha_a, winrate_3y = winrate, beta_3y = beta,
  74. skewness_3y = skewness, kurtosis_3y = kurtosis, worstmonth_3y = wrst_month, maxdrawdown_3y = drawdown
  75. FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
  76. UPDATE t
  77. SET stddev_4y = std_dev_a, downsidedev_4y = ds_dev_a, alpha_4y = alpha_a, winrate_4y = winrate, beta_4y = beta,
  78. skewness_4y = skewness, kurtosis_4y = kurtosis, worstmonth_4y = wrst_month, maxdrawdown_4y = drawdown
  79. FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
  80. UPDATE t
  81. SET stddev_5y = std_dev_a, downsidedev_5y = ds_dev_a, alpha_5y = alpha_a, winrate_5y = winrate, beta_5y = beta,
  82. skewness_5y = skewness, kurtosis_5y = kurtosis, worstmonth_5y = wrst_month, maxdrawdown_5y = drawdown
  83. FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
  84. UPDATE t
  85. SET stddev_10y = std_dev_a, downsidedev_10y = ds_dev_a, alpha_10y = alpha_a, winrate_10y = winrate, beta_10y = beta,
  86. skewness_10y = skewness, kurtosis_10y = kurtosis, worstmonth_10y = wrst_month, maxdrawdown_10y = drawdown
  87. FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
  88. UPDATE t
  89. SET stddev_ytd = std_dev_a, downsidedev_ytd = ds_dev_a, alpha_ytd = alpha_a, winrate_ytd = winrate, beta_ytd = beta,
  90. skewness_ytd = skewness, kurtosis_ytd = kurtosis, worstmonth_ytd = wrst_month, maxdrawdown_ytd = drawdown
  91. FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
  92. UPDATE t
  93. SET stddev_incep = std_dev_a, downsidedev_incep = ds_dev_a, alpha_incep = alpha_a, winrate_incep = winrate, beta_incep = beta,
  94. skewness_incep = skewness, kurtosis_incep = kurtosis, worstmonth_incep = wrst_month, maxdrawdown_incep = drawdown
  95. FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
  96. INSERT INTO fund_risk_stats SELECT * FROM t;
  97. } else {
  98. }
  99. }
  100. /*
  101. * 按照 fund_riskadjret_stats 表结构准备数据记录
  102. *
  103. *
  104. */
  105. def generate_fund_riskadjret_stats(fund_info, indicators, isToMySQL, mutable fund_riskadjret_stats) {
  106. t = null;
  107. if(isToMySQL) {
  108. t = SELECT entity_id, end_date,
  109. sharpe_a AS sharperatio_6m, sortino_a AS sortinoratio_6m, treynor AS treynorratio_6m, jensen_a AS jensen_6m,
  110. calmar AS calmarratio_6m, omega AS omegaratio_6m, kappa AS kapparatio_6m
  111. FROM indicators['PBI-6M'] AS ind
  112. INNER JOIN fund_info fi ON ind.entity_id = fi.entity_id
  113. WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
  114. UPDATE t
  115. SET sharperatio_1y = sharpe_a, sortinoratio_1y = sortino_a, treynorratio_1y = treynor, jensen_1y = jensen_a,
  116. calmarratio_1y = calmar, omegaratio_1y = omega, kapparatio_1y = kappa
  117. FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
  118. UPDATE t
  119. SET sharperatio_2y = sharpe_a, sortinoratio_2y = sortino_a, treynorratio_2y = treynor, jensen_2y = jensen_a,
  120. calmarratio_2y = calmar, omegaratio_2y = omega, kapparatio_2y = kappa
  121. FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
  122. UPDATE t
  123. SET sharperatio_3y = sharpe_a, sortinoratio_3y = sortino_a, treynorratio_3y = treynor, jensen_3y = jensen_a,
  124. calmarratio_3y = calmar, omegaratio_3y = omega, kapparatio_3y = kappa
  125. FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
  126. UPDATE t
  127. SET sharperatio_4y = sharpe_a, sortinoratio_4y = sortino_a, treynorratio_4y = treynor, jensen_4y = jensen_a,
  128. calmarratio_4y = calmar, omegaratio_4y = omega, kapparatio_4y = kappa
  129. FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
  130. UPDATE t
  131. SET sharperatio_5y = sharpe_a, sortinoratio_5y = sortino_a, treynorratio_5y = treynor, jensen_5y = jensen_a,
  132. calmarratio_5y = calmar, omegaratio_5y = omega, kapparatio_5y = kappa
  133. FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
  134. UPDATE t
  135. SET sharperatio_10y = sharpe_a, sortinoratio_10y = sortino_a, treynorratio_10y = treynor, jensen_10y = jensen_a,
  136. calmarratio_10y = calmar, omegaratio_10y = omega, kapparatio_10y = kappa
  137. FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
  138. UPDATE t
  139. SET sharperatio_ytd = sharpe_a, sortinoratio_ytd = sortino_a, treynorratio_ytd = treynor, jensen_ytd = jensen_a,
  140. calmarratio_ytd = calmar, omegaratio_ytd = omega, kapparatio_ytd = kappa
  141. FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
  142. UPDATE t
  143. SET sharperatio_incep = sharpe_a, sortinoratio_incep = sortino_a, treynorratio_incep = treynor, jensen_incep = jensen_a,
  144. calmarratio_incep = calmar, omegaratio_incep = omega, kapparatio_incep = kappa
  145. FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
  146. INSERT INTO fund_riskadjret_stats SELECT * FROM t;
  147. } else {
  148. }
  149. }
  150. /*
  151. * 按照 fund_indicator 表结构准备数据记录
  152. *
  153. *
  154. */
  155. def generate_fund_indicator(fund_info, indicators, isToMySQL, mutable fund_indicator) {
  156. t = null;
  157. if(isToMySQL) {
  158. t = SELECT entity_id, end_date, info_a AS info_ratio_6m, m2_a AS m2_6m, track_error_a AS tracking_error_6m
  159. FROM indicators['PBI-6M'] AS ind
  160. INNER JOIN fund_info fi ON ind.entity_id = fi.entity_id
  161. WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
  162. UPDATE t
  163. SET info_ratio_1y = info_a, m2_1y = m2_a, tracking_error_1y = track_error_a
  164. FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
  165. UPDATE t
  166. SET info_ratio_2y = info_a, m2_2y = m2_a, tracking_error_2y = track_error_a, var_2y = var, cvar_2y = cvar
  167. FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
  168. UPDATE t
  169. SET info_ratio_3y = info_a, m2_3y = m2_a, tracking_error_3y = track_error_a, var_3y = var, cvar_3y = cvar
  170. FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
  171. UPDATE t
  172. SET info_ratio_4y = info_a, m2_4y = m2_a, tracking_error_4y = track_error_a, var_4y = var, cvar_4y = cvar
  173. FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
  174. UPDATE t
  175. SET info_ratio_5y = info_a, m2_5y = m2_a, tracking_error_5y = track_error_a, var_5y = var, cvar_5y = cvar
  176. FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
  177. UPDATE t
  178. SET info_ratio_10y = info_a, m2_10y = m2_a, tracking_error_10y = track_error_a, var_10y = var, cvar_10y = cvar
  179. FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
  180. UPDATE t
  181. SET info_ratio_ytd = info_a, m2_ytd = m2_a, tracking_error_ytd = track_error_a
  182. FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
  183. UPDATE t
  184. SET info_ratio_incep = info_a, m2_incep = m2_a, tracking_error_incep = track_error_a, var_incep = var, cvar_incep = cvar
  185. FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
  186. INSERT INTO fund_indicator SELECT * FROM t;
  187. } else {
  188. }
  189. }
  190. /*
  191. * 按照 fund_style_stats 表结构准备数据记录
  192. *
  193. *
  194. */
  195. def generate_fund_style_stats(fund_info, indicators, isToMySQL, mutable fund_style_stats) {
  196. t = null;
  197. if(isToMySQL) {
  198. t = SELECT entity_id, end_date, upside_capture_ret AS upsidecapture_ret_6m, downside_capture_ret AS downsidecapture_ret_6m,
  199. upside_capture_ratio AS upsidecapture_ratio_6m, downside_capture_ratio AS downsidecapture_ratio_6m
  200. FROM indicators['PBI-6M'] AS ind
  201. INNER JOIN fund_info fi ON ind.entity_id = fi.entity_id
  202. WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
  203. UPDATE t
  204. SET upsidecapture_ret_1y = upside_capture_ret, downsidecapture_ret_1y = downside_capture_ret,
  205. upsidecapture_ratio_1y = upside_capture_ratio, downsidecapture_ratio_1y = downside_capture_ratio
  206. FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
  207. UPDATE t
  208. SET upsidecapture_ret_2y = upside_capture_ret, downsidecapture_ret_2y = downside_capture_ret,
  209. upsidecapture_ratio_2y = upside_capture_ratio, downsidecapture_ratio_2y = downside_capture_ratio
  210. FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
  211. UPDATE t
  212. SET upsidecapture_ret_3y = upside_capture_ret, downsidecapture_ret_3y = downside_capture_ret,
  213. upsidecapture_ratio_3y = upside_capture_ratio, downsidecapture_ratio_3y = downside_capture_ratio
  214. FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
  215. UPDATE t
  216. SET upsidecapture_ret_4y = upside_capture_ret, downsidecapture_ret_4y = downside_capture_ret,
  217. upsidecapture_ratio_4y = upside_capture_ratio, downsidecapture_ratio_4y = downside_capture_ratio
  218. FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
  219. UPDATE t
  220. SET upsidecapture_ret_5y = upside_capture_ret, downsidecapture_ret_5y = downside_capture_ret,
  221. upsidecapture_ratio_5y = upside_capture_ratio, downsidecapture_ratio_5y = downside_capture_ratio
  222. FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
  223. UPDATE t
  224. SET upsidecapture_ret_10y = upside_capture_ret, downsidecapture_ret_10y = downside_capture_ret,
  225. upsidecapture_ratio_10y = upside_capture_ratio, downsidecapture_ratio_10y = downside_capture_ratio
  226. FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
  227. UPDATE t
  228. SET upsidecapture_ret_ytd = upside_capture_ret, downsidecapture_ret_ytd = downside_capture_ret,
  229. upsidecapture_ratio_ytd = upside_capture_ratio, downsidecapture_ratio_ytd = downside_capture_ratio
  230. FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
  231. UPDATE t
  232. SET upsidecapture_ret_incep = upside_capture_ret, downsidecapture_ret_incep = downside_capture_ret,
  233. upsidecapture_ratio_incep = upside_capture_ratio, downsidecapture_ratio_incep = downside_capture_ratio
  234. FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
  235. INSERT INTO fund_style_stats SELECT * FROM t;
  236. } else {
  237. }
  238. }
  239. /*
  240. * 建表 fund_performance
  241. */
  242. def create_fund_performance() {
  243. return table(1000:0,
  244. ['entity_id', 'end_date', 'price_date', 'cumulative_nav',
  245. 'ret_1m', 'ret_1m_a', 'ret_3m', 'ret_3m_a', 'ret_6m', 'ret_6m_a',
  246. 'ret_1y', 'ret_1y_a', 'ret_2y', 'ret_2y_a', 'ret_3y', 'ret_3y_a', 'ret_4y', 'ret_4y_a',
  247. 'ret_5y', 'ret_5y_a', 'ret_10y', 'ret_10y_a', 'ret_ytd', 'ret_ytd_a', 'ret_incep', 'ret_incep_a'],
  248. [SYMBOL, MONTH, DATE, DOUBLE,
  249. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  250. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  251. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
  252. }
  253. /*
  254. * 建表 fund_indicator
  255. */
  256. def create_fund_indicator() {
  257. return table(1000:0,
  258. ['entity_id', 'end_date',
  259. 'info_ratio_6m', 'm2_6m', 'tracking_error_6m',
  260. 'info_ratio_1y', 'm2_1y', 'tracking_error_1y',
  261. 'info_ratio_2y', 'm2_2y', 'tracking_error_2y', 'var_2y', 'cvar_2y',
  262. 'info_ratio_3y', 'm2_3y', 'tracking_error_3y', 'var_3y', 'cvar_3y',
  263. 'info_ratio_4y', 'm2_4y', 'tracking_error_4y', 'var_4y', 'cvar_4y',
  264. 'info_ratio_5y', 'm2_5y', 'tracking_error_5y', 'var_5y', 'cvar_5y',
  265. 'info_ratio_10y', 'm2_10y', 'tracking_error_10y', 'var_10y', 'cvar_10y',
  266. 'info_ratio_ytd', 'm2_ytd', 'tracking_error_ytd',
  267. 'info_ratio_incep', 'm2_incep','tracking_error_incep', 'var_incep', 'cvar_incep'],
  268. [SYMBOL, MONTH,
  269. DOUBLE, DOUBLE, DOUBLE,
  270. DOUBLE, DOUBLE, DOUBLE,
  271. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  272. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  273. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  274. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  275. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  276. DOUBLE, DOUBLE, DOUBLE,
  277. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
  278. }
  279. /*
  280. * 建表 fund_risk_stats
  281. */
  282. def create_fund_risk_stats() {
  283. return table(1000:0,
  284. ['entity_id', 'end_date',
  285. 'stddev_6m', 'downsidedev_6m', 'alpha_6m', 'winrate_6m', 'beta_6m', 'skewness_6m', 'kurtosis_6m', 'worstmonth_6m', 'maxdrawdown_6m',
  286. 'stddev_1y', 'downsidedev_1y', 'alpha_1y', 'winrate_1y', 'beta_1y', 'skewness_1y', 'kurtosis_1y', 'worstmonth_1y', 'maxdrawdown_1y',
  287. 'stddev_2y', 'downsidedev_2y', 'alpha_2y', 'winrate_2y', 'beta_2y', 'skewness_2y', 'kurtosis_2y', 'worstmonth_2y', 'maxdrawdown_2y',
  288. 'stddev_3y', 'downsidedev_3y', 'alpha_3y', 'winrate_3y', 'beta_3y', 'skewness_3y', 'kurtosis_3y', 'worstmonth_3y', 'maxdrawdown_3y',
  289. 'stddev_4y', 'downsidedev_4y', 'alpha_4y', 'winrate_4y', 'beta_4y', 'skewness_4y', 'kurtosis_4y', 'worstmonth_4y', 'maxdrawdown_4y',
  290. 'stddev_5y', 'downsidedev_5y', 'alpha_5y', 'winrate_5y', 'beta_5y', 'skewness_5y', 'kurtosis_5y', 'worstmonth_5y', 'maxdrawdown_5y',
  291. 'stddev_10y', 'downsidedev_10y','alpha_10y', 'winrate_10y', 'beta_10y', 'skewness_10y', 'kurtosis_10y', 'worstmonth_10y', 'maxdrawdown_10y',
  292. 'stddev_ytd', 'downsidedev_ytd', 'alpha_ytd', 'winrate_ytd', 'beta_ytd', 'skewness_ytd', 'kurtosis_ytd', 'worstmonth_ytd', 'maxdrawdown_ytd',
  293. 'stddev_incep', 'downsidedev_incep', 'alpha_incep', 'winrate_incep', 'beta_incep', 'skewness_incep', 'kurtosis_incep', 'worstmonth_incep', 'maxdrawdown_incep'],
  294. [SYMBOL, MONTH,
  295. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  296. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  297. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  298. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  299. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  300. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  301. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  302. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  303. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
  304. }
  305. /*
  306. * 建表 fund_riskadjret_stats
  307. */
  308. def create_fund_riskadjret_stats() {
  309. return table(1000:0,
  310. ['entity_id', 'end_date',
  311. 'sharperatio_6m', 'sortinoratio_6m', 'treynorratio_6m', 'jensen_6m', 'calmarratio_6m', 'omegaratio_6m', 'kapparatio_6m',
  312. 'sharperatio_1y', 'sortinoratio_1y', 'treynorratio_1y', 'jensen_1y', 'calmarratio_1y', 'omegaratio_1y', 'kapparatio_1y',
  313. 'sharperatio_2y', 'sortinoratio_2y', 'treynorratio_2y', 'jensen_2y', 'calmarratio_2y', 'omegaratio_2y', 'kapparatio_2y',
  314. 'sharperatio_3y', 'sortinoratio_3y', 'treynorratio_3y', 'jensen_3y', 'calmarratio_3y', 'omegaratio_3y', 'kapparatio_3y',
  315. 'sharperatio_4y', 'sortinoratio_4y', 'treynorratio_4y', 'jensen_4y', 'calmarratio_4y', 'omegaratio_4y', 'kapparatio_4y',
  316. 'sharperatio_5y', 'sortinoratio_5y', 'treynorratio_5y', 'jensen_5y', 'calmarratio_5y', 'omegaratio_5y', 'kapparatio_5y',
  317. 'sharperatio_10y', 'sortinoratio_10y', 'treynorratio_10y', 'jensen_10y', 'calmarratio_10y', 'omegaratio_10y', 'kapparatio_10y',
  318. 'sharperatio_ytd', 'sortinoratio_ytd', 'treynorratio_ytd', 'jensen_ytd', 'calmarratio_ytd', 'omegaratio_ytd', 'kapparatio_ytd',
  319. 'sharperatio_incep', 'sortinoratio_incep', 'treynorratio_incep', 'jensen_incep', 'calmarratio_incep', 'omegaratio_incep', 'kapparatio_incep'],
  320. [SYMBOL, MONTH,
  321. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  322. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  323. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  324. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  325. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  326. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  327. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  328. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  329. DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
  330. }
  331. /*
  332. * 建表 fund_style_stats
  333. */
  334. def create_fund_style_stats() {
  335. return table(1000:0,
  336. ['entity_id', 'end_date',
  337. 'upsidecapture_ret_6m', 'downsidecapture_ret_6m', 'upsidecapture_ratio_6m', 'downsidecapture_ratio_6m',
  338. 'upsidecapture_ret_1y', 'downsidecapture_ret_1y', 'upsidecapture_ratio_1y', 'downsidecapture_ratio_1y',
  339. 'upsidecapture_ret_2y', 'downsidecapture_ret_2y', 'upsidecapture_ratio_2y', 'downsidecapture_ratio_2y',
  340. 'upsidecapture_ret_3y', 'downsidecapture_ret_3y', 'upsidecapture_ratio_3y', 'downsidecapture_ratio_3y',
  341. 'upsidecapture_ret_4y', 'downsidecapture_ret_4y', 'upsidecapture_ratio_4y', 'downsidecapture_ratio_4y',
  342. 'upsidecapture_ret_5y', 'downsidecapture_ret_5y', 'upsidecapture_ratio_5y', 'downsidecapture_ratio_5y',
  343. 'upsidecapture_ret_10y', 'downsidecapture_ret_10y', 'upsidecapture_ratio_10y', 'downsidecapture_ratio_10y',
  344. 'upsidecapture_ret_ytd', 'downsidecapture_ret_ytd', 'upsidecapture_ratio_ytd', 'downsidecapture_ratio_ytd',
  345. 'upsidecapture_ret_incep', 'downsidecapture_ret_incep', 'upsidecapture_ratio_incep', 'downsidecapture_ratio_incep'],
  346. [SYMBOL, MONTH,
  347. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  348. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  349. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  350. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  351. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  352. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  353. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  354. DOUBLE, DOUBLE, DOUBLE, DOUBLE,
  355. DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
  356. }
  357. /*
  358. * 根据 mysql 表改动某些字段
  359. */
  360. def chg_columns_for_mysql(mutable tb_mysql) {
  361. tb_mysql.rename!('entity_id', 'fund_id');
  362. // 将 dolphinDB 的 MONTH 换成 MySQL 的 YYYY-MM 格式
  363. v_end_date = EXEC end_date.temporalFormat('yyyy-MM') FROM tb_mysql;
  364. tb_mysql.replaceColumn!('end_date', v_end_date);
  365. }
  366. /*
  367. * 定时任务:最新净值触发的业绩指标计算
  368. *
  369. * @param entityType <STRING>: 'MF', 'HF'...
  370. * @param date <DATETIME>: 净值更新时间
  371. *
  372. * TODO: 目前收益表在MySQL中,所以需要将计算的最新收益与MySQL中的历史数据合并
  373. */
  374. def calFundPerformance(entityType, date) {
  375. rt = '';
  376. very_old_date = 1990.01.01;
  377. if(find(['HF', 'MF'], entityType) < 0) return null;
  378. // 取有最新净值变动的基金列表
  379. tb_cal_funds = get_entity_list_by_nav_updatetime(entityType, NULL, date, true);
  380. if(tb_cal_funds.isVoid() || tb_cal_funds.size() == 0 ) return;
  381. tb_fund_performance = create_fund_performance();
  382. tb_fund_indicator = create_fund_indicator();
  383. tb_fund_risk_stats = create_fund_risk_stats();
  384. tb_fund_riskadjret_stats = create_fund_riskadjret_stats();
  385. tb_fund_style_stats = create_fund_style_stats();
  386. // 分批跑
  387. i = 0;
  388. batch_size = 1000;
  389. do {
  390. funds = tb_cal_funds[i:batch_size];
  391. fund_info = SELECT entity_id, price_date, inception_date, benchmark_id, ini_value
  392. FROM ej(funds, get_fund_info(funds.entity_id), 'entity_id', 'fund_id');
  393. // 计算月收益
  394. rets = mix_monthly_returns(entityType, fund_info);
  395. // 计算月度指标
  396. rets.rename!('cumulative_nav', 'nav');
  397. indicators = cal_monthly_indicators(entityType, 'PBI', rets);
  398. // TODO: 最新更新的指标存入数据库
  399. generate_fund_performance(fund_info, indicators, true, tb_fund_performance);
  400. generate_fund_indicator(fund_info, indicators, true, tb_fund_indicator);
  401. generate_fund_risk_stats(fund_info, indicators, true, tb_fund_risk_stats);
  402. generate_fund_riskadjret_stats(fund_info, indicators, true, tb_fund_riskadjret_stats);
  403. generate_fund_style_stats(fund_info, indicators, true, tb_fund_style_stats);
  404. i += batch_size;
  405. } while (i < batch_size);
  406. // } while (i <= tb_cal_funds.size());
  407. // saverisk_stats
  408. try {
  409. chg_columns_for_mysql(tb_fund_performance);
  410. save_table(tb_fund_performance, 'mfdb.fund_performance', true);
  411. chg_columns_for_mysql(tb_fund_indicator);
  412. save_table(tb_fund_indicator, 'mfdb.fund_indicator', true);
  413. chg_columns_for_mysql(tb_fund_risk_stats);
  414. save_table(tb_fund_risk_stats, 'mfdb.fund_risk_stats', true);
  415. chg_columns_for_mysql(tb_fund_riskadjret_stats);
  416. save_table(tb_fund_riskadjret_stats, 'mfdb.fund_riskadjret_stats', true);
  417. chg_columns_for_mysql(tb_fund_style_stats);
  418. save_table(tb_fund_style_stats, 'mfdb.fund_style_stats', true);
  419. } catch(ex) {
  420. //TODO: Log errors
  421. rt = ex;
  422. }
  423. return rt;
  424. }