Browse Source

小修小补

Joey 4 months ago
parent
commit
9f8aad49e3

+ 50 - 4
modules/dataSaver.dos

@@ -95,16 +95,32 @@ def create_entity_nav(is_id_integer=false) {
 
 
 /*
- *   建表 XXXX_fitted_curve
+ *   建公司/经理净值表 XXXX_fitted_curve
  */
-def create_entity_fitted_curve() {
+def create_mc_fitted_curve() {
 
     return table(1000:0, 
                 ['entity_id', 'curve_type', 'strategy', 'end_date', 'cumulative_nav', 'fund_num'],
                 [SYMBOL, INT, INT, STRING, DOUBLE, INT]);
 }
 
+/*
+ *   建公司/经理业绩表 xxx_performance
+ * 
+ */
+def create_mc_performance() {
 
+    return table(1000:0, 
+                ['entity_id', 'curve_type', 'strategy', 'end_date', 'price_date', 'cumulative_nav',
+                 'ret_1m', 'ret_1m_a', 'ret_3m', 'ret_3m_a', 'ret_6m', 'ret_6m_a',
+                 'ret_1y', 'ret_1y_a', 'ret_2y', 'ret_2y_a', 'ret_3y', 'ret_3y_a', 'ret_4y', 'ret_4y_a', 
+                 'ret_5y', 'ret_5y_a', 'ret_10y', 'ret_10y_a', 'ret_ytd', 'ret_ytd_a', 'ret_incep', 'ret_incep_a'],
+                [SYMBOL, INT, INT, MONTH, DATE, DOUBLE,
+                 DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                 DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                 DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+	
+}
 
 /*
  *   建表 XXXX_performance
@@ -322,13 +338,30 @@ def create_entity_index_coe(is_id_integer=false) {
 
 	return table(1000:0,
 	            ['entity_id', 'end_date', 'index_id',
-	             'coe_1y', 'coe_3y', 'coe_5y', 'info_ratio_1y', 'info_ratio_3y', 'info_ratio_5y',
+	             'coe_1y', 'coe_3y', 'coe_5y', //'info_ratio_1y', 'info_ratio_3y', 'info_ratio_5y',
 	             't_value_1y', 't_value_3y', 't_value_5y', 'beta_1y', 'beta_3y', 'beta_5y'],
 	            [iif(is_id_integer, INT, SYMBOL), MONTH, SYMBOL,
-	             DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+	             DOUBLE, DOUBLE, DOUBLE, //DOUBLE, DOUBLE, DOUBLE,
 	             DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
 }
 
+
+/*
+ *   建表 xxx_index_coe
+ * 
+ */
+def create_mc_index_coe(is_id_integer=false) {
+
+	return table(1000:0,
+	            ['entity_id', 'curve_type', 'strategy', 'end_date', 'index_id',
+	             'coe_1y', 'coe_3y', 'coe_5y', //'info_ratio_1y', 'info_ratio_3y', 'info_ratio_5y',
+	             't_value_1y', 't_value_3y', 't_value_5y', 'beta_1y', 'beta_3y', 'beta_5y'],
+	            [SYMBOL, INT, INT, MONTH, SYMBOL,
+	             DOUBLE, DOUBLE, DOUBLE, //DOUBLE, DOUBLE, DOUBLE,
+	             DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+}
+
+
 /*
  *   建表 xxx_factor_bfi_max_r2
  * 
@@ -355,6 +388,19 @@ def create_entity_factor_bfi(is_id_integer=false) {
 }
 
 /*
+ *   建基金经理/公司 bfi连接表 xxx_factor_bfi
+ * 
+ */
+def create_mc_factor_bfi(is_id_integer=false) {
+
+		return table(1000:0,
+	            ['entity_id', 'curve_type', 'strategy', 'end_date', 'factor_id',
+	             'coe', 'r2', 'performance_flag', 't_value_1y', 'beta_1y'],
+	            [SYMBOL, INT, INT, MONTH, SYMBOL,
+	             DOUBLE, DOUBLE, STRING, DOUBLE, DOUBLE]);
+}
+
+/*
  *   建表 XXXX_indicator_ranking
  */
 def create_entity_indicator_ranking(is_id_integer=false) {

+ 86 - 0
modules/indicatorCalculator.dos

@@ -1080,6 +1080,92 @@ def cal_monthly_indicators(entity_type, indicator_type, monthly_returns) {
 
 
 /*
+ *   通用基金经理/公司月度指标计算
+ * 
+ *   @param entity_type <STRING>:
+ *   @param indicator_type <STRING>: PBI, BFI
+ *   @param monthly_returns <TABLE>: NEED COLUMN: entity_id, end_date, price_date, nav, ret
+ * 
+ *   @return <DICT TABLE>: ['PBI-INCEP', 'PBI-YTD', 'PBI-3M', 'PBI-6M', 'PBI-1Y', 'PBI-2Y', 'PBI-3Y', 'PBI-4Y', 'PBI-5Y', 'PBI-10Y']
+ * 
+ */
+def cal_mc_monthly_indicators(entity_type, indicator_type, monthly_returns) {
+
+    if(find(['PL', 'CO'], entity_type) < 0) return null;
+
+    if(monthly_returns.isVoid() || monthly_returns.size() < 1) return null;
+
+    oldest_date = EXEC price_date.min() FROM monthly_returns;
+
+    v_entity_ids = EXEC DISTINCT entity_id FROM monthly_returns;
+
+    if(entity_type == 'PL') {
+	    entity_info = get_personnel_info_for_perf(v_entity_ids);
+	    entity_info.rename!('manager_id', 'entity_id');
+    }
+	 else {
+    	entity_info = get_company_info_for_perf(v_entity_ids);
+    	entity_info.rename!('company_id', 'entity_id');
+	 }
+    	
+    if(entity_info.isVoid() || entity_info.size() == 0) { return null };
+    
+    end_day = today();
+
+    // 取基金和基准的对照表
+    if(indicator_type == 'BFI') {
+
+        benchmark = SELECT DISTINCT entity_id, curve_type, strategy, end_date.temporalParse('yyyy-MM') AS end_date, factor_id AS benchmark_id 
+                    FROM get_mc_bfi_factors(entity_type, v_entity_ids, oldest_date.month(), end_day.month());
+
+    } else {
+        // 主基准, 对应公募混合基金平均 FA00000VNB 
+        benchmark = SELECT DISTINCT entity_id, end_date, iif(benchmark_id.isVoid(), 'FA00000VNB', benchmark_id) AS benchmark_id
+                    FROM ej(entity_info, monthly_returns, ['entity_id', 'curve_type', 'strategy']) ;
+
+    }
+
+    // 取所有出现的基准月收益
+    bmk_ret = get_benchmark_return(benchmark, end_day);
+
+    //if(bmk_ret.isVoid() || bmk_ret.size() == 0) { return null; }
+
+    // TODO: risk free指数月收益存在fund_performance表,所以先将就用 fund_id 表示。之后统一改为更准确的名字
+    risk_free_rate = SELECT entity_id AS fund_id, temporalParse(end_date, 'yyyy-MM') AS end_date, ret FROM get_risk_free_rate(oldest_date, end_day);
+
+    if(risk_free_rate.isVoid() || risk_free_rate.size() == 0) { return null; }
+
+	// 指标计算
+	d_rt = dict(STRING, ANY);
+	v_curve_type = [1, 4, 7];
+	for(cur in v_curve_type) {
+
+		t_ei = SELECT entity_id, inception_date, benchmark_id, ini_value FROM entity_info WHERE curve_type = cur AND strategy = 0;
+		t_mr = SELECT entity_id, end_date, price_date, ret, nav FROM monthly_returns WHERE curve_type = cur AND strategy = 0;
+		
+	    if(indicator_type == 'BFI') {
+	
+	        t0 = cal_trailing_bfi_indicators(t_ei, benchmark, end_day, t_mr, bmk_ret, risk_free_rate);
+	
+	        v_table_name = ['BFI-INCEP', 'BFI-YTD', 'BFI-3M', 'BFI-6M', 'BFI-1Y', 'BFI-2Y', 'BFI-3Y', 'BFI-4Y', 'BFI-5Y', 'BFI-10Y'];
+	
+	    } else {
+	
+	        t0 = cal_trailing_indicators(t_ei, benchmark, end_day, t_mr, bmk_ret, risk_free_rate);
+
+	        v_table_name = ['PBI-INCEP', 'PBI-YTD', 'PBI-3M', 'PBI-6M', 'PBI-1Y', 'PBI-2Y', 'PBI-3Y', 'PBI-4Y', 'PBI-5Y', 'PBI-10Y'];
+	    }
+
+	    d_indicator = dict(v_table_name, t0);
+
+	    d_rt[cur$STRING] = d_indicator; 
+	}
+
+    return d_rt;
+	
+}
+
+/*
  *   【Morningstar Integration】通用月度指标计算
  * 
  *   @param entity_type <STRING>:

+ 259 - 2
modules/operationDataPuller.dos

@@ -170,9 +170,9 @@ def get_cus_fund_info(fund_ids) {
  *           get_factor_info(NULL);
  *  
  */
-def get_factor_info(fund_ids) {
+def get_factor_info(factor_ids) {
 
-    s_entity_ids = ids_to_string(fund_ids);
+    s_entity_ids = ids_to_string(factor_ids);
     
     s_entity_sql = iif(s_entity_ids == NULL || s_entity_ids == '', '', " AND fi.factor_id IN (" + s_entity_ids + ")");
 
@@ -191,9 +191,218 @@ def get_factor_info(fund_ids) {
     return t
 }
 
+/*
+ *  取基金经理有效信息
+ * 
+ *  NOTE: Will return multiple records per company!
+ *  
+ *  Example: get_personnel_info(['PL000000AN', 'PL000001GH']);
+ */
+def get_personnel_info(personnel_ids) {
+
+    s_entity_ids = ids_to_string(personnel_ids);
+    
+    s_entity_sql = iif(s_entity_ids == NULL || s_entity_ids == '', '', " AND pi.personnel_id IN (" + s_entity_ids + ")");
+
+    s_query = "SELECT pi.personnel_id AS manager_id, fi.raise_type, fs.strategy, 
+                      MIN(map.management_start_date) AS inception_date, 
+                      CASE fs.strategy WHEN 1 THEN 'IN00000008'
+                                       WHEN 2 THEN 'IN00000008'
+                                       WHEN 3 THEN 'IN0000008S'
+                                       WHEN 4 THEN 'IN00000008'
+                                       WHEN 5 THEN 'IN00000008'
+                                       WHEN 6 THEN 'IN00000077'
+                                       WHEN 7 THEN 'FA00000VNB'
+                                       WHEN 8 THEN 'FA00000VNB'
+                                       WHEN 101 THEN 'IN00000008'
+                                       WHEN 102 THEN 'FA00000VNB'
+                                       WHEN 103 THEN 'IN00000077'
+                                       WHEN 104 THEN 'IN0000007G'
+                                       WHEN 105 THEN 'IN0000009M'
+                                       ELSE 'IN00000008' END AS benchmark_id, 
+                      1 AS ini_value
+               FROM mfdb.personnel_information pi
+               INNER JOIN mfdb.fund_manager_mapping map ON pi.personnel_id = map.fund_manager_id
+               INNER JOIN mfdb.fund_information fi ON map.fund_id = fi.fund_id
+               INNER JOIN mfdb.fund_strategy fs ON fi.fund_id = fs.fund_id
+               WHERE pi.isvalid = 1 " +
+                 s_entity_sql + "
+                 AND map.isvalid = 1
+                 AND fi.isvalid = 1 
+                 AND fs.isvalid = 1
+                 AND fs.strategy > 0
+               GROUP BY pi.personnel_id, fi.raise_type, fs.strategy
+               ORDER BY pi.personnel_id"
+
+    conn = connect_mysql()
+
+    t = odbc::query(conn, s_query)
+
+    conn.close()
+
+    return t
+}
+
+
+/*
+ *  取基金经理简版信息 (curve_type + 全strategy)
+ * 
+ *  NOTE: 仿照 MySQL 的设定,curve_type: 1-私募, 4-公募, 7-公私募综合; strategy: 0-不分策略
+ *  
+ *  Example: get_personnel_info_for_perf(['PL000000AN', 'PL000001GH']);
+ */
+def get_personnel_info_for_perf(personnel_ids) {
+
+    s_entity_ids = ids_to_string(personnel_ids);
+    
+    s_entity_sql = iif(s_entity_ids == NULL || s_entity_ids == '', '', " AND pi.personnel_id IN (" + s_entity_ids + ")");
+
+    s_query = "SELECT * FROM (
+	    		   SELECT pi.personnel_id AS manager_id,
+	    				  IF(fi.raise_type = 1, 1, 4) AS curve_type,
+	    				  0 AS strategy, 
+	                      MIN(map.management_start_date) AS inception_date, 
+	                      'FA00000VNB' AS benchmark_id, 
+	                      1 AS ini_value
+	               FROM mfdb.personnel_information pi
+	               INNER JOIN mfdb.fund_manager_mapping map ON pi.personnel_id = map.fund_manager_id
+	               INNER JOIN mfdb.fund_information fi ON map.fund_id = fi.fund_id
+	               WHERE pi.isvalid = 1 " +
+	                 s_entity_sql + "
+	                 AND map.isvalid = 1
+	                 AND fi.isvalid = 1 
+	               GROUP BY pi.personnel_id, fi.raise_type
+	               UNION
+	               SELECT pi.personnel_id AS manager_id,
+	    				  7 AS curve_type,
+	    				  0 AS strategy, 
+	                      MIN(map.management_start_date) AS inception_date, 
+	                      'FA00000VNB' AS benchmark_id, 
+	                      1 AS ini_value
+	               FROM mfdb.personnel_information pi
+	               INNER JOIN mfdb.fund_manager_mapping map ON pi.personnel_id = map.fund_manager_id
+	               INNER JOIN mfdb.fund_information fi ON map.fund_id = fi.fund_id
+	               WHERE pi.isvalid = 1 " +
+	                 s_entity_sql + "
+	                 AND map.isvalid = 1
+	                 AND fi.isvalid = 1 
+	               GROUP BY pi.personnel_id) t
+	           ORDER BY manager_id, curve_type, strategy;";
+
+    conn = connect_mysql()
+
+    t = odbc::query(conn, s_query)
+
+    conn.close()
+
+    return t
+}
+
 
 
 /*
+ *  取基金公司简版信息 (curve_type + 全strategy)
+ * 
+ *  NOTE: 仿照 MySQL 的设定,curve_type: 1-私募, 4-公募, 7-公私募综合; strategy: 0-不分策略
+ *  
+ *  Example: get_company_info_for_perf(['CO0001003W', 'CO00000017']);
+ */
+def get_company_info_for_perf(company_ids) {
+
+    s_entity_ids = ids_to_string(company_ids);
+    
+    s_entity_sql = iif(s_entity_ids == NULL || s_entity_ids == '', '', " AND ci.company_id IN (" + s_entity_ids + ")");
+
+    s_query = "SELECT * FROM (
+	    		   SELECT ci.company_id,
+	    				  IF(fi.raise_type = 1, 1, 4) AS curve_type,
+	    				  0 AS strategy, 
+	                      MIN(IFNULL(fi.inception_date, ci.establish_date)) AS inception_date, 
+	                      'FA00000VNB' AS benchmark_id, 
+	                      1 AS ini_value
+	               FROM mfdb.company_information ci
+	               INNER JOIN mfdb.fund_information fi ON ci.company_id = fi.advisor_id
+	               WHERE ci.isvalid = 1 " +
+	                 s_entity_sql + "
+	                 AND fi.isvalid = 1 
+	               GROUP BY ci.company_id, fi.raise_type
+	               UNION
+	               SELECT ci.company_id,
+	    				  7 AS curve_type,
+	    				  0 AS strategy, 
+	                      MIN(IFNULL(fi.inception_date, ci.establish_date)) AS inception_date,
+	                      'FA00000VNB' AS benchmark_id, 
+	                      1 AS ini_value
+	               FROM mfdb.company_information ci
+	               INNER JOIN mfdb.fund_information fi ON ci.company_id = fi.advisor_id
+	               WHERE ci.isvalid = 1 " +
+	                 s_entity_sql + "
+	                 AND fi.isvalid = 1 
+	               GROUP BY ci.company_id) t
+	           ORDER BY company_id, curve_type, strategy;";
+
+    conn = connect_mysql()
+
+    t = odbc::query(conn, s_query)
+
+    conn.close()
+
+    return t
+}
+
+/*
+ *  取基金公司有效信息
+ * 
+ *  NOTE: Will return multiple records per company!
+ *  
+ *  Example: get_company_info(['CO0001003W', 'CO00000017']);
+ * 
+ */
+def get_company_info(company_ids) {
+
+    s_entity_ids = ids_to_string(company_ids);
+    
+    s_entity_sql = iif(s_entity_ids == NULL || s_entity_ids == '', '', " AND ci.company_id IN (" + s_entity_ids + ")");
+
+    s_query = "SELECT ci.company_id, fi.raise_type, 
+                      fs.strategy, 
+                      MIN(IFNULL(fi.inception_date, ci.establish_date)) AS inception_date, 
+                      CASE fs.strategy WHEN 1 THEN 'IN00000008'
+                                       WHEN 2 THEN 'IN00000008'
+                                       WHEN 3 THEN 'IN0000008S'
+                                       WHEN 4 THEN 'IN00000008'
+                                       WHEN 5 THEN 'IN00000008'
+                                       WHEN 6 THEN 'IN00000077'
+                                       WHEN 7 THEN 'FA00000VNB'
+                                       WHEN 8 THEN 'FA00000VNB'
+                                       WHEN 101 THEN 'IN00000008'
+                                       WHEN 102 THEN 'FA00000VNB'
+                                       WHEN 103 THEN 'IN00000077'
+                                       WHEN 104 THEN 'IN0000007G'
+                                       WHEN 105 THEN 'IN0000009M'
+                                       ELSE 'IN00000008' END AS benchmark_id, 
+                      1 AS ini_value
+               FROM mfdb.company_information ci
+               INNER JOIN mfdb.fund_information fi ON ci.company_id = fi.advisor_id
+               INNER JOIN mfdb.fund_strategy fs ON fi.fund_id = fs.fund_id 
+               WHERE ci.isvalid = 1 " +
+                 s_entity_sql + "
+                 AND fi.isvalid = 1
+                 AND fs.isvalid = 1
+                 AND fs.strategy > 0
+               GROUP BY ci.company_id, fi.raise_type, fs.strategy
+               ORDER BY ci.company_id"
+
+    conn = connect_mysql()
+
+    t = odbc::query(conn, s_query)
+
+    conn.close()
+
+    return t
+}
+
+/*
  *   取基金组合基础有效信息
  * 
  *   Example: get_entity_info('HF', ['HF000004KN','HF000103EU','HF00018WXG']);
@@ -230,6 +439,15 @@ def get_entity_info(entity_type, entity_ids) {
 
     	t = get_factor_info(s_entity_ids);
     	t.rename!('factor_id', 'entity_id');
+    } else if(entity_type == 'PL') {
+
+    	t = get_personnel_info(s_entity_ids);
+    	t.rename!('manager_id', 'entity_id');
+    	
+    } else if(entity_type == 'CO') {
+
+    	t = get_company_info(s_entity_ids);
+    	t.rename!('company_id', 'entity_id');    	
     }
 
 	return t;
@@ -375,6 +593,45 @@ def get_entity_bfi_factors(entity_type, entity_ids, month_start, month_end, upda
     return t;
 }
 
+
+/*
+ *  取某时间段的基金经理 BFI基准
+ *
+ * 
+ *  Example: get_mc_bfi_factors('PL', ['PL000000NS', 'PL00000ICF'], 1990.01M, 2024.06M);
+ * 
+ */
+def get_mc_bfi_factors(entity_type, entity_ids, month_start, month_end, updatetime=1990.01.01) {
+
+    tmp = get_bfi_by_category_group_table_description(entity_type);
+
+    s_entity_ids = ids_to_string(entity_ids);
+
+    sql_entity_id = '';
+
+    if(s_entity_ids != NULL) {
+    	sql_entity_id = " AND " + tmp.sec_id_col[0] + " IN (" + s_entity_ids + ")";
+    }
+
+    s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, curve_type, strategy, end_date, factor_id 
+               FROM " + tmp.table_name[0] + "
+               WHERE isvalid = 1 " +
+                 sql_entity_id + "
+                 AND end_date >= '" + month_start.temporalFormat('yyyy-MM') + "'
+                 AND end_date <= '" + month_end.temporalFormat('yyyy-MM') + "'
+                 AND updatetime >= '" + updatetime$STRING + "'
+               ORDER BY " + tmp.sec_id_col[0] + ", end_date, factor_id";
+
+    conn = connect_mysql();
+
+    t = odbc::query(conn, s_query);
+
+    conn.close();
+
+    return t;
+}
+
+
 /*
  *   取基金-经理关系表
  *   

+ 41 - 10
modules/performanceDataPuller.dos

@@ -524,9 +524,9 @@ def get_benchmark_return(benchmarks, end_day) {
     t_index_id = SELECT DISTINCT benchmark_id FROM benchmarks WHERE benchmark_id LIKE 'IN%';;
     s_index_ids = iif(isVoid(t_index_id), "",  "'" + t_index_id.benchmark_id.concat("','") + "'");
 
-   // 前缀为 FA 的 benchmark id
-   t_factor_id = SELECT DISTINCT benchmark_id FROM benchmarks WHERE benchmark_id LIKE 'FA%';
-   s_factor_ids = iif(isVoid(t_factor_id), "",  "'" + t_factor_id.benchmark_id.concat("','") + "'");
+    // 前缀为 FA 的 benchmark id
+    t_factor_id = SELECT DISTINCT benchmark_id FROM benchmarks WHERE benchmark_id LIKE 'FA%';
+    s_factor_ids = iif(isVoid(t_factor_id), "",  "'" + t_factor_id.benchmark_id.concat("','") + "'");
 
 
     // 目前指数的月度业绩存在 fund_performance 表
@@ -961,7 +961,7 @@ def get_fund_bfi_bm_indicator_ranking(fund_ids, end_date, factor_ids, isFromMySQ
  *  取算相关性所需要的指数/因子ID
  * 
  *  NOTE: 与 Java 使用的逻辑相同, 在cm_class_asset_index中有当月performance的指数加上 CSI5 和 Cap3Style 的 factor
- *        唯一的不同是将历史已经停止维护的老指数筛掉(必须有当前月份的指数收益)
+ *        唯一的不同是将历史已经停止维护的老指数筛掉(必须有上月的指数收益)
  *
  *  Example: get_correlation_index_list();
  */
@@ -970,7 +970,7 @@ def get_correlation_index_list() {
     s_query = "SELECT a.fund_id AS entity_id
     		   FROM mfdb.fund_performance AS a
           	   LEFT JOIN pfdb.cm_class_asset_index AS b ON a.fund_id = b.index_id 
-	           WHERE a.end_date = LEFT(CURRENT_DATE, 7)
+	           WHERE a.end_date = LEFT(DATE_SUB(CURRENT_DATE, INTERVAL 1 MONTH), 7)
 	           AND a.fund_id LIKE 'IN%' 
 	           AND b.isvalid = 1 
 	           ORDER BY a.fund_id ASC";
@@ -1111,7 +1111,6 @@ def get_company_list_by_fund_updatetime(updatetime, isFromMySQL=true) {
  */
 def get_manager_list_by_fund_updatetime(updatetime, isFromMySQL=true) {
 
-
     if(isFromMySQL == true) {
 
         s_query = "SELECT mi.personnel_id AS manager_id, MIN(fp.end_date) AS end_date
@@ -1126,16 +1125,48 @@ def get_manager_list_by_fund_updatetime(updatetime, isFromMySQL=true) {
                      AND fp.end_date <= DATE_FORMAT(IFNULL(fmp.management_end_date, CURRENT_DATE), '%y-%m')
                    GROUP BY mi.personnel_id;";
      
-        conn = connect_mysql()
+        conn = connect_mysql();
      
-        t = odbc::query(conn, s_query)
+        t = odbc::query(conn, s_query);
      
-        conn.close()
+        conn.close();
 
     } else {
         
     
     }
 
-    return t
+    return t;
+}
+
+/*
+ *   取基金经理/公司月度业绩表更新的收益日期
+ * 
+ *   Example: get_mc_performance_by_updatetime('PL', 2024.11.01, true);
+ *   		  get_mc_performance_by_updatetime('CO', 2024.11.01, true);
+ */
+def get_mc_performance_by_updatetime(entity_type, updatetime, isFromMySQL=true) {
+
+	des = get_performance_table_description(entity_type)[0];
+
+    if(isFromMySQL == true) {
+
+        s_query = "SELECT " + des.sec_id_col + " AS entity_id, curve_type, strategy, MIN(fp.end_date) AS end_date, MIN(fp.price_date) AS price_date
+                   FROM " + des.table_name + " fp
+                   WHERE fp.isvalid = 1
+                     AND fp.updatetime >= '" + updatetime + "'
+                   GROUP BY fp. " + des.sec_id_col + ", curve_type, strategy
+                   ORDER BY fp." + des.sec_id_col + ", curve_type, strategy;";
+     
+        conn = connect_mysql();
+     
+        t = odbc::query(conn, s_query);
+     
+        conn.close();
+
+    } else {
+    
+    }
+
+    return t;
 }

+ 3 - 3
modules/sqlUtilities.dos

@@ -337,9 +337,9 @@ def get_bfi_by_category_group_table_description(entity_type) {
 
     // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合, 经理
     INSERT INTO tmp_universe VALUES ( 
-        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'MG'],
-        ['pfdb.pf_fund_factor_bfi_by_category_group', 'pfdb.pf_fund_factor_bfi_by_category_group', NULL, NULL, NULL, NULL, NULL, 'pfdb.pf_portfolio_factor_bfi_by_category_group', 'pf_manager_factor_bfi_by_category_group'],
-        ['fund_id', 'fund_id', NULL, NULL, NULL, NULL, NULL, 'portfolio_id', 'mamanger_id'] );
+        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL'],
+        ['pfdb.pf_fund_factor_bfi_by_category_group', 'pfdb.pf_fund_factor_bfi_by_category_group', NULL, NULL, NULL, NULL, NULL, 'pfdb.pf_portfolio_factor_bfi_by_category_group', 'pfdb.pf_manager_factor_bfi_by_category_group'],
+        ['fund_id', 'fund_id', NULL, NULL, NULL, NULL, NULL, 'portfolio_id', 'manager_id'] );
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
 }