excel学习库

excel表格_excel函数公式大全_execl从入门到精通

和ChatGPT一起工作 - 个人量化财务数据准备

【我会持续更新这个话题,感兴趣的同学可以关注。欢迎大家留言交流】

上次说到通过baostock和yfinance拉取了历史报价数据,存在了本地的数据库中。本想要不要就此开始搞搞策略。大概的翻了翻各类资料和书之后,觉得,自己对股票投资的基础知识还是了解的不够充分,虽然有个FE的学位,但是过于专向,偏向数据及工具角度。于是密集看了两天书,决定还是从价值投资入手,学习的同时做些小模型出来先。

于是又遇到了财务数据问题。

问ChatGPT,它推荐的是yfinance和alphavanatage,但实测yfinance的财务报告接口已经不能用了,alphavanatage又对A股不甚友好。很多量化公司,机构或者组织会提供已经整理好的数据,不过都需要花钱购买。作为一个小白,在有希望获得收益前,能不出血就不出血。

平时用同花顺挺顺手,同花顺的F10里各种宝藏。看了一下,有完整的财务报告三张表:资产负债表,现金流表,收益表。

而且同花顺提供报告下载功能(导出数据),导出后是xls格式。各种数据很全,在同花顺网站看到的,表格里都包含。

既然这样的话,完全可以以同花顺作为财务报告的数据源

这时候直接给ChatGPT出要求还是太早,有一些探索的工作还是需要灵活性更强的自然人去做。

和ChatGPT一起工作心得:
以当前的各类环境(环境分散,对人类友好)而言,面对一件未知信息多,不知道明确做法的事的时候,自然人的优势更大。
先以自然人的灵活性去快速探索一下,摸到一个可尝试的方向和大概的方法,然后再把高速高效的做这件事的工作交给ChatGPT去完成。

所以我大概搜了下同花顺是否有数据自动获取途径,发现并没有API之类的可以直接用。于是我手动点开了几个股票的报表,发现,在浏览器下他们的下载链接的pattern具有一致性,大概是:

1.income_statement:http://basic.10jqka.com.cn/api/stock/export.php?export=benefit&type=report&code={stock_code}2.balance_sheet:http://basic.10jqka.com.cn/api/stock/export.php?export=debt&type=report&code={stock_code}3.cash_flows:http://basic.10jqka.com.cn/api/stock/export.php?export=cash&type=report&code={stock_code}

那下一步就简单了,直接和ChatGPT说,让它帮我搞定下载加存储在本地的工作。

于是,我让它帮我设计了这么几件事:

  1. 数据下载:

  • 从我的stock_list table里读取股票代码(上篇讲过,使用baostock获取到的股票代码,单独维护),然后根据财务报告的链接pattern分别生成下载链接;

  • 分别下载到本地不同的文件夹下(balance_sheet, income_statement, cash_flows);

2. 数据处理:

  • 从每一种报告里摘取完整数据项目列表,用于创建数据库里对应table的column项;

3. 数据存储:

  • 把每一个股票的财务报告xls文件数据存储到对应的本地数据库table里;

大体上讲就需要做这么三件事;做完后,关于股票的财务报告数据就算准备完成了。

和ChatGPT一起工作心得:
一开始不要直接进入代码阶段。以为自己已经想的很清楚了,也过于自信自己的表达能力,妄图一蹴而就把所有步骤一段代码就搞定,这在极大概率上是会掉坑的。
因为你对数据的细节极有可能做不到完全了解,以为有ChatGPT的帮助可以一步到位,想在一开始就采取“一锅端一勺烩”的方式来做事,会在中间遇到问题时非常痛苦。
正确的做法是,先和ChatGPT沟通好,大体上需要做哪些步骤。然后对每个步骤拆分,一步步走。这样遇到之前不了解的问题时,方便揪到关键点。

下面一步步说:

1. 数据下载: - 从我的stock_list table里读取股票代码(上篇讲过,使用baostock获取到的股票代码,单独维护),然后根据财务报告的链接pattern分别生成下载链接; - 分别下载到本地不同的文件夹下;

这一步看似不难,ChatGPT直接给出的代码也是最简单的http下载方案,但是并不work。我们分析了一下得出(主要是它分析):

ChatGPT:一些网站采取措施,通过检测和阻止脚本或机器人的请求来防止自动下载或web抓取。这通常通过分析请求头来完成,例如User-Agent头,它标识发起请求的客户端软件。网站可能需要特定的头,包括自定义的头,以允许访问其内容。在某些情况下,您可能需要包含一个模仿流行web浏览器的特定用户代理标头或其他标头,如Referer、Accept、Accept- language或Cookie,以成功地从网站下载内容。重要的是要注意,从网站抓取和下载内容可能会违反他们的服务条款,在继续之前,你应该总是检查和尊重网站的robots.txt文件和政策。

最后采取了如下方式:

def download_and_save_to_local_path(stock_code):    urls = generate_download_urls(stock_code)#generate_download_urls() is to generate url links with patterns    # Simulate a request from Chrome by adding headers    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',        'Referer': 'http://basic.10jqka.com.cn/300113/finance.html',    }    for report_type, url in urls.items():        try:            response = requests.get(url, headers=headers)            response.raise_for_status()            # Extract the filename from the response headers            content_disposition = response.headers.get('Content-Disposition')            filename = unquote(content_disposition.split('filename=')[-1]) if 'filename=' in content_disposition else 'unknown_file.xls'            local_file_path = os.path.join(download_directory, filename)            with open(local_file_path, "wb") as file:                file.write(response.content)        except requests.exceptions.RequestException as e:            print(f"Error downloading file: {e}")        except Exception as e:            print(f"Error saving file: {e}")

于是来到第二步:

2. 数据处理: - 从每一种报告里摘取完整数据项目列表,用于创建数据库里对应table的column项;

这里走过一个坑。财务报告里的财务数据项是中文,且有的非常长,在存储的时候不方便而且会有一些问题;另外每个股票的财务报表里的项目数甚至项目名都不尽相同。于是我打算:

1、自动遍历一遍文件,把所有项目名都摘出来;

2、把中文项名换成简单的英文项名;

3、做一个中英项目名的mapping表(有的中文名不一样但其实意思一样的,在这里都可以使用同一个英文项名,方便以后处理)。

拆解之后就很简单了,直接和ChatGPT说。因为需求清晰又不复杂,所以ChatGPT给出来的代码准确性和可用性非常高。

在这个过程里的另一个坑是,Python里常见的包对xls这个旧的文件格式支持的不是很好,各种问题。所以先做一个xls-to-xlsx的转换是最方便的。而这个操作,即便是GPT-4也解决的不好,错误反复的犯,到最后甚至我觉得它脑子已经乱了(不知道是不是当前的conversation过长,干扰信息过多)。于是我Google了一下,很快找到了一个很简单的方法解决了这个问题。

和ChatGPT一起工作心得:
当你发现你把一个错误反馈给ChatGPT但是它貌似开始又给你之前的一个错误方案的时候,最好不要再继续了。
这时候或者另开一个对话,以规避当前因为对话过长导致的信息扰乱带来的ChatGPT逻辑和记忆混乱的问题;或者自己去网上寻找其他方案,因为此时一般说明ChatGPT可能是因为版本时间问题还不知道最新的方案。

代码如下:

# 把所有xls文件转换为xlsx文件def convert_all_files_to_xlsx(input_dir,output_dir):    # Create the output directory if it doesn't exist    os.makedirs(output_dir, exist_ok=True)    # Iterate through all files in the input directory    for file in os.listdir(input_dir):        # Skip files that start with a period (e.g., temporary files)        if file.startswith('.'):            continue        # Check if the file has a .xls extension        if file.endswith('.xls'):            # Construct the input and output file paths            input_file_path = os.path.join(input_dir, file)            output_file_path = os.path.join(output_dir, f'{os.path.splitext(file)[0]}.xlsx')            # Convert the XLS file to an XLSX file            x2x = XLS2XLSX(input_file_path)            x2x.to_xlsx(output_file_path)    print("All XLS files have been converted to XLSX files.")# 从xlsx文件里读取第一列数据(财务数据项)def read_unique_values_from_first_column(directory):    # Create an empty DataFrame to store the unique values    unique_values_df = pd.DataFrame()    # Iterate through the files in the directory    for filename in os.listdir(directory):        if filename.endswith(".xlsx"):            print(f"filename is {filename}")            # Read the first column of the Excel file            filepath = os.path.join(directory, filename)            df = pd.read_excel(filepath, usecols=[0], engine='openpyxl')            # Concatenate the unique values to the existing DataFrame            unique_values_df = pd.concat([unique_values_df, df]).drop_duplicates()    return unique_values_df# 把数据存在一个本地的xlsx文件里,用于之后做mapping表def save_df_to_xlsx_file(df):    # Specify the file name and path    file_name = '/path/filename.xlsx'    # Save the DataFrame to an Excel file    df.to_excel(file_name, index=False, engine='openpyxl')

于是获取了一个抓取了所有数据项名的xlsx文件。在这个文件里,可以手动或者让ChatGPT自动翻译给出简短的英文数据项名。然后直接使用这个mapping创建一个在本地数据库里对应的table。

之后可以根据这个table手动创建(因为数据项多,所以不想写进代码里自动创建)一个财务报告表(比如balance_sheet 表),以供下一步把每个股票的对应财务数据写入。

现在来到第三步:

3. 数据存储: - 把每一个股票的财务报告xls文件数据存储到对应的本地数据库table里;

因为在第二步里做了一个xls到xlsx的转换,所以这里可以从xlsx文件里读取数据并且存到对应的table里。

这里拆解一下,我会先把每个xlsx文件的数据项中文名根据mapping表转换成英文名,然后根据不同的名在财务报告table里对应的数据项名下写下数据。

代码如下:

# 根据mappting table为每一个xlsx做mapping,把第一列的数据项名从中文换成英文简名def map_first_row_with_mapping_table(input_file_path, mapping_table, db_connection):    # Read the input XLSX file    df = pd.read_excel(input_file_path)    # Get the first row of data    first_column = df.iloc[:,0].tolist()    # Iterate through the first row data    for index, value in enumerate(first_column):        # Query the mapping table        with db_connection.cursor() as cursor:            cursor.execute("SELECT ori_name, column_name FROM {} WHERE ori_name = %s".format(mapping_table),                           (value,))            result = cursor.fetchone()        # If a matching ori_name is found, replace the value with the corresponding column_name        if result:            first_column[index] = result[1]    # Replace the first row of the DataFrame with the updated first row    df.iloc[:,0] = first_column    return df# 如果要根据xlsx存到数据库表里,需要对当前xlsx做一个转置处理def transpose_xlsx(filename,stock_code):    df = pd.read_excel(filename, header=1)    df = df.T  # Transpose the DataFrame.    df.reset_index(inplace=True)  # Reset the index and use the default integer index.    df.columns = df.iloc[0]  # Set the column names to the first row of the DataFrame    df = df.drop(0)  # Drop the first row, as it's now the same as the column names.    # Remove duplicate column names after transposing the DataFrame    df = df.loc[:, ~df.columns.duplicated()]    # Remove columns with NaN column names    df = df.loc[:, df.columns.notnull()]    df['stock_code'] = stock_code    # Remove the 'Unnamed' column from the DataFrame    df = df.loc[:, ~df.columns.str.contains('Unnamed')]    return df# 插入数据到数据库表里def insert_data(data_frame, connection, table_name,database):    # Get existing column names from the database table    cursor = connection.cursor()    cursor.execute(f"""        SELECT COLUMN_NAME        FROM INFORMATION_SCHEMA.COLUMNS        WHERE TABLE_SCHEMA = '{database}'        AND TABLE_NAME = '{table_name}'    """)    table_columns = [row[0] for row in cursor.fetchall()]    # Filter the DataFrame to only include columns that exist in the table    filtered_df = data_frame.loc[:, data_frame.columns.intersection(table_columns)]    # Insert the records into the database table    for index, row in filtered_df.iterrows():        row = row.dropna()  # Drop 'nan' values from the row        column_names = ', '.join(row.index)        placeholders = ', '.join(['%s'] * len(row))        insert_query = f"INSERT INTO {table_name} ({column_names}) VALUES ({placeholders})"        cursor.execute(insert_query, tuple(row))    # Commit the transaction    connection.commit()

至此,大功告成。

以上给出来的方案看似很简单直接,但是在整个过程里,细小的问题还是很多,走了不少弯路。在遇到阻碍时,及时和ChatGPT交流可以快速解决绝大多数问题,生产效率比自己单打独斗要高上不止一点。尤其在对它给的现成的代码copy and paste时简直不要太爽。

我本人其实是工科出身,本来coding应该是基本技能,但是我对于记忆各种语法细节完全没有兴趣,看到哪里要有逗号哪里要这么写而不能那么写,就特别劝退。之前如果不是太难的就用笨方法,太难的就不试了,除非是那种用了coding可以极大提高生产效率的我才会自己写代码。而现在,在我的应用环境里,有了ChatGPT,coding已经完全不成为阻碍,自己有想法又知道如何和ChatGPT配合工作,很多做不了的事就可以轻易做到。我已经开发了几个非常好用的chrome插件,现在又在尝试做个人量化。

在这个尝试的过程里,我也有一些关于ChatGPT的感受,像我之前在想法里说的:

如何与AI协同?

如果你本身对一件事的理解是0,AI只能帮你做到3;如果你本身是5,AI可以帮你做到12。
你自己对要做的事了解的越清楚,越可以给出更高效更有针对性的提示,AI也会更大倍数的作为帮你提高生产效率的工具,和你一起提供更高的总体价值。

所以,AI的年代,正确的和AI协同的方法是:

当你对于一件事的了解是0的时候,使用AI作为教师,帮你提升到5;然后使用AI作为生产效率工具,一起把事情做到12。

作为一个使用ChatGPT做coding的人,我完全没有一点cheating的感觉。因为这个工具的出现,我现在可以把注意力focus到我认为价值最大的部分(比如量化的方法和策略),既是AI时代的所谓【自然人的脑力】部分。至于coding这种AI时代的【机器的体力】部分,就留给AI去处理吧。

这也是新时代的“术业有专攻”。

最后,总结一下:

作为一个自然人,永远要知道自己和AI的区别:

你需要有明确的目的性,知道自己在做什么,和如何寻求AI的帮助把它做到,或者做的更好。

以及:

起码在当前时代,【自然人】更适合利用自己的创造性、灵活性、意图性,去做更多的摸索和开拓的部分;等路被指出方向或被开拓出来之后,标准化的、复杂的、重复的工作,就都可以留给AI了。

【我会持续更新这个话题,感兴趣的同学可以关注。非常欢迎大家留言交流】

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«    2024年12月    »
1
2345678
9101112131415
16171819202122
23242526272829
3031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
    文章归档
      友情链接