module fundit::performanceDataPuller use fundit::sqlUtilities /* * 通用取有更新的数据 * * NOTE: isvalid = 0 的记录也会被返回 * * Example: get_data_by_updatetime('mfdb.fund_performance_weekly', 2024.11.14T11:10:00, true); * */ def get_data_by_updatetime(table_name, updatetime, isFromMySQL=true) { if(isFromMySQL == true) { s_query = "SELECT * FROM " + table_name + " WHERE updatetime >= '" + updatetime + "'"; conn = connect_mysql() t = odbc::query(conn, s_query) conn.close() } else { } return t } /* * 取有周收益更新的基金组合列表及其最早日期 * * @param entity_type : MF,HF,MI,FI * @param entity_ids * * Example: get_entity_list_by_weekly_return_updatetime('PF', NULL, 2024.11.20, true); */ def get_entity_list_by_weekly_return_updatetime(entity_type, entity_ids, updatetime, isFromMySQL=true) { tmp = get_performance_weekly_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 + ")"; } sql_entity_id += iif(entity_type == 'PF', '', " AND " + tmp.sec_id_col[0] + " LIKE '" + tmp.prefix[0] + "%'"); if(isFromMySQL == true) { s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, MIN(price_date) 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"; conn = connect_mysql() t = odbc::query(conn, s_query) conn.close() } else { } return t } /* * 取有更新的最早周收益数据日期 * * @return * * Example: get_oldest_date_by_weekly_return_updatetime('MF', 2024.11.20, true); */ def get_oldest_date_by_weekly_return_updatetime(entity_type, updatetime, isFromMySQL=true) { rt = null; tmp = get_performance_weekly_table_description(entity_type); if(tmp.isVoid() || tmp.size() == 0 ) return rt; sql_entity_id = iif(entity_type == 'PF', '', " AND " + tmp.sec_id_col[0] + " LIKE '" + tmp.prefix[0] + "%'"); if(isFromMySQL == true) { nav_table_name = tmp.table_name[0]; s_query = "SELECT MIN(price_date) AS price_date FROM " + tmp.table_name[0] + " WHERE updatetime >= '" + updatetime$STRING + "'" + sql_entity_id + " AND " + tmp.cumulative_nav_col[0] + " > 0 GROUP BY " + tmp.sec_id_col[0]; conn = connect_mysql() t = odbc::query(conn, s_query) conn.close() if(t.isVoid() || t.size() == 0) return rt; rt = t[0].price_date; } else { } return rt; } /* * 通用取周净值 * * Example: get_weekly_ret('MF', ['MF00003PW1'], 2024.06.01, today(), true); * get_weekly_ret('PF', [166002], 2024.06.01, today(), true); */ def get_weekly_ret(entity_type, entity_ids, start_date=1990.01.01, end_date=2099.12.31, isFromMySQL=true){ s_entity_ids = ids_to_string(entity_ids); if(s_entity_ids == null || s_entity_ids == '') return null; tmp = get_performance_weekly_table_description(entity_type); if(isFromMySQL == true) { s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, year_week, price_date, ret_1w 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 AND price_date BETWEEN '" + start_date + "' AND '" + end_date + "' ORDER BY " + tmp.sec_id_col[0] + ", price_date"; conn = connect_mysql() t = odbc::query(conn, s_query) conn.close() } else { tb_local = load_table_from_local("fundit", tmp.table_name[0]) } return t } /* * 通用取周收益 * */ def get_entity_weekly_rets(entity_type, entity_info) { rets = null; if(entity_info.isVoid() || entity_info.size() == 0) return rets; very_old_date = '1990.01.01'; // 简单起见,取整个数据集的最新日期(month-end production时取上月最后一天即可 end_day = entity_info.price_date.max(); return get_weekly_ret(entity_type, entity_info.entity_id, very_old_date, end_day, true); } /* * 通用取月收益 * * @param entity_type : * @param entity_ids : * @param start_date : * @param end_date : * @param isFromMySQL : * * * 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) { s_entity_ids = ids_to_string(entity_ids); if(s_entity_ids == null || s_entity_ids == '') return null; tmp = get_performance_table_description(entity_type); 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, " + 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 AND end_date BETWEEN '" + yyyymm_start + "' AND '" + yyyymm_end + "' ORDER BY " + tmp.sec_id_col[0] + ", end_date"; conn = connect_mysql() t = odbc::query(conn, s_query) conn.close() } else { tb_local = load_table_from_local("fundit", tmp.table_name[0]) s_col = (sqlCol(tmp.sec_id_col[0]), sqlCol("end_date"), sqlColAlias(, "ret"), sqlColAlias(, "nav"), sqlCol("ret_ytd_a"), sqlCol("ret_incep_a")) // TODO: how to make the "fund_id" dynamicly decided by tmp.sec_id_col[0], then rename to "entity_id"? s_where = expr(, in, s_entity_ids.strReplace("'", "").split(",")) t = sql(s_col, tb_local, s_where).eval() } return t } /* * 取无风险月度利率 * * get_risk_free_rate(1990.01.01, today()) */ def get_risk_free_rate(start_date, end_date) { return get_monthly_ret('MI', "'IN0000000M'", start_date, end_date, true); } /* * 取基金最新收益及净值 * * Example: get_entity_list_by_latest_return_updatetime('HF', ['HF000004KN','HF00018WXG'], 2024.01.01, true) * get_entity_list_by_latest_return_updatetime('HF', NULL, 2024.11.01, true) */ def get_entity_list_by_latest_return_updatetime(entity_type, entity_ids, updatetime, isFromMySQL=true) { tmp = get_latest_performance_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 + ")"; } sql_entity_id += iif(entity_type == 'PF', '', " AND " + tmp.sec_id_col[0] + " LIKE '" + tmp.prefix[0] + "%'"); if(isFromMySQL == true) { s_query = "SELECT " + tmp.sec_id_col[0] + " AS entity_id, price_date, end_date FROM " + tmp.table_name[0] + " WHERE isvalid = 1 " + sql_entity_id + " AND " + tmp.cumulative_nav_col[0] + " > 0 AND updatetime >= '" + updatetime$STRING + "' ORDER BY " + tmp.sec_id_col[0]; conn = connect_mysql() t = odbc::query(conn, s_query) conn.close() } else { tb_local = load_table_from_local("fundit", "mfdb.fund_latest_nav_performance") s_col = sqlCol("*") s_where = expr(, in, entity_ids.strReplace("'", "").split(",")) t = sql(s_col, tb_local, s_where).eval() } return t } /* * 通用取给定日期之后(含此日期)的净值 * * @param price_date * * * * Example: get_nav_by_price_date('MF', "'MF00003PW1','MF00003PW2'", 2024.05.01, false); * 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); 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 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 isvalid = 1 " + sql_entity_id + sql_price_date + " AND " + tmp.cumulative_nav_col[0] + " > 0 ORDER BY " + tmp.sec_id_col[0] + ", " + tmp.price_date_col[0]; conn = connect_mysql(); t = odbc::query(conn, s_query); conn.close(); } else { tb_local = load_table_from_local("fundit", tmp.table_name[0]); pd = price_date; t =