|
@@ -3,15 +3,18 @@ use fundit::fundCalculator
|
|
|
use fundit::dataPuller
|
|
|
|
|
|
/*
|
|
|
- * 根据私募基金净值序列计算月收益序列(适合提供给指标运算)
|
|
|
+ * 根据基金净值序列计算月收益序列(适合提供给指标运算)
|
|
|
*
|
|
|
* Create: 20240907 Joey
|
|
|
* TODO: missing pulling data from local
|
|
|
* TODO: ONLY support month return now
|
|
|
*
|
|
|
+ * @param entity_type <STRING>: NAV universe, 'HF','MF','PF','EQ'... defined in get_nav_table_description()
|
|
|
* @param fund_ids <STRING VECTOR>: 基金ID
|
|
|
* @param isFromMySQL <BOOL>: 净值来源 1 - 远程MySQL、 0 - 本地 DolphinDB
|
|
|
*
|
|
|
+ * Example: cal_fund_monthly_returns('HF', "'HF000004KN','HF000103EU','HF00018WXG'", true);
|
|
|
+ *
|
|
|
*/
|
|
|
def cal_fund_monthly_returns(entity_type, fund_ids, isFromMySQL){
|
|
|
|
|
@@ -23,45 +26,45 @@ def cal_fund_monthly_returns(entity_type, fund_ids, isFromMySQL){
|
|
|
// 用于保证老基金也能取到所有历史净值
|
|
|
very_old_price_date = 1990.01.01;
|
|
|
|
|
|
- // 基金基本信息,包括初始净值
|
|
|
- tb_fund_info = get_fund_info(fund_ids);
|
|
|
-
|
|
|
- // 基金净值
|
|
|
- tb_nav = SELECT * FROM get_nav_by_price_date(entity_type, fund_ids, very_old_price_date, isFromMySQL);
|
|
|
-
|
|
|
- tb_month_end = table(100:0, ['fund_id', 'price_date'], [STRING, DATE]);
|
|
|
- // 填充好各基金有效期内所有月份的最后一天
|
|
|
- for( f in tb_fund_info )
|
|
|
- {
|
|
|
- INSERT INTO tb_month_end SELECT fund_id, price_date FROM table(f.fund_id.take(1) AS fund_id).cj(table(temporalSeq(f.inception_date, today(), 'M') AS price_date)) ;
|
|
|
- }
|
|
|
-
|
|
|
- UPDATE tb_month_end SET end_date = price_date.month();
|
|
|
-
|
|
|
- tb_monthly_nav = SELECT fund_id, monthEnd(price_date).month().last() AS end_date, price_date.last() AS price_date, cumulative_nav.last() AS cumulative_nav
|
|
|
- FROM tb_nav
|
|
|
- GROUP BY fund_id, monthEnd(price_date);
|
|
|
+ // 基金基本信息,包括初始净值
|
|
|
+ tb_fund_info = get_fund_info(fund_ids);
|
|
|
|
|
|
- // 完整月末日期的净值序列(包括缺失数据为NULL)
|
|
|
- tb_monthly_nav = SELECT me.fund_id, me.end_date, n.price_date, n.cumulative_nav
|
|
|
- FROM tb_month_end me
|
|
|
- LEFT JOIN tb_monthly_nav n ON me.fund_id = n.fund_id AND me.end_date = n.end_date
|
|
|
- ORDER BY me.fund_id, me.end_date;
|
|
|
+ // 基金净值
|
|
|
+ tb_nav = SELECT * FROM get_nav_by_price_date(entity_type, fund_ids, very_old_price_date, isFromMySQL);
|
|
|
|
|
|
- // 补一下成立日的初始净值
|
|
|
- // NOTE: DolphinDB 遇见 EXISTS 语句时,似乎主表的 alias 失效,只好用全名
|
|
|
- INSERT INTO tb_monthly_nav
|
|
|
- SELECT fund_id, inception_date.month(), inception_date, ifNull(ini_value, 1)
|
|
|
- FROM tb_fund_info fi
|
|
|
- WHERE NOT EXISTS ( SELECT * FROM tb_monthly_nav n WHERE fund_id = tb_fund_info.fund_id AND n.price_date = tb_fund_info.inception_date);
|
|
|
+ tb_month_end = table(100:0, ['fund_id', 'price_date'], [STRING, DATE]);
|
|
|
+ // 填充好各基金有效期内所有月份的最后一天
|
|
|
+ for( f in tb_fund_info )
|
|
|
+ {
|
|
|
+ INSERT INTO tb_month_end SELECT fund_id, price_date FROM table(f.fund_id.take(1) AS fund_id).cj(table(temporalSeq(f.inception_date, today(), 'M') AS price_date)) ;
|
|
|
+ }
|
|
|
|
|
|
- // 算 ratios 之前先把时间顺序排好
|
|
|
- tb_monthly_nav.sortBy!(['fund_id', 'end_date', 'price_date'], [1, 1, 1]);
|
|
|
+ UPDATE tb_month_end SET end_date = price_date.month();
|
|
|
+
|
|
|
+ tb_monthly_nav = SELECT fund_id, monthEnd(price_date).month().last() AS end_date, price_date.last() AS price_date, cumulative_nav.last() AS cumulative_nav
|
|
|
+ FROM tb_nav
|
|
|
+ GROUP BY fund_id, monthEnd(price_date);
|
|
|
+
|
|
|
+ // 完整月末日期的净值序列(包括缺失数据为NULL)
|
|
|
+ tb_monthly_nav = SELECT me.fund_id, me.end_date, n.price_date, n.cumulative_nav
|
|
|
+ FROM tb_month_end me
|
|
|
+ LEFT JOIN tb_monthly_nav n ON me.fund_id = n.fund_id AND me.end_date = n.end_date
|
|
|
+ ORDER BY me.fund_id, me.end_date;
|
|
|
+
|
|
|
+ // 补一下成立日的初始净值
|
|
|
+ // NOTE: DolphinDB 遇见 EXISTS 语句时,似乎主表的 alias 失效,只好用全名
|
|
|
+ INSERT INTO tb_monthly_nav
|
|
|
+ SELECT fund_id, inception_date.month(), inception_date, ifNull(ini_value, 1)
|
|
|
+ FROM tb_fund_info fi
|
|
|
+ WHERE NOT EXISTS ( SELECT * FROM tb_monthly_nav n WHERE fund_id = tb_fund_info.fund_id AND n.price_date = tb_fund_info.inception_date);
|
|
|
+
|
|
|
+ // 算 ratios 之前先把时间顺序排好
|
|
|
+ tb_monthly_nav.sortBy!(['fund_id', 'end_date', 'price_date'], [1, 1, 1]);
|
|
|
|
|
|
- // 计算月收益
|
|
|
- tb_rets = SELECT fund_id, end_date, price_date, cumulative_nav, cumulative_nav.ratios() - 1 AS ret
|
|
|
- FROM tb_monthly_nav
|
|
|
- CONTEXT BY fund_id;
|
|
|
+ // 计算月收益
|
|
|
+ tb_rets = SELECT fund_id, end_date, price_date, cumulative_nav, cumulative_nav.ratios() - 1 AS ret
|
|
|
+ FROM tb_monthly_nav
|
|
|
+ CONTEXT BY fund_id;
|
|
|
|
|
|
|
|
|
// the records without return calculated but do have nav are still useful for some calculations
|
|
@@ -71,8 +74,8 @@ def cal_fund_monthly_returns(entity_type, fund_ids, isFromMySQL){
|
|
|
/*
|
|
|
* 月末 fund_performance 表计算
|
|
|
*
|
|
|
- * @param fund_ids: 逗号分隔的ID
|
|
|
- * @param end_date:
|
|
|
+ * @param fund_ids <STRING>: 逗号分隔的ID
|
|
|
+ * @param end_date <STRING>: YYYY-MM
|
|
|
*
|
|
|
* Example: cal_fund_performance("'HF000004KN','HF00018WXG','HF000103EU'", '2024-06', true);
|
|
|
*/
|