Browse Source

小修小补

Joey 4 months ago
parent
commit
1d4ceb439d

+ 367 - 232
modules/dataSaver.dos

@@ -166,6 +166,35 @@ def create_entity_indicator(is_id_integer=false) {
                 DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
 }
 
+
+/*
+ *   建公司/经理表 XXX_indicator
+ */
+def create_mc_indicator() {
+
+    return table(1000:0,
+               ['entity_id', 'curve_type', 'strategy', 'end_date',
+                'info_ratio_6m', 'm2_6m', 'tracking_error_6m',
+                'info_ratio_1y', 'm2_1y', 'tracking_error_1y',
+                'info_ratio_2y', 'm2_2y', 'tracking_error_2y', 'var_2y', 'cvar_2y', 
+                'info_ratio_3y', 'm2_3y', 'tracking_error_3y', 'var_3y', 'cvar_3y', 
+                'info_ratio_4y', 'm2_4y', 'tracking_error_4y', 'var_4y', 'cvar_4y', 
+                'info_ratio_5y', 'm2_5y', 'tracking_error_5y', 'var_5y', 'cvar_5y', 
+                'info_ratio_10y', 'm2_10y', 'tracking_error_10y', 'var_10y', 'cvar_10y', 
+                'info_ratio_ytd', 'm2_ytd', 'tracking_error_ytd', 
+                'info_ratio_incep', 'm2_incep','tracking_error_incep', 'var_incep', 'cvar_incep'],
+               [SYMBOL, INT, INT, MONTH,
+                DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+}
+
 /*
  *   建表 XXX_risk_stats
  *   
@@ -197,6 +226,37 @@ def create_entity_risk_stats(is_id_integer=false) {
 
 }
 
+
+/*
+ *   建基金经理/公司表 XXX_risk_stats
+ *   
+ */
+def create_mc_risk_stats() {
+
+    return table(1000:0,
+               ['entity_id', 'curve_type', 'strategy', 'end_date',
+                'stddev_6m', 'downsidedev_6m', 'alpha_6m', 'winrate_6m', 'beta_6m', 'skewness_6m', 'kurtosis_6m', 'worstmonth_6m', 'maxdrawdown_6m', 
+                'stddev_1y', 'downsidedev_1y', 'alpha_1y', 'winrate_1y', 'beta_1y', 'skewness_1y', 'kurtosis_1y', 'worstmonth_1y', 'maxdrawdown_1y', 
+                'stddev_2y', 'downsidedev_2y', 'alpha_2y', 'winrate_2y', 'beta_2y', 'skewness_2y', 'kurtosis_2y', 'worstmonth_2y', 'maxdrawdown_2y', 
+                'stddev_3y', 'downsidedev_3y', 'alpha_3y', 'winrate_3y', 'beta_3y', 'skewness_3y', 'kurtosis_3y', 'worstmonth_3y', 'maxdrawdown_3y', 
+                'stddev_4y', 'downsidedev_4y', 'alpha_4y', 'winrate_4y', 'beta_4y', 'skewness_4y', 'kurtosis_4y', 'worstmonth_4y', 'maxdrawdown_4y', 
+                'stddev_5y', 'downsidedev_5y', 'alpha_5y', 'winrate_5y', 'beta_5y', 'skewness_5y', 'kurtosis_5y', 'worstmonth_5y', 'maxdrawdown_5y', 
+                'stddev_10y', 'downsidedev_10y','alpha_10y', 'winrate_10y', 'beta_10y', 'skewness_10y', 'kurtosis_10y', 'worstmonth_10y', 'maxdrawdown_10y', 
+                'stddev_ytd', 'downsidedev_ytd', 'alpha_ytd', 'winrate_ytd', 'beta_ytd', 'skewness_ytd', 'kurtosis_ytd', 'worstmonth_ytd', 'maxdrawdown_ytd', 
+                'stddev_incep', 'downsidedev_incep', 'alpha_incep', 'winrate_incep', 'beta_incep', 'skewness_incep', 'kurtosis_incep', 'worstmonth_incep', 'maxdrawdown_incep'],
+               [SYMBOL, INT, INT, MONTH,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+
+}
+
 /*
  *   建表 XXX_riskadjret_stats
  */
@@ -225,6 +285,36 @@ def create_entity_riskadjret_stats(is_id_integer=false) {
                 DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
 }
 
+
+/*
+ *   建基金经理/公司表 XXX_riskadjret_stats
+ */
+def create_mc_riskadjret_stats() {
+
+    return table(1000:0,
+               ['entity_id', 'curve_type', 'strategy', 'end_date',
+                'sharperatio_6m', 'sortinoratio_6m', 'treynorratio_6m', 'jensen_6m', 'calmarratio_6m', 'omegaratio_6m', 'kapparatio_6m',
+                'sharperatio_1y', 'sortinoratio_1y', 'treynorratio_1y', 'jensen_1y', 'calmarratio_1y', 'omegaratio_1y', 'kapparatio_1y',
+                'sharperatio_2y', 'sortinoratio_2y', 'treynorratio_2y', 'jensen_2y', 'calmarratio_2y', 'omegaratio_2y', 'kapparatio_2y',
+                'sharperatio_3y', 'sortinoratio_3y', 'treynorratio_3y', 'jensen_3y', 'calmarratio_3y', 'omegaratio_3y', 'kapparatio_3y',
+                'sharperatio_4y', 'sortinoratio_4y', 'treynorratio_4y', 'jensen_4y', 'calmarratio_4y', 'omegaratio_4y', 'kapparatio_4y',
+                'sharperatio_5y', 'sortinoratio_5y', 'treynorratio_5y', 'jensen_5y', 'calmarratio_5y', 'omegaratio_5y', 'kapparatio_5y',
+                'sharperatio_10y', 'sortinoratio_10y', 'treynorratio_10y', 'jensen_10y', 'calmarratio_10y', 'omegaratio_10y', 'kapparatio_10y',
+                'sharperatio_ytd', 'sortinoratio_ytd', 'treynorratio_ytd', 'jensen_ytd', 'calmarratio_ytd', 'omegaratio_ytd', 'kapparatio_ytd',
+                'sharperatio_incep', 'sortinoratio_incep', 'treynorratio_incep', 'jensen_incep', 'calmarratio_incep', 'omegaratio_incep', 'kapparatio_incep'],
+               [SYMBOL, INT, INT, MONTH,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+}
+
+
 /*
  *   建表 XXX_style_stats
  */
@@ -253,6 +343,35 @@ def create_entity_style_stats(is_id_integer=false) {
                 DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
 }
 
+
+/*
+ *   建基金经理/公司表 XXX_style_stats
+ */
+def create_mc_style_stats() {
+
+    return table(1000:0,
+               ['entity_id', 'curve_type', 'strategy', 'end_date',
+                'upsidecapture_ret_6m', 'downsidecapture_ret_6m', 'upsidecapture_ratio_6m', 'downsidecapture_ratio_6m',
+                'upsidecapture_ret_1y', 'downsidecapture_ret_1y', 'upsidecapture_ratio_1y', 'downsidecapture_ratio_1y',
+                'upsidecapture_ret_2y', 'downsidecapture_ret_2y', 'upsidecapture_ratio_2y', 'downsidecapture_ratio_2y',
+                'upsidecapture_ret_3y', 'downsidecapture_ret_3y', 'upsidecapture_ratio_3y', 'downsidecapture_ratio_3y',
+                'upsidecapture_ret_4y', 'downsidecapture_ret_4y', 'upsidecapture_ratio_4y', 'downsidecapture_ratio_4y',
+                'upsidecapture_ret_5y', 'downsidecapture_ret_5y', 'upsidecapture_ratio_5y', 'downsidecapture_ratio_5y',
+                'upsidecapture_ret_10y', 'downsidecapture_ret_10y', 'upsidecapture_ratio_10y', 'downsidecapture_ratio_10y',
+                'upsidecapture_ret_ytd', 'downsidecapture_ret_ytd', 'upsidecapture_ratio_ytd', 'downsidecapture_ratio_ytd',
+                'upsidecapture_ret_incep', 'downsidecapture_ret_incep', 'upsidecapture_ratio_incep', 'downsidecapture_ratio_incep'],
+               [SYMBOL, INT, INT, MONTH,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+                DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+}
+
 /*
  *   建表 XXX_bfi_bm_indicator
  */
@@ -301,6 +420,52 @@ def create_entity_bfi_indicator(is_id_integer=false) {
 
 
 /*
+ *   建基金经理/公司表 XXX_bfi_bm_indicator
+ */
+def create_mc_bfi_indicator() {
+
+	return table(1000:0,
+			   ['entity_id', 'curve_type', 'strategy', 'end_date', 'factor_id',
+                'upsidecapture_ret_6m', 'downsidecapture_ret_6m', 'upsidecapture_ratio_6m', 'downsidecapture_ratio_6m',
+                'alpha_6m', 'winrate_6m', 'beta_6m', 'info_ratio_6m', 'tracking_error_6m', 'jensen_6m',
+                'upsidecapture_ret_1y', 'downsidecapture_ret_1y', 'upsidecapture_ratio_1y', 'downsidecapture_ratio_1y',
+                'alpha_1y', 'winrate_1y', 'beta_1y', 'info_ratio_1y', 'tracking_error_1y', 'jensen_1y',
+                'upsidecapture_ret_2y', 'downsidecapture_ret_2y', 'upsidecapture_ratio_2y', 'downsidecapture_ratio_2y',
+                'alpha_2y', 'winrate_2y', 'beta_2y', 'info_ratio_2y', 'tracking_error_2y', 'jensen_2y',
+                'upsidecapture_ret_3y', 'downsidecapture_ret_3y', 'upsidecapture_ratio_3y', 'downsidecapture_ratio_3y',
+                'alpha_3y', 'winrate_3y', 'beta_3y', 'info_ratio_3y', 'tracking_error_3y', 'jensen_3y',
+                'upsidecapture_ret_4y', 'downsidecapture_ret_4y', 'upsidecapture_ratio_4y', 'downsidecapture_ratio_4y',
+                'alpha_4y', 'winrate_4y', 'beta_4y', 'info_ratio_4y', 'tracking_error_4y', 'jensen_4y',
+                'upsidecapture_ret_5y', 'downsidecapture_ret_5y', 'upsidecapture_ratio_5y', 'downsidecapture_ratio_5y',
+                'alpha_5y', 'winrate_5y', 'beta_5y', 'info_ratio_5y', 'tracking_error_5y', 'jensen_5y',
+                'upsidecapture_ret_10y', 'downsidecapture_ret_10y', 'upsidecapture_ratio_10y', 'downsidecapture_ratio_10y',
+                'alpha_10y', 'winrate_10y', 'beta_10y', 'info_ratio_10y', 'tracking_error_10y', 'jensen_10y',
+                'upsidecapture_ret_ytd', 'downsidecapture_ret_ytd', 'upsidecapture_ratio_ytd', 'downsidecapture_ratio_ytd',
+                'alpha_ytd', 'winrate_ytd', 'beta_ytd', 'info_ratio_ytd', 'tracking_error_ytd', 'jensen_ytd',
+                'upsidecapture_ret_incep', 'downsidecapture_ret_incep', 'upsidecapture_ratio_incep', 'downsidecapture_ratio_incep',
+                'alpha_incep', 'winrate_incep', 'beta_incep', 'info_ratio_incep', 'tracking_error_incep', 'jensen_incep'],
+			   [SYMBOL, INT, INT, MONTH, SYMBOL,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE,
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, 
+				DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE] );
+}
+
+/*
  *  建表 xxx_performance_weekly
  */
 def create_entity_performance_weekly(is_id_integer=false) {
@@ -479,61 +644,53 @@ def chg_columns_for_mysql(mutable tb_mysql, id_col_name) {
     tb_mysql.replaceColumn!('end_date', v_end_date);
 }
 
-
 /*
  *   按照 XXX_performance 表结构准备数据记录
  * 
+ *   @param entity_info <TABLE>: [COLUMNS] entity_id, end_date (用于筛掉不必要的老记录), [curve_type, strategy]
+ *   @param indicators <DICT>: 指标类型-区间:数据表
+ *   @param entity_performance <TABLE>: 被更新的数据表
+ *   @param extra_keys <VECTOR>: 只有基金经理和公司会用到,对应 [curve_type, strategy]
  * 
+ *   TODO: price_date is NULL for some records
  */
-def generate_entity_performance(entity_info, indicators, isToMySQL, mutable entity_performance) {
+def generate_entity_performance(entity_info, indicators, isToMySQL, mutable entity_performance, extra_keys=[]) {
 
     t = null;
 
+    if(extra_keys.isNothing() || extra_keys.isVoid()) v_extra_keys = array(STRING);
+    else v_extra_keys = extra_keys;
+
     if(isToMySQL) {
 
        if(indicators['PBI-3M'].isVoid() || indicators['PBI-3M'].size() == 0) return;
 
-        t = SELECT entity_id AS 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
-            FROM indicators['PBI-3M'] AS ind
-            INNER JOIN entity_info fi ON ind.entity_id = fi.entity_id
-            WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
-        
-        UPDATE t
-        SET ret_6m = trailing_ret, ret_6m_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-6M'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_1y = trailing_ret, ret_1y_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_2y = trailing_ret, ret_2y_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_3y = trailing_ret, ret_3y_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_4y = trailing_ret, ret_4y_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_5y = trailing_ret, ret_5y_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_10y = trailing_ret, ret_10y_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET ret_ytd = trailing_ret, ret_ytd_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
-        
-        // 取消了 ret_incep_a_all (没意义) 和 ret_incep_a_gips (ret_incep_a 与之相等)
-        UPDATE t
-        SET ret_incep = trailing_ret, ret_incep_a = trailing_ret_a
-        FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
+        t = sql(select =(sqlCol('entity_id'),
+         				 sqlCol(extra_keys.join('end_date')),
+        				 sqlCol('price_date'), 
+                         sqlCol(['nav', 'ret', 'ret', 'trailing_ret', 'trailing_ret_a'], , ['cumulative_nav', 'ret_1m', 'ret_1m_a', 'ret_3m', 'ret_3m_a'])
+                        ),
+        		from = ej(indicators['PBI-3M'] AS a, entity_info AS fi, ['entity_id'].join(v_extra_keys)),
+        		where = < end_date >= fi_price_date.month()> // 过滤掉不必更新的旧记录, 这里用系统字段的别名 fi_price_date 有点脏,但目前没办法
+        	   ).eval();
+        	
+
+        v_trailing = ['6m', '1y', '2y', '3y', '4y', '5y', '10y', 'ytd', 'incep'];
+        for(tr in v_trailing) {
+
+			col_name = 'ret_' + tr;
+			col_a_name = 'ret_' + tr + '_a';
+
+			t.addColumn([col_name, col_a_name], [DOUBLE, DOUBLE]);
+
+			if(!indicators['PBI-'+tr.upper()].isVoid()) {
+
+				sqlUpdate(table = t,
+				          updates = [<trailing_ret as _$col_name>, <trailing_ret_a as _$col_a_name>],
+				          from = <ej(t, indicators['PBI-'+tr.upper()], ['entity_id'].join(v_extra_keys).join(['end_date']))>
+						 ).eval();
+			}
+	    }
 
         INSERT INTO entity_performance SELECT * FROM t;
 
@@ -542,64 +699,59 @@ def generate_entity_performance(entity_info, indicators, isToMySQL, mutable enti
     }
 }
 
+
 /*
  *   按照 XXX_risk_stats 表结构准备数据记录
  * 
  * 
  */
-def generate_entity_risk_stats(entity_info, indicators, isToMySQL, mutable entity_risk_stats) {
+def generate_entity_risk_stats(entity_info, indicators, isToMySQL, mutable entity_risk_stats, extra_keys) {
 
     t = null;
 
-   if(indicators['PBI-6M'].isVoid() || indicators['PBI-6M'].size() == 0) return;
+    if(extra_keys.isNothing() || extra_keys.isVoid()) v_extra_keys = array(STRING);
+    else v_extra_keys = extra_keys;
+
+	if(indicators['PBI-6M'].isVoid() || indicators['PBI-6M'].size() == 0) return;
 
     if(isToMySQL) {
 
-        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,
-                                        skewness AS skewness_6m, kurtosis AS kurtosis_6m, wrst_month AS worstmonth_6m, drawdown AS maxdrawdown_6m // mfdb中的真实字段名是 6m_maxdrawdown
-            FROM indicators['PBI-6M'] AS ind
-            INNER JOIN entity_info fi ON ind.entity_id = fi.entity_id
-            WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
-        
-        UPDATE t
-        SET stddev_1y = std_dev_a, downsidedev_1y = ds_dev_a, alpha_1y = alpha_a, winrate_1y = winrate, beta_1y = beta,
-            skewness_1y = skewness, kurtosis_1y = kurtosis, worstmonth_1y = wrst_month, maxdrawdown_1y = drawdown
-        FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_2y = std_dev_a, downsidedev_2y = ds_dev_a, alpha_2y = alpha_a, winrate_2y = winrate, beta_2y = beta,
-            skewness_2y = skewness, kurtosis_2y = kurtosis, worstmonth_2y = wrst_month, maxdrawdown_2y = drawdown
-        FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_3y = std_dev_a, downsidedev_3y = ds_dev_a, alpha_3y = alpha_a, winrate_3y = winrate, beta_3y = beta,
-            skewness_3y = skewness, kurtosis_3y = kurtosis, worstmonth_3y = wrst_month, maxdrawdown_3y = drawdown
-        FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_4y = std_dev_a, downsidedev_4y = ds_dev_a, alpha_4y = alpha_a, winrate_4y = winrate, beta_4y = beta,
-            skewness_4y = skewness, kurtosis_4y = kurtosis, worstmonth_4y = wrst_month, maxdrawdown_4y = drawdown
-        FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_5y = std_dev_a, downsidedev_5y = ds_dev_a, alpha_5y = alpha_a, winrate_5y = winrate, beta_5y = beta,
-            skewness_5y = skewness, kurtosis_5y = kurtosis, worstmonth_5y = wrst_month, maxdrawdown_5y = drawdown
-        FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_10y = std_dev_a, downsidedev_10y = ds_dev_a, alpha_10y = alpha_a, winrate_10y = winrate, beta_10y = beta,
-            skewness_10y = skewness, kurtosis_10y = kurtosis, worstmonth_10y = wrst_month, maxdrawdown_10y = drawdown
-        FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_ytd = std_dev_a, downsidedev_ytd = ds_dev_a, alpha_ytd = alpha_a, winrate_ytd = winrate, beta_ytd = beta,
-            skewness_ytd = skewness, kurtosis_ytd = kurtosis, worstmonth_ytd = wrst_month, maxdrawdown_ytd = drawdown // mfdb中的真实字段名是 ytd_maxdrawdown
-        FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET stddev_incep = std_dev_a, downsidedev_incep = ds_dev_a, alpha_incep = alpha_a, winrate_incep = winrate, beta_incep = beta,
-            skewness_incep = skewness, kurtosis_incep = kurtosis, worstmonth_incep = wrst_month, maxdrawdown_incep = drawdown
-        FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
+        t = sql(select =(sqlCol('entity_id'),
+         				 sqlCol(extra_keys.join('end_date')),
+                         sqlCol(['std_dev_a', 'ds_dev_a', 'alpha_a', 'winrate', 'beta', 'skewness', 'kurtosis', 'wrst_month', 'drawdown'],
+                         , ['stddev_6m', 'downsidedev_6m', 'alpha_6m', 'winrate_6m', 'beta_6m', 'skewness_6m', 'kurtosis_6m', 'worstmonth_6m', 'maxdrawdown_6m'])
+                        ),
+        		from = ej(indicators['PBI-6M'] AS a, entity_info AS fi, ['entity_id'].join(v_extra_keys)),
+        		where = < end_date >= fi_price_date.month()> // 过滤掉不必更新的旧记录
+        	   ).eval();
+
+
+        v_trailing = ['1y', '2y', '3y', '4y', '5y', '10y', 'ytd', 'incep'];
+        for(tr in v_trailing) {
+
+			col_std_dev = 'stddev_' + tr;
+			col_ds_dev = 'downsidedev_' + tr;
+			col_alpha = 'alpha_' + tr;
+			col_winrate = 'winrate_' + tr;
+			col_beta = 'beta_' + tr;
+			col_skewness = 'skewness_' + tr;
+			col_kurtosis = 'kurtosis_' + tr;
+			col_wrst_month = 'worstmonth_' + tr;
+			col_drawdown = 'maxdrawdown_' + tr;
+
+			t.addColumn([col_std_dev, col_ds_dev, col_alpha, col_winrate, col_beta, col_skewness, col_kurtosis, col_wrst_month, col_drawdown],
+						[DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+
+			if(!indicators['PBI-'+tr.upper()].isVoid()) {
+
+				sqlUpdate(table = t,
+				          updates = [<std_dev_a as _$col_std_dev>, <ds_dev_a as _$col_ds_dev>, <alpha_a as _$col_alpha>,
+				                     <winrate as _$col_winrate>, <beta as _$col_beta>, <skewness as _$col_skewness>,
+				                     <kurtosis as _$col_kurtosis>, <wrst_month as _$col_wrst_month>, <drawdown as _$col_drawdown>],
+				          from = <ej(t, indicators['PBI-'+tr.upper()], ['entity_id'].join(v_extra_keys).join(['end_date']))>
+						 ).eval();
+			}
+	    }
         
         INSERT INTO entity_risk_stats SELECT * FROM t;
 
@@ -613,60 +765,50 @@ def generate_entity_risk_stats(entity_info, indicators, isToMySQL, mutable entit
  * 
  * 
  */
-def generate_entity_riskadjret_stats(entity_info, indicators, isToMySQL, mutable entity_riskadjret_stats) {
+def generate_entity_riskadjret_stats(entity_info, indicators, isToMySQL, mutable entity_riskadjret_stats, extra_keys) {
 
     t = null;
 
+    if(extra_keys.isNothing() || extra_keys.isVoid()) v_extra_keys = array(STRING);
+    else v_extra_keys = extra_keys;
+
    if(indicators['PBI-6M'].isVoid() || indicators['PBI-6M'].size() == 0) return;
 
     if(isToMySQL) {
 
-        t = SELECT entity_id, end_date,
-                   sharpe_a AS sharperatio_6m, sortino_a AS sortinoratio_6m, treynor AS treynorratio_6m, jensen_a AS jensen_6m,
-                   calmar AS calmarratio_6m, omega AS omegaratio_6m, kappa AS kapparatio_6m
-            FROM indicators['PBI-6M'] AS ind
-            INNER JOIN entity_info fi ON ind.entity_id = fi.entity_id
-            WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
-        
-        UPDATE t
-        SET sharperatio_1y = sharpe_a, sortinoratio_1y = sortino_a, treynorratio_1y = treynor, jensen_1y = jensen_a,
-            calmarratio_1y = calmar, omegaratio_1y = omega, kapparatio_1y = kappa
-        FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_2y = sharpe_a, sortinoratio_2y = sortino_a, treynorratio_2y = treynor, jensen_2y = jensen_a,
-            calmarratio_2y = calmar, omegaratio_2y = omega, kapparatio_2y = kappa
-        FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_3y = sharpe_a, sortinoratio_3y = sortino_a, treynorratio_3y = treynor, jensen_3y = jensen_a,
-            calmarratio_3y = calmar, omegaratio_3y = omega, kapparatio_3y = kappa
-        FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_4y = sharpe_a, sortinoratio_4y = sortino_a, treynorratio_4y = treynor, jensen_4y = jensen_a,
-            calmarratio_4y = calmar, omegaratio_4y = omega, kapparatio_4y = kappa
-        FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_5y = sharpe_a, sortinoratio_5y = sortino_a, treynorratio_5y = treynor, jensen_5y = jensen_a,
-            calmarratio_5y = calmar, omegaratio_5y = omega, kapparatio_5y = kappa
-        FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_10y = sharpe_a, sortinoratio_10y = sortino_a, treynorratio_10y = treynor, jensen_10y = jensen_a,
-            calmarratio_10y = calmar, omegaratio_10y = omega, kapparatio_10y = kappa
-        FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_ytd = sharpe_a, sortinoratio_ytd = sortino_a, treynorratio_ytd = treynor, jensen_ytd = jensen_a,
-            calmarratio_ytd = calmar, omegaratio_ytd = omega, kapparatio_ytd = kappa
-        FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET sharperatio_incep = sharpe_a, sortinoratio_incep = sortino_a, treynorratio_incep = treynor, jensen_incep = jensen_a,
-            calmarratio_incep = calmar, omegaratio_incep = omega, kapparatio_incep = kappa
-        FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
+        t = sql(select =(sqlCol('entity_id'),
+         				 sqlCol(extra_keys.join('end_date')),
+                         sqlCol(['sharpe_a', 'sortino_a', 'treynor', 'jensen_a', 'calmar', 'omega', 'kappa'],
+                         , ['sharperatio_6m', 'sortinoratio_6m', 'treynorratio_6m', 'jensen_6m', 'calmarratio_6m', 'omegaratio_6m', 'kapparatio_6m'])
+                        ),
+        		from = ej(indicators['PBI-6M'] AS a, entity_info AS fi, ['entity_id'].join(v_extra_keys)),
+        		where = < end_date >= fi_price_date.month()> // 过滤掉不必更新的旧记录
+        	   ).eval();
+        	   
+        v_trailing = ['1y', '2y', '3y', '4y', '5y', '10y', 'ytd', 'incep'];
+        for(tr in v_trailing) {
+
+			col_sharpe = 'sharperatio_' + tr;
+			col_sortino = 'sortinoratio_' + tr;
+			col_treynor = 'treynorratio_' + tr;
+			col_jensen = 'jensen_' + tr;
+			col_calmar = 'calmarratio_' + tr;
+			col_omega = 'omegaratio_' + tr;
+			col_kappa = 'kapparatio_' + tr;
+
+			t.addColumn([col_sharpe, col_sortino, col_treynor, col_jensen, col_calmar, col_omega, col_kappa],
+						[DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+
+			if(!indicators['PBI-'+tr.upper()].isVoid()) {
+				sqlUpdate(table = t,
+				          updates = [<sharpe_a as _$col_sharpe>, <sortino_a as _$col_sortino>, <treynor as _$col_treynor>,
+				                     <jensen_a as _$col_jensen>, <calmar as _$col_calmar>, <omega as _$col_omega>,
+				                     <kappa as _$col_kappa>],
+				          from = <ej(t, indicators['PBI-'+tr.upper()], ['entity_id'].join(v_extra_keys).join(['end_date']))>
+						 ).eval();
+				
+			}
+	    }
         
         INSERT INTO entity_riskadjret_stats SELECT * FROM t;
 
@@ -680,51 +822,52 @@ def generate_entity_riskadjret_stats(entity_info, indicators, isToMySQL, mutable
  * 
  * 
  */
-def generate_entity_indicator(entity_info, indicators, isToMySQL, mutable entity_indicator) {
+def generate_entity_indicator(entity_info, indicators, isToMySQL, mutable entity_indicator, extra_keys) {
 
     t = null;
 
+    if(extra_keys.isNothing() || extra_keys.isVoid()) v_extra_keys = array(STRING);
+    else v_extra_keys = extra_keys;
+
    if(indicators['PBI-6M'].isVoid() || indicators['PBI-6M'].size() == 0) return;
 
     if(isToMySQL) {
 
-        t = SELECT entity_id, end_date, info_a AS info_ratio_6m, m2_a AS m2_6m, track_error_a AS tracking_error_6m
-            FROM indicators['PBI-6M'] AS ind
-            INNER JOIN entity_info fi ON ind.entity_id = fi.entity_id
-            WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
-      
-        UPDATE t
-        SET info_ratio_1y = info_a, m2_1y = m2_a, tracking_error_1y = track_error_a
-        FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_2y = info_a, m2_2y = m2_a, tracking_error_2y = track_error_a, var_2y = var, cvar_2y = cvar
-        FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_3y = info_a, m2_3y = m2_a, tracking_error_3y = track_error_a, var_3y = var, cvar_3y = cvar
-        FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_4y = info_a, m2_4y = m2_a, tracking_error_4y = track_error_a, var_4y = var, cvar_4y = cvar
-        FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_5y = info_a, m2_5y = m2_a, tracking_error_5y = track_error_a, var_5y = var, cvar_5y = cvar
-        FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_10y = info_a, m2_10y = m2_a, tracking_error_10y = track_error_a, var_10y = var, cvar_10y = cvar
-        FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_ytd = info_a, m2_ytd = m2_a, tracking_error_ytd = track_error_a
-        FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET info_ratio_incep = info_a, m2_incep = m2_a, tracking_error_incep = track_error_a, var_incep = var, cvar_incep = cvar
-        FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
-        
+        t = sql(select =(sqlCol('entity_id'),
+         				 sqlCol(extra_keys.join('end_date')),
+                         sqlCol(['info_a', 'm2_a', 'track_error_a'],
+                         , ['info_ratio_6m', 'm2_6m', 'tracking_error_6m'])
+                        ),
+        		from = ej(indicators['PBI-6M'] AS a, entity_info AS fi, ['entity_id'].join(v_extra_keys)),
+        		where = < end_date >= fi_price_date.month()> // 过滤掉不必更新的旧记录
+        	   ).eval();
+        	   
+        v_trailing = ['1y', '2y', '3y', '4y', '5y', '10y', 'ytd', 'incep'];
+        for(tr in v_trailing) {
+
+			col_info = 'info_ratio_' + tr;
+			col_m2 = 'm2_' + tr;
+			col_track_error = 'tracking_error_' + tr;
+			col_var = 'var_' + tr;
+			col_cvar = 'cvar_' + tr;
+
+			t.addColumn([col_info, col_m2, col_track_error],
+						[DOUBLE, DOUBLE, DOUBLE]);
+
+			if(tr != 'ytd') // YTD 没有 VAR, CVAR
+				t.addColumn([col_var, col_cvar], [DOUBLE, DOUBLE]);
+
+			if(!indicators['PBI-'+tr.upper()].isVoid()) {
+
+				sqlUpdate(table = t,
+				          updates = iif(tr != 'ytd', [<info_a as _$col_info>, <m2_a as _$col_m2>, <track_error_a as _$col_track_error>,
+				          			 <var as _$col_var>, <cvar as _$col_cvar>], [<info_a as _$col_info>, <m2_a as _$col_m2>, <track_error_a as _$col_track_error>]),
+				          from = <ej(t, indicators['PBI-'+tr.upper()], ['entity_id'].join(v_extra_keys).join(['end_date']))>
+						 ).eval();
+			}
+	    }
+        // var, cvar 只有2年及更长时间才计算
+        t.dropColumns!(['var_1y', 'cvar_1y']);
         INSERT INTO entity_indicator SELECT * FROM t;
 
     } else {
@@ -737,60 +880,47 @@ def generate_entity_indicator(entity_info, indicators, isToMySQL, mutable entity
  * 
  * 
  */
-def generate_entity_style_stats(entity_info, indicators, isToMySQL, mutable entity_style_stats) {
+def generate_entity_style_stats(entity_info, indicators, isToMySQL, mutable entity_style_stats, extra_keys) {
 
     t = null;
 
+    if(extra_keys.isNothing() || extra_keys.isVoid()) v_extra_keys = array(STRING);
+    else v_extra_keys = extra_keys;
+
    if(indicators['PBI-6M'].isVoid() || indicators['PBI-6M'].size() == 0) return;
 
     if(isToMySQL) {
 
-        t = SELECT entity_id, end_date, upside_capture_ret AS upsidecapture_ret_6m, downside_capture_ret AS downsidecapture_ret_6m,
-                                        upside_capture_ratio AS upsidecapture_ratio_6m, downside_capture_ratio AS downsidecapture_ratio_6m
-            FROM indicators['PBI-6M'] AS ind
-            INNER JOIN entity_info fi ON ind.entity_id = fi.entity_id
-            WHERE ind.end_date >= fi.price_date.month(); // 过滤掉不必更新的旧记录
-        
-        UPDATE t
-        SET upsidecapture_ret_1y = upside_capture_ret, downsidecapture_ret_1y = downside_capture_ret,
-            upsidecapture_ratio_1y = upside_capture_ratio, downsidecapture_ratio_1y = downside_capture_ratio
-        FROM ej(t, indicators['PBI-1Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_2y = upside_capture_ret, downsidecapture_ret_2y = downside_capture_ret,
-            upsidecapture_ratio_2y = upside_capture_ratio, downsidecapture_ratio_2y = downside_capture_ratio
-        FROM ej(t, indicators['PBI-2Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_3y = upside_capture_ret, downsidecapture_ret_3y = downside_capture_ret,
-            upsidecapture_ratio_3y = upside_capture_ratio, downsidecapture_ratio_3y = downside_capture_ratio
-        FROM ej(t, indicators['PBI-3Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_4y = upside_capture_ret, downsidecapture_ret_4y = downside_capture_ret,
-            upsidecapture_ratio_4y = upside_capture_ratio, downsidecapture_ratio_4y = downside_capture_ratio
-        FROM ej(t, indicators['PBI-4Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_5y = upside_capture_ret, downsidecapture_ret_5y = downside_capture_ret,
-            upsidecapture_ratio_5y = upside_capture_ratio, downsidecapture_ratio_5y = downside_capture_ratio
-        FROM ej(t, indicators['PBI-5Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_10y = upside_capture_ret, downsidecapture_ret_10y = downside_capture_ret,
-            upsidecapture_ratio_10y = upside_capture_ratio, downsidecapture_ratio_10y = downside_capture_ratio
-        FROM ej(t, indicators['PBI-10Y'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_ytd = upside_capture_ret, downsidecapture_ret_ytd = downside_capture_ret,
-            upsidecapture_ratio_ytd = upside_capture_ratio, downsidecapture_ratio_ytd = downside_capture_ratio
-        FROM ej(t, indicators['PBI-YTD'], ['entity_id', 'end_date']);
-        
-        UPDATE t
-        SET upsidecapture_ret_incep = upside_capture_ret, downsidecapture_ret_incep = downside_capture_ret,
-            upsidecapture_ratio_incep = upside_capture_ratio, downsidecapture_ratio_incep = downside_capture_ratio
-        FROM ej(t, indicators['PBI-INCEP'], ['entity_id', 'end_date']);
-        
+        t = sql(select =(sqlCol('entity_id'),
+         				 sqlCol(extra_keys.join('end_date')),
+                         sqlCol(['upside_capture_ret', 'downside_capture_ret', 'upside_capture_ratio', 'downside_capture_ratio'],
+                         , ['upsidecapture_ret_6m', 'downsidecapture_ret_6m', 'upsidecapture_ratio_6m', 'downsidecapture_ratio_6m'])
+                        ),
+        		from = ej(indicators['PBI-6M'] AS a, entity_info AS fi, ['entity_id'].join(v_extra_keys)),
+        		where = < end_date >= fi_price_date.month()> // 过滤掉不必更新的旧记录
+        	   ).eval();
+        	   
+        v_trailing = ['1y', '2y', '3y', '4y', '5y', '10y', 'ytd', 'incep'];
+        for(tr in v_trailing) {
+
+			col_upside_capture_ret = 'upsidecapture_ret_' + tr;
+			col_downside_capture_ret = 'downsidecapture_ret_' + tr;
+			col_upside_capture_ratio = 'upsidecapture_ratio_' + tr;
+			col_downside_capture_ratio = 'downsidecapture_ratio_' + tr;
+
+			t.addColumn([col_upside_capture_ret, col_downside_capture_ret, col_upside_capture_ratio, col_downside_capture_ratio],
+						[DOUBLE, DOUBLE, DOUBLE, DOUBLE]);
+
+			if(!indicators['PBI-'+tr.upper()].isVoid()) {
+
+				sqlUpdate(table = t,
+				          updates = [<upside_capture_ret as _$col_upside_capture_ret>, <downside_capture_ret as _$col_downside_capture_ret>,
+				                     <upside_capture_ratio as _$col_upside_capture_ratio>, <downside_capture_ratio as _$col_downside_capture_ratio>],
+				          from = <ej(t, indicators['PBI-'+tr.upper()], ['entity_id'].join(v_extra_keys).join(['end_date']))>
+						 ).eval();
+			}
+	    }
+
         INSERT INTO entity_style_stats SELECT * FROM t;
 
     } else {
@@ -805,14 +935,19 @@ def generate_entity_style_stats(entity_info, indicators, isToMySQL, mutable enti
  *   TODO: why we need isToMySQL here?
  *         其它的指标恐怕也要按这个改,因为私募可能会有近6月没有数据但近2年之类的周期有数据的情况!
  */
-def generate_entity_bfi_indicator(entity_info, indicators, isToMySQL, mutable entity_bfi_indicator) {
+def generate_entity_bfi_indicator(entity_info, indicators, isToMySQL, mutable entity_bfi_indicator, extra_keys) {
 
     t = null;
 
+    if(extra_keys.isNothing() || extra_keys.isVoid()) v_extra_keys = array(STRING);
+    else v_extra_keys = extra_keys;
+
 	v_cols_from = ['upside_capture_ret', 'downside_capture_ret', 'upside_capture_ratio', 'downside_capture_ratio', 'alpha_a', 'winrate', 'beta', 'info_a', 'track_error_a', 'jensen_a'];
 	v_cols_to = ['upsidecapture_ret', 'downsidecapture_ret', 'upsidecapture_ratio', 'downsidecapture_ratio', 'alpha', 'winrate', 'beta', 'info_ratio', 'tracking_error', 'jensen'];
 	v_cols_useless = ['track_error', 'info', 'alpha', 'treynor', 'jensen', 'm2', 'm2_a']; // 标准指标中不被当前表覆盖的数据点
 
+	v_join_key = ['entity_id', 'benchmark_id', 'end_date'].join(v_extra_keys);
+
     if(isToMySQL) {
 
 		t = lj(
@@ -824,15 +959,15 @@ def generate_entity_bfi_indicator(entity_info, indicators, isToMySQL, mutable en
 									lj(
 										lj(
 											lj(entity_info,
-											   indicators['BFI-6M'] AS t_6m, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-											indicators['BFI-1Y'] AS t_1y, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-										indicators['BFI-2Y'] AS t_2y, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-									indicators['BFI-3Y'] AS t_3y, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-								indicators['BFI-4Y'] AS t_4y, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-							indicators['BFI-5Y'] AS t_5y, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-						indicators['BFI-10Y'] AS t_10y, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-					indicators['BFI-YTD'] AS t_ytd, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless),
-				indicators['BFI-INCEP'] AS t_incep, ['entity_id', 'benchmark_id', 'end_date']).dropColumns!(v_cols_useless);
+											   indicators['BFI-6M'] AS t_6m, v_join_key).dropColumns!(v_cols_useless),
+											indicators['BFI-1Y'] AS t_1y, v_join_key).dropColumns!(v_cols_useless),
+										indicators['BFI-2Y'] AS t_2y, v_join_key).dropColumns!(v_cols_useless),
+									indicators['BFI-3Y'] AS t_3y, v_join_key).dropColumns!(v_cols_useless),
+								indicators['BFI-4Y'] AS t_4y, v_join_key).dropColumns!(v_cols_useless),
+							indicators['BFI-5Y'] AS t_5y, v_join_key).dropColumns!(v_cols_useless),
+						indicators['BFI-10Y'] AS t_10y, v_join_key).dropColumns!(v_cols_useless),
+					indicators['BFI-YTD'] AS t_ytd, v_join_key).dropColumns!(v_cols_useless),
+				indicators['BFI-INCEP'] AS t_incep, v_join_key).dropColumns!(v_cols_useless);
 				
 		t.rename!(v_cols_from, v_cols_to + '_6m');
 		t.rename!('t_1y_' + v_cols_from, v_cols_to + '_1y');

+ 12 - 6
modules/indicatorCalculator.dos

@@ -986,7 +986,7 @@ def cal_trailing(func, entity_info, benchmarks, end_day, tb_ret, bmk_ret, risk_f
  * 
  */
 def cal_trailing_indicators(entity_info, benchmarks, end_day, tb_ret, bmk_ret, risk_free_rate) {
-	
+
     return cal_trailing(cal_indicators, entity_info, benchmarks, end_day, tb_ret, bmk_ret, risk_free_rate);
 
 }
@@ -1084,7 +1084,7 @@ 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
+ *   @param monthly_returns <TABLE>: NEED COLUMN: entity_id, curve_type, strategy, 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']
  * 
@@ -1135,7 +1135,7 @@ def cal_mc_monthly_indicators(entity_type, indicator_type, monthly_returns) {
 
     if(risk_free_rate.isVoid() || risk_free_rate.size() == 0) { return null; }
 
-	// 指标计算
+	// 指标计算,因为 cal_traling_xxx 不支持 curve_type & strategy, 所以做个循环
 	d_rt = dict(STRING, ANY);
 	v_curve_type = [1, 4, 7];
 	for(cur in v_curve_type) {
@@ -1145,18 +1145,24 @@ def cal_mc_monthly_indicators(entity_type, indicator_type, monthly_returns) {
 		
 	    if(indicator_type == 'BFI') {
 	
-	        t0 = cal_trailing_bfi_indicators(t_ei, benchmark, end_day, t_mr, bmk_ret, risk_free_rate);
+	        v_indicators = cal_trailing_bfi_indicators(t_ei, benchmark, end_day, t_mr, bmk_ret, risk_free_rate);
+
+	        for(tb in v_indicators)
+		        tb.cj(table(cur AS curve_type, 0 AS strategy));
 	
 	        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_indicators = cal_trailing_indicators(t_ei, benchmark, end_day, t_mr, bmk_ret, risk_free_rate);
+
+	        for(tb in v_indicators)
+				UPDATE tb SET curve_type = cur, strategy = 0;
 
 	        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_indicator = dict(v_table_name, v_indicators);
 
 	    d_rt[cur$STRING] = d_indicator; 
 	}

+ 27 - 16
modules/performanceDataPuller.dos

@@ -198,6 +198,7 @@ def get_entity_weekly_rets(entity_type, entity_info) {
  * 
  *  Example: get_monthly_ret('HF', ['HF000004KN','HF000103EU','HF00018WXG'], 2000.01.01, 2024.03.01, true);
  *           get_monthly_ret('PF', [166002], 2000.01.01, 2024.03.01, true);
+ *           get_monthly_ret('PL', ['PL000000NS', 'PL00000ICF'], 2000.01.01, 2024.12.02, true);
  */
 def get_monthly_ret(entity_type, entity_ids, start_date, end_date, isFromMySQL) {
 
@@ -210,9 +211,11 @@ def get_monthly_ret(entity_type, entity_ids, start_date, end_date, isFromMySQL)
     yyyymm_start = start_date.temporalFormat("yyyy-MM")
     yyyymm_end = end_date.temporalFormat("yyyy-MM")
 
+    sql_extra_cols = iif(entity_type in ['PL', 'CO'], "curve_type, strategy, ", "");
+
     if(isFromMySQL == true) {
 
-        s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, end_date, price_date, ret_1m AS ret, " + tmp.cumulative_nav_col[0] + " AS nav
+        s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, " + sql_extra_cols + "end_date, price_date, ret_1m AS ret, " + tmp.cumulative_nav_col[0] + " AS nav
                    FROM " + tmp.table_name[0] + "
                    WHERE " + tmp.sec_id_col[0] + " IN (" + s_entity_ids + ")
                       AND isvalid = 1
@@ -307,33 +310,40 @@ def get_entity_list_by_latest_return_updatetime(entity_type, entity_ids, updatet
 /*
  * 通用取给定日期之后(含此日期)的净值
  * 
- * 
- * Create: 202408                                                    Joey
- *                 TODO: add isvalid and nav > 0 for local version
+ * @param price_date <DATE/MONTH>
+ *             
  * 
  *
  * Example: get_nav_by_price_date('HF', "'HF000004KN','HF00018WXG'", 2024.05.01, true);
  *          get_nav_by_price_date('MI', "'IN00000008','IN0000000M'", 2024.05.01, true);
+ *          get_nav_by_price_date('PL', NULL, 2024.11.01, true);
  */
 def get_nav_by_price_date(entity_type, entity_ids, price_date, isFromMySQL) {
 
     s_entity_ids = ids_to_string(entity_ids);
 
-    if(s_entity_ids == null || s_entity_ids == '') return null;
-
     tmp = get_nav_table_description(entity_type);
+    
+    if(s_entity_ids == null || s_entity_ids == '') sql_entity_id = '';
+    else sql_entity_id = " AND " +  tmp.sec_id_col[0] + " IN (" + s_entity_ids + ")";
+
+	if(entity_type in ('PL', 'CO')) {
+		sql_price_date = " AND " + tmp.price_date_col[0] + " >= '" + price_date.month().temporalFormat('yyyy-MM') + "'";
+	}
+	else {
+		sql_price_date = " AND " + tmp.price_date_col[0] + " >= '" + price_date.temporalFormat('yyyy-MM-dd') + "'";
+	}
 
     if(isFromMySQL == true) {
 
         nav_table_name = tmp.table_name[0];
     
-        s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, price_date, " + tmp.cumulative_nav_col[0] + " AS cumulative_nav, " + tmp.nav_col[0] + " AS nav
+        s_query = "SELECT DISTINCT " + tmp.sec_id_col[0] + " AS entity_id, " + tmp.price_date_col[0] + ", " + tmp.cumulative_nav_col[0] + " AS cumulative_nav, " + tmp.nav_col[0] + " AS nav
                    FROM " + tmp.table_name[0] + "
-                   WHERE " + tmp.sec_id_col[0] + " IN (" + s_entity_ids + ")
-                     AND isvalid = 1
+                   WHERE isvalid = 1 " +
+                     sql_entity_id + sql_price_date + "
                      AND " + tmp.cumulative_nav_col[0] + " > 0
-                     AND price_date >= '" + price_date$STRING + "'
-                   ORDER BY " + tmp.sec_id_col[0] + ", price_date";
+                   ORDER BY " + tmp.sec_id_col[0] + ", " +  tmp.price_date_col[0];
     
         conn = connect_mysql();
     
@@ -410,6 +420,7 @@ def get_index_nav_by_price_date(index_ids, price_date) {
  *  Example: get_entity_list_by_nav_updatetime('MF', ['MF00003PW1', 'MF00003PW2'], 2024.09.26, true);
  *           get_entity_list_by_nav_updatetime('HF', null, 2024.07.19T10:00:00, true);
  *           get_entity_list_by_nav_updatetime('PF', '166002,166114', 2024.06.20, true);
+ *           get_entity_list_by_nav_updatetime('PL', NULL, 2024.10.20, true);
  * 
  */
 def get_entity_list_by_nav_updatetime(entity_type, entity_ids, updatetime, isFromMySQL) {
@@ -424,18 +435,18 @@ def get_entity_list_by_nav_updatetime(entity_type, entity_ids, updatetime, isFro
     	sql_entity_id = " AND " + tmp.sec_id_col[0] + " IN (" + s_entity_ids + ")";
     }
 
+    sql_extra_keys = iif(entity_type in ('PL', 'CO'), ", curve_type, strategy", "");
+
     if(isFromMySQL == true) {
 
-        nav_table_name = tmp.table_name[0];
-    
-        s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, MIN(price_date) AS price_date 
+        s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id" + sql_extra_keys + ", MIN(" + tmp.price_date_col[0] + ") AS price_date 
                    FROM " + tmp.table_name[0] + "
                    WHERE isvalid = 1 " +
                      sql_entity_id + "
                      AND " + tmp.cumulative_nav_col[0] + " > 0
                      AND updatetime >= '" + updatetime$STRING + "'
-                   GROUP BY " + tmp.sec_id_col[0] + "
-                   ORDER BY " + tmp.sec_id_col[0] + ", price_date";
+                   GROUP BY " + tmp.sec_id_col[0] + sql_extra_keys + "
+                   ORDER BY " + tmp.sec_id_col[0] + ", " + tmp.price_date_col[0];
     
         conn = connect_mysql();
     

+ 30 - 29
modules/sqlUtilities.dos

@@ -134,17 +134,18 @@ def get_rbsa_index() {
 def get_nav_table_description(entity_type) {
 
     tmp_universe = table(100:0, 
-                         ['type', 'table_name', 'sec_id_col', 'cumulative_nav_col', 'nav_col', 'prefix'],
-                         [STRING, STRING, STRING, STRING, STRING, STRING]);
+                         ['type', 'table_name', 'sec_id_col', 'cumulative_nav_col', 'nav_col', 'prefix', 'price_date_col'],
+                         [STRING, STRING, STRING, STRING, STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,股票,市场指数,图译指数,私有指数,图译因子,组合
+    // 分别对应:私募,公募,私有基金,股票,市场指数,图译指数,私有指数,图译因子,组合, 基金经理, 基金公司
     INSERT INTO tmp_universe VALUES (
-        ['HF', 'MF', 'CF', 'EQ', 'MI', 'FI', 'CI', 'FA', 'PF'],
-        ['mfdb.nav', 'mfdb.public_nav', 'pfdb.pf_cus_fund_nav', 'mfdb.stock_price', 'mfdb.market_indexes', 'mfdb.indexes_ty_index', 'pfdb.cm_udf_index_nav', 'pfdb.cm_factor_value', 'pfdb.pf_portfolio_nav'],
-        ['fund_id', 'fund_id', 'fund_id', 'sec_id', 'index_id', 'index_id', 'index_id', 'factor_id', 'portfolio_id'],
-        ['cumulative_nav', 'cumulative_nav', 'cumulative_nav', 'cumulative_nav', 'close', 'index_value', 'cumulative_nav', 'factor_value', 'cumulative_nav'],
-        ['nav', 'nav', 'nav', 'nav', 'close', 'index_value', 'cumulative_nav', 'factor_value', 'cumulative_nav'],
-        ['HF', 'MF', 'CF', 'EQ', 'IN', 'IN', 'CI', 'FA', '']);
+        ['HF', 'MF', 'CF', 'EQ', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL', 'CO'],
+        ['mfdb.nav', 'mfdb.public_nav', 'pfdb.pf_cus_fund_nav', 'mfdb.stock_price', 'mfdb.market_indexes', 'mfdb.indexes_ty_index', 'pfdb.cm_udf_index_nav', 'pfdb.cm_factor_value', 'pfdb.pf_portfolio_nav', 'mfdb.fund_manager_fitted_curve', 'mfdb.company_fitted_curve'],
+        ['fund_id', 'fund_id', 'fund_id', 'sec_id', 'index_id', 'index_id', 'index_id', 'factor_id', 'portfolio_id', 'fund_manager_id', 'company_id'],
+        ['cumulative_nav', 'cumulative_nav', 'cumulative_nav', 'cumulative_nav', 'close', 'index_value', 'cumulative_nav', 'factor_value', 'cumulative_nav', 'cumulative_nav', 'cumulative_nav'],
+        ['nav', 'nav', 'nav', 'nav', 'close', 'index_value', 'cumulative_nav', 'factor_value', 'cumulative_nav', 'cumulative_nav', 'cumulative_nav'],
+        ['HF', 'MF', 'CF', 'EQ', 'IN', 'IN', 'CI', 'FA', '', 'PL', 'CO'],
+        ['price_date', 'price_date', 'price_date', 'price_date', 'price_date', 'price_date', 'price_date', 'price_date', 'price_date', 'end_date', 'end_date']);
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
     
@@ -227,11 +228,11 @@ def get_indicator_table_description(entity_type) {
                          ['type', 'table_name', 'sec_id_col'],
                          [STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合
+    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合,基金经理,基金公司
     INSERT INTO tmp_universe VALUES ( 
-        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF'],
-        ['mfdb.fund_indicator', 'mfdb.fund_indicator', 'pfdb.pf_cus_fund_indicator', 'mfdb.fund_indicator', 'mfdb.fund_indicator', 'pfdb.cm_udf_index_indicator', 'pfdb.cm_factor_indicator', 'pfdb.pf_portfolio_indicator'],
-        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id'] );
+        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL', 'CO'],
+        ['mfdb.fund_indicator', 'mfdb.fund_indicator', 'pfdb.pf_cus_fund_indicator', 'mfdb.fund_indicator', 'mfdb.fund_indicator', 'pfdb.cm_udf_index_indicator', 'pfdb.cm_factor_indicator', 'pfdb.pf_portfolio_indicator', 'mfdb.manager_indicator', 'mfdb.company_indicator'],
+        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id', 'manager_id', 'company_id'] );
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
 
@@ -248,11 +249,11 @@ def get_risk_stats_table_description(entity_type) {
                          ['type', 'table_name', 'sec_id_col'],
                          [STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合
+    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合,基金经理,基金公司
     INSERT INTO tmp_universe VALUES ( 
-        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF'],
-        ['mfdb.fund_risk_stats', 'mfdb.fund_risk_stats', 'pfdb.pf_cus_fund_risk_stats', 'mfdb.fund_risk_stats', 'mfdb.fund_risk_stats', 'pfdb.cm_udf_index_risk_stats', 'pfdb.cm_factor_risk_stats', 'pfdb.pf_portfolio_risk_stats'],
-        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id'] );
+        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL', 'CO'],
+        ['mfdb.fund_risk_stats', 'mfdb.fund_risk_stats', 'pfdb.pf_cus_fund_risk_stats', 'mfdb.fund_risk_stats', 'mfdb.fund_risk_stats', 'pfdb.cm_udf_index_risk_stats', 'pfdb.cm_factor_risk_stats', 'pfdb.pf_portfolio_risk_stats', 'mfdb.manager_risk_stats', 'mfdb.company_risk_stats'],
+        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id', 'manager_id', 'company_id'] );
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
 
@@ -269,11 +270,11 @@ def get_riskadjret_stats_table_description(entity_type) {
                          ['type', 'table_name', 'sec_id_col'],
                          [STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合
+    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合,基金经理,基金公司
     INSERT INTO tmp_universe VALUES ( 
-        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF'],
-        ['mfdb.fund_riskadjret_stats', 'mfdb.fund_riskadjret_stats', 'pfdb.pf_cus_fund_riskadjret_stats', 'mfdb.fund_riskadjret_stats', 'mfdb.fund_riskadjret_stats', 'pfdb.cm_udf_index_riskadjret_stats', 'pfdb.cm_factor_riskadjret_stats', 'pfdb.pf_portfolio_riskadjret_stats'],
-        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id'] );
+        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL', 'CO'],
+        ['mfdb.fund_riskadjret_stats', 'mfdb.fund_riskadjret_stats', 'pfdb.pf_cus_fund_riskadjret_stats', 'mfdb.fund_riskadjret_stats', 'mfdb.fund_riskadjret_stats', 'pfdb.cm_udf_index_riskadjret_stats', 'pfdb.cm_factor_riskadjret_stats', 'pfdb.pf_portfolio_riskadjret_stats', 'mfdb.manager_riskadjret_stats', 'mfdb.company_riskadjret_stats'],
+        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id', 'manager_id', 'company_id'] );
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
 
@@ -291,11 +292,11 @@ def get_capture_style_table_description(entity_type) {
                          ['type', 'table_name', 'sec_id_col'],
                          [STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合
+    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合,基金经理,基金公司
     INSERT INTO tmp_universe VALUES ( 
-        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF'],
-        ['mfdb.fund_style_stats', 'mfdb.fund_style_stats', 'pfdb.pf_cus_fund_style_stats', 'mfdb.fund_style_stats', 'mfdb.fund_style_stats', 'pfdb.cm_udf_index_style_stats', 'pfdb.cm_factor_style_stats', 'pfdb.pf_portfolio_style_stats'],
-        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id'] );
+        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL', 'CO'],
+        ['mfdb.fund_style_stats', 'mfdb.fund_style_stats', 'pfdb.pf_cus_fund_style_stats', 'mfdb.fund_style_stats', 'mfdb.fund_style_stats', 'pfdb.cm_udf_index_style_stats', 'pfdb.cm_factor_style_stats', 'pfdb.pf_portfolio_style_stats', 'mfdb.manager_style_stats', 'mfdb.company_style_stats'],
+        ['fund_id', 'fund_id', 'fund_id', 'fund_id', 'fund_id', 'index_id', 'factor_id', 'portfolio_id', 'manager_id', 'company_id'] );
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
 
@@ -313,11 +314,11 @@ def get_bfi_indicator_table_description(entity_type) {
                          ['type', 'table_name', 'sec_id_col'],
                          [STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合
+    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合,基金经理
     INSERT INTO tmp_universe VALUES ( 
-        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF'],
+        ['HF', 'MF', 'CF', 'MI', 'FI', 'CI', 'FA', 'PF', 'PL'],
         ['mfdb.fund_ty_bfi_bm_indicator', 'mfdb.fund_ty_bfi_bm_indicator', NULL, NULL, NULL, NULL, NULL, 'pfdb.pf_portfolio_ty_bfi_bm_indicator'],
-        ['fund_id', 'fund_id', NULL, NULL, NULL, NULL, NULL, 'portfolio_id'] );
+        ['fund_id', 'fund_id', NULL, NULL, NULL, NULL, NULL, 'portfolio_id', 'manager_id'] );
 
     return (SELECT * FROM tmp_universe u WHERE u.type = entity_type);
 
@@ -335,7 +336,7 @@ def get_bfi_by_category_group_table_description(entity_type) {
                          ['type', 'table_name', 'sec_id_col'],
                          [STRING, STRING, STRING]);
 
-    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合, 经理
+    // 分别对应:私募,公募,私有基金,市场指数,图译指数,私有指数,图译因子,组合, ,基金经理
     INSERT INTO tmp_universe VALUES ( 
         ['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'],

+ 1 - 2
modules/task_weeklyPerformnce.dos

@@ -284,8 +284,7 @@ def calEntityBfiIndicatorTask(entityType, date) {
 
             // 数据初始化时将指标存入本地,做排名之用
             if(end_day <= get_ini_data_const()['date']) {
-            	save_table(tb_bfi_indicator, t_desc.table_name[0], false);
-            }
+            	save_table(tb_bfi_indicator, t_desc0.table_name[0], false);
 
         } catch(ex) {