【简单小工具】基金代码爬虫工具和基金过往收益表现回测工具

数据来源东方财富网,仅供个人学习交流使用,严禁用于各种违法违规行为。

Part1:定义一个爬虫方法

import os
import requests
import pandas as pd
import time

# 基金代码列表
fund_codes = [
        #  '009272'
        # ,
        '008205'
        # ,'011062'
        # ,'900050'
        # ,'004043'
        # ,'013752'
        # ,'009267'
        # ,'006962'
        # ,'010324'
        # ,'160514'
]
start_date = '2022-01-01'
end_date = '2024-11-18'

模拟一个浏览器头,并定义一个爬虫方法:

def fetch_fund_data(fund_code, start_date, end_date):
    base_url = "https://api.fund.eastmoney.com/f10/lsjz"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36',
        'Referer': 'https://fund.eastmoney.com/',
        'Accept': 'application/json, text/javascript, */*; q=0.01',
    }
    page = 1
    all_data = []

    while True:
        params = {
            'fundCode': fund_code,
            'pageIndex': page,
            'pageSize': 20,
            'startDate': start_date,
            'endDate': end_date,
        }
        response = requests.get(base_url, headers=headers, params=params)
        
        # 检查请求是否成功
        if response.status_code != 200:
            print(f"Request failed for fund {fund_code} with status code:", response.status_code)
            break
        
        data = response.json()

        # 检查数据结构
        if 'Data' not in data or 'LSJZList' not in data['Data']:
            print(f"Unexpected data format for fund {fund_code}.")
            break

        if not data['Data']['LSJZList']:
            break

        all_data.extend(data['Data']['LSJZList'])
        page += 1
        time.sleep(0.2)  # 延时避免频繁请求,可以通过调整间隔

    return all_data


def save_to_csv(fund_data, fund_code):
    # 生成文件名
    filename = f"fund_{fund_code}_data.csv"
    downloads_folder = os.path.join(os.path.expanduser("~"), "Downloads")
    file_path = os.path.join(downloads_folder, filename)
    
    # 将数据保存到个人电脑的downloads下载文件夹
    df = pd.DataFrame(fund_data)
    df.to_csv(file_path, index=False, encoding='utf-8-sig')
    print(f"Data for fund {fund_code} saved to {file_path}")

调度方法,存储爬取基金数据。

# 遍历每个基金代码,获取数据并保存
for fund_code in fund_codes:
    print(f"Fetching data for fund {fund_code}...")
    fund_data = fetch_fund_data(fund_code, start_date, end_date)
    if fund_data:  # 检查是否有数据
        save_to_csv(fund_data, fund_code)
    else:
        print(f"No data fetched for fund {fund_code}.")

Fetching data for fund 008205…
Data for fund 008205 saved to

第一步结束,把爬取的信息存储在本地的某个文件夹(这里我定义的是windows电脑的下载文件夹),可以自行改动。

Part2:对爬取数据的基金净值做分析,计算不同周期下的最高最低收益率,并返回两类收益率和对应的买入卖出时间点

def calculate_max_min_returns(file_path, date_column, value_column, fund_code, holding_period_months=12):
    """
    计算指定基金在至少持有一定月数后的最高和最低回报率。
    
    参数:  
    - file_path (str): CSV 文件的路径。
    - date_column (str): 数据记录日期的列名。
    - value_column (str): 基金累计净值的列名。
    - fund_code (str): 基金代码(用于输出提示)。
    - holding_period_months (int): 至少持有的月份数,默认为12个月。
    
    返回:
    - max_return, min_return, best_buy_date, best_sell_date, worst_buy_date, worst_sell_date
    """
    # 加载基金净值数据
    df = pd.read_csv(file_path)

    # 格式化日期字段和排序
    df[date_column] = pd.to_datetime(df[date_column])  
    df.sort_values(by=date_column, inplace=True)  

    # 初始化最大和最小回报率变量
    max_return = float('-inf')
    min_return = float('inf')
    best_buy_date = None
    best_sell_date = None
    worst_buy_date = None
    worst_sell_date = None

    # 遍历每一个买入日期
    for i, buy_row in df.iterrows():
        buy_date = buy_row[date_column]
        buy_value = buy_row[value_column]

        # 找到买入日期至少 holding_period_months 个月后的所有交易日
        months_later_date = buy_date + pd.DateOffset(months=holding_period_months)
        sell_candidates = df[df[date_column] >= months_later_date]
        if sell_candidates.empty:
            break  # 如果没有满足条件的日期,跳出循环

        # 遍历所有符合条件的卖出日期
        for _, sell_row in sell_candidates.iterrows():
            sell_date = sell_row[date_column]
            sell_value = sell_row[value_column]

            # 计算回报率
            return_rate = (sell_value - buy_value) / buy_value

            # 更新最高回报
            if return_rate > max_return:    
                max_return = return_rate
                best_buy_date = buy_date
                best_sell_date = sell_date

            # 更新最低回报
            if return_rate < min_return:
                min_return = return_rate
                worst_buy_date = buy_date
                worst_sell_date = sell_date

    # 输出结果
    print(f"基金代码: {fund_code}")
    print(f"最高回报率: {max_return * 100:.2f}% (买入日期: {best_buy_date.date()}, 卖出日期: {best_sell_date.date()})")
    print(f"最低回报率: {min_return * 100:.2f}% (买入日期: {worst_buy_date.date()}, 卖出日期: {worst_sell_date.date()})")
    
    
    
    # 当作为参数传入别的函数时,解除注释内容
    # return max_return, min_return, best_buy_date, best_sell_date, worst_buy_date, worst_sell_date


调度一下后,

# 批量计算每个基金的最大和最小回报
for fund_code in fund_codes:
    file_path = os.path.join(os.path.expanduser("~"), "Downloads", f"fund_{fund_code}_data.csv")
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"Warning: 未找到基金 {fund_code} 的净值信息文件 {file_path},跳过该基金。")
        continue  # 跳过当前基金,进入下一个循环

    # # 输出当前基金代码,并调用计算函数
    #  参数:
    # - file_path (str): CSV 文件的路径。
    # - date_column (str): 数据记录日期的列名。
    # - value_column (str): 基金累计净值的列名。
    # - fund_code (str): 基金代码(用于输出提示)。
    # - holding_period_months (int): 至少持有的月份数,默认为12个月。
    
    print(f"\n计算基金 {fund_code} 的回报情况:")
    calculate_max_min_returns(file_path, date_column='FSRQ', value_column='LJJZ', fund_code=fund_code, holding_period_months=12)

计算基金 008205 的回报情况:
基金代码: 008205
最高回报率: 8.37% (买入日期: 2022-01-04, 卖出日期: 2024-11-15)
最低回报率: 1.06% (买入日期: 2022-01-28, 卖出日期: 2023-01-30)

支持提交多个基金代码,支持设定不同时间范围内的基金变化。灵活度很高,欢迎交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值