|
@@ -95,7 +95,6 @@ def calEntityPerformance(entity_type, navs) {
|
|
|
/*
|
|
|
* 计算组合净值并存入数据库
|
|
|
*
|
|
|
- * TODO: release 时改变同步目标表为正式表
|
|
|
*/
|
|
|
def cal_and_save_portfolio_nav(cal_portfolio_info, is_save_local) {
|
|
|
|
|
@@ -150,136 +149,14 @@ def cal_and_save_portfolio_nav(cal_portfolio_info, is_save_local) {
|
|
|
return rt;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * 计算组合标准指标并存入数据库
|
|
|
- *
|
|
|
- * TODO: release 时改变同步目标表为正式表
|
|
|
- */
|
|
|
-def cal_and_save_portfolio_indicators(cal_portfolio_info, is_save_local) {
|
|
|
-
|
|
|
- rt = '';
|
|
|
-
|
|
|
- // 准备类似MySQL结构的数据表
|
|
|
- tb_portfolio_performance = create_entity_performance(true);
|
|
|
-
|
|
|
- tb_portfolio_indicator = create_entity_indicator(true);
|
|
|
- tb_portfolio_risk_stats = create_entity_risk_stats(true);
|
|
|
- tb_portfolio_riskadjret_stats = create_entity_riskadjret_stats(true);
|
|
|
- tb_portfolio_style_stats = create_entity_style_stats(true);
|
|
|
-
|
|
|
- tb_portfolio_performance_weekly = create_entity_performance_weekly(true);
|
|
|
- tb_portfolio_latest_performance = create_entity_latest_performance(true);
|
|
|
-
|
|
|
-
|
|
|
- // 分批跑
|
|
|
- i = 0;
|
|
|
- batch_size = 1000;
|
|
|
-
|
|
|
- all_portfolio_id = EXEC DISTINCT portfolio_id FROM cal_portfolio_info;
|
|
|
-
|
|
|
- do {
|
|
|
-
|
|
|
- cal_port = SELECT * FROM cal_portfolio_info
|
|
|
- WHERE portfolio_id IN all_portfolio_id[i : min(all_portfolio_id.size(), i+batch_size)];
|
|
|
-
|
|
|
- if(cal_port.isVoid() || cal_port.size() == 0) break;
|
|
|
-
|
|
|
- // 取数据库月度净值及前值 5 sec
|
|
|
- s_json = (SELECT portfolio_id, 1900.01.01 AS price_date FROM cal_port GROUP BY portfolio_id).rename!('portfolio_id', 'sec_id').toStdJson();
|
|
|
- tb_monthly_nav = get_nav_for_return_calculation('PF', 'm', s_json);
|
|
|
-
|
|
|
- // 把 portfolio id 字段从字符串换回整型,不然后面Join table的时候会出错
|
|
|
- v_portfolio_id = tb_monthly_nav.sec_id$INT;
|
|
|
- tb_monthly_nav.replaceColumn!('sec_id', v_portfolio_id);
|
|
|
- tb_monthly_nav.dropColumns!('nav').rename!(['sec_id', 'cumulative_nav'], ['portfolio_id', 'nav']);
|
|
|
-
|
|
|
- // 计算各标准指标
|
|
|
- indicators = calPortfolioPerformance(tb_monthly_nav);
|
|
|
-
|
|
|
- // 仿照MySQL的表结构准备好记录 (1s)
|
|
|
- port_info = (SELECT portfolio_id, start_cal_date.min() AS price_date FROM cal_port GROUP BY portfolio_id).rename!('portfolio_id', 'entity_id');
|
|
|
-
|
|
|
- generate_entity_performance(port_info, indicators, true, tb_portfolio_performance);
|
|
|
- generate_entity_indicator(port_info, indicators, true, tb_portfolio_indicator);
|
|
|
- generate_entity_risk_stats(port_info, indicators, true, tb_portfolio_risk_stats);
|
|
|
- generate_entity_riskadjret_stats(port_info, indicators, true, tb_portfolio_riskadjret_stats);
|
|
|
- generate_entity_style_stats(port_info, indicators, true, tb_portfolio_style_stats);
|
|
|
-
|
|
|
- // 计算周收益 (49s)
|
|
|
- port_info = SELECT * FROM ej(port_info, get_entity_info('PF', all_portfolio_id[i : min(all_portfolio_id.size(), i+batch_size)]), 'entity_id')
|
|
|
- rets_w = cal_weekly_returns('PF', port_info);
|
|
|
-
|
|
|
- if(! rets_w.isVoid() && rets_w.size() > 0) {
|
|
|
- // 把 portfolio id 字段从字符串换回整型,不然后面Join table的时候会出错
|
|
|
- v_portfolio_id = rets_w.entity_id$INT;
|
|
|
- rets_w.replaceColumn!('entity_id', v_portfolio_id);
|
|
|
-
|
|
|
- generate_entity_performance_weekly(port_info, rets_w, true, tb_portfolio_performance_weekly);
|
|
|
- }
|
|
|
-
|
|
|
- // 计算最新收益 (23s)
|
|
|
- perf_latest = cal_latest_performance('PF', port_info, true);
|
|
|
-
|
|
|
- if(! perf_latest.isVoid() && perf_latest.size() > 0) {
|
|
|
- generate_entity_latest_performance(port_info, perf_latest, true, tb_portfolio_latest_performance);
|
|
|
- }
|
|
|
-
|
|
|
- i += batch_size;
|
|
|
-
|
|
|
- } while (i <= cal_portfolio_info.size());
|
|
|
-
|
|
|
-
|
|
|
- if(! tb_portfolio_performance.isVoid() && tb_portfolio_performance.size() > 0) {
|
|
|
-
|
|
|
- // save data to MySQL
|
|
|
- try {
|
|
|
-
|
|
|
- chg_columns_for_mysql(tb_portfolio_performance, 'portfolio_id');
|
|
|
- save_and_sync(tb_portfolio_performance, 'raw_db.pf_portfolio_performance', 'raw_db.pf_portfolio_performance');
|
|
|
-
|
|
|
- chg_columns_for_mysql(tb_portfolio_indicator, 'portfolio_id');
|
|
|
- save_and_sync(tb_portfolio_indicator, 'raw_db.pf_portfolio_indicator', 'raw_db.pf_portfolio_indicator');
|
|
|
-
|
|
|
- chg_columns_for_mysql(tb_portfolio_risk_stats, 'portfolio_id');
|
|
|
- save_and_sync(tb_portfolio_risk_stats, 'raw_db.pf_portfolio_risk_stats', 'raw_db.pf_portfolio_risk_stats');
|
|
|
-
|
|
|
- chg_columns_for_mysql(tb_portfolio_riskadjret_stats, 'portfolio_id');
|
|
|
- save_and_sync(tb_portfolio_riskadjret_stats, 'raw_db.pf_portfolio_riskadjret_stats', 'raw_db.pf_portfolio_riskadjret_stats');
|
|
|
-
|
|
|
- chg_columns_for_mysql(tb_portfolio_style_stats, 'portfolio_id');
|
|
|
- save_and_sync(tb_portfolio_style_stats, 'raw_db.pf_portfolio_style_stats', 'raw_db.pf_portfolio_style_stats');
|
|
|
-
|
|
|
- save_and_sync(tb_portfolio_performance_weekly, 'raw_db.pf_portfolio_performance_weekly', 'raw_db.pf_portfolio_performance_weekly');
|
|
|
-
|
|
|
- save_and_sync(tb_portfolio_latest_performance, 'raw_db.pf_portfolio_latest_performance', 'raw_db.pf_portfolio_latest_performance');
|
|
|
-
|
|
|
- // 数据初始化时将指标存入本地
|
|
|
- if(is_save_local == true) {
|
|
|
- save_table(tb_portfolio_performance, 'pfdb.pf_portfolio_performance', false);
|
|
|
- save_table(tb_portfolio_indicator, 'pfdb.pf_portfolio_indicator', false);
|
|
|
- save_table(tb_portfolio_risk_stats, 'pfdb.pf_portfolio_risk_stats', false);
|
|
|
- save_table(tb_portfolio_riskadjret_stats, 'pfdb.pf_portfolio_riskadjret_stats', false);
|
|
|
- save_table(tb_portfolio_style_stats, 'pfdb.pf_portfolio_style_stats', false);
|
|
|
- save_table(tb_portfolio_performance_weekly, 'pfdb.pf_portfolio_performance_weekly', false);
|
|
|
- save_table(tb_portfolio_latest_performance, 'pfdb.pf_portfolio_latest_performance', false);
|
|
|
- }
|
|
|
-
|
|
|
- } catch(ex) {
|
|
|
-
|
|
|
- //TODO: Log errors
|
|
|
- rt = ex;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return rt;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
/*
|
|
|
* 通用计算标准指标并存入数据库
|
|
|
+ *
|
|
|
+ * @param entity_type <STRING>
|
|
|
+ * @param cal_entity_info <TABLE>: [COLUMNS] entity_id, start_cal_date
|
|
|
+ * @param is_save_local <BOOL>
|
|
|
*
|
|
|
- * TODO: release 时改变同步目标表为正式表
|
|
|
*/
|
|
|
def cal_and_save_entity_indicators(entity_type, cal_entity_info, is_save_local) {
|
|
|
|
|
@@ -486,7 +363,7 @@ def cal_and_save_factor_nav(cal_factor_info, is_save_local) {
|
|
|
|
|
|
if(!t_tmp.isVoid() && t_tmp.size() > 0) {
|
|
|
INSERT INTO t_factor_value
|
|
|
- SELECT entity_id AS factor_id, price_date, nav AS factor_value FROM cal_nav_by_return('FA', t_factor, t);
|
|
|
+ SELECT entity_id AS factor_id, price_date, nav AS factor_value FROM t_tmp;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -505,6 +382,8 @@ def cal_and_save_factor_nav(cal_factor_info, is_save_local) {
|
|
|
* [定时任务]批量计算bfi因子净值、收益及指标
|
|
|
*
|
|
|
* @param updatetime <DATETIME>: 成分指数净值更新时间,忽略或传入1989.01.01及更早的日期被认为在做数据初始化
|
|
|
+ *
|
|
|
+ * TODO: 由减运算合成的BFI还未涉及,如FA00000SMB
|
|
|
*
|
|
|
*
|
|
|
* Example: CalFactorPerformanceTask(2024.10.28);
|
|
@@ -531,3 +410,58 @@ def CalFactorPerformanceTask(updatetime) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+ * [定时任务]批量计算各类平均指数的点位
|
|
|
+ *
|
|
|
+ * @param updatetime <DATETIME>: 成分指数净值更新时间,忽略或传入1989.01.01及更早的日期被认为在做数据初始化
|
|
|
+ *
|
|
|
+ * TODO: M* category average, manager, company
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * Example: CalCategoryAverageNavTask(2024.11.01);
|
|
|
+ * CalCategoryAverageNavTask(1989.01.01); -- 【初始化专用】
|
|
|
+ */
|
|
|
+def CalCategoryAverageNavTask(updatetime) {
|
|
|
+
|
|
|
+ rt = '';
|
|
|
+
|
|
|
+ v_category_type = ['strategy', 'substrategy', 'bfi'];
|
|
|
+
|
|
|
+ // 取有周收益有更新的最早日期
|
|
|
+ date_hedge_fund = get_oldest_date_by_weekly_return_updatetime('PF', updatetime, true);
|
|
|
+ date_mutual_fund = get_oldest_date_by_weekly_return_updatetime('MF', updatetime, true);
|
|
|
+
|
|
|
+ if(date_hedge_fund.isNull() && date_mutual_fund.isNull()) return rt;
|
|
|
+
|
|
|
+ is_save_local = iif(updatetime <= get_ini_data_const()['date'], true, false);
|
|
|
+
|
|
|
+ //
|
|
|
+ for(category_type in v_category_type) {
|
|
|
+
|
|
|
+ oldest_date = min([date_hedge_fund, date_mutual_fund]);
|
|
|
+
|
|
|
+ // it could take mysql a few minutes to get results
|
|
|
+ t_ret = get_category_avg_weekly_return(category_type, oldest_date, 5, 30, true);
|
|
|
+
|
|
|
+ if(t_ret.isVoid() || t_ret.size() == 0) continue;
|
|
|
+
|
|
|
+ t_ret.rename!('index_id', 'entity_id');
|
|
|
+
|
|
|
+ t_tmp = cal_entity_nav_by_return('FI', t_ret, 'w');
|
|
|
+
|
|
|
+ if(! t_tmp.isVoid() && t_tmp.size() > 0) {
|
|
|
+
|
|
|
+ t_index_value = SELECT entity_id AS index_id, price_date, nav AS index_value, incl_cal_count AS incl_cal_fund_count, total_cnt AS total_fund_count
|
|
|
+ FROM ej(t_tmp, t_ret, ['entity_id', 'price_date']);
|
|
|
+ indexes_ty_index
|
|
|
+ save_and_sync(t_index_value, 'raw_db.indexes_ty_index', );
|
|
|
+
|
|
|
+ if(is_save_local == true) {
|
|
|
+ save_table(t_index_value, 'mfdb.indexes_ty_index', false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return rt;
|
|
|
+}
|
|
|
+
|