Joey 1 týždeň pred
rodič
commit
5ac918d776
1 zmenil súbory, kde vykonal 80 pridanie a 20 odobranie
  1. 80 20
      modules/indicatorCalculator.dos

+ 80 - 20
modules/indicatorCalculator.dos

@@ -30,17 +30,22 @@ def get_annulization_multiple(freq) {
  *     @param ret: 收益表,需要有 entity_id, price_dat, end_date, nav 
  *     @param freq: 数据频率,d, w, m, q, s, a
  *     
+ *     NOTE: standard deviation of Java version is noncompliant-GIPS annulized number
+ *     
  *     Create:  20240904                                                                     Joey
  *                       TODO: var and cvar are silightly off compared with Java version
  *     
  */
-def cal_basic_performance(ret) {
+def cal_basic_performance(ret, freq) {
 
     t =	SELECT entity_id, max(end_date) AS end_date, max(price_date) AS price_date, min(price_date) AS min_date,
-	           (nav.last() \ nav.first() - 1).round(6) AS trailing_ret,
+	           //(nav.last() \ nav.first() - 1).round(6) AS trailing_ret,
+	           ((1+ret).prod()-1).round(6) AS trailing_ret,
 	           iif(price_date.max().month()-price_date.min().month()>12,
-	               (nav.last() \ nav.first()).pow(365 \(max(price_date) - min(price_date)))-1, 
-	               (nav.last() \ nav.first() - 1)).round(6) AS trailing_ret_a,
+	               //(nav.last() \ nav.first()).pow(365 \(max(price_date) - min(price_date)))-1, 
+	               //(nav.last() \ nav.first() - 1)).round(6) AS trailing_ret_a,
+                   ((1+ret).prod()-1) * sqrt(get_annulization_multiple(freq)),
+	               ((1+ret).prod()-1)).round(6) AS trailing_ret_a,
                ret.std() AS std_dev,
                ret.skew(false) AS skewness,
                ret.kurtosis(false) - 3 AS kurtosis,
@@ -112,7 +117,7 @@ def cal_omega_sortino_kappa(ret, risk_free_rate) {
 
 /*
  *   Alpha & Beta
- *   
+ *   NOTE: alpha of Java version is noncompliant-GIPS annulized number
  */
 def cal_alpha_beta(ret, bmk_ret, risk_free) {
 
@@ -158,6 +163,7 @@ def cal_benchmark_tracking(ret, bmk_ret) {
 
 /*
  *    Sharpe Ratio
+ *    NOTE: Java version is noncompliant-GIPS annulized number
  */
 def cal_sharpe(ret, std_dev, risk_free_rate) {
 
@@ -165,6 +171,7 @@ def cal_sharpe(ret, std_dev, risk_free_rate) {
              FROM ret t
              INNER JOIN std_dev std ON t.entity_id = std.entity_id
              INNER JOIN risk_free_rate rfr ON t.end_date = rfr.end_date
+             WHERE std.std_dev[0] <> 0
              GROUP BY t.entity_id;
 
     return sharpe;
@@ -222,6 +229,7 @@ def cal_calmar(ret_a){
 /*
  *     Modigliani Modigliani Measure (M2)
  *     NOTE: M2 = sharpe * std(benchmark) + risk_free_rate
+ *     NOTE: Java version is noncompliant-GIPS annulized number 
  */
 def cal_m2(ret, bmk_ret, risk_free_rate) {
 
@@ -237,10 +245,11 @@ def cal_m2(ret, bmk_ret, risk_free_rate) {
 
 /*
  *   Monthly Since_inception_date Indicator Calculation
- *   @param: ret: historical return table
- *           index_ret: historical benchmark return table
- *           risk_free: historical risk free rate table
- *
+ *   @param: ret <TABLE>: 收益表,NEED COLUMNS entity_id, price_dat, end_date, nav 
+ *   @param index_ret <TABLE>: historical benchmark return table, NEED COLUMNS fund_id, end_date, ret
+ *   @param risk_free <TABLE>: historical risk free rate table, NEED COLUMNS fund_id, end_date, ret
+ *   @param freq <CHAR>: 数据频率,d, w, m, q, s, a
+ *   
  *   @return: indicators table
  *   
  *   
@@ -256,7 +265,7 @@ def cal_indicators(mutable ret, index_ret, risk_free, freq) {
     ret.sortBy!(['entity_id', 'price_date'], [1, 1]);
 
     // 收益、标准差、偏度、峰度、最大回撤、VaR, CVaR
-    rtn = cal_basic_performance(ret);
+    rtn = cal_basic_performance(ret, freq);
 
     // alpha, beta
     alpha_beta = cal_alpha_beta(ret, index_ret, risk_free);
@@ -297,20 +306,71 @@ def cal_indicators(mutable ret, index_ret, risk_free, freq) {
     plainAnnu = get_annulization_multiple(freq);
     sqrtAnnu = sqrt(get_annulization_multiple(freq));
 
-    r.addColumn(['ds_dev_a', 'alpha_a', 'sharpe_a', 'sortino_a', 'jensen_a', 'track_error_a', 'info_a', 'm2_a'], [DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+    r.addColumn(['std_dev_a', 'ds_dev_a', 'alpha_a', 'sharpe_a', 'sortino_a', 'jensen_a', 'track_error_a', 'info_a', 'm2_a'],
+                [DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
 
     UPDATE r 
-      SET ds_dev_a = ds_dev * sqrtAnnu,
-          alpha_a = alpha * plainAnnu,
-          sharpe_a = sharpe * sqrtAnnu,
-          sortino_a = sortino * sqrtAnnu,
-          jensen_a = jensen * plainAnnu,
-          track_error_a = track_error * sqrtAnnu,
-          info_a = info * sqrtAnnu,
-          m2_a = m2 * plainAnnu
-    WHERE price_date.month() - min_date.month() >= 12;
+      SET std_dev_a = std_dev * iif(price_date.month() - min_date.month() >= 11, sqrtAnnu, 1),
+          ds_dev_a = ds_dev * iif(price_date.month() - min_date.month() >= 11, sqrtAnnu, 1),
+          alpha_a = alpha * iif(price_date.month() - min_date.month() >= 11, plainAnnu, 1),
+          sharpe_a = sharpe * iif(price_date.month() - min_date.month() >= 11, sqrtAnnu, 1),
+          sortino_a = sortino * iif(price_date.month() - min_date.month() >= 11, sqrtAnnu, 1),
+          jensen_a = jensen * iif(price_date.month() - min_date.month() >= 11, plainAnnu, 1),
+          track_error_a = track_error * iif(price_date.month() - min_date.month() >= 11, sqrtAnnu, 1),
+          info_a = info * iif(price_date.month() - min_date.month() >= 11, sqrtAnnu, 1),
+          m2_a = m2 * iif(price_date.month() - min_date.month() >= 11, plainAnnu, 1);
     
     return r;
 }
 
+/*
+ *   Calculate trailing 6m, ytd, 1y, 2y, 3y, 4y, 5y, 10y and since inception indicators
+ *   
+ *   @param: ret <TABLE>: 收益表,NEED COLUMNS entity_id, price_dat, end_date, nav 
+ *   @param: end_day <DATE>: 计算截止日期
+ *   @param index_ret <TABLE>: historical benchmark return table, NEED COLUMNS fund_id, end_date, ret
+ *   @param risk_free <TABLE>: historical risk free rate table, NEED COLUMNS fund_id, end_date, ret
+ *   @param freq <CHAR>: 数据频率,d, w, m, q, s, a
+
+ * 
+ */
+def cal_all_trailing_indicators(mutable tb_ret, end_day, bmk_ret, risk_free_rate, freq) {
+    
+    // since inception
+    r_incep = cal_indicators(tb_ret, bmk_ret, risk_free_rate, 'm');
+    
+    // ytd
+    tb_ret_ytd = SELECT * FROM tb_ret WHERE end_date >= end_day.yearBegin().month();
+    r_ytd = cal_indicators(tb_ret_ytd, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 6m
+    tb_ret_6m = SELECT * FROM tb_ret WHERE end_date > end_day.month()-6;
+    r_6m = cal_indicators(tb_ret_6m, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 1y
+    tb_ret_1y = SELECT * FROM tb_ret WHERE end_date > end_day.month()-12;
+    r_1y = cal_indicators(tb_ret_1y, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 2y
+    tb_ret_2y = SELECT * FROM tb_ret WHERE end_date > end_day.month()-24;
+    r_2y = cal_indicators(tb_ret_2y, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 3y
+    tb_ret_3y = SELECT * FROM tb_ret WHERE end_date > end_day.month()-36;
+    r_3y = cal_indicators(tb_ret_3y, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 4y
+    tb_ret_4y = SELECT * FROM tb_ret WHERE end_date > end_day.month()-48;
+    r_4y = cal_indicators(tb_ret_4y, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 5y
+    tb_ret_5y = SELECT * FROM tb_ret WHERE end_date > end_day.month()-60;
+    r_5y = cal_indicators(tb_ret_5y, bmk_ret, risk_free_rate, 'm');
+    
+    // trailing 10y
+    tb_ret_10y = SELECT * FROM tb_ret WHERE end_date > end_day.month()-120;
+    r_10y = cal_indicators(tb_ret_10y, bmk_ret, risk_free_rate, 'm');
+
+    return r_incep, r_ytd, r_6m, r_1y, r_2y, r_3y, r_4y, r_5y, r_10y;
+}