Commit a570b2f0 authored by 赵杰's avatar 赵杰

修复bug

parent 30bd88a4
...@@ -381,8 +381,10 @@ class PortfolioDiagnose(object): ...@@ -381,8 +381,10 @@ class PortfolioDiagnose(object):
if self.end_date is None: if self.end_date is None:
self.end_date = datetime.datetime(datetime.date.today().year, self.end_date = datetime.datetime(datetime.date.today().year,
datetime.date.today().month, 1) - datetime.timedelta(1) datetime.date.today().month, 1) - datetime.timedelta(1)
if self.start_date is None:
self.start_date = cal_date(self.end_date, 'Y', 1) self.start_date = cal_date(self.end_date, 'Y', 1)
else:
self.start_date = datetime.datetime(start_date.year, start_date.month, start_date.day)
self.replace_pair = dict() # 由于数据不足半年而被替换为相同基金经理和策略的原基金和替换基金的映射 self.replace_pair = dict() # 由于数据不足半年而被替换为相同基金经理和策略的原基金和替换基金的映射
self.no_data_fund = [] # 未在数据库中找到基金净值或者基金经理记录的基金 self.no_data_fund = [] # 未在数据库中找到基金净值或者基金经理记录的基金
self.abandon_fund_score = [] # 打分不满足要求的基金 self.abandon_fund_score = [] # 打分不满足要求的基金
...@@ -544,15 +546,16 @@ class PortfolioDiagnose(object): ...@@ -544,15 +546,16 @@ class PortfolioDiagnose(object):
proposal_nav = rename_col(proposal_nav, proposal) proposal_nav = rename_col(proposal_nav, proposal)
# 按最大周期进行重采样,计算新建组合的相关性 # 按最大周期进行重采样,计算新建组合的相关性
prod = pd.merge(prod, proposal_nav, how='outer', on='end_date').astype(float) prod_with_new_fund = pd.merge(prod, proposal_nav, how='outer', on='end_date').astype(float)
prod.sort_index(inplace=True) prod_with_new_fund.sort_index(inplace=True)
prod.ffill(inplace=True) prod_with_new_fund.ffill(inplace=True)
prod = resample(prod, get_trade_cal(), min(self.freq_list))
self.new_correlation = cal_correlation(prod) prod_with_new_fund = resample(prod_with_new_fund, get_trade_cal(), min(self.freq_list))
self.new_correlation = cal_correlation(prod_with_new_fund)
judge_correlation = self.new_correlation.fillna(0) judge_correlation = self.new_correlation.fillna(0)
if np.all(judge_correlation < 0.8): if np.all(judge_correlation < 0.8):
prod = prod_with_new_fund
self.proposal_fund.append(proposal) self.proposal_fund.append(proposal)
max_len -= 1 max_len -= 1
# add_strategy -= {proposal_strategy} # add_strategy -= {proposal_strategy}
...@@ -561,7 +564,8 @@ class PortfolioDiagnose(object): ...@@ -561,7 +564,8 @@ class PortfolioDiagnose(object):
if max_len == 0: if max_len == 0:
break break
else: else:
prod.drop(columns=proposal, inplace=True) # prod.drop(columns=proposal, inplace=True)
self.freq_list.pop()
prod.dropna(how='all', inplace=True) prod.dropna(how='all', inplace=True)
prod.fillna(method='bfill', inplace=True) prod.fillna(method='bfill', inplace=True)
...@@ -704,9 +708,9 @@ class PortfolioDiagnose(object): ...@@ -704,9 +708,9 @@ class PortfolioDiagnose(object):
# 正收益基金数量 # 正收益基金数量
group_hold_data = pd.DataFrame(group_result[group_name]["group_hoding_info"]) group_hold_data = pd.DataFrame(group_result[group_name]["group_hoding_info"])
profit_positive_num = group_hold_data[group_hold_data["profit"] > 0]["profit"].count() profit_positive_num = len(group_hold_data[group_hold_data["profit"] > 0]["fund_name"].unique())
if profit_positive_num > 0: if profit_positive_num > 0:
profit_positive_evaluate = str(profit_positive_num) + "只基金取正收益," profit_positive_evaluate = str(profit_positive_num) + "只基金取得正收益取得正收益,"
else: else:
profit_positive_evaluate = "" profit_positive_evaluate = ""
...@@ -733,7 +737,7 @@ class PortfolioDiagnose(object): ...@@ -733,7 +737,7 @@ class PortfolioDiagnose(object):
strategy_distribution_evaluate = "策略上有一定分散" strategy_distribution_evaluate = "策略上有一定分散"
else: else:
strategy_distribution_evaluate = "策略分散程度不高" strategy_distribution_evaluate = "策略分散程度不高"
except ZeroDivisionError: except:
strategy_distribution_evaluate = "策略分散程度不高" strategy_distribution_evaluate = "策略分散程度不高"
# 相关性 # 相关性
if len(self.abandon_fund_corr) > 0: if len(self.abandon_fund_corr) > 0:
...@@ -824,7 +828,13 @@ class PortfolioDiagnose(object): ...@@ -824,7 +828,13 @@ class PortfolioDiagnose(object):
return_compare_df = pd.merge(index_return[["new_index_return"]], old_return_df[["cum_return_ratio"]], return_compare_df = pd.merge(index_return[["new_index_return"]], old_return_df[["cum_return_ratio"]],
right_index=True, right_index=True,
left_index=True) left_index=True)
start = return_compare_df.index.values[0]
if start > pd.to_datetime(self.start_date):
row = [0, 0]
return_compare_df.loc[pd.to_datetime(self.start_date)] = row
return_compare_df["date"] = return_compare_df.index return_compare_df["date"] = return_compare_df.index
return_compare_df.sort_values(by="date", inplace=True)
return_compare_df["date"] = return_compare_df["date"].apply(lambda x: x.strftime("%Y-%m-%d")) return_compare_df["date"] = return_compare_df["date"].apply(lambda x: x.strftime("%Y-%m-%d"))
return_compare_df.iloc[1:-1, :]["date"] = "" return_compare_df.iloc[1:-1, :]["date"] = ""
old_return_compare_result = { old_return_compare_result = {
...@@ -944,7 +954,12 @@ class PortfolioDiagnose(object): ...@@ -944,7 +954,12 @@ class PortfolioDiagnose(object):
# 新组合夏普比率 # 新组合夏普比率
sim = simple_return(propose_fund_return_limit_data["new_return"]+1) sim = simple_return(propose_fund_return_limit_data["new_return"]+1)
exc = excess_return(sim, BANK_RATE, n_freq) exc = excess_return(sim, BANK_RATE, n_freq)
new_sharpe = sharpe_ratio(exc, sim, n_freq) try:
new_sharpe = sharpe_ratio(exc, sim, n_freq)
if new_sharpe is None or math.isnan(new_sharpe):
new_sharpe = 0
except:
new_sharpe = 0
# 指数收益 # 指数收益
index_return = index_return[index_return.index >= group_order_start_date] index_return = index_return[index_return.index >= group_order_start_date]
...@@ -956,7 +971,12 @@ class PortfolioDiagnose(object): ...@@ -956,7 +971,12 @@ class PortfolioDiagnose(object):
index_drawdown = max_drawdown(index_return["new_index_return"]+1) index_drawdown = max_drawdown(index_return["new_index_return"]+1)
index_sim = simple_return(index_return["new_index_return"]+1) index_sim = simple_return(index_return["new_index_return"]+1)
index_exc = excess_return(index_sim, BANK_RATE, n_freq) index_exc = excess_return(index_sim, BANK_RATE, n_freq)
index_sharpe = sharpe_ratio(index_exc, index_sim, n_freq) try:
index_sharpe = sharpe_ratio(index_exc, index_sim, n_freq)
if index_sharpe is None or math.isnan(index_sharpe):
index_sharpe = 0.0
except:
index_sharpe = 0.0
# 收益对比数据 # 收益对比数据
return_compare_df = pd.merge(index_return[["new_index_return"]], old_return_df[["cum_return_ratio"]], right_index=True, return_compare_df = pd.merge(index_return[["new_index_return"]], old_return_df[["cum_return_ratio"]], right_index=True,
......
...@@ -1041,28 +1041,28 @@ ...@@ -1041,28 +1041,28 @@
<table class="tss1_table"> <table class="tss1_table">
<tr> <tr>
<td> <td>
{%if month_rise>=0%} {%if (month_rise|float)>=0%}
本月涨幅:<span class="red">{{month_rise}}%</span> 本月涨幅:<span class="red">{{month_rise}}%</span>
{%else%} {%else%}
本月涨幅:<span class="green">{{month_rise}}%</span> 本月涨幅:<span class="green">{{month_rise}}%</span>
{%endif%} {%endif%}
</td> </td>
<td> <td>
{%if now_month_income>=0%} {%if (now_month_income| float) >=0%}
本月收益:<span class="red">{{now_month_income}}元</span> 本月收益:<span class="red">{{now_month_income}}元</span>
{%else%} {%else%}
本月收益:<span class="green">{{now_month_income}}元</span> 本月收益:<span class="green">{{now_month_income}}元</span>
{%endif%} {%endif%}
</td> </td>
<td> <td>
{%if year_totoal_rate_of_return>=0%} {%if (year_totoal_rate_of_return|float)>=0%}
今年累计收益率:<span class="red">{{year_totoal_rate_of_return}}%</span> 今年累计收益率:<span class="red">{{year_totoal_rate_of_return}}%</span>
{%else%} {%else%}
今年累计收益率:<span class="green">{{year_totoal_rate_of_return}}%</span> 今年累计收益率:<span class="green">{{year_totoal_rate_of_return}}%</span>
{%endif%} {%endif%}
</td> </td>
<td> <td>
{%if now_year_income>=0%} {%if (now_year_income|float)>=0%}
今年累计收益:<span class="red">{{now_year_income}}元</span> 今年累计收益:<span class="red">{{now_year_income}}元</span>
{%else%} {%else%}
今年累计收益:<span class="green">{{now_year_income}}元</span> 今年累计收益:<span class="green">{{now_year_income}}元</span>
...@@ -1071,21 +1071,21 @@ ...@@ -1071,21 +1071,21 @@
</tr> </tr>
<tr> <tr>
<td> <td>
{%if now_yield>=0%} {%if (now_yield|float)>=0%}
成立以来累计收益率:<span class="red">{{now_yield}}%</span> 成立以来累计收益率:<span class="red">{{now_yield}}%</span>
{%else%} {%else%}
成立以来累计收益率:<span class="green">{{now_yield}}%</span> 成立以来累计收益率:<span class="green">{{now_yield}}%</span>
{%endif%} {%endif%}
</td> </td>
<td> <td>
{%if now_annualised_return>=0%} {%if (now_annualised_return|float)>=0%}
年化收益率:<span class="red">{{now_annualised_return}}%</span> 年化收益率:<span class="red">{{now_annualised_return}}%</span>
{%else%} {%else%}
年化收益率:<span class="green">{{now_annualised_return}}%</span> 年化收益率:<span class="green">{{now_annualised_return}}%</span>
{%endif%} {%endif%}
</td> </td>
<td> <td>
{%if now_withdrawal>=0%} {%if (now_withdrawal|float)>=0%}
最大回撤:<span class="red">{{now_withdrawal}}%</span> 最大回撤:<span class="red">{{now_withdrawal}}%</span>
{%else%} {%else%}
最大回撤:<span class="green">{{now_withdrawal}}%</span> 最大回撤:<span class="green">{{now_withdrawal}}%</span>
...@@ -1117,7 +1117,7 @@ ...@@ -1117,7 +1117,7 @@
</td> </td>
<td> <td>
{%if total_profit>=0%} {%if (total_profit|float)>=0%}
累计盈利:<span class="red">{{total_profit}}元</span> 累计盈利:<span class="red">{{total_profit}}元</span>
{%else%} {%else%}
累计盈利:<span class="green">{{total_profit}}元</span> 累计盈利:<span class="green">{{total_profit}}元</span>
......
...@@ -80,7 +80,10 @@ def get_frequency(df): ...@@ -80,7 +80,10 @@ def get_frequency(df):
# freq_series = index_series - index_series.shift(1) # freq_series = index_series - index_series.shift(1)
freq_series = index_series.diff(1) freq_series = index_series.diff(1)
logging.log(logging.DEBUG, freq_series.describe()) logging.log(logging.DEBUG, freq_series.describe())
f = freq_series.mode()[0].days try:
f = freq_series.mode()[0].days
except:
return 250
if f in range(0, 3): if f in range(0, 3):
return 250 return 250
elif f in range(6, 9): elif f in range(6, 9):
...@@ -92,7 +95,7 @@ def get_frequency(df): ...@@ -92,7 +95,7 @@ def get_frequency(df):
elif f in range(110, 133): elif f in range(110, 133):
return 3 return 3
else: else:
raise ValueError return 250
def get_trade_cal(): def get_trade_cal():
......
...@@ -78,7 +78,8 @@ class DataIntegrate: ...@@ -78,7 +78,8 @@ class DataIntegrate:
self.all_folio_result[group_name] = cur_group_portfolio_result self.all_folio_result[group_name] = cur_group_portfolio_result
def get_portfolio_diagnose(self, portfolio, client_type=1, invest_amount=10000000): def get_portfolio_diagnose(self, portfolio, client_type=1, invest_amount=10000000):
portfolio_diagnose = PortfolioDiagnose(client_type=client_type, portfolio=portfolio, invest_amount=invest_amount) portfolio_diagnose = PortfolioDiagnose(client_type=client_type, portfolio=portfolio, invest_amount=invest_amount,
start_date=self.user_customer.start_date)
portfolio_diagnose.optimize() portfolio_diagnose.optimize()
return portfolio_diagnose return portfolio_diagnose
...@@ -246,7 +247,7 @@ class DataIntegrate: ...@@ -246,7 +247,7 @@ class DataIntegrate:
'team': template_folder + '/v2/img/default-user.png', 'team': template_folder + '/v2/img/default-user.png',
# 全局数据 # 全局数据
'customer_name': self.customer_name, 'customer_name': self.customer_name,
'year_month': self.user_customer.month_start_date.strftime("%Y-%m"), 'year_month': self.user_customer.month_start_date.strftime("%Y{}%m{}").format("年", "月"),
'month': self.user_customer.month_start_date.strftime("%m"), 'month': self.user_customer.month_start_date.strftime("%m"),
'start_date': self.user_customer.start_date.strftime("%Y-%m-%d"), 'start_date': self.user_customer.start_date.strftime("%Y-%m-%d"),
'latest_worth_day': self.user_customer.last_nav_date, 'latest_worth_day': self.user_customer.last_nav_date,
...@@ -254,11 +255,11 @@ class DataIntegrate: ...@@ -254,11 +255,11 @@ class DataIntegrate:
'customer_old': 42, 'customer_old': 42,
'customer_level': '平衡型', 'customer_level': '平衡型',
# 综述数据 # 综述数据
'now_allocation_amount': self.total_cost, 'now_yield': self.now_yield, 'index_yield': self.index_yield, 'now_allocation_amount': '{:,}'.format(self.total_cost), 'now_yield': self.now_yield, 'index_yield': self.index_yield,
'now_annualised_return': self.now_annualised_return, 'now_annualised_return': self.now_annualised_return,
'now_withdrawal': self.now_withdrawal, 'index_withdrawal': self.index_withdrawal, 'expected_withdrawal': 20, 'now_withdrawal': self.now_withdrawal, 'index_withdrawal': self.index_withdrawal, 'expected_withdrawal': 20,
'now_year_income': self.now_year_income, 'now_month_income': self.now_month_income, 'now_year_income': '{:,}'.format(self.now_year_income), 'now_month_income': '{:,}'.format(self.now_month_income),
'final_balance': self.final_balance, 'total_profit': self.total_profit, 'final_balance': '{:,}'.format(self.final_balance), 'total_profit': '{:,}'.format(self.total_profit),
'monthly_return_performance_pic': self.monthly_return_performance_pic, 'monthly_return_performance_pic': self.monthly_return_performance_pic,
'month_rise': self.month_rise, 'year_totoal_rate_of_return': self.year_totoal_rate_of_return, 'month_rise': self.month_rise, 'year_totoal_rate_of_return': self.year_totoal_rate_of_return,
...@@ -324,5 +325,6 @@ class DataIntegrate: ...@@ -324,5 +325,6 @@ class DataIntegrate:
if __name__ == '__main__': if __name__ == '__main__':
start = time.time() start = time.time()
DataIntegrate(ifa_id='USER_INFO15914346866762', customer_id='202009281545001') dt = DataIntegrate(ifa_id='USER_INFO15917853924996', customer_id='6741679287251775488')
dt.render_data()
print('耗时{}秒'.format(round(time.time()-start, 2))) print('耗时{}秒'.format(round(time.time()-start, 2)))
...@@ -49,7 +49,12 @@ def sharpe_ratio(excess_return, simple_return, n): ...@@ -49,7 +49,12 @@ def sharpe_ratio(excess_return, simple_return, n):
n: 数据类型, 周(52), 月(12), 日(250) n: 数据类型, 周(52), 月(12), 日(250)
""" """
import math import math
d = math.sqrt(n) * excess_return / simple_return.std(ddof=1) try:
d = math.sqrt(n) * excess_return / simple_return.std(ddof=1)
if d == float("inf") or d == float("-inf"):
return 0.0
except:
return 0.0
return d return d
...@@ -294,6 +299,8 @@ def resample(df, trading_cal, freq): ...@@ -294,6 +299,8 @@ def resample(df, trading_cal, freq):
[DataFrame]: [重采样后剔除不在交易日历中的净值表和交易日历以净值日期为索引的合表] [DataFrame]: [重采样后剔除不在交易日历中的净值表和交易日历以净值日期为索引的合表]
""" """
freq_dict = {1: 'B', 2: 'W-FRI', 3: 'M', 4: 'SM', 5: 'Q'} freq_dict = {1: 'B', 2: 'W-FRI', 3: 'M', 4: 'SM', 5: 'Q'}
if math.isnan(freq):
freq = 2
resample_freq = freq_dict[freq] resample_freq = freq_dict[freq]
# 按采样频率进行重采样并进行净值的前向填充 # 按采样频率进行重采样并进行净值的前向填充
df = df.resample(rule=resample_freq).ffill() df = df.resample(rule=resample_freq).ffill()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment