Skip to content

Commit

Permalink
0.9.58 update
Browse files Browse the repository at this point in the history
  • Loading branch information
zengbin93 committed Aug 24, 2024
1 parent bd7ba95 commit 7698520
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
14 changes: 10 additions & 4 deletions czsc/utils/st_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,28 @@ def show_daily_return(df: pd.DataFrame, **kwargs):
- legend_only_cols: list,仅在图例中展示的列名
- use_st_table: bool,是否使用 st.table 展示绩效指标,默认为 False
- plot_cumsum: bool,是否展示日收益累计曲线,默认为 True
- yearly_days: int,年交易天数,默认为 252
"""
if not df.index.dtype == "datetime64[ns]":
df["dt"] = pd.to_datetime(df["dt"])
df.set_index("dt", inplace=True)
assert df.index.dtype == "datetime64[ns]", "index必须是datetime64[ns]类型, 请先使用 pd.to_datetime 进行转换"
yearly_days = kwargs.get("yearly_days", 252)

df = df.copy().fillna(0)
df.sort_index(inplace=True, ascending=True)

def _stats(df_, type_="持有日"):
df_ = df_.copy()
stats = []
for col in df_.columns:
for _col in df_.columns:
if type_ == "持有日":
col_stats = czsc.daily_performance([x for x in df_[col] if x != 0])
col_stats = czsc.daily_performance([x for x in df_[_col] if x != 0], yearly_days=yearly_days)
else:
assert type_ == "交易日", "type_ 参数必须是 持有日 或 交易日"
col_stats = czsc.daily_performance(df_[col])
col_stats["日收益名称"] = col
col_stats = czsc.daily_performance(df_[_col])
col_stats["日收益名称"] = _col
stats.append(col_stats)

stats = pd.DataFrame(stats).set_index("日收益名称")
Expand All @@ -51,6 +53,7 @@ def _stats(df_, type_="持有日"):
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["最大回撤"])
stats = stats.background_gradient(cmap="RdYlGn_r", axis=None, subset=["卡玛"])
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["年化波动率"])
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["下行波动率"])
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["盈亏平衡点"])
stats = stats.background_gradient(cmap="RdYlGn_r", axis=None, subset=["日胜率"])
stats = stats.background_gradient(cmap="RdYlGn_r", axis=None, subset=["非零覆盖"])
Expand All @@ -61,6 +64,7 @@ def _stats(df_, type_="持有日"):
{
"盈亏平衡点": "{:.2f}",
"年化波动率": "{:.2%}",
"下行波动率": "{:.2%}",
"最大回撤": "{:.2%}",
"卡玛": "{:.2f}",
"年化": "{:.2%}",
Expand Down Expand Up @@ -585,6 +589,7 @@ def show_yearly_stats(df, ret_col, **kwargs):
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["最大回撤"])
stats = stats.background_gradient(cmap="RdYlGn_r", axis=None, subset=["卡玛"])
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["年化波动率"])
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["下行波动率"])
stats = stats.background_gradient(cmap="RdYlGn", axis=None, subset=["盈亏平衡点"])
stats = stats.background_gradient(cmap="RdYlGn_r", axis=None, subset=["日胜率"])
stats = stats.background_gradient(cmap="RdYlGn_r", axis=None, subset=["非零覆盖"])
Expand All @@ -596,6 +601,7 @@ def show_yearly_stats(df, ret_col, **kwargs):
{
"盈亏平衡点": "{:.2f}",
"年化波动率": "{:.2%}",
"下行波动率": "{:.2%}",
"最大回撤": "{:.2%}",
"卡玛": "{:.2f}",
"年化": "{:.2%}",
Expand Down
7 changes: 6 additions & 1 deletion czsc/utils/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ def daily_performance(daily_returns, **kwargs):
- 卡玛比率 = 年化收益率 / 最大回撤(如果最大回撤不为零,则除以最大回撤;否则为10)
- 日胜率 = 大于零的日收益率的个数 / 日收益率的总个数
- 年化波动率 = 日收益率的标准差 * 标准差的根号252
- 下行波动率 = 日收益率中小于零的日收益率的标准差 * 标准差的根号252
- 非零覆盖 = 非零的日收益率个数 / 日收益率的总个数
- 回撤风险 = 最大回撤 / 年化波动率;一般认为 1 以下为低风险,1-2 为中风险,2 以上为高风险
4. 将所有指标的值存储在一个字典中,其中键为指标名称,值为相应的计算结果。
4. 将所有指标的值存储在字典中,其中键为指标名称,值为相应的计算结果。
:param daily_returns: 日收益率数据,样例:
[0.01, 0.02, -0.01, 0.03, 0.02, -0.02, 0.01, -0.01, 0.02, 0.01]
Expand All @@ -101,6 +102,7 @@ def daily_performance(daily_returns, **kwargs):
"卡玛": 0,
"日胜率": 0,
"年化波动率": 0,
"下行波动率": 0,
"非零覆盖": 0,
"盈亏平衡点": 0,
"新高间隔": 0,
Expand All @@ -118,6 +120,8 @@ def daily_performance(daily_returns, **kwargs):
annual_volatility = np.std(daily_returns) * np.sqrt(yearly_days)
none_zero_cover = len(daily_returns[daily_returns != 0]) / len(daily_returns)

downside_volatility = np.std(daily_returns[daily_returns < 0]) * np.sqrt(yearly_days)

# 计算最大新高间隔
max_interval = Counter(np.maximum.accumulate(cum_returns).tolist()).most_common(1)[0][1]

Expand All @@ -141,6 +145,7 @@ def __min_max(x, min_val, max_val, digits=4):
"卡玛": __min_max(kama, -10, 10, 2),
"日胜率": round(win_pct, 4),
"年化波动率": round(annual_volatility, 4),
"下行波动率": round(downside_volatility, 4),
"非零覆盖": round(none_zero_cover, 4),
"盈亏平衡点": round(cal_break_even_point(daily_returns), 4),
"新高间隔": max_interval,
Expand Down

0 comments on commit 7698520

Please sign in to comment.