101 lines
3.2 KiB
Python
101 lines
3.2 KiB
Python
"""
|
|
Script Name:
|
|
Description: 从富途获取复权因子数据。
|
|
参考地址: https://openapi.futunn.com/futu-api-doc/quote/get-rehab.html
|
|
|
|
Author: [Your Name]
|
|
Created Date: YYYY-MM-DD
|
|
Last Modified: YYYY-MM-DD
|
|
Version: 1.0
|
|
|
|
Modification History:
|
|
- YYYY-MM-DD [Your Name]:
|
|
- YYYY-MM-DD [Your Name]:
|
|
- YYYY-MM-DD [Your Name]:
|
|
"""
|
|
|
|
import logging
|
|
import pymysql
|
|
import time
|
|
from futu import *
|
|
import pandas as pd
|
|
import config
|
|
|
|
# 设置日志
|
|
config.setup_logging()
|
|
|
|
# 连接 MySQL 数据库
|
|
def get_mysql_connection():
|
|
return pymysql.connect(**config.db_config)
|
|
|
|
# 获取股票代码列表
|
|
def get_stock_codes(table_name):
|
|
connection = get_mysql_connection()
|
|
with connection.cursor(pymysql.cursors.DictCursor) as cursor:
|
|
cursor.execute(f"SELECT code, code_name FROM {table_name} ")
|
|
result = cursor.fetchall()
|
|
connection.close()
|
|
return result
|
|
|
|
# 插入或更新复权信息
|
|
def insert_or_update_rehab_data(connection, rehab_data, code, name):
|
|
try:
|
|
with connection.cursor() as cursor:
|
|
sql = """
|
|
INSERT INTO futu_rehab (code, name, ex_div_date, forward_adj_factorA, forward_adj_factorB, backward_adj_factorA, backward_adj_factorB)
|
|
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
|
ON DUPLICATE KEY UPDATE
|
|
forward_adj_factorA = VALUES(forward_adj_factorA),
|
|
forward_adj_factorB = VALUES(forward_adj_factorB),
|
|
backward_adj_factorA = VALUES(backward_adj_factorA),
|
|
backward_adj_factorB = VALUES(backward_adj_factorB)
|
|
"""
|
|
for row in rehab_data.itertuples(index=False):
|
|
cursor.execute(sql, (code, name, row.ex_div_date, row.forward_adj_factorA, row.forward_adj_factorB, row.backward_adj_factorA, row.backward_adj_factorB))
|
|
connection.commit()
|
|
except pymysql.MySQLError as e:
|
|
logging.error(f"Error occurred while inserting or updating rehab data: {e}", exc_info=True)
|
|
|
|
# 从 Futu API 获取复权信息
|
|
def get_rehab_data(code):
|
|
quote_ctx = OpenQuoteContext(host='127.0.0.1', port=11111)
|
|
ret, data = quote_ctx.get_rehab(code)
|
|
|
|
quote_ctx.close()
|
|
if ret == RET_OK:
|
|
return data
|
|
else:
|
|
logging.error(f"Failed to get rehab data for {code}: {data}")
|
|
return None
|
|
|
|
# 主函数
|
|
def process_stock_data(table_name, prefix=''):
|
|
stocks = get_stock_codes(table_name)
|
|
connection = get_mysql_connection()
|
|
|
|
for stock in stocks:
|
|
code = stock['code']
|
|
name = stock['code_name']
|
|
|
|
# 拼接 'US.' 前缀对于 sp500 表中的股票
|
|
full_code = f"{prefix}{code}" if prefix else code
|
|
|
|
logging.info(f"Processing {full_code} ({name})")
|
|
|
|
# 获取复权数据
|
|
rehab_data = get_rehab_data(full_code)
|
|
if rehab_data is not None:
|
|
# 插入或更新复权数据
|
|
insert_or_update_rehab_data(connection, rehab_data, full_code, name)
|
|
logging.info(f"Inserted/Updated rehab data for {full_code} ({name})")
|
|
|
|
time.sleep(3)
|
|
|
|
connection.close()
|
|
|
|
if __name__ == "__main__":
|
|
# 处理 hs300 表数据,不需要加 'US.' 前缀
|
|
process_stock_data("hs300")
|
|
|
|
# 处理 sp500 表数据,加 'US.' 前缀
|
|
process_stock_data("sp500", prefix='US.') |