基金持仓成本分析脚本

liy36 / 2024-08-07 / 原文

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#

from collections import namedtuple

# 定义一个命名元组来存储赎回费率的期限和费率
RedemptionRate = namedtuple("RedemptionRate", ["days", "rate"])


def calculate_costs(P, T, F_A, M_A, S_A, T_A, R_A, M_C, S_C, T_C, R_C):
    # A类基金总成本
    C_A = P * F_A + P * (M_A + S_A + T_A) * (T / 365) + P * R_A(T)
    # C类基金总成本
    C_C = P * (M_C + S_C + T_C) * (T / 365) + P * R_C(T)
    return C_A, C_C


def redemption_fee_A(T, redemption_rates_A):
    for rate in redemption_rates_A:
        if T <= rate.days:
            return rate.rate
    return 0  # 持有时间大于所有设定的期限时,赎回费为0%


def redemption_fee_C(T, redemption_rates_C):
    for rate in redemption_rates_C:
        if T <= rate.days:
            return rate.rate
    return 0  # 持有时间大于所有设定的期限时,赎回费为0%


# 初始投资金额
P = 10000  # 示例金额,可以修改

# 持有时间(天)
T_values = [30, 60, 90, 180, 365, 730]  # 示例持有时间,可以修改

# A类基金费用结构(百分比表示)
F_A = 0.05 / 100  # 0.05% 前端收费
M_A = 0.15 / 100  # 0.15% 年管理费
S_A = 0 / 100  # 0% 销售服务费
T_A = 0.05 / 100  # 0.05% 托管费

# C类基金费用结构(百分比表示)
M_C = 0.15 / 100  # 0.15% 年管理费
S_C = 0.1 / 100  # 0.05% 销售服务费
T_C = 0.05 / 100  # 0.05% 托管费

# A类基金赎回费率(天数:费率)
redemption_rates_A = {
    RedemptionRate(days=7, rate=1.5 / 100),  # 小于7天,1.5%
    RedemptionRate(days=30, rate=0.1 / 100),  # 大于7天小于30天,0.1%
}

# C类基金赎回费率(天数:费率)
redemption_rates_C = {
    RedemptionRate(days=7, rate=1.5 / 100),  # 小于7天,1.5%
    RedemptionRate(days=30, rate=0.1 / 100),  # 大于7天小于30天,0.1%
}

print(
    f"{'持有时间(天)':<10} {'A类基金总成本':<10} {'C类基金总成本':<10} {'更便宜的基金':<10}"
)
print("=" * 70)

recommendation_threshold = None

for T in T_values:
    C_A, C_C = calculate_costs(
        P,
        T,
        F_A,
        M_A,
        S_A,
        T_A,
        lambda T: redemption_fee_A(T, redemption_rates_A),
        M_C,
        S_C,
        T_C,
        lambda T: redemption_fee_C(T, redemption_rates_C),
    )
    cheaper_fund = "A类" if C_A < C_C else "C类"
    print(f"{T:<15} {C_A:<20.2f} {C_C:<20.2f} {cheaper_fund:<15}")
    if recommendation_threshold is None and C_A < C_C:
        recommendation_threshold = T

if recommendation_threshold is None:
    recommendation_threshold = "所有持有时间均推荐C类"
else:
    # 精确找到临界点
    for T in range(recommendation_threshold - 30, recommendation_threshold + 30):
        C_A, C_C = calculate_costs(
            P,
            T,
            F_A,
            M_A,
            S_A,
            T_A,
            lambda T: redemption_fee_A(T, redemption_rates_A),
            M_C,
            S_C,
            T_C,
            lambda T: redemption_fee_C(T, redemption_rates_C),
        )
        if C_A < C_C:
            recommendation_threshold = T
            break

print("=" * 70)
if isinstance(recommendation_threshold, int):
    print(
        f"大于{recommendation_threshold}天推荐A类,小于等于{recommendation_threshold}天推荐C类"
    )
else:
    print(recommendation_threshold)

输出

持有时间(天)    A类基金总成本    C类基金总成本    更便宜的基金    
======================================================================
30              16.64                12.47                C类             
60              8.29                 4.93                 C类             
90              9.93                 7.40                 C类             
180             14.86                14.79                C类             
365             25.00                30.00                A类             
730             45.00                60.00                A类             
======================================================================
大于335天推荐A类,小于等于335天推荐C类