fund-investment-calculator


Namefund-investment-calculator JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
Summary基金定投收益计算工具,支持自动获取净值数据和交易日判断
upload_time2025-10-07 10:37:00
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT
keywords fund investment financial calculator 定投
VCS
bugtrack_url
requirements akshare exchange-calendars pandas scipy
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 基金定投收益计算工具

使用 `akshare` 获取基金净值数据,`exchange_calendars` 判断交易日,自动计算定投收益。

## 安装依赖

```bash
pip install -r requirements.txt
```

## 功能特性

- ✅ 自动计算定投日期(月/周定投)
- ✅ 支持手动投资日期配置
- ✅ 支持定投失败日期配置
- ✅ 自动获取基金净值数据
- ✅ 交易日智能判断(非交易日顺延)
- ✅ 计算总体收益、年化收益率、IRR
- ✅ 计算每笔投资的收益明细
- ✅ 支持历史任意时点收益计算

## 快速开始

### 示例1:每月定投

```python
from datetime import date
from fund import Fund

# 创建基金对象
fund = Fund(
    fund_code="005827",              # 基金代码
    buy_fee_rate=0.0015,             # 申购费率 0.15%
    regular_rule={
        "start_date": date(2024, 1, 15),
        "interval": "monthly",        # 每月定投
        "day": 15,                    # 每月15日
        "amount": 1000                # 每次1000元
    },
    skip_dates=[date(2024, 3, 15)],  # 跳过的日期
    manual_investments=[              # 手动投资
        {"date": date(2024, 2, 10), "amount": 5000}
    ]
)

# 获取所有投资日期
dates = fund.get_all_investment_dates()

# 获取投资记录明细
records = fund.get_investment_records()

# 计算总体收益
result = fund.calculate_return()
print(f"收益率: {result['return_rate']:.2f}%")
print(f"IRR: {result['irr']:.2f}%")

# 计算每笔投资收益
each_result = fund.calculate_each_investment_return()
```

### 示例2:每周定投

```python
fund = Fund(
    fund_code="110022",
    regular_rule={
        "start_date": date(2024, 9, 1),
        "interval": "weekly",
        "weekday": 4,                 # 每周五(0=周一)
        "amount": 500
    }
)
```

### 示例3:计算历史收益

```python
# 计算9月30日的收益
result = fund.calculate_return(as_of_date=date(2024, 9, 30))

# 不传日期则使用最新净值
result = fund.calculate_return()
```

## API 说明

### Fund 类

#### 构造函数

```python
Fund(
    fund_code: str,                      # 基金代码(6位)
    fund_name: str = None,               # 基金名称(可选,自动获取)
    buy_fee_rate: float = 0.0015,        # 申购费率
    regular_rule: dict = None,           # 定投规则
    skip_dates: list[date] = None,       # 跳过的日期
    manual_investments: list[dict] = None # 手动投资
)
```

**定投规则格式:**

每月定投:
```python
{
    "start_date": date(2024, 1, 15),
    "interval": "monthly",
    "day": 15,                # 每月的日期
    "amount": 1000
}
```

每周定投:
```python
{
    "start_date": date(2024, 1, 1),
    "interval": "weekly",
    "weekday": 4,             # 0=周一, 4=周五
    "amount": 500
}
```

双周定投:
```python
{
    "start_date": date(2024, 1, 1),
    "interval": "biweekly",
    "weekday": 4,
    "amount": 500
}
```

#### 方法

##### `get_all_investment_dates() -> list[date]`

返回所有投资日期(定投+手动),按时间排序。

##### `get_investment_records() -> list[dict]`

返回每笔投资的详细记录:

```python
[{
    "date": date,           # 投资日期
    "amount": float,        # 投入本金
    "fee": float,           # 手续费
    "net_amount": float,    # 扣费后金额
    "nav": float,           # 买入净值
    "shares": float         # 买入份额
}, ...]
```

##### `calculate_return(as_of_date: date = None) -> dict`

计算总体收益:

```python
{
    "as_of_date": date,           # 计算日期
    "total_cost": float,          # 总投入(含手续费)
    "total_net_cost": float,      # 总投入(扣除手续费)
    "total_shares": float,        # 总份额
    "current_nav": float,         # 当前净值
    "current_value": float,       # 当前价值
    "profit": float,              # 收益金额
    "return_rate": float,         # 收益率(%)
    "annualized_return": float,   # 年化收益率(%)
    "irr": float                  # 内部收益率(%)
}
```

##### `calculate_each_investment_return(as_of_date: date = None) -> list[dict]`

计算每笔投资的收益:

```python
[{
    "date": date,
    "amount": float,          # 投入金额
    "buy_nav": float,         # 买入净值
    "shares": float,          # 买入份额
    "current_nav": float,     # 当前净值
    "current_value": float,   # 当前价值
    "profit": float,          # 该笔收益
    "return_rate": float      # 该笔收益率(%)
}, ...]
```

## 运行示例

```bash
python example.py
```

## 注意事项

1. **净值更新时间**:基金净值在交易日收盘后(晚上18:00-22:00)公布
2. **交易日处理**:非交易日会自动顺延到下一个交易日
3. **费率**:仅考虑申购费,不考虑赎回费
4. **数据来源**:使用 akshare 从东方财富获取数据,免费无需token

## 收益率说明

### 简单收益率
```
收益率 = (当前价值 - 总投入) / 总投入 × 100%
```

### 年化收益率
```
年化收益率 = 收益率 / 持有天数 × 365
```

### IRR(内部收益率)
考虑资金的时间价值,求解使净现值为0的收益率,更准确反映投资回报。

## 常见问题

**Q: 为什么定投日期不是我设定的日期?**
A: 如果设定日期是非交易日(周末/节假日),会自动顺延到下一个交易日。

**Q: 如何查看历史某一天的收益?**
A: 使用 `calculate_return(as_of_date=date(2024, 9, 30))`

**Q: 手动投资和定投日期重叠怎么办?**
A: 系统会分别记录,两笔投资都会生效。

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fund-investment-calculator",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "fund, investment, financial, calculator, \u5b9a\u6295",
    "author": null,
    "author_email": "liwenyi <lwy.lwy@163.com>",
    "download_url": "https://files.pythonhosted.org/packages/30/f5/03c5c357fc4838a6f842bf2f7ac432cae3d35d1003afb0a3bd313c64a40b/fund_investment_calculator-0.1.0.tar.gz",
    "platform": null,
    "description": "# \u57fa\u91d1\u5b9a\u6295\u6536\u76ca\u8ba1\u7b97\u5de5\u5177\n\n\u4f7f\u7528 `akshare` \u83b7\u53d6\u57fa\u91d1\u51c0\u503c\u6570\u636e\uff0c`exchange_calendars` \u5224\u65ad\u4ea4\u6613\u65e5\uff0c\u81ea\u52a8\u8ba1\u7b97\u5b9a\u6295\u6536\u76ca\u3002\n\n## \u5b89\u88c5\u4f9d\u8d56\n\n```bash\npip install -r requirements.txt\n```\n\n## \u529f\u80fd\u7279\u6027\n\n- \u2705 \u81ea\u52a8\u8ba1\u7b97\u5b9a\u6295\u65e5\u671f\uff08\u6708/\u5468\u5b9a\u6295\uff09\n- \u2705 \u652f\u6301\u624b\u52a8\u6295\u8d44\u65e5\u671f\u914d\u7f6e\n- \u2705 \u652f\u6301\u5b9a\u6295\u5931\u8d25\u65e5\u671f\u914d\u7f6e\n- \u2705 \u81ea\u52a8\u83b7\u53d6\u57fa\u91d1\u51c0\u503c\u6570\u636e\n- \u2705 \u4ea4\u6613\u65e5\u667a\u80fd\u5224\u65ad\uff08\u975e\u4ea4\u6613\u65e5\u987a\u5ef6\uff09\n- \u2705 \u8ba1\u7b97\u603b\u4f53\u6536\u76ca\u3001\u5e74\u5316\u6536\u76ca\u7387\u3001IRR\n- \u2705 \u8ba1\u7b97\u6bcf\u7b14\u6295\u8d44\u7684\u6536\u76ca\u660e\u7ec6\n- \u2705 \u652f\u6301\u5386\u53f2\u4efb\u610f\u65f6\u70b9\u6536\u76ca\u8ba1\u7b97\n\n## \u5feb\u901f\u5f00\u59cb\n\n### \u793a\u4f8b1\uff1a\u6bcf\u6708\u5b9a\u6295\n\n```python\nfrom datetime import date\nfrom fund import Fund\n\n# \u521b\u5efa\u57fa\u91d1\u5bf9\u8c61\nfund = Fund(\n    fund_code=\"005827\",              # \u57fa\u91d1\u4ee3\u7801\n    buy_fee_rate=0.0015,             # \u7533\u8d2d\u8d39\u7387 0.15%\n    regular_rule={\n        \"start_date\": date(2024, 1, 15),\n        \"interval\": \"monthly\",        # \u6bcf\u6708\u5b9a\u6295\n        \"day\": 15,                    # \u6bcf\u670815\u65e5\n        \"amount\": 1000                # \u6bcf\u6b211000\u5143\n    },\n    skip_dates=[date(2024, 3, 15)],  # \u8df3\u8fc7\u7684\u65e5\u671f\n    manual_investments=[              # \u624b\u52a8\u6295\u8d44\n        {\"date\": date(2024, 2, 10), \"amount\": 5000}\n    ]\n)\n\n# \u83b7\u53d6\u6240\u6709\u6295\u8d44\u65e5\u671f\ndates = fund.get_all_investment_dates()\n\n# \u83b7\u53d6\u6295\u8d44\u8bb0\u5f55\u660e\u7ec6\nrecords = fund.get_investment_records()\n\n# \u8ba1\u7b97\u603b\u4f53\u6536\u76ca\nresult = fund.calculate_return()\nprint(f\"\u6536\u76ca\u7387: {result['return_rate']:.2f}%\")\nprint(f\"IRR: {result['irr']:.2f}%\")\n\n# \u8ba1\u7b97\u6bcf\u7b14\u6295\u8d44\u6536\u76ca\neach_result = fund.calculate_each_investment_return()\n```\n\n### \u793a\u4f8b2\uff1a\u6bcf\u5468\u5b9a\u6295\n\n```python\nfund = Fund(\n    fund_code=\"110022\",\n    regular_rule={\n        \"start_date\": date(2024, 9, 1),\n        \"interval\": \"weekly\",\n        \"weekday\": 4,                 # \u6bcf\u5468\u4e94\uff080=\u5468\u4e00\uff09\n        \"amount\": 500\n    }\n)\n```\n\n### \u793a\u4f8b3\uff1a\u8ba1\u7b97\u5386\u53f2\u6536\u76ca\n\n```python\n# \u8ba1\u7b979\u670830\u65e5\u7684\u6536\u76ca\nresult = fund.calculate_return(as_of_date=date(2024, 9, 30))\n\n# \u4e0d\u4f20\u65e5\u671f\u5219\u4f7f\u7528\u6700\u65b0\u51c0\u503c\nresult = fund.calculate_return()\n```\n\n## API \u8bf4\u660e\n\n### Fund \u7c7b\n\n#### \u6784\u9020\u51fd\u6570\n\n```python\nFund(\n    fund_code: str,                      # \u57fa\u91d1\u4ee3\u7801\uff086\u4f4d\uff09\n    fund_name: str = None,               # \u57fa\u91d1\u540d\u79f0\uff08\u53ef\u9009\uff0c\u81ea\u52a8\u83b7\u53d6\uff09\n    buy_fee_rate: float = 0.0015,        # \u7533\u8d2d\u8d39\u7387\n    regular_rule: dict = None,           # \u5b9a\u6295\u89c4\u5219\n    skip_dates: list[date] = None,       # \u8df3\u8fc7\u7684\u65e5\u671f\n    manual_investments: list[dict] = None # \u624b\u52a8\u6295\u8d44\n)\n```\n\n**\u5b9a\u6295\u89c4\u5219\u683c\u5f0f\uff1a**\n\n\u6bcf\u6708\u5b9a\u6295\uff1a\n```python\n{\n    \"start_date\": date(2024, 1, 15),\n    \"interval\": \"monthly\",\n    \"day\": 15,                # \u6bcf\u6708\u7684\u65e5\u671f\n    \"amount\": 1000\n}\n```\n\n\u6bcf\u5468\u5b9a\u6295\uff1a\n```python\n{\n    \"start_date\": date(2024, 1, 1),\n    \"interval\": \"weekly\",\n    \"weekday\": 4,             # 0=\u5468\u4e00, 4=\u5468\u4e94\n    \"amount\": 500\n}\n```\n\n\u53cc\u5468\u5b9a\u6295\uff1a\n```python\n{\n    \"start_date\": date(2024, 1, 1),\n    \"interval\": \"biweekly\",\n    \"weekday\": 4,\n    \"amount\": 500\n}\n```\n\n#### \u65b9\u6cd5\n\n##### `get_all_investment_dates() -> list[date]`\n\n\u8fd4\u56de\u6240\u6709\u6295\u8d44\u65e5\u671f\uff08\u5b9a\u6295+\u624b\u52a8\uff09\uff0c\u6309\u65f6\u95f4\u6392\u5e8f\u3002\n\n##### `get_investment_records() -> list[dict]`\n\n\u8fd4\u56de\u6bcf\u7b14\u6295\u8d44\u7684\u8be6\u7ec6\u8bb0\u5f55\uff1a\n\n```python\n[{\n    \"date\": date,           # \u6295\u8d44\u65e5\u671f\n    \"amount\": float,        # \u6295\u5165\u672c\u91d1\n    \"fee\": float,           # \u624b\u7eed\u8d39\n    \"net_amount\": float,    # \u6263\u8d39\u540e\u91d1\u989d\n    \"nav\": float,           # \u4e70\u5165\u51c0\u503c\n    \"shares\": float         # \u4e70\u5165\u4efd\u989d\n}, ...]\n```\n\n##### `calculate_return(as_of_date: date = None) -> dict`\n\n\u8ba1\u7b97\u603b\u4f53\u6536\u76ca\uff1a\n\n```python\n{\n    \"as_of_date\": date,           # \u8ba1\u7b97\u65e5\u671f\n    \"total_cost\": float,          # \u603b\u6295\u5165\uff08\u542b\u624b\u7eed\u8d39\uff09\n    \"total_net_cost\": float,      # \u603b\u6295\u5165\uff08\u6263\u9664\u624b\u7eed\u8d39\uff09\n    \"total_shares\": float,        # \u603b\u4efd\u989d\n    \"current_nav\": float,         # \u5f53\u524d\u51c0\u503c\n    \"current_value\": float,       # \u5f53\u524d\u4ef7\u503c\n    \"profit\": float,              # \u6536\u76ca\u91d1\u989d\n    \"return_rate\": float,         # \u6536\u76ca\u7387\uff08%\uff09\n    \"annualized_return\": float,   # \u5e74\u5316\u6536\u76ca\u7387\uff08%\uff09\n    \"irr\": float                  # \u5185\u90e8\u6536\u76ca\u7387\uff08%\uff09\n}\n```\n\n##### `calculate_each_investment_return(as_of_date: date = None) -> list[dict]`\n\n\u8ba1\u7b97\u6bcf\u7b14\u6295\u8d44\u7684\u6536\u76ca\uff1a\n\n```python\n[{\n    \"date\": date,\n    \"amount\": float,          # \u6295\u5165\u91d1\u989d\n    \"buy_nav\": float,         # \u4e70\u5165\u51c0\u503c\n    \"shares\": float,          # \u4e70\u5165\u4efd\u989d\n    \"current_nav\": float,     # \u5f53\u524d\u51c0\u503c\n    \"current_value\": float,   # \u5f53\u524d\u4ef7\u503c\n    \"profit\": float,          # \u8be5\u7b14\u6536\u76ca\n    \"return_rate\": float      # \u8be5\u7b14\u6536\u76ca\u7387\uff08%\uff09\n}, ...]\n```\n\n## \u8fd0\u884c\u793a\u4f8b\n\n```bash\npython example.py\n```\n\n## \u6ce8\u610f\u4e8b\u9879\n\n1. **\u51c0\u503c\u66f4\u65b0\u65f6\u95f4**\uff1a\u57fa\u91d1\u51c0\u503c\u5728\u4ea4\u6613\u65e5\u6536\u76d8\u540e\uff08\u665a\u4e0a18:00-22:00\uff09\u516c\u5e03\n2. **\u4ea4\u6613\u65e5\u5904\u7406**\uff1a\u975e\u4ea4\u6613\u65e5\u4f1a\u81ea\u52a8\u987a\u5ef6\u5230\u4e0b\u4e00\u4e2a\u4ea4\u6613\u65e5\n3. **\u8d39\u7387**\uff1a\u4ec5\u8003\u8651\u7533\u8d2d\u8d39\uff0c\u4e0d\u8003\u8651\u8d4e\u56de\u8d39\n4. **\u6570\u636e\u6765\u6e90**\uff1a\u4f7f\u7528 akshare \u4ece\u4e1c\u65b9\u8d22\u5bcc\u83b7\u53d6\u6570\u636e\uff0c\u514d\u8d39\u65e0\u9700token\n\n## \u6536\u76ca\u7387\u8bf4\u660e\n\n### \u7b80\u5355\u6536\u76ca\u7387\n```\n\u6536\u76ca\u7387 = (\u5f53\u524d\u4ef7\u503c - \u603b\u6295\u5165) / \u603b\u6295\u5165 \u00d7 100%\n```\n\n### \u5e74\u5316\u6536\u76ca\u7387\n```\n\u5e74\u5316\u6536\u76ca\u7387 = \u6536\u76ca\u7387 / \u6301\u6709\u5929\u6570 \u00d7 365\n```\n\n### IRR\uff08\u5185\u90e8\u6536\u76ca\u7387\uff09\n\u8003\u8651\u8d44\u91d1\u7684\u65f6\u95f4\u4ef7\u503c\uff0c\u6c42\u89e3\u4f7f\u51c0\u73b0\u503c\u4e3a0\u7684\u6536\u76ca\u7387\uff0c\u66f4\u51c6\u786e\u53cd\u6620\u6295\u8d44\u56de\u62a5\u3002\n\n## \u5e38\u89c1\u95ee\u9898\n\n**Q: \u4e3a\u4ec0\u4e48\u5b9a\u6295\u65e5\u671f\u4e0d\u662f\u6211\u8bbe\u5b9a\u7684\u65e5\u671f\uff1f**\nA: \u5982\u679c\u8bbe\u5b9a\u65e5\u671f\u662f\u975e\u4ea4\u6613\u65e5\uff08\u5468\u672b/\u8282\u5047\u65e5\uff09\uff0c\u4f1a\u81ea\u52a8\u987a\u5ef6\u5230\u4e0b\u4e00\u4e2a\u4ea4\u6613\u65e5\u3002\n\n**Q: \u5982\u4f55\u67e5\u770b\u5386\u53f2\u67d0\u4e00\u5929\u7684\u6536\u76ca\uff1f**\nA: \u4f7f\u7528 `calculate_return(as_of_date=date(2024, 9, 30))`\n\n**Q: \u624b\u52a8\u6295\u8d44\u548c\u5b9a\u6295\u65e5\u671f\u91cd\u53e0\u600e\u4e48\u529e\uff1f**\nA: \u7cfb\u7edf\u4f1a\u5206\u522b\u8bb0\u5f55\uff0c\u4e24\u7b14\u6295\u8d44\u90fd\u4f1a\u751f\u6548\u3002\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u57fa\u91d1\u5b9a\u6295\u6536\u76ca\u8ba1\u7b97\u5de5\u5177\uff0c\u652f\u6301\u81ea\u52a8\u83b7\u53d6\u51c0\u503c\u6570\u636e\u548c\u4ea4\u6613\u65e5\u5224\u65ad",
    "version": "0.1.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/wenyili/fund-investment-calculator/issues",
        "Homepage": "https://github.com/wenyili/fund-investment-calculator",
        "Repository": "https://github.com/wenyili/fund-investment-calculator"
    },
    "split_keywords": [
        "fund",
        " investment",
        " financial",
        " calculator",
        " \u5b9a\u6295"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0749808484342ecfe0f569d464de4edeee39485ab8a4b977619bf4fd0ac0afc1",
                "md5": "ae4ae9e88c9207418a88cb0060d5792f",
                "sha256": "c1e8ebb29f56133cee8ad84e758c17077acf5ed3ebd37c72b6b8d0b6990f4a9a"
            },
            "downloads": -1,
            "filename": "fund_investment_calculator-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ae4ae9e88c9207418a88cb0060d5792f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 11449,
            "upload_time": "2025-10-07T10:36:59",
            "upload_time_iso_8601": "2025-10-07T10:36:59.648465Z",
            "url": "https://files.pythonhosted.org/packages/07/49/808484342ecfe0f569d464de4edeee39485ab8a4b977619bf4fd0ac0afc1/fund_investment_calculator-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "30f503c5c357fc4838a6f842bf2f7ac432cae3d35d1003afb0a3bd313c64a40b",
                "md5": "edc99b1e925bc3e34e1d68dd72addae8",
                "sha256": "56a00f39d9a516900655a3b2f43c2b87e477d061cef7bbe1e3c5d619f7ec7e4f"
            },
            "downloads": -1,
            "filename": "fund_investment_calculator-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "edc99b1e925bc3e34e1d68dd72addae8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 15242,
            "upload_time": "2025-10-07T10:37:00",
            "upload_time_iso_8601": "2025-10-07T10:37:00.936684Z",
            "url": "https://files.pythonhosted.org/packages/30/f5/03c5c357fc4838a6f842bf2f7ac432cae3d35d1003afb0a3bd313c64a40b/fund_investment_calculator-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-07 10:37:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "wenyili",
    "github_project": "fund-investment-calculator",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "akshare",
            "specs": [
                [
                    ">=",
                    "1.14.0"
                ]
            ]
        },
        {
            "name": "exchange-calendars",
            "specs": [
                [
                    ">=",
                    "4.5.0"
                ]
            ]
        },
        {
            "name": "pandas",
            "specs": [
                [
                    ">=",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "scipy",
            "specs": [
                [
                    ">=",
                    "1.11.0"
                ]
            ]
        }
    ],
    "lcname": "fund-investment-calculator"
}
        
Elapsed time: 1.88432s