Browse Source

小修小补

Joey 4 months ago
parent
commit
9c2d477e2b
2 changed files with 49 additions and 12 deletions
  1. 39 3
      modules/operationDataPuller.dos
  2. 10 9
      modules/returnCalculator.dos

+ 39 - 3
modules/operationDataPuller.dos

@@ -133,7 +133,7 @@ def get_portfolio_info(portfolio_ids) {
 }
 
 /*
- *  取组合有效信息
+ *  取私有基金有效信息
  * 
  *  Example: get_cus_fund_info(['CF0000005V','CF000000CE']);
  *           get_cus_fund_info(NULL);
@@ -164,6 +164,36 @@ def get_cus_fund_info(fund_ids) {
 }
 
 /*
+ *  取因子有效信息
+ * 
+ *  Example: get_factor_info(['FA00000VNB','FA00000VMJ']);
+ *           get_factor_info(NULL);
+ *  
+ */
+def get_factor_info(fund_ids) {
+
+    s_entity_ids = ids_to_string(fund_ids);
+    
+    s_entity_sql = iif(s_entity_ids == NULL || s_entity_ids == '', '', " AND fi.factor_id IN (" + s_entity_ids + ")");
+
+    s_query = "SELECT fi.factor_id, fi.factor_type, fi.inception_date, NULL AS benchmark_id, IFNULL(initial_value, 1) AS ini_value
+               FROM pfdb.cm_factor_information fi
+               WHERE fi.isvalid = 1 " +
+                 s_entity_sql + "
+               ORDER BY fi.factor_id"
+
+    conn = connect_mysql()
+
+    t = odbc::query(conn, s_query)
+
+    conn.close()
+
+    return t
+}
+
+
+
+/*
  *   取基金组合基础有效信息
  * 
  *   Example: get_entity_info('HF', ['HF000004KN','HF000103EU','HF00018WXG']);
@@ -195,6 +225,11 @@ def get_entity_info(entity_type, entity_ids) {
 
     	t = get_cus_fund_info(s_entity_ids);
     	t.rename!('fund_id', 'entity_id');
+
+    } else if(entity_type == 'FA') {
+
+    	t = get_factor_info(s_entity_ids);
+    	t.rename!('factor_id', 'entity_id');
     }
 
 	return t;
@@ -267,6 +302,7 @@ def get_portfolio_primary_benchmark(portfolio_ids, month_start, month_end) {
  *  Example: get_entity_primary_benchmark('MF', "'MF00003PW2', 'MF00003PW1', 'MF00003PXO'", '1990-01', '2024-06');
  *           get_entity_primary_benchmark('PF', [166002,166114], '1990-01', '2024-08');
  *           get_entity_primary_benchmark('MI', ['IN00000008', 'IN0000000M'], '2024-07', '2024-08');
+ *           get_entity_primary_benchmark('FA', ['FA00000VNB', 'FA00000VMJ'], '2024-01', '2024-08');
  */
 def get_entity_primary_benchmark(entity_type, entity_ids, month_start, month_end) {
 
@@ -291,8 +327,8 @@ def get_entity_primary_benchmark(entity_type, entity_ids, month_start, month_end
         t.rename!('portfolio_id', 'entity_id');
 
     } else if(entity_type IN ['MI', 'FI', 'FA', 'CI', 'EQ']) {
-        // 对于指数、因子来说,没有什么基准。但为了指标计算不得不在这里设个假的
-    	t = SELECT entity_id, end_date, 'IN00000008' AS benchmark_id
+
+    	t = SELECT entity_id, end_date, NULL AS benchmark_id
     	    FROM cj(get_entity_info(entity_type, s_entity_ids), table(temporalParse(month_start, 'yyyy-MM')..temporalParse(month_end, 'yyyy-MM') AS end_date))
     	    WHERE end_date >= iif(inception_date.isNull(), 1990.01M, inception_date.month())
     }

+ 10 - 9
modules/returnCalculator.dos

@@ -7,8 +7,8 @@ use fundit::performanceDataPuller
 /*
  *  通用月收益计算
  * 
- *  @param entity_info <TABLE>: COLUMN NEED entity_id, price_date, inception_date, ini_value
- *  @param nav <TABLE>: COLUMN NEED entity_id, price_date, cumulative_nav
+ *  @param entity_info <TABLE>: [COLUMNS] entity_id, price_date, inception_date, ini_value
+ *  @param nav <TABLE>: [COLUMNS] entity_id, price_date, cumulative_nav
  * 
  */
 def cal_monthly_returns_by_nav(entity_info, mutable nav) {
@@ -183,7 +183,7 @@ def cal_weekly_returns(entity_type, entity_info){
 
     tb_rets_1w = null;
 
-    if(!(entity_type IN ['HF', 'MF', 'PF', 'MI', 'FI'])) return tb_rets_1w;
+    if(!(entity_type IN ['HF', 'MF', 'PF', 'MI', 'FI', 'FA'])) return tb_rets_1w;
     
     // 将每支证券ID+某个日期转为JSON用于调用sp
     s_json = (SELECT entity_id AS sec_id, price_date FROM entity_info).toStdJson();
@@ -192,8 +192,9 @@ def cal_weekly_returns(entity_type, entity_info){
      tb_nav = get_nav_for_return_calculation(entity_type, 'w', s_json);
      tb_nav.rename!('sec_id', 'entity_id');
 
-    UPDATE tb_nav SET year_week = price_date.year()$STRING + (price_date.weekOfYear()$STRING).lpad(2, "0");
-    
+    UPDATE tb_nav  // 当12月31日是周四、五、六时,该周为第52周,所以次年前几天有可能是上一年的第52,53周
+    SET year_week = iif(price_date.weekOfYear() >= 52 && price_date.monthOfYear() == 1, price_date.year()-1, price_date.year())$STRING + (price_date.weekOfYear()$STRING).lpad(2, "0");
+
     tb_weekly_nav = SELECT entity_id, year_week, price_date.last() AS price_date, cumulative_nav.last() AS cumulative_nav
                     FROM tb_nav n
                     INNER JOIN entity_info ei ON n.entity_id = ei.entity_id
@@ -391,10 +392,10 @@ def cal_latest_performance(entity_type, entity_info, isFromMySQL) {
                FROM tb_last_nav a
                INNER JOIN entity_info fi ON a.entity_id = fi.entity_id
     
-    // annulized since reception return
-    UPDATE tb_incep SET ret_incep_a = (1 + ret_incep).pow(365.25\(price_date-inception_date)) - 1
+    // annulized since reception return following GIPS rule
+    UPDATE tb_incep SET ret_incep_a = iif((price_date-inception_date)<=365, ret_incep, (1 + ret_incep).pow(365.25\(price_date-inception_date)) - 1)
     UPDATE tb_incep SET ret_incep_a_all = ret_incep_a,
-                        ret_incep_a_gips = iif((price_date-inception_date)<365, ret_incep, ret_incep_a)
+                        ret_incep_a_gips = ret_incep_a
 
     // 最大回撤
     tb_drawdown_1m = SELECT a.entity_id, max( 1 - b.cumulative_nav \ b.cumulative_nav.cummax() ) AS drawdown_1m
@@ -424,7 +425,7 @@ def cal_latest_performance(entity_type, entity_info, isFromMySQL) {
                      ytd.ret_ytd, incep.ret_incep, incep.ret_incep_a, incep.ret_incep_a_all, incep.ret_incep_a_gips,
                      dd_m1.drawdown_1m AS maxdrawdown_1m, dd_m3.drawdown_3m AS maxdrawdown_3m, dd_y1.drawdown_1y AS maxdrawdown_1y,
                      dd_incep.drawdown_incep AS maxdrawdown_incep,
-                     iif(dd_incep.drawdown_incep == 0, null,incep.ret_incep_a \ dd_incep.drawdown_incep) AS calmarratio_incep
+                     iif(dd_incep.drawdown_incep.round(4) == 0 || incep.ret_incep_a > 1000, NULL, incep.ret_incep_a \ dd_incep.drawdown_incep) AS calmarratio_incep
               FROM tb_last_return a
               LEFT JOIN tb_1d d1 ON a.entity_id = d1.entity_id
               LEFT JOIN tb_1w w1 ON a.entity_id = w1.entity_id