modify scripts
This commit is contained in:
@ -8,6 +8,9 @@ db_config = {
|
||||
'password': 'mysqlpw',
|
||||
'database': 'stockdb'
|
||||
}
|
||||
# 读取环境变量,来修改 db_config 中host的值
|
||||
if 'DB_HOST' in os.environ:
|
||||
db_config['host'] = os.environ['DB_HOST']
|
||||
|
||||
home_dir = os.path.expanduser("~")
|
||||
global_host_data_dir = f'{home_dir}/hostdir/stock_data'
|
||||
|
||||
195
src/db_utils/reports_mysql.py
Normal file
195
src/db_utils/reports_mysql.py
Normal file
@ -0,0 +1,195 @@
|
||||
import pymysql
|
||||
from pymysql.cursors import DictCursor
|
||||
import logging
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
class DatabaseConnectionError(Exception):
|
||||
pass
|
||||
|
||||
class StockReportMysql:
|
||||
# 定义类属性(静态变量)
|
||||
TBL_STOCK = 'reports_stock'
|
||||
TBL_NEW_STOCK = 'reports_newstrock' # 注意原拼写可能存在笔误(strock应为stock)
|
||||
TBL_STRATEGY = 'reports_strategy'
|
||||
TBL_MACRESEARCH = 'reports_macresearch'
|
||||
TBL_INDUSTRY = 'reports_industry'
|
||||
|
||||
def __init__(self, db_host, db_user, db_password, db_name, port=3306):
|
||||
"""
|
||||
初始化MySQL连接
|
||||
:param db_host: 数据库主机地址
|
||||
:param db_user: 数据库用户名
|
||||
:param db_password: 数据库密码
|
||||
:param db_name: 数据库名称
|
||||
:param port: 数据库端口,默认3306
|
||||
"""
|
||||
self.db_host = db_host
|
||||
self.db_user = db_user
|
||||
self.db_password = db_password
|
||||
self.db_name = db_name
|
||||
self.port = port
|
||||
self.conn = None
|
||||
self.cursor = None
|
||||
try:
|
||||
self.conn = pymysql.connect(
|
||||
host=self.db_host,
|
||||
user=self.db_user,
|
||||
password=self.db_password,
|
||||
database=self.db_name,
|
||||
port=self.port,
|
||||
charset='utf8mb4' # 支持中文
|
||||
)
|
||||
#self.cursor = self.conn.cursor(dictionary=False) # 使用非字典游标,保持与原代码兼容
|
||||
self.cursor = self.conn.cursor() # 使用默认游标
|
||||
except pymysql.MySQLError as e:
|
||||
logging.error(f"数据库连接失败: {e}")
|
||||
raise DatabaseConnectionError("数据库连接失败")
|
||||
|
||||
def __get_table_columns_and_defaults(self, tbl_name):
|
||||
"""获取表的列信息及默认值(适配MySQL)"""
|
||||
try:
|
||||
# 查询information_schema获取列信息
|
||||
self.cursor.execute("""
|
||||
SELECT COLUMN_NAME, COLUMN_DEFAULT
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_NAME = %s AND TABLE_SCHEMA = %s
|
||||
""", (tbl_name, self.db_name))
|
||||
columns = self.cursor.fetchall()
|
||||
column_info = {}
|
||||
for col in columns:
|
||||
col_name = col[0]
|
||||
default_value = col[1]
|
||||
# MySQL默认值可能包含函数(如CURRENT_TIMESTAMP),需要特殊处理
|
||||
column_info[col_name] = default_value
|
||||
return column_info
|
||||
except pymysql.MySQLError as e:
|
||||
logging.error(f"获取表结构失败: {e}")
|
||||
return None
|
||||
|
||||
def __check_and_process_data(self, data, tbl_name):
|
||||
"""数据校验和处理(逻辑与原代码保持一致)"""
|
||||
column_info = self.__get_table_columns_and_defaults(tbl_name=tbl_name)
|
||||
if column_info is None:
|
||||
return None
|
||||
processed_data = {}
|
||||
for col, default in column_info.items():
|
||||
if col == 'id': # 自增主键,不需要用户提供
|
||||
continue
|
||||
if col == 'created_at' or col == 'updated_at': # 日期字段由数据库或代码控制
|
||||
continue
|
||||
if col in ['author', 'authorID']:
|
||||
# 将列表转换为逗号分隔字符串
|
||||
values = data.get(col, [])
|
||||
processed_data[col] = ','.join(values) if values else None
|
||||
# 确保不超过255字符
|
||||
if processed_data[col] and len(processed_data[col]) > 250:
|
||||
processed_data[col] = processed_data[col][:250]
|
||||
elif col in data:
|
||||
processed_data[col] = data[col]
|
||||
else:
|
||||
# 使用默认值
|
||||
pass
|
||||
return processed_data
|
||||
|
||||
def insert_or_update_common(self, data, tbl_name, uniq_key='infoCode'):
|
||||
"""插入或更新数据(适配MySQL的ON DUPLICATE KEY UPDATE)"""
|
||||
try:
|
||||
processed_data = self.__check_and_process_data(data, tbl_name)
|
||||
if processed_data is None:
|
||||
return None
|
||||
|
||||
columns = ', '.join(processed_data.keys())
|
||||
values = list(processed_data.values())
|
||||
placeholders = ', '.join(['%s' for _ in values]) # MySQL使用%s作为占位符
|
||||
|
||||
# 构造更新子句(排除唯一键字段)
|
||||
update_clause = ', '.join(
|
||||
[f"{col}=VALUES({col})" for col in processed_data.keys() if col != uniq_key]
|
||||
) + ', updated_at=NOW()' # MySQL使用NOW()获取当前时间
|
||||
|
||||
sql = f'''
|
||||
INSERT INTO {tbl_name} ({columns}, created_at, updated_at)
|
||||
VALUES ({placeholders}, NOW(), NOW())
|
||||
ON DUPLICATE KEY UPDATE {update_clause}
|
||||
'''
|
||||
self.cursor.execute(sql, values)
|
||||
self.conn.commit()
|
||||
|
||||
# 获取插入或更新后的记录ID
|
||||
self.cursor.execute(f"SELECT id FROM {tbl_name} WHERE {uniq_key} = %s", (data[uniq_key],))
|
||||
result = self.cursor.fetchone()
|
||||
return result[0] if result else None
|
||||
except pymysql.MySQLError as e:
|
||||
logging.error(f"插入或更新数据失败: {e}")
|
||||
self.conn.rollback() # 出错时回滚
|
||||
return None
|
||||
|
||||
def update_pages(self, data, tbl_name, uniq_key='infoCode'):
|
||||
"""更新附件页数(使用参数化查询防止SQL注入)"""
|
||||
try:
|
||||
# 注意:原代码直接拼接SQL有注入风险,此处改为参数化查询
|
||||
sql = f'''
|
||||
UPDATE {tbl_name}
|
||||
SET attachPages = %s
|
||||
WHERE id = %s
|
||||
'''
|
||||
self.cursor.execute(sql, (data['attachPages'], data['id']))
|
||||
self.conn.commit()
|
||||
return data['id']
|
||||
except pymysql.MySQLError as e:
|
||||
logging.error(f"更新页数失败: {e}")
|
||||
self.conn.rollback()
|
||||
return None
|
||||
|
||||
def query_reports_comm(self, tbl_name, querystr='', limit=None):
|
||||
"""查询报告列表(适配MySQL语法)"""
|
||||
try:
|
||||
# 验证表名合法性
|
||||
valid_tables = [
|
||||
self.TBL_STOCK, self.TBL_NEW_STOCK,
|
||||
self.TBL_INDUSTRY, self.TBL_MACRESEARCH,
|
||||
self.TBL_STRATEGY
|
||||
]
|
||||
if tbl_name not in valid_tables:
|
||||
logging.warning(f'无效的表名: {tbl_name}')
|
||||
return None
|
||||
|
||||
# 构造查询SQL
|
||||
sql = f"""
|
||||
SELECT id, infoCode, title, orgSName, industryName, stockName, publishDate
|
||||
FROM {tbl_name}
|
||||
WHERE 1=1 {querystr}
|
||||
"""
|
||||
# 添加限制条件
|
||||
if limit:
|
||||
sql += f' LIMIT {limit}'
|
||||
|
||||
self.cursor.execute(sql)
|
||||
results = self.cursor.fetchall()
|
||||
|
||||
# 获取列名
|
||||
column_names = [description[0] for description in self.cursor.description]
|
||||
|
||||
# 转换为字典列表
|
||||
result_dict_list = []
|
||||
for row in results:
|
||||
row_dict = {column_names[i]: value for i, value in enumerate(row)}
|
||||
result_dict_list.append(row_dict)
|
||||
|
||||
return result_dict_list
|
||||
except pymysql.MySQLError as e:
|
||||
logging.error(f"查询失败: {e}")
|
||||
return None
|
||||
|
||||
def __del__(self):
|
||||
"""析构函数,关闭数据库连接(适配pymysql)"""
|
||||
try:
|
||||
# pymysql中通过ping()判断连接是否有效,若连接已关闭会抛出异常
|
||||
if self.conn:
|
||||
self.conn.ping() # 尝试检测连接是否存活
|
||||
self.cursor.close()
|
||||
self.conn.close()
|
||||
except (pymysql.MySQLError, AttributeError):
|
||||
# 捕获连接已关闭、游标不存在等异常,避免析构时报错
|
||||
pass
|
||||
@ -11,8 +11,9 @@ from datetime import datetime, timedelta
|
||||
from functools import partial
|
||||
import src.crawler.em.reports as em
|
||||
import src.utils.utils as utils
|
||||
from src.config.config import global_host_data_dir, global_share_db_dir
|
||||
from src.config.config import global_host_data_dir, global_share_db_dir, db_config
|
||||
from src.db_utils.reports import StockReportDB, DatabaseConnectionError
|
||||
from src.db_utils.reports_mysql import StockReportMysql
|
||||
from src.logger.logger import setup_logging
|
||||
import PyPDF2
|
||||
|
||||
@ -83,6 +84,17 @@ def fetch_reports_list_general(fetch_func, table_name, s_date, e_date, data_dir_
|
||||
# 统一以 infoCode 为 UNIQE 键,所以这里对它进行赋值
|
||||
if row.get('infoCode') is None and row.get('encodeUrl'):
|
||||
row['infoCode'] = row['encodeUrl']
|
||||
row['count_all'] = row.get('count', 0) # 兼容旧数据
|
||||
row['curr_column'] = row.get('column', 'None') # 兼容旧数据
|
||||
if 'stockName' not in row or row['stockName'] is None or row['stockName']=='':
|
||||
row['stockName'] = ''
|
||||
if 'stockCode' not in row or row['stockCode'] is None or row['stockCode']=='':
|
||||
row['stockCode'] = ''
|
||||
if 'newPeIssueA' in row and row['newPeIssueA'] is None:
|
||||
try:
|
||||
row['newPeIssueA'] = float(row.get('newPeIssueA', 0))
|
||||
except ValueError:
|
||||
row['newPeIssueA'] = 0.0
|
||||
row_id = db_tools.insert_or_update_common(row, table_name)
|
||||
if row_id:
|
||||
logging.debug(f'insert one row. rowid:{row_id}, ')
|
||||
@ -325,7 +337,9 @@ def main(cmd, mode, args_debug, args_force, begin, end):
|
||||
# 初始化DB
|
||||
global db_tools
|
||||
try:
|
||||
db_tools = StockReportDB(db_path)
|
||||
#db_tools = StockReportDB(db_path)
|
||||
db_tools = StockReportMysql(db_host=db_config['host'], db_user=db_config['user'], db_password=db_config['password'], db_name = db_config['database'], port=3306) # 使用配置文件中的数据库配置
|
||||
|
||||
# 进行数据库操作
|
||||
except DatabaseConnectionError as e:
|
||||
logging.error(f"数据库连接失败: {e}")
|
||||
|
||||
@ -0,0 +1,253 @@
|
||||
"""Auto update from stockdb
|
||||
|
||||
Revision ID: 33c9c4443fa8
|
||||
Revises: 9680e7b8e29b
|
||||
Create Date: 2025-08-10 18:03:56.817265
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '33c9c4443fa8'
|
||||
down_revision: Union[str, Sequence[str], None] = '9680e7b8e29b'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('reports_industry',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='自增主键'),
|
||||
sa.Column('infoCode', sa.String(length=255), nullable=False, comment='报告唯一标识'),
|
||||
sa.Column('title', sa.String(length=512), nullable=True, comment='报告标题'),
|
||||
sa.Column('stockName', sa.String(length=100), nullable=True, comment='股票名称'),
|
||||
sa.Column('stockCode', sa.String(length=50), nullable=True, comment='股票代码'),
|
||||
sa.Column('orgCode', sa.String(length=50), nullable=True, comment='机构代码'),
|
||||
sa.Column('orgName', sa.String(length=255), nullable=True, comment='机构全称'),
|
||||
sa.Column('orgSName', sa.String(length=100), nullable=True, comment='机构简称'),
|
||||
sa.Column('publishDate', sa.String(length=50), nullable=True, comment='发布日期'),
|
||||
sa.Column('column', sa.String(length=255), nullable=True, comment='栏目'),
|
||||
sa.Column('predictNextTwoYearEps', sa.String(length=50), nullable=True, comment='未来两年EPS预测'),
|
||||
sa.Column('predictNextTwoYearPe', sa.String(length=50), nullable=True, comment='未来两年PE预测'),
|
||||
sa.Column('predictNextYearEps', sa.String(length=50), nullable=True, comment='明年EPS预测'),
|
||||
sa.Column('predictNextYearPe', sa.String(length=50), nullable=True, comment='明年PE预测'),
|
||||
sa.Column('predictThisYearEps', sa.String(length=50), nullable=True, comment='今年EPS预测'),
|
||||
sa.Column('predictThisYearPe', sa.String(length=50), nullable=True, comment='今年PE预测'),
|
||||
sa.Column('predictLastYearEps', sa.String(length=50), nullable=True, comment='去年EPS预测'),
|
||||
sa.Column('predictLastYearPe', sa.String(length=50), nullable=True, comment='去年PE预测'),
|
||||
sa.Column('actualLastTwoYearEps', sa.String(length=50), nullable=True, comment='前两年实际EPS'),
|
||||
sa.Column('actualLastYearEps', sa.String(length=50), nullable=True, comment='去年实际EPS'),
|
||||
sa.Column('industryCode', sa.String(length=50), nullable=True, comment='行业代码'),
|
||||
sa.Column('industryName', sa.String(length=100), nullable=True, comment='行业名称'),
|
||||
sa.Column('emIndustryCode', sa.String(length=50), nullable=True, comment='东方财富行业代码'),
|
||||
sa.Column('indvInduCode', sa.String(length=50), nullable=True, comment='个性化行业代码'),
|
||||
sa.Column('indvInduName', sa.String(length=100), nullable=True, comment='个性化行业名称'),
|
||||
sa.Column('emRatingCode', sa.String(length=50), nullable=True, comment='东方财富评级代码'),
|
||||
sa.Column('emRatingValue', sa.String(length=50), nullable=True, comment='东方财富评级值'),
|
||||
sa.Column('emRatingName', sa.String(length=100), nullable=True, comment='东方财富评级名称'),
|
||||
sa.Column('lastEmRatingCode', sa.String(length=50), nullable=True, comment='上次东方财富评级代码'),
|
||||
sa.Column('lastEmRatingValue', sa.String(length=50), nullable=True, comment='上次东方财富评级值'),
|
||||
sa.Column('lastEmRatingName', sa.String(length=100), nullable=True, comment='上次东方财富评级名称'),
|
||||
sa.Column('ratingChange', sa.String(length=50), nullable=True, comment='评级变动'),
|
||||
sa.Column('reportType', sa.Integer(), nullable=True, comment='报告类型'),
|
||||
sa.Column('author', sa.String(length=255), nullable=True, comment='作者(逗号分隔)'),
|
||||
sa.Column('indvIsNew', sa.String(length=20), nullable=True, comment='是否为新研报'),
|
||||
sa.Column('researcher', sa.String(length=255), nullable=True, comment='研究员'),
|
||||
sa.Column('newListingDate', sa.String(length=50), nullable=True, comment='新上市日期'),
|
||||
sa.Column('newPurchaseDate', sa.String(length=50), nullable=True, comment='新买入日期'),
|
||||
sa.Column('newIssuePrice', sa.String(length=50), nullable=True, comment='新发行价格'),
|
||||
sa.Column('newPeIssueA', sa.String(length=50), nullable=True, comment='新发行市盈率A'),
|
||||
sa.Column('indvAimPriceT', sa.String(length=50), nullable=True, comment='目标价上限'),
|
||||
sa.Column('indvAimPriceL', sa.String(length=50), nullable=True, comment='目标价下限'),
|
||||
sa.Column('attachType', sa.String(length=50), nullable=True, comment='附件类型'),
|
||||
sa.Column('attachSize', sa.Integer(), nullable=True, comment='附件大小'),
|
||||
sa.Column('attachPages', sa.Integer(), nullable=True, comment='附件页数'),
|
||||
sa.Column('encodeUrl', sa.String(length=512), nullable=True, comment='加密URL'),
|
||||
sa.Column('sRatingName', sa.String(length=100), nullable=True, comment='评级名称'),
|
||||
sa.Column('sRatingCode', sa.String(length=50), nullable=True, comment='评级代码'),
|
||||
sa.Column('market', sa.String(length=50), nullable=True, comment='市场'),
|
||||
sa.Column('authorID', sa.String(length=255), nullable=True, comment='作者ID(逗号分隔)'),
|
||||
sa.Column('count', sa.Integer(), nullable=True, comment='计数'),
|
||||
sa.Column('orgType', sa.String(length=50), nullable=True, comment='机构类型'),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False, comment='创建时间'),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False, comment='更新时间'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('infoCode')
|
||||
)
|
||||
op.create_table('reports_macresearch',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='自增主键'),
|
||||
sa.Column('infoCode', sa.String(length=255), nullable=False, comment='报告唯一标识'),
|
||||
sa.Column('json_id', sa.String(length=50), nullable=True, comment='JSON ID'),
|
||||
sa.Column('title', sa.String(length=512), nullable=True, comment='报告标题'),
|
||||
sa.Column('author', sa.String(length=255), nullable=True, comment='作者(逗号分隔)'),
|
||||
sa.Column('orgName', sa.String(length=255), nullable=True, comment='机构全称'),
|
||||
sa.Column('orgCode', sa.String(length=50), nullable=True, comment='机构代码'),
|
||||
sa.Column('orgSName', sa.String(length=100), nullable=True, comment='机构简称'),
|
||||
sa.Column('publishDate', sa.String(length=50), nullable=True, comment='发布日期'),
|
||||
sa.Column('encodeUrl', sa.String(length=512), nullable=True, comment='加密URL'),
|
||||
sa.Column('researcher', sa.String(length=255), nullable=True, comment='研究员'),
|
||||
sa.Column('market', sa.String(length=50), nullable=True, comment='市场'),
|
||||
sa.Column('industryCode', sa.String(length=50), nullable=True, comment='行业代码'),
|
||||
sa.Column('industryName', sa.String(length=100), nullable=True, comment='行业名称'),
|
||||
sa.Column('authorID', sa.String(length=255), nullable=True, comment='作者ID(逗号分隔)'),
|
||||
sa.Column('count', sa.Integer(), nullable=True, comment='计数'),
|
||||
sa.Column('orgType', sa.String(length=50), nullable=True, comment='机构类型'),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False, comment='创建时间'),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False, comment='更新时间'),
|
||||
sa.Column('stockCode', sa.String(length=50), nullable=False, comment='股票代码(默认空字符串)'),
|
||||
sa.Column('stockName', sa.String(length=100), nullable=False, comment='股票名称(默认空字符串)'),
|
||||
sa.Column('attachPages', sa.Integer(), nullable=True, comment='附件页数'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('infoCode')
|
||||
)
|
||||
op.create_table('reports_newstrock',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='自增主键'),
|
||||
sa.Column('infoCode', sa.String(length=255), nullable=False, comment='报告唯一标识'),
|
||||
sa.Column('title', sa.String(length=512), nullable=True, comment='报告标题'),
|
||||
sa.Column('stockName', sa.String(length=100), nullable=True, comment='股票名称'),
|
||||
sa.Column('stockCode', sa.String(length=50), nullable=True, comment='股票代码'),
|
||||
sa.Column('orgCode', sa.String(length=50), nullable=True, comment='机构代码'),
|
||||
sa.Column('orgName', sa.String(length=255), nullable=True, comment='机构全称'),
|
||||
sa.Column('orgSName', sa.String(length=100), nullable=True, comment='机构简称'),
|
||||
sa.Column('publishDate', sa.String(length=50), nullable=True, comment='发布日期'),
|
||||
sa.Column('column', sa.String(length=255), nullable=True, comment='栏目'),
|
||||
sa.Column('actualLastTwoYearEps', sa.String(length=50), nullable=True, comment='前两年实际EPS'),
|
||||
sa.Column('actualLastYearEps', sa.String(length=50), nullable=True, comment='去年实际EPS'),
|
||||
sa.Column('industryCode', sa.String(length=50), nullable=True, comment='行业代码'),
|
||||
sa.Column('industryName', sa.String(length=100), nullable=True, comment='行业名称'),
|
||||
sa.Column('emIndustryCode', sa.String(length=50), nullable=True, comment='东方财富行业代码'),
|
||||
sa.Column('indvInduCode', sa.String(length=50), nullable=True, comment='个性化行业代码'),
|
||||
sa.Column('indvInduName', sa.String(length=100), nullable=True, comment='个性化行业名称'),
|
||||
sa.Column('emRatingCode', sa.String(length=50), nullable=True, comment='东方财富评级代码'),
|
||||
sa.Column('emRatingValue', sa.String(length=50), nullable=True, comment='东方财富评级值'),
|
||||
sa.Column('emRatingName', sa.String(length=100), nullable=True, comment='东方财富评级名称'),
|
||||
sa.Column('lastEmRatingCode', sa.String(length=50), nullable=True, comment='上次东方财富评级代码'),
|
||||
sa.Column('lastEmRatingValue', sa.String(length=50), nullable=True, comment='上次东方财富评级值'),
|
||||
sa.Column('lastEmRatingName', sa.String(length=100), nullable=True, comment='上次东方财富评级名称'),
|
||||
sa.Column('ratingChange', sa.String(length=50), nullable=True, comment='评级变动'),
|
||||
sa.Column('reportType', sa.Integer(), nullable=True, comment='报告类型'),
|
||||
sa.Column('author', sa.String(length=255), nullable=True, comment='作者(逗号分隔)'),
|
||||
sa.Column('indvIsNew', sa.String(length=20), nullable=True, comment='是否为新研报'),
|
||||
sa.Column('researcher', sa.String(length=255), nullable=True, comment='研究员'),
|
||||
sa.Column('newListingDate', sa.String(length=50), nullable=True, comment='新上市日期'),
|
||||
sa.Column('newPurchaseDate', sa.String(length=50), nullable=True, comment='新买入日期'),
|
||||
sa.Column('newIssuePrice', sa.Float(), nullable=True, comment='新发行价格'),
|
||||
sa.Column('newPeIssueA', sa.Float(), nullable=True, comment='新发行市盈率A'),
|
||||
sa.Column('indvAimPriceT', sa.String(length=50), nullable=True, comment='目标价上限'),
|
||||
sa.Column('indvAimPriceL', sa.String(length=50), nullable=True, comment='目标价下限'),
|
||||
sa.Column('attachType', sa.String(length=50), nullable=True, comment='附件类型'),
|
||||
sa.Column('attachSize', sa.Integer(), nullable=True, comment='附件大小'),
|
||||
sa.Column('attachPages', sa.Integer(), nullable=True, comment='附件页数'),
|
||||
sa.Column('encodeUrl', sa.String(length=512), nullable=True, comment='加密URL'),
|
||||
sa.Column('sRatingName', sa.String(length=100), nullable=True, comment='评级名称'),
|
||||
sa.Column('sRatingCode', sa.String(length=50), nullable=True, comment='评级代码'),
|
||||
sa.Column('market', sa.String(length=50), nullable=True, comment='市场'),
|
||||
sa.Column('newStockSort', sa.String(length=50), nullable=True, comment='新股分类'),
|
||||
sa.Column('authorID', sa.String(length=255), nullable=True, comment='作者ID(逗号分隔)'),
|
||||
sa.Column('count', sa.Integer(), nullable=True, comment='计数'),
|
||||
sa.Column('orgType', sa.String(length=50), nullable=True, comment='机构类型'),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False, comment='创建时间'),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False, comment='更新时间'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('infoCode')
|
||||
)
|
||||
op.create_table('reports_stock',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='自增主键'),
|
||||
sa.Column('infoCode', sa.String(length=255), nullable=False, comment='报告唯一标识'),
|
||||
sa.Column('title', sa.String(length=512), nullable=True, comment='报告标题'),
|
||||
sa.Column('stockName', sa.String(length=100), nullable=True, comment='股票名称'),
|
||||
sa.Column('stockCode', sa.String(length=50), nullable=True, comment='股票代码'),
|
||||
sa.Column('orgCode', sa.String(length=50), nullable=True, comment='机构代码'),
|
||||
sa.Column('orgName', sa.String(length=255), nullable=True, comment='机构全称'),
|
||||
sa.Column('orgSName', sa.String(length=100), nullable=True, comment='机构简称'),
|
||||
sa.Column('publishDate', sa.String(length=50), nullable=True, comment='发布日期'),
|
||||
sa.Column('column', sa.String(length=255), nullable=True, comment='栏目'),
|
||||
sa.Column('predictNextTwoYearEps', sa.String(length=50), nullable=True, comment='未来两年EPS预测'),
|
||||
sa.Column('predictNextTwoYearPe', sa.String(length=50), nullable=True, comment='未来两年PE预测'),
|
||||
sa.Column('predictNextYearEps', sa.String(length=50), nullable=True, comment='明年EPS预测'),
|
||||
sa.Column('predictNextYearPe', sa.String(length=50), nullable=True, comment='明年PE预测'),
|
||||
sa.Column('predictThisYearEps', sa.String(length=50), nullable=True, comment='今年EPS预测'),
|
||||
sa.Column('predictThisYearPe', sa.String(length=50), nullable=True, comment='今年PE预测'),
|
||||
sa.Column('predictLastYearEps', sa.String(length=50), nullable=True, comment='去年EPS预测'),
|
||||
sa.Column('predictLastYearPe', sa.String(length=50), nullable=True, comment='去年PE预测'),
|
||||
sa.Column('actualLastTwoYearEps', sa.String(length=50), nullable=True, comment='前两年实际EPS'),
|
||||
sa.Column('actualLastYearEps', sa.String(length=50), nullable=True, comment='去年实际EPS'),
|
||||
sa.Column('industryCode', sa.String(length=50), nullable=True, comment='行业代码'),
|
||||
sa.Column('industryName', sa.String(length=100), nullable=True, comment='行业名称'),
|
||||
sa.Column('emIndustryCode', sa.String(length=50), nullable=True, comment='东方财富行业代码'),
|
||||
sa.Column('indvInduCode', sa.String(length=50), nullable=True, comment='个性化行业代码'),
|
||||
sa.Column('indvInduName', sa.String(length=100), nullable=True, comment='个性化行业名称'),
|
||||
sa.Column('emRatingCode', sa.String(length=50), nullable=True, comment='东方财富评级代码'),
|
||||
sa.Column('emRatingValue', sa.String(length=50), nullable=True, comment='东方财富评级值'),
|
||||
sa.Column('emRatingName', sa.String(length=100), nullable=True, comment='东方财富评级名称'),
|
||||
sa.Column('lastEmRatingCode', sa.String(length=50), nullable=True, comment='上次东方财富评级代码'),
|
||||
sa.Column('lastEmRatingValue', sa.String(length=50), nullable=True, comment='上次东方财富评级值'),
|
||||
sa.Column('lastEmRatingName', sa.String(length=100), nullable=True, comment='上次东方财富评级名称'),
|
||||
sa.Column('ratingChange', sa.Integer(), nullable=True, comment='评级变动'),
|
||||
sa.Column('reportType', sa.Integer(), nullable=True, comment='报告类型'),
|
||||
sa.Column('author', sa.String(length=255), nullable=True, comment='作者(逗号分隔)'),
|
||||
sa.Column('indvIsNew', sa.String(length=20), nullable=True, comment='是否为新研报'),
|
||||
sa.Column('researcher', sa.String(length=255), nullable=True, comment='研究员'),
|
||||
sa.Column('newListingDate', sa.String(length=50), nullable=True, comment='新上市日期'),
|
||||
sa.Column('newPurchaseDate', sa.String(length=50), nullable=True, comment='新买入日期'),
|
||||
sa.Column('newIssuePrice', sa.Float(), nullable=True, comment='新发行价格'),
|
||||
sa.Column('newPeIssueA', sa.Float(), nullable=True, comment='新发行市盈率A'),
|
||||
sa.Column('indvAimPriceT', sa.String(length=50), nullable=True, comment='目标价上限'),
|
||||
sa.Column('indvAimPriceL', sa.String(length=50), nullable=True, comment='目标价下限'),
|
||||
sa.Column('attachType', sa.String(length=50), nullable=True, comment='附件类型'),
|
||||
sa.Column('attachSize', sa.Integer(), nullable=True, comment='附件大小'),
|
||||
sa.Column('attachPages', sa.Integer(), nullable=True, comment='附件页数'),
|
||||
sa.Column('encodeUrl', sa.String(length=512), nullable=True, comment='加密URL'),
|
||||
sa.Column('sRatingName', sa.String(length=100), nullable=True, comment='评级名称'),
|
||||
sa.Column('sRatingCode', sa.String(length=50), nullable=True, comment='评级代码'),
|
||||
sa.Column('market', sa.String(length=50), nullable=True, comment='市场'),
|
||||
sa.Column('authorID', sa.String(length=255), nullable=True, comment='作者ID(逗号分隔)'),
|
||||
sa.Column('count', sa.Integer(), nullable=True, comment='计数'),
|
||||
sa.Column('orgType', sa.String(length=50), nullable=True, comment='机构类型'),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False, comment='创建时间'),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False, comment='更新时间'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('infoCode')
|
||||
)
|
||||
op.create_table('reports_strategy',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='自增主键'),
|
||||
sa.Column('infoCode', sa.String(length=255), nullable=False, comment='报告唯一标识'),
|
||||
sa.Column('title', sa.String(length=512), nullable=True, comment='报告标题'),
|
||||
sa.Column('author', sa.String(length=255), nullable=True, comment='作者(逗号分隔)'),
|
||||
sa.Column('orgName', sa.String(length=255), nullable=True, comment='机构全称'),
|
||||
sa.Column('orgCode', sa.String(length=50), nullable=True, comment='机构代码'),
|
||||
sa.Column('orgSName', sa.String(length=100), nullable=True, comment='机构简称'),
|
||||
sa.Column('publishDate', sa.String(length=50), nullable=True, comment='发布日期'),
|
||||
sa.Column('encodeUrl', sa.String(length=512), nullable=True, comment='加密URL'),
|
||||
sa.Column('researcher', sa.String(length=255), nullable=True, comment='研究员'),
|
||||
sa.Column('market', sa.String(length=50), nullable=True, comment='市场'),
|
||||
sa.Column('industryCode', sa.String(length=50), nullable=True, comment='行业代码'),
|
||||
sa.Column('industryName', sa.String(length=100), nullable=True, comment='行业名称'),
|
||||
sa.Column('authorID', sa.String(length=255), nullable=True, comment='作者ID(逗号分隔)'),
|
||||
sa.Column('count', sa.Integer(), nullable=True, comment='计数'),
|
||||
sa.Column('orgType', sa.String(length=50), nullable=True, comment='机构类型'),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False, comment='创建时间'),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False, comment='更新时间'),
|
||||
sa.Column('stockName', sa.String(length=100), nullable=False, comment='股票名称(默认空字符串)'),
|
||||
sa.Column('stockCode', sa.String(length=50), nullable=False, comment='股票代码(默认空字符串)'),
|
||||
sa.Column('attachPages', sa.Integer(), nullable=True, comment='附件页数'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('infoCode')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('reports_strategy')
|
||||
op.drop_table('reports_stock')
|
||||
op.drop_table('reports_newstrock')
|
||||
op.drop_table('reports_macresearch')
|
||||
op.drop_table('reports_industry')
|
||||
# ### end Alembic commands ###
|
||||
@ -0,0 +1,62 @@
|
||||
"""Auto update from stockdb
|
||||
|
||||
Revision ID: c72bb1f27166
|
||||
Revises: 33c9c4443fa8
|
||||
Create Date: 2025-08-10 18:36:58.748680
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'c72bb1f27166'
|
||||
down_revision: Union[str, Sequence[str], None] = '33c9c4443fa8'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('reports_industry', sa.Column('curr_column', sa.String(length=255), nullable=True, comment='栏目'))
|
||||
op.add_column('reports_industry', sa.Column('count_all', sa.Integer(), nullable=True, comment='计数'))
|
||||
op.drop_column('reports_industry', 'column')
|
||||
op.drop_column('reports_industry', 'count')
|
||||
op.add_column('reports_macresearch', sa.Column('count_all', sa.Integer(), nullable=True, comment='计数'))
|
||||
op.drop_column('reports_macresearch', 'count')
|
||||
op.add_column('reports_newstrock', sa.Column('curr_column', sa.String(length=255), nullable=True, comment='栏目'))
|
||||
op.add_column('reports_newstrock', sa.Column('count_all', sa.Integer(), nullable=True, comment='计数'))
|
||||
op.drop_column('reports_newstrock', 'column')
|
||||
op.drop_column('reports_newstrock', 'count')
|
||||
op.add_column('reports_stock', sa.Column('curr_column', sa.String(length=255), nullable=True, comment='栏目'))
|
||||
op.add_column('reports_stock', sa.Column('count_all', sa.Integer(), nullable=True, comment='计数'))
|
||||
op.drop_column('reports_stock', 'column')
|
||||
op.drop_column('reports_stock', 'count')
|
||||
op.add_column('reports_strategy', sa.Column('count_all', sa.Integer(), nullable=True, comment='计数'))
|
||||
op.drop_column('reports_strategy', 'count')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('reports_strategy', sa.Column('count', mysql.INTEGER(), autoincrement=False, nullable=True, comment='计数'))
|
||||
op.drop_column('reports_strategy', 'count_all')
|
||||
op.add_column('reports_stock', sa.Column('count', mysql.INTEGER(), autoincrement=False, nullable=True, comment='计数'))
|
||||
op.add_column('reports_stock', sa.Column('column', mysql.VARCHAR(length=255), nullable=True, comment='栏目'))
|
||||
op.drop_column('reports_stock', 'count_all')
|
||||
op.drop_column('reports_stock', 'curr_column')
|
||||
op.add_column('reports_newstrock', sa.Column('count', mysql.INTEGER(), autoincrement=False, nullable=True, comment='计数'))
|
||||
op.add_column('reports_newstrock', sa.Column('column', mysql.VARCHAR(length=255), nullable=True, comment='栏目'))
|
||||
op.drop_column('reports_newstrock', 'count_all')
|
||||
op.drop_column('reports_newstrock', 'curr_column')
|
||||
op.add_column('reports_macresearch', sa.Column('count', mysql.INTEGER(), autoincrement=False, nullable=True, comment='计数'))
|
||||
op.drop_column('reports_macresearch', 'count_all')
|
||||
op.add_column('reports_industry', sa.Column('count', mysql.INTEGER(), autoincrement=False, nullable=True, comment='计数'))
|
||||
op.add_column('reports_industry', sa.Column('column', mysql.VARCHAR(length=255), nullable=True, comment='栏目'))
|
||||
op.drop_column('reports_industry', 'count_all')
|
||||
op.drop_column('reports_industry', 'curr_column')
|
||||
# ### end Alembic commands ###
|
||||
@ -1,6 +1,7 @@
|
||||
from sqlalchemy import BigInteger, Date, DateTime, Double, Float, Integer, String, text, Numeric
|
||||
from sqlalchemy.dialects.mysql import TINYINT, VARCHAR
|
||||
from typing import Optional
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
||||
import datetime
|
||||
@ -446,3 +447,227 @@ class FutuTradingDayModel(Base):
|
||||
String(20),
|
||||
comment="交易日类型"
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ReportsStock(Base):
|
||||
__tablename__ = "reports_stock"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="自增主键")
|
||||
infoCode: Mapped[str] = mapped_column(String(255), unique=True, comment="报告唯一标识")
|
||||
title: Mapped[Optional[str]] = mapped_column(String(512), comment="报告标题")
|
||||
stockName: Mapped[Optional[str]] = mapped_column(String(100), comment="股票名称")
|
||||
stockCode: Mapped[Optional[str]] = mapped_column(String(50), comment="股票代码")
|
||||
orgCode: Mapped[Optional[str]] = mapped_column(String(50), comment="机构代码")
|
||||
orgName: Mapped[Optional[str]] = mapped_column(String(255), comment="机构全称")
|
||||
orgSName: Mapped[Optional[str]] = mapped_column(String(100), comment="机构简称")
|
||||
publishDate: Mapped[Optional[str]] = mapped_column(String(50), comment="发布日期")
|
||||
curr_column: Mapped[Optional[str]] = mapped_column(String(255), comment="栏目") # 注意:column是SQL关键字,建议后续改名
|
||||
predictNextTwoYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="未来两年EPS预测")
|
||||
predictNextTwoYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="未来两年PE预测")
|
||||
predictNextYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="明年EPS预测")
|
||||
predictNextYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="明年PE预测")
|
||||
predictThisYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="今年EPS预测")
|
||||
predictThisYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="今年PE预测")
|
||||
predictLastYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="去年EPS预测")
|
||||
predictLastYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="去年PE预测")
|
||||
actualLastTwoYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="前两年实际EPS")
|
||||
actualLastYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="去年实际EPS")
|
||||
industryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="行业代码")
|
||||
industryName: Mapped[Optional[str]] = mapped_column(String(100), comment="行业名称")
|
||||
emIndustryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富行业代码")
|
||||
indvInduCode: Mapped[Optional[str]] = mapped_column(String(50), comment="个性化行业代码")
|
||||
indvInduName: Mapped[Optional[str]] = mapped_column(String(100), comment="个性化行业名称")
|
||||
emRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富评级代码")
|
||||
emRatingValue: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富评级值")
|
||||
emRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="东方财富评级名称")
|
||||
lastEmRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="上次东方财富评级代码")
|
||||
lastEmRatingValue: Mapped[Optional[str]] = mapped_column(String(50), comment="上次东方财富评级值")
|
||||
lastEmRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="上次东方财富评级名称")
|
||||
ratingChange: Mapped[Optional[int]] = mapped_column(Integer, comment="评级变动")
|
||||
reportType: Mapped[Optional[int]] = mapped_column(Integer, comment="报告类型")
|
||||
author: Mapped[Optional[str]] = mapped_column(String(255), comment="作者(逗号分隔)")
|
||||
indvIsNew: Mapped[Optional[str]] = mapped_column(String(20), comment="是否为新研报")
|
||||
researcher: Mapped[Optional[str]] = mapped_column(String(255), comment="研究员")
|
||||
newListingDate: Mapped[Optional[str]] = mapped_column(String(50), comment="新上市日期")
|
||||
newPurchaseDate: Mapped[Optional[str]] = mapped_column(String(50), comment="新买入日期")
|
||||
newIssuePrice: Mapped[Optional[float]] = mapped_column(Float, comment="新发行价格")
|
||||
newPeIssueA: Mapped[Optional[float]] = mapped_column(Float, comment="新发行市盈率A")
|
||||
indvAimPriceT: Mapped[Optional[str]] = mapped_column(String(50), comment="目标价上限")
|
||||
indvAimPriceL: Mapped[Optional[str]] = mapped_column(String(50), comment="目标价下限")
|
||||
attachType: Mapped[Optional[str]] = mapped_column(String(50), comment="附件类型")
|
||||
attachSize: Mapped[Optional[int]] = mapped_column(Integer, comment="附件大小")
|
||||
attachPages: Mapped[Optional[int]] = mapped_column(Integer, comment="附件页数")
|
||||
encodeUrl: Mapped[Optional[str]] = mapped_column(String(512), comment="加密URL")
|
||||
sRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="评级名称")
|
||||
sRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="评级代码")
|
||||
market: Mapped[Optional[str]] = mapped_column(String(50), comment="市场")
|
||||
authorID: Mapped[Optional[str]] = mapped_column(String(255), comment="作者ID(逗号分隔)")
|
||||
count_all: Mapped[Optional[int]] = mapped_column(Integer, comment="计数")
|
||||
orgType: Mapped[Optional[str]] = mapped_column(String(50), comment="机构类型")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), comment="创建时间")
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
|
||||
class ReportsIndustry(Base):
|
||||
__tablename__ = "reports_industry"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="自增主键")
|
||||
infoCode: Mapped[str] = mapped_column(String(255), unique=True, comment="报告唯一标识")
|
||||
title: Mapped[Optional[str]] = mapped_column(String(512), comment="报告标题")
|
||||
stockName: Mapped[Optional[str]] = mapped_column(String(100), comment="股票名称")
|
||||
stockCode: Mapped[Optional[str]] = mapped_column(String(50), comment="股票代码")
|
||||
orgCode: Mapped[Optional[str]] = mapped_column(String(50), comment="机构代码")
|
||||
orgName: Mapped[Optional[str]] = mapped_column(String(255), comment="机构全称")
|
||||
orgSName: Mapped[Optional[str]] = mapped_column(String(100), comment="机构简称")
|
||||
publishDate: Mapped[Optional[str]] = mapped_column(String(50), comment="发布日期")
|
||||
curr_column: Mapped[Optional[str]] = mapped_column(String(255), comment="栏目") # 注意:column是SQL关键字
|
||||
predictNextTwoYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="未来两年EPS预测")
|
||||
predictNextTwoYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="未来两年PE预测")
|
||||
predictNextYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="明年EPS预测")
|
||||
predictNextYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="明年PE预测")
|
||||
predictThisYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="今年EPS预测")
|
||||
predictThisYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="今年PE预测")
|
||||
predictLastYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="去年EPS预测")
|
||||
predictLastYearPe: Mapped[Optional[str]] = mapped_column(String(50), comment="去年PE预测")
|
||||
actualLastTwoYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="前两年实际EPS")
|
||||
actualLastYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="去年实际EPS")
|
||||
industryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="行业代码")
|
||||
industryName: Mapped[Optional[str]] = mapped_column(String(100), comment="行业名称")
|
||||
emIndustryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富行业代码")
|
||||
indvInduCode: Mapped[Optional[str]] = mapped_column(String(50), comment="个性化行业代码")
|
||||
indvInduName: Mapped[Optional[str]] = mapped_column(String(100), comment="个性化行业名称")
|
||||
emRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富评级代码")
|
||||
emRatingValue: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富评级值")
|
||||
emRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="东方财富评级名称")
|
||||
lastEmRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="上次东方财富评级代码")
|
||||
lastEmRatingValue: Mapped[Optional[str]] = mapped_column(String(50), comment="上次东方财富评级值")
|
||||
lastEmRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="上次东方财富评级名称")
|
||||
ratingChange: Mapped[Optional[str]] = mapped_column(String(50), comment="评级变动")
|
||||
reportType: Mapped[Optional[int]] = mapped_column(Integer, comment="报告类型")
|
||||
author: Mapped[Optional[str]] = mapped_column(String(255), comment="作者(逗号分隔)")
|
||||
indvIsNew: Mapped[Optional[str]] = mapped_column(String(20), comment="是否为新研报")
|
||||
researcher: Mapped[Optional[str]] = mapped_column(String(255), comment="研究员")
|
||||
newListingDate: Mapped[Optional[str]] = mapped_column(String(50), comment="新上市日期")
|
||||
newPurchaseDate: Mapped[Optional[str]] = mapped_column(String(50), comment="新买入日期")
|
||||
newIssuePrice: Mapped[Optional[str]] = mapped_column(String(50), comment="新发行价格")
|
||||
newPeIssueA: Mapped[Optional[str]] = mapped_column(String(50), comment="新发行市盈率A")
|
||||
indvAimPriceT: Mapped[Optional[str]] = mapped_column(String(50), comment="目标价上限")
|
||||
indvAimPriceL: Mapped[Optional[str]] = mapped_column(String(50), comment="目标价下限")
|
||||
attachType: Mapped[Optional[str]] = mapped_column(String(50), comment="附件类型")
|
||||
attachSize: Mapped[Optional[int]] = mapped_column(Integer, comment="附件大小")
|
||||
attachPages: Mapped[Optional[int]] = mapped_column(Integer, comment="附件页数")
|
||||
encodeUrl: Mapped[Optional[str]] = mapped_column(String(512), comment="加密URL")
|
||||
sRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="评级名称")
|
||||
sRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="评级代码")
|
||||
market: Mapped[Optional[str]] = mapped_column(String(50), comment="市场")
|
||||
authorID: Mapped[Optional[str]] = mapped_column(String(255), comment="作者ID(逗号分隔)")
|
||||
count_all: Mapped[Optional[int]] = mapped_column(Integer, comment="计数")
|
||||
orgType: Mapped[Optional[str]] = mapped_column(String(50), comment="机构类型")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), comment="创建时间")
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
|
||||
class ReportsNewstrock(Base):
|
||||
__tablename__ = "reports_newstrock" # 注意:原表名可能存在笔误(应为newstock)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="自增主键")
|
||||
infoCode: Mapped[str] = mapped_column(String(255), unique=True, comment="报告唯一标识")
|
||||
title: Mapped[Optional[str]] = mapped_column(String(512), comment="报告标题")
|
||||
stockName: Mapped[Optional[str]] = mapped_column(String(100), comment="股票名称")
|
||||
stockCode: Mapped[Optional[str]] = mapped_column(String(50), comment="股票代码")
|
||||
orgCode: Mapped[Optional[str]] = mapped_column(String(50), comment="机构代码")
|
||||
orgName: Mapped[Optional[str]] = mapped_column(String(255), comment="机构全称")
|
||||
orgSName: Mapped[Optional[str]] = mapped_column(String(100), comment="机构简称")
|
||||
publishDate: Mapped[Optional[str]] = mapped_column(String(50), comment="发布日期")
|
||||
curr_column: Mapped[Optional[str]] = mapped_column(String(255), comment="栏目") # 注意:column是SQL关键字
|
||||
actualLastTwoYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="前两年实际EPS")
|
||||
actualLastYearEps: Mapped[Optional[str]] = mapped_column(String(50), comment="去年实际EPS")
|
||||
industryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="行业代码")
|
||||
industryName: Mapped[Optional[str]] = mapped_column(String(100), comment="行业名称")
|
||||
emIndustryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富行业代码")
|
||||
indvInduCode: Mapped[Optional[str]] = mapped_column(String(50), comment="个性化行业代码")
|
||||
indvInduName: Mapped[Optional[str]] = mapped_column(String(100), comment="个性化行业名称")
|
||||
emRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富评级代码")
|
||||
emRatingValue: Mapped[Optional[str]] = mapped_column(String(50), comment="东方财富评级值")
|
||||
emRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="东方财富评级名称")
|
||||
lastEmRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="上次东方财富评级代码")
|
||||
lastEmRatingValue: Mapped[Optional[str]] = mapped_column(String(50), comment="上次东方财富评级值")
|
||||
lastEmRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="上次东方财富评级名称")
|
||||
ratingChange: Mapped[Optional[str]] = mapped_column(String(50), comment="评级变动")
|
||||
reportType: Mapped[Optional[int]] = mapped_column(Integer, comment="报告类型")
|
||||
author: Mapped[Optional[str]] = mapped_column(String(255), comment="作者(逗号分隔)")
|
||||
indvIsNew: Mapped[Optional[str]] = mapped_column(String(20), comment="是否为新研报")
|
||||
researcher: Mapped[Optional[str]] = mapped_column(String(255), comment="研究员")
|
||||
newListingDate: Mapped[Optional[str]] = mapped_column(String(50), comment="新上市日期")
|
||||
newPurchaseDate: Mapped[Optional[str]] = mapped_column(String(50), comment="新买入日期")
|
||||
newIssuePrice: Mapped[Optional[float]] = mapped_column(Float, comment="新发行价格")
|
||||
newPeIssueA: Mapped[Optional[float]] = mapped_column(Float, comment="新发行市盈率A")
|
||||
indvAimPriceT: Mapped[Optional[str]] = mapped_column(String(50), comment="目标价上限")
|
||||
indvAimPriceL: Mapped[Optional[str]] = mapped_column(String(50), comment="目标价下限")
|
||||
attachType: Mapped[Optional[str]] = mapped_column(String(50), comment="附件类型")
|
||||
attachSize: Mapped[Optional[int]] = mapped_column(Integer, comment="附件大小")
|
||||
attachPages: Mapped[Optional[int]] = mapped_column(Integer, comment="附件页数")
|
||||
encodeUrl: Mapped[Optional[str]] = mapped_column(String(512), comment="加密URL")
|
||||
sRatingName: Mapped[Optional[str]] = mapped_column(String(100), comment="评级名称")
|
||||
sRatingCode: Mapped[Optional[str]] = mapped_column(String(50), comment="评级代码")
|
||||
market: Mapped[Optional[str]] = mapped_column(String(50), comment="市场")
|
||||
newStockSort: Mapped[Optional[str]] = mapped_column(String(50), comment="新股分类")
|
||||
authorID: Mapped[Optional[str]] = mapped_column(String(255), comment="作者ID(逗号分隔)")
|
||||
count_all: Mapped[Optional[int]] = mapped_column(Integer, comment="计数")
|
||||
orgType: Mapped[Optional[str]] = mapped_column(String(50), comment="机构类型")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), comment="创建时间")
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
|
||||
class ReportsStrategy(Base):
|
||||
__tablename__ = "reports_strategy"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="自增主键")
|
||||
infoCode: Mapped[str] = mapped_column(String(255), unique=True, comment="报告唯一标识")
|
||||
title: Mapped[Optional[str]] = mapped_column(String(512), comment="报告标题")
|
||||
author: Mapped[Optional[str]] = mapped_column(String(255), comment="作者(逗号分隔)")
|
||||
orgName: Mapped[Optional[str]] = mapped_column(String(255), comment="机构全称")
|
||||
orgCode: Mapped[Optional[str]] = mapped_column(String(50), comment="机构代码")
|
||||
orgSName: Mapped[Optional[str]] = mapped_column(String(100), comment="机构简称")
|
||||
publishDate: Mapped[Optional[str]] = mapped_column(String(50), comment="发布日期")
|
||||
encodeUrl: Mapped[Optional[str]] = mapped_column(String(512), comment="加密URL")
|
||||
researcher: Mapped[Optional[str]] = mapped_column(String(255), comment="研究员")
|
||||
market: Mapped[Optional[str]] = mapped_column(String(50), comment="市场")
|
||||
industryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="行业代码")
|
||||
industryName: Mapped[Optional[str]] = mapped_column(String(100), comment="行业名称")
|
||||
authorID: Mapped[Optional[str]] = mapped_column(String(255), comment="作者ID(逗号分隔)")
|
||||
count_all: Mapped[Optional[int]] = mapped_column(Integer, comment="计数")
|
||||
orgType: Mapped[Optional[str]] = mapped_column(String(50), comment="机构类型")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), comment="创建时间")
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
stockName: Mapped[str] = mapped_column(String(100), default="", nullable=False, comment="股票名称(默认空字符串)")
|
||||
stockCode: Mapped[str] = mapped_column(String(50), default="", nullable=False, comment="股票代码(默认空字符串)")
|
||||
attachPages: Mapped[Optional[int]] = mapped_column(Integer, comment="附件页数")
|
||||
|
||||
|
||||
class ReportsMacresearch(Base):
|
||||
__tablename__ = "reports_macresearch"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="自增主键")
|
||||
infoCode: Mapped[str] = mapped_column(String(255), unique=True, comment="报告唯一标识")
|
||||
json_id: Mapped[Optional[str]] = mapped_column(String(50), comment="JSON ID")
|
||||
title: Mapped[Optional[str]] = mapped_column(String(512), comment="报告标题")
|
||||
author: Mapped[Optional[str]] = mapped_column(String(255), comment="作者(逗号分隔)")
|
||||
orgName: Mapped[Optional[str]] = mapped_column(String(255), comment="机构全称")
|
||||
orgCode: Mapped[Optional[str]] = mapped_column(String(50), comment="机构代码")
|
||||
orgSName: Mapped[Optional[str]] = mapped_column(String(100), comment="机构简称")
|
||||
publishDate: Mapped[Optional[str]] = mapped_column(String(50), comment="发布日期")
|
||||
encodeUrl: Mapped[Optional[str]] = mapped_column(String(512), comment="加密URL")
|
||||
researcher: Mapped[Optional[str]] = mapped_column(String(255), comment="研究员")
|
||||
market: Mapped[Optional[str]] = mapped_column(String(50), comment="市场")
|
||||
industryCode: Mapped[Optional[str]] = mapped_column(String(50), comment="行业代码")
|
||||
industryName: Mapped[Optional[str]] = mapped_column(String(100), comment="行业名称")
|
||||
authorID: Mapped[Optional[str]] = mapped_column(String(255), comment="作者ID(逗号分隔)")
|
||||
count_all: Mapped[Optional[int]] = mapped_column(Integer, comment="计数")
|
||||
orgType: Mapped[Optional[str]] = mapped_column(String(50), comment="机构类型")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), comment="创建时间")
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
stockCode: Mapped[str] = mapped_column(String(50), default="", nullable=False, comment="股票代码(默认空字符串)")
|
||||
stockName: Mapped[str] = mapped_column(String(100), default="", nullable=False, comment="股票名称(默认空字符串)")
|
||||
attachPages: Mapped[Optional[int]] = mapped_column(Integer, comment="附件页数")
|
||||
|
||||
Reference in New Issue
Block a user