update
This commit is contained in:
@@ -8,6 +8,27 @@
|
|||||||
## 投资认知提升合集:https://www.bilibili.com/video/BV1ugBMBAEbW
|
## 投资认知提升合集:https://www.bilibili.com/video/BV1ugBMBAEbW
|
||||||
|
|
||||||
如果你希望能在股市中长久生存下去,建议你能把上面的合集看完,会对你有很大帮助的!
|
如果你希望能在股市中长久生存下去,建议你能把上面的合集看完,会对你有很大帮助的!
|
||||||
|
|
||||||
|
## ⭐ 2026.2.27更新 - 宏观周期分析 🧭
|
||||||
|
|
||||||
|
**全新板块:康波周期 × 美林投资时钟 × 中国政策分析**
|
||||||
|
|
||||||
|
基于视频[康波周期理论](https://www.bilibili.com/video/BV1QNcEzREzY)和视频[美林投资时钟](https://www.bilibili.com/video/BV1Zuf5BUEhH),由4位AI分析师协同研判当前宏观经济所处的周期位置!
|
||||||
|
|
||||||
|
**核心功能:**
|
||||||
|
- 🌊 **康波周期分析** — 判断当前处于50-60年长周期的哪个阶段(回升/繁荣/衰退/萧条)
|
||||||
|
- ⏰ **美林投资时钟** — 判断当前处于3-5年中短周期的哪个象限(复苏/过热/滞胀/衰退)
|
||||||
|
- 🏛️ **中国政策分析** — 货币/财政/产业/房地产政策全面解读(中国化第三维度)
|
||||||
|
- 👔 **首席宏观策略师** — 三维综合研判,"周期仪表盘"资产配置建议
|
||||||
|
- 📊 **自动采集宏观数据** — GDP、CPI/PPI、PMI、M2、LPR利率、大宗商品等
|
||||||
|
|
||||||
|
**适用场景:**
|
||||||
|
- 战略性资产配置决策(买房/创业/大额投资)
|
||||||
|
- 中短期投资组合调整
|
||||||
|
- 理解当前经济环境,避免"在高点接盘、在低点割肉"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## ⭐ 2026.2.27更新 - AI模型自由切换 🤖
|
## ⭐ 2026.2.27更新 - AI模型自由切换 🤖
|
||||||
|
|
||||||
**重大改进:AI模型全局可配置化**
|
**重大改进:AI模型全局可配置化**
|
||||||
|
|||||||
@@ -276,6 +276,9 @@ def main():
|
|||||||
</div>
|
</div>
|
||||||
""", unsafe_allow_html=True)
|
""", unsafe_allow_html=True)
|
||||||
|
|
||||||
|
# 学习资源展示
|
||||||
|
st.info("📺 **新手必看干货**:为了在股市长久生存,建议您观看 👉 [股票知识讲解合集](https://www.bilibili.com/video/BV1Y2FGzzEeS/) 和 [投资认知提升合集](https://www.bilibili.com/video/BV1ugBMBAEbW) 👈,相信会对您有很大帮助!")
|
||||||
|
|
||||||
# 侧边栏
|
# 侧边栏
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
# 快捷导航 - 移到顶部
|
# 快捷导航 - 移到顶部
|
||||||
@@ -285,7 +288,7 @@ def main():
|
|||||||
if st.button("🏠 股票分析", width='stretch', key="nav_home", help="返回首页,进行单只股票的深度分析"):
|
if st.button("🏠 股票分析", width='stretch', key="nav_home", help="返回首页,进行单只股票的深度分析"):
|
||||||
# 清除所有功能页面标志
|
# 清除所有功能页面标志
|
||||||
for key in ['show_history', 'show_monitor', 'show_config', 'show_main_force',
|
for key in ['show_history', 'show_monitor', 'show_config', 'show_main_force',
|
||||||
'show_sector_strategy', 'show_longhubang', 'show_portfolio', 'show_low_price_bull', 'show_news_flow']:
|
'show_sector_strategy', 'show_longhubang', 'show_portfolio', 'show_low_price_bull', 'show_news_flow', 'show_macro_cycle']:
|
||||||
if key in st.session_state:
|
if key in st.session_state:
|
||||||
del st.session_state[key]
|
del st.session_state[key]
|
||||||
|
|
||||||
@@ -344,7 +347,14 @@ def main():
|
|||||||
if st.button("📰 新闻流量", width='stretch', key="nav_news_flow", help="新闻流量监测与短线指导"):
|
if st.button("📰 新闻流量", width='stretch', key="nav_news_flow", help="新闻流量监测与短线指导"):
|
||||||
st.session_state.show_news_flow = True
|
st.session_state.show_news_flow = True
|
||||||
for key in ['show_history', 'show_monitor', 'show_config', 'show_main_force',
|
for key in ['show_history', 'show_monitor', 'show_config', 'show_main_force',
|
||||||
'show_sector_strategy', 'show_portfolio', 'show_smart_monitor', 'show_low_price_bull', 'show_longhubang']:
|
'show_sector_strategy', 'show_portfolio', 'show_smart_monitor', 'show_low_price_bull', 'show_longhubang', 'show_macro_cycle']:
|
||||||
|
if key in st.session_state:
|
||||||
|
del st.session_state[key]
|
||||||
|
|
||||||
|
if st.button("🧭 宏观周期", width='stretch', key="nav_macro_cycle", help="康波周期 × 美林投资时钟 × 政策分析"):
|
||||||
|
st.session_state.show_macro_cycle = True
|
||||||
|
for key in ['show_history', 'show_monitor', 'show_config', 'show_main_force',
|
||||||
|
'show_sector_strategy', 'show_portfolio', 'show_smart_monitor', 'show_low_price_bull', 'show_longhubang', 'show_news_flow']:
|
||||||
if key in st.session_state:
|
if key in st.session_state:
|
||||||
del st.session_state[key]
|
del st.session_state[key]
|
||||||
|
|
||||||
@@ -462,7 +472,18 @@ def main():
|
|||||||
1. 数据获取 → 2. 技术分析
|
1. 数据获取 → 2. 技术分析
|
||||||
3. 基本面分析 → 4. 资金分析
|
3. 基本面分析 → 4. 资金分析
|
||||||
5. 情绪数据(ARBR) → 6. 新闻(qstock)
|
5. 情绪数据(ARBR) → 6. 新闻(qstock)
|
||||||
7. AI团队分析 → 8. 团队讨论 → 9. 决策
|
7. AI分析 → 8. 团队讨论 → 9. 决策
|
||||||
|
""")
|
||||||
|
|
||||||
|
# 学习资源
|
||||||
|
with st.expander("📺 学习视频合集"):
|
||||||
|
st.markdown("""
|
||||||
|
**📢 B站干货合集**
|
||||||
|
|
||||||
|
如果你希望能在股市中长久生存下去,建议你能把下面的合集看完,会对你有很大帮助的!
|
||||||
|
|
||||||
|
- 📚 [股票知识讲解合集](https://www.bilibili.com/video/BV1Y2FGzzEeS/)
|
||||||
|
- 🧠 [投资认知提升合集](https://www.bilibili.com/video/BV1ugBMBAEbW)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 检查是否显示历史记录
|
# 检查是否显示历史记录
|
||||||
@@ -524,6 +545,12 @@ def main():
|
|||||||
display_news_flow_monitor()
|
display_news_flow_monitor()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 检查是否显示宏观周期分析
|
||||||
|
if 'show_macro_cycle' in st.session_state and st.session_state.show_macro_cycle:
|
||||||
|
from macro_cycle_ui import display_macro_cycle
|
||||||
|
display_macro_cycle()
|
||||||
|
return
|
||||||
|
|
||||||
# 检查是否显示环境配置
|
# 检查是否显示环境配置
|
||||||
if 'show_config' in st.session_state and st.session_state.show_config:
|
if 'show_config' in st.session_state and st.session_state.show_config:
|
||||||
display_config_manager()
|
display_config_manager()
|
||||||
|
|||||||
@@ -0,0 +1,458 @@
|
|||||||
|
"""
|
||||||
|
宏观周期分析 - AI智能体模块
|
||||||
|
包含四位专业分析师:康波周期分析师、美林时钟分析师、中国政策分析师、首席宏观策略师
|
||||||
|
"""
|
||||||
|
|
||||||
|
from deepseek_client import DeepSeekClient
|
||||||
|
from typing import Dict, Any
|
||||||
|
import time
|
||||||
|
import config
|
||||||
|
|
||||||
|
|
||||||
|
class MacroCycleAgents:
|
||||||
|
"""宏观周期AI智能体集合"""
|
||||||
|
|
||||||
|
def __init__(self, model=None):
|
||||||
|
self.model = model or config.DEFAULT_MODEL_NAME
|
||||||
|
self.deepseek_client = DeepSeekClient(model=self.model)
|
||||||
|
print(f"[宏观周期] AI智能体系统初始化 (模型: {self.model})")
|
||||||
|
|
||||||
|
def kondratieff_wave_agent(self, macro_data_text: str) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
康波周期分析师 - 判断当前处于康德拉季耶夫长波的哪个阶段
|
||||||
|
|
||||||
|
职责:
|
||||||
|
- 分析当前技术革命阶段(第五轮信息技术康波的位置)
|
||||||
|
- 判断回升/繁荣/衰退/萧条四阶段中的位置
|
||||||
|
- 分析大宗商品与康波的关系
|
||||||
|
- 给出战略性资产配置方向
|
||||||
|
"""
|
||||||
|
print("🌊 康波周期分析师正在分析...")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
prompt = f"""
|
||||||
|
你是一位资深的康德拉季耶夫长波周期研究专家,拥有深厚的经济史研究功底,深入研究过周金涛先生的"人生发财靠康波"理论。
|
||||||
|
|
||||||
|
以下是当前中国的宏观经济数据:
|
||||||
|
{macro_data_text}
|
||||||
|
|
||||||
|
请你基于康波周期理论,对当前全球和中国经济进行深度分析:
|
||||||
|
|
||||||
|
## 一、康波周期基础判断
|
||||||
|
|
||||||
|
### 1. 历史康波定位
|
||||||
|
回顾历史五轮康波周期(蒸汽机→铁路钢铁→电力化工→汽车计算机→信息技术),判断:
|
||||||
|
- 当前处于第五轮信息技术康波的哪个具体阶段(回升期/繁荣期/衰退期/萧条期)?
|
||||||
|
- 给出判断依据和关键特征
|
||||||
|
- 该阶段大约始于何年,预计持续到何年?
|
||||||
|
|
||||||
|
### 2. 技术革命驱动分析
|
||||||
|
- 第五轮康波的核心技术(互联网/移动互联网)是否已经进入红利消退期?
|
||||||
|
- AI人工智能、新能源、生物科技等是否有可能成为第六轮康波的驱动力?
|
||||||
|
- 新旧技术转换的当前进展如何?
|
||||||
|
|
||||||
|
### 3. 大宗商品与康波
|
||||||
|
- 当前大宗商品(黄金、原油、铜等)的表现是否符合康波阶段特征?
|
||||||
|
- 结合数据判断是否处于康波衰退期的大宗商品超级牛市阶段?
|
||||||
|
|
||||||
|
## 二、康波阶段特征验证
|
||||||
|
|
||||||
|
对照当前经济数据,验证是否符合你判断的康波阶段特征:
|
||||||
|
- GDP增速趋势是否匹配?
|
||||||
|
- 通胀水平(CPI/PPI)是否匹配?
|
||||||
|
- 资产价格(股市、房地产)走势是否匹配?
|
||||||
|
- 就业与社会情绪是否匹配?
|
||||||
|
- 政策环境是否匹配?
|
||||||
|
|
||||||
|
## 三、康波视角下的战略建议
|
||||||
|
|
||||||
|
### 1. 当前阶段的核心策略
|
||||||
|
- 整体应该进攻还是防守?
|
||||||
|
- 应该积累现金还是配置资产?
|
||||||
|
|
||||||
|
### 2. 战略资产配置方向
|
||||||
|
给出康波视角的大类资产配置建议:
|
||||||
|
- 股票(配置比例建议及方向)
|
||||||
|
- 债券(配置比例建议)
|
||||||
|
- 大宗商品/黄金(配置比例建议)
|
||||||
|
- 现金(配置比例建议)
|
||||||
|
- 房地产(配置建议)
|
||||||
|
|
||||||
|
### 3. 布局下一轮康波
|
||||||
|
- 如果第六轮康波即将到来,应提前布局哪些方向?
|
||||||
|
- 需要回避哪些夕阳产业?
|
||||||
|
|
||||||
|
### 4. 对普通人的人生建议
|
||||||
|
根据周金涛"人生发财靠康波"的理念,当前阶段普通人应该:
|
||||||
|
- 在职业选择上注意什么?
|
||||||
|
- 在投资理财上注意什么?
|
||||||
|
- 在消费与储蓄上如何平衡?
|
||||||
|
|
||||||
|
## 四、康波周期仪表盘
|
||||||
|
|
||||||
|
请给出一个简洁的康波定位总结:
|
||||||
|
- 🌊 当前康波阶段:[回升期/繁荣期/衰退期/萧条期]
|
||||||
|
- 📍 阶段进度:[初期/中期/末期]
|
||||||
|
- ⏱️ 预计本阶段剩余时间:约X年
|
||||||
|
- 🎯 核心策略关键词:[如"防守为主,播种未来"]
|
||||||
|
- ⚠️ 信心度:[1-10分]
|
||||||
|
|
||||||
|
请给出专业、深入、有数据支撑的分析报告。
|
||||||
|
"""
|
||||||
|
messages = [
|
||||||
|
{"role": "system", "content": "你是全球顶尖的康德拉季耶夫长波周期研究专家,深研周金涛的理论体系,擅长将60年长周期框架应用于当前经济形势分析,帮助投资者做出战略性决策。"},
|
||||||
|
{"role": "user", "content": prompt}
|
||||||
|
]
|
||||||
|
|
||||||
|
analysis = self.deepseek_client.call_api(messages, max_tokens=6000)
|
||||||
|
print(" ✓ 康波周期分析师分析完成")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"agent_name": "康波周期分析师",
|
||||||
|
"agent_icon": "🌊",
|
||||||
|
"agent_role": "判断当前处于康德拉季耶夫长波(50-60年大周期)的哪个阶段,给出战略性资产配置方向",
|
||||||
|
"analysis": analysis,
|
||||||
|
"focus_areas": ["康波定位", "技术革命", "大宗商品超级周期", "战略资产配置"],
|
||||||
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
}
|
||||||
|
|
||||||
|
def merrill_lynch_clock_agent(self, macro_data_text: str) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
美林投资时钟分析师 - 判断当前处于美林时钟的哪个象限
|
||||||
|
|
||||||
|
职责:
|
||||||
|
- 根据经济增长和通胀两个维度判断象限
|
||||||
|
- 结合中国特色(政策第三维度)
|
||||||
|
- 给出中短期资产配置建议
|
||||||
|
"""
|
||||||
|
print("⏰ 美林时钟分析师正在分析...")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
prompt = f"""
|
||||||
|
你是一位精通美林投资时钟理论的资深资产配置策略师,同时深入了解中国经济的特殊性,能够将经典美林时钟做"中国化改造"。
|
||||||
|
|
||||||
|
以下是当前中国的宏观经济数据:
|
||||||
|
{macro_data_text}
|
||||||
|
|
||||||
|
请基于美林投资时钟理论,对当前中国的经济周期进行分析:
|
||||||
|
|
||||||
|
## 一、经典美林时钟定位
|
||||||
|
|
||||||
|
### 1. 两大核心指标研判
|
||||||
|
**经济增长维度(↑/→/↓):**
|
||||||
|
- GDP增速趋势判断(同比、环比、PMI佐证)
|
||||||
|
- 工业增加值/制造业景气度
|
||||||
|
- 消费、投资、出口三驾马车的状态
|
||||||
|
- 综合判断:经济增长向上还是向下?
|
||||||
|
|
||||||
|
**通货膨胀维度(↑/→/↓):**
|
||||||
|
- CPI走势分析(核心CPI)
|
||||||
|
- PPI走势分析
|
||||||
|
- M2/社融与信贷扩张情况
|
||||||
|
- 综合判断:通胀向上还是向下?
|
||||||
|
|
||||||
|
### 2. 象限定位
|
||||||
|
根据以上两个维度,判断当前处于美林时钟的哪个象限:
|
||||||
|
- 🟢 复苏期(增长↑ + 通胀↓)→ 配股票
|
||||||
|
- 🔴 过热期(增长↑ + 通胀↑)→ 配商品
|
||||||
|
- 🟡 滞胀期(增长↓ + 通胀↑)→ 持现金
|
||||||
|
- 🔵 衰退期(增长↓ + 通胀↓)→ 配债券
|
||||||
|
|
||||||
|
### 3. 时钟转动方向
|
||||||
|
- 当前正从哪个象限向哪个象限转动?
|
||||||
|
- 预计转动速度如何?(中国时钟转动通常比美国快)
|
||||||
|
- 是否存在"跳跃"或"逆转"的可能?
|
||||||
|
|
||||||
|
## 二、中国化美林时钟(三维分析)
|
||||||
|
|
||||||
|
### 1. 第三维度:政策方向
|
||||||
|
这是中国版美林时钟最重要的增量分析:
|
||||||
|
- 货币政策方向(宽松/中性/收紧?):分析LPR、MLF、准备金率等
|
||||||
|
- 财政政策方向(积极/稳健/收缩?):分析专项债、减税降费等
|
||||||
|
- 产业政策方向:重点扶持哪些领域?
|
||||||
|
- 房地产政策方向:放松还是收紧?
|
||||||
|
- 政策的即时效果和滞后效应
|
||||||
|
|
||||||
|
### 2. 中国特色修正
|
||||||
|
- 中国利率市场化程度对时钟的影响
|
||||||
|
- 政府干预对时钟转动的扭曲效应
|
||||||
|
- A股散户占比高对资产定价的影响
|
||||||
|
- 房地产作为"第五类资产"的配置考量
|
||||||
|
|
||||||
|
## 三、资产配置建议
|
||||||
|
|
||||||
|
### 1. 基于当前象限的配置
|
||||||
|
给出各大类资产的具体配置比例建议:
|
||||||
|
| 资产类别 | 配置比例 | 理由 |
|
||||||
|
|---------|---------|------|
|
||||||
|
| A股股票 | X% | ... |
|
||||||
|
| 债券/固收 | X% | ... |
|
||||||
|
| 大宗商品/黄金 | X% | ... |
|
||||||
|
| 现金/货币基金 | X% | ... |
|
||||||
|
| 房地产 | X% | ... |
|
||||||
|
|
||||||
|
### 2. 板块/行业建议
|
||||||
|
- 当前象限最受益的行业/板块(3-5个)
|
||||||
|
- 应规避的行业/板块(2-3个)
|
||||||
|
- "政策友好型"重点关注方向
|
||||||
|
|
||||||
|
### 3. 时间框架
|
||||||
|
- 当前配置建议的有效期约多久?
|
||||||
|
- 需要密切关注哪些信号来判断时钟转动?
|
||||||
|
|
||||||
|
## 四、美林时钟仪表盘
|
||||||
|
|
||||||
|
请给出一个简洁的定位总结:
|
||||||
|
- ⏰ 当前象限:[复苏期/过热期/滞胀期/衰退期]
|
||||||
|
- 📊 经济增长:[↑上行/→持平/↓下行]
|
||||||
|
- 📈 通胀水平:[↑上行/→持平/↓下行]
|
||||||
|
- 🏛️ 政策方向:[宽松/中性/收紧]
|
||||||
|
- 🎯 最优资产:[股票/商品/现金/债券]
|
||||||
|
- ⚠️ 信心度:[1-10分]
|
||||||
|
|
||||||
|
请给出专业、数据驱动的分析报告。
|
||||||
|
"""
|
||||||
|
messages = [
|
||||||
|
{"role": "system", "content": "你是一位精通美林投资时钟理论的顶级资产配置策略师,擅长将经典框架进行中国化改造,加入政策分析作为第三维度,帮助中国投资者做出精准的中短期资产配置决策。"},
|
||||||
|
{"role": "user", "content": prompt}
|
||||||
|
]
|
||||||
|
|
||||||
|
analysis = self.deepseek_client.call_api(messages, max_tokens=6000)
|
||||||
|
print(" ✓ 美林时钟分析师分析完成")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"agent_name": "美林时钟分析师",
|
||||||
|
"agent_icon": "⏰",
|
||||||
|
"agent_role": "判断当前处于美林投资时钟的哪个象限(3-5年中短周期),给出资产配置建议",
|
||||||
|
"analysis": analysis,
|
||||||
|
"focus_areas": ["经济增长", "通胀水平", "政策方向", "资产配置"],
|
||||||
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
}
|
||||||
|
|
||||||
|
def china_policy_agent(self, macro_data_text: str) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
中国政策分析师 - 分析中国特色政策环境
|
||||||
|
|
||||||
|
职责:
|
||||||
|
- 分析当前政策环境
|
||||||
|
- 评估政策对周期的影响
|
||||||
|
- 识别政策驱动的投资机会
|
||||||
|
"""
|
||||||
|
print("🏛️ 中国政策分析师正在分析...")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
prompt = f"""
|
||||||
|
你是一位资深的中国宏观政策研究专家,深谙中国经济的"有形之手"运作方式,擅长从政策信号中挖掘投资机会。
|
||||||
|
|
||||||
|
以下是当前中国的宏观经济数据和新闻:
|
||||||
|
{macro_data_text}
|
||||||
|
|
||||||
|
请从政策角度进行深度分析:
|
||||||
|
|
||||||
|
## 一、当前政策全景
|
||||||
|
|
||||||
|
### 1. 货币政策分析
|
||||||
|
- 央行近期操作解读(降准/降息/MLF/逆回购等)
|
||||||
|
- LPR利率走势及未来方向
|
||||||
|
- M2增速与社融规模分析
|
||||||
|
- 流动性环境评估:宽松/适度/偏紧?
|
||||||
|
- 对标历史政策宽松周期,当前处于什么阶段?
|
||||||
|
|
||||||
|
### 2. 财政政策分析
|
||||||
|
- 专项债发行规模和进度
|
||||||
|
- 减税降费政策力度
|
||||||
|
- 基建投资方向和力度
|
||||||
|
- 财政赤字率水平
|
||||||
|
- 是否有大规模刺激计划的信号?
|
||||||
|
|
||||||
|
### 3. 产业政策分析
|
||||||
|
- 当前国家战略重点方向(如AI、新能源、半导体、生物医药等)
|
||||||
|
- "专精特新"等政策支持力度
|
||||||
|
- 国产替代进展
|
||||||
|
- 数字经济/新质生产力政策
|
||||||
|
|
||||||
|
### 4. 房地产政策分析
|
||||||
|
- 限购限贷政策变化
|
||||||
|
- 房贷利率走势
|
||||||
|
- 保交楼/房企纾困进展
|
||||||
|
- 房地产政策的底线和目标
|
||||||
|
|
||||||
|
## 二、政策对周期的影响
|
||||||
|
|
||||||
|
### 1. 政策是"顺周期"还是"逆周期"?
|
||||||
|
- 当前的政策是在托底经济还是防止过热?
|
||||||
|
- 政策的主要目标是什么(稳增长/防风险/调结构)?
|
||||||
|
|
||||||
|
### 2. 政策对美林时钟的扭曲效应
|
||||||
|
- 政策宽松是否可能让时钟"跳跃"?
|
||||||
|
- 政策刺激是否可能造成"短暂过热"的假象?
|
||||||
|
- 历史上类似政策环境下市场的表现
|
||||||
|
|
||||||
|
### 3. 政策拐点信号
|
||||||
|
- 需要关注哪些政策信号来判断下一步方向?
|
||||||
|
- 最可能的政策转向时间节点
|
||||||
|
|
||||||
|
## 三、政策驱动的投资机会
|
||||||
|
|
||||||
|
### 1. "政策友好型"资产
|
||||||
|
列出当前最受政策青睐的领域和方向
|
||||||
|
|
||||||
|
### 2. 政策支持的具体行业/板块
|
||||||
|
给出3-5个受益于当前政策环境的行业
|
||||||
|
|
||||||
|
### 3. 政策风险警示
|
||||||
|
哪些领域面临政策收紧或监管风险?
|
||||||
|
|
||||||
|
## 四、政策环境仪表盘
|
||||||
|
|
||||||
|
请给出简洁总结:
|
||||||
|
- 🏛️ 货币政策:[极宽松/宽松/中性/偏紧/收紧]
|
||||||
|
- 💰 财政政策:[大力刺激/积极/稳健/收缩]
|
||||||
|
- 🏭 产业政策重点:[3-5个关键词]
|
||||||
|
- 🏠 房地产政策:[大力托底/政策松绑/中性/调控]
|
||||||
|
- 🎯 政策核心目标:[一句话概括]
|
||||||
|
- ⚠️ 政策转向风险:[高/中/低]
|
||||||
|
|
||||||
|
请给出专业、深入的政策分析报告。
|
||||||
|
"""
|
||||||
|
messages = [
|
||||||
|
{"role": "system", "content": "你是一位资深的中国宏观经济政策研究专家,深入了解中国政府的经济调控方式和政策意图,擅长从政策中发现投资机会和风险。"},
|
||||||
|
{"role": "user", "content": prompt}
|
||||||
|
]
|
||||||
|
|
||||||
|
analysis = self.deepseek_client.call_api(messages, max_tokens=5000)
|
||||||
|
print(" ✓ 中国政策分析师分析完成")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"agent_name": "中国政策分析师",
|
||||||
|
"agent_icon": "🏛️",
|
||||||
|
"agent_role": "分析中国特色政策环境,评估政策对周期的影响,识别政策驱动的投资机会",
|
||||||
|
"analysis": analysis,
|
||||||
|
"focus_areas": ["货币政策", "财政政策", "产业政策", "房地产政策", "政策拐点"],
|
||||||
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
}
|
||||||
|
|
||||||
|
def chief_macro_strategist_agent(self, kondratieff_report: str, merrill_report: str, policy_report: str, macro_data_text: str) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
首席宏观策略师 - 综合三位分析师的观点,形成最终策略
|
||||||
|
|
||||||
|
职责:
|
||||||
|
- 整合康波、美林时钟、政策三个维度
|
||||||
|
- 构建"周期仪表盘"
|
||||||
|
- 给出最终的综合建议
|
||||||
|
"""
|
||||||
|
print("👔 首席宏观策略师正在综合研判...")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
prompt = f"""
|
||||||
|
你是一位顶级的首席宏观策略师,你需要整合三位分析师的报告,形成最终的综合判断和投资策略。
|
||||||
|
|
||||||
|
【康波周期分析师报告】
|
||||||
|
{kondratieff_report}
|
||||||
|
|
||||||
|
【美林时钟分析师报告】
|
||||||
|
{merrill_report}
|
||||||
|
|
||||||
|
【中国政策分析师报告】
|
||||||
|
{policy_report}
|
||||||
|
|
||||||
|
请你综合以上三份报告,进行最终的综合研判:
|
||||||
|
|
||||||
|
## 一、周期仪表盘(双指针+政策风向标)
|
||||||
|
|
||||||
|
构建一个完整的"周期仪表盘":
|
||||||
|
|
||||||
|
### 康波指针(战略方向)
|
||||||
|
- 当前阶段:[回升期/繁荣期/衰退期/萧条期]
|
||||||
|
- 阶段进度:[初期/中期/末期]
|
||||||
|
- 战略方向:[进攻/稳健/防守/极度防守]
|
||||||
|
|
||||||
|
### 美林指针(战术节奏)
|
||||||
|
- 当前象限:[复苏/过热/滞胀/衰退]
|
||||||
|
- 转动方向:向[下一个象限]转动
|
||||||
|
- 战术方向:[积极做多/获利了结/持币观望/配置债券]
|
||||||
|
|
||||||
|
### 政策风向标(中国特色)
|
||||||
|
- 政策方向:[强力宽松/宽松/中性/收紧]
|
||||||
|
- 对周期的影响:[加速/减缓/扭曲/逆转]
|
||||||
|
|
||||||
|
### 双指针共振分析
|
||||||
|
- 两个指针方向是否一致?
|
||||||
|
- 共振或矛盾意味着什么?
|
||||||
|
- 综合信号:[强烈看多/偏多/中性/偏空/强烈看空]
|
||||||
|
|
||||||
|
## 二、综合资产配置建议
|
||||||
|
|
||||||
|
### 1. 最终配置方案
|
||||||
|
结合康波(战略)+ 美林(战术)+ 政策(催化),给出最终的资产配置建议:
|
||||||
|
|
||||||
|
| 资产类别 | 推荐配置 | 康波逻辑 | 美林逻辑 | 政策逻辑 |
|
||||||
|
|---------|---------|---------|---------|---------|
|
||||||
|
| A股/港股 | X% | ... | ... | ... |
|
||||||
|
| 债券/固收 | X% | ... | ... | ... |
|
||||||
|
| 黄金 | X% | ... | ... | ... |
|
||||||
|
| 大宗商品 | X% | ... | ... | ... |
|
||||||
|
| 现金 | X% | ... | ... | ... |
|
||||||
|
| 房地产 | X% | ... | ... | ... |
|
||||||
|
|
||||||
|
### 2. 重点板块/方向(3-5个)
|
||||||
|
结合三个维度共振的最优方向
|
||||||
|
|
||||||
|
### 3. 风险警示
|
||||||
|
需要高度警惕的风险因素
|
||||||
|
|
||||||
|
## 三、不同人群的具体建议
|
||||||
|
|
||||||
|
### 1. 保守型投资者(风险厌恶)
|
||||||
|
- 资产配置建议
|
||||||
|
- 核心策略
|
||||||
|
|
||||||
|
### 2. 稳健型投资者(平衡风险收益)
|
||||||
|
- 资产配置建议
|
||||||
|
- 核心策略
|
||||||
|
|
||||||
|
### 3. 进取型投资者(愿承受风险)
|
||||||
|
- 资产配置建议
|
||||||
|
- 核心策略
|
||||||
|
|
||||||
|
## 四、核心观点总结
|
||||||
|
|
||||||
|
请用简洁有力的语言总结:
|
||||||
|
1. **一句话定位**:当前经济周期的核心判断
|
||||||
|
2. **核心策略**:用一句话概括应对策略
|
||||||
|
3. **最大机会**:当前最值得把握的方向
|
||||||
|
4. **最大风险**:最需要警惕的风险
|
||||||
|
5. **时间节点**:下一个重要的周期转折点大约在何时
|
||||||
|
|
||||||
|
## 五、周金涛名言对照
|
||||||
|
|
||||||
|
选择一句最契合当前阶段的周金涛名言,并解释为什么这句话适用于当下。
|
||||||
|
|
||||||
|
请给出权威、全面、可操作的综合策略报告。
|
||||||
|
"""
|
||||||
|
messages = [
|
||||||
|
{"role": "system", "content": "你是一位世界级的首席宏观策略师,擅长将康波长周期、美林投资时钟和中国政策环境三个维度有机结合,为投资者提供既有战略高度又有战术灵活性的综合投资策略。你的判断沉稳、客观、有数据支撑。"},
|
||||||
|
{"role": "user", "content": prompt}
|
||||||
|
]
|
||||||
|
|
||||||
|
analysis = self.deepseek_client.call_api(messages, max_tokens=6000)
|
||||||
|
print(" ✓ 首席宏观策略师综合研判完成")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"agent_name": "首席宏观策略师",
|
||||||
|
"agent_icon": "👔",
|
||||||
|
"agent_role": "整合康波周期、美林时钟、中国政策三维分析,构建周期仪表盘,给出最终综合策略",
|
||||||
|
"analysis": analysis,
|
||||||
|
"focus_areas": ["周期仪表盘", "综合资产配置", "双指针共振", "分人群建议"],
|
||||||
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 测试
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("测试宏观周期AI智能体系统")
|
||||||
|
print("=" * 60)
|
||||||
|
agents = MacroCycleAgents()
|
||||||
|
print(f"模型: {agents.model}")
|
||||||
|
print("初始化完成")
|
||||||
@@ -0,0 +1,559 @@
|
|||||||
|
"""
|
||||||
|
宏观周期分析 - 数据采集模块
|
||||||
|
采集宏观经济数据(GDP、CPI/PPI、PMI、利率、M2、大宗商品等)
|
||||||
|
用于康波周期和美林投资时钟分析
|
||||||
|
"""
|
||||||
|
|
||||||
|
import akshare as ak
|
||||||
|
import pandas as pd
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import warnings
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class MacroCycleDataFetcher:
|
||||||
|
"""宏观经济数据采集器"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
print("[宏观周期] 数据采集器初始化...")
|
||||||
|
self.max_retries = 3
|
||||||
|
|
||||||
|
def _safe_request(self, func, *args, **kwargs):
|
||||||
|
"""安全请求,带重试"""
|
||||||
|
for i in range(self.max_retries):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
if i < self.max_retries - 1:
|
||||||
|
time.sleep(2)
|
||||||
|
else:
|
||||||
|
logger.warning(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_all_macro_data(self) -> dict:
|
||||||
|
"""
|
||||||
|
获取所有宏观经济数据
|
||||||
|
Returns:
|
||||||
|
dict: 包含多维度宏观数据的字典
|
||||||
|
"""
|
||||||
|
print("\n[宏观周期] 开始采集宏观经济数据...")
|
||||||
|
data = {
|
||||||
|
"success": False,
|
||||||
|
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
"gdp": {},
|
||||||
|
"cpi_ppi": {},
|
||||||
|
"pmi": {},
|
||||||
|
"money_supply": {},
|
||||||
|
"interest_rate": {},
|
||||||
|
"market_indices": {},
|
||||||
|
"commodities": {},
|
||||||
|
"real_estate": {},
|
||||||
|
"employment": {},
|
||||||
|
"news": [],
|
||||||
|
"errors": []
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. GDP
|
||||||
|
print(" 1/9 获取GDP数据...")
|
||||||
|
try:
|
||||||
|
gdp_data = self._get_gdp_data()
|
||||||
|
if gdp_data:
|
||||||
|
data["gdp"] = gdp_data
|
||||||
|
print(" ✓ GDP数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"GDP: {e}")
|
||||||
|
print(f" ✗ GDP数据获取失败: {e}")
|
||||||
|
|
||||||
|
# 2. CPI/PPI
|
||||||
|
print(" 2/9 获取CPI/PPI数据...")
|
||||||
|
try:
|
||||||
|
cpi_ppi = self._get_cpi_ppi_data()
|
||||||
|
if cpi_ppi:
|
||||||
|
data["cpi_ppi"] = cpi_ppi
|
||||||
|
print(" ✓ CPI/PPI数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"CPI/PPI: {e}")
|
||||||
|
print(f" ✗ CPI/PPI获取失败: {e}")
|
||||||
|
|
||||||
|
# 3. PMI
|
||||||
|
print(" 3/9 获取PMI数据...")
|
||||||
|
try:
|
||||||
|
pmi = self._get_pmi_data()
|
||||||
|
if pmi:
|
||||||
|
data["pmi"] = pmi
|
||||||
|
print(" ✓ PMI数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"PMI: {e}")
|
||||||
|
print(f" ✗ PMI获取失败: {e}")
|
||||||
|
|
||||||
|
# 4. 货币供应量 M2
|
||||||
|
print(" 4/9 获取货币供应数据...")
|
||||||
|
try:
|
||||||
|
money = self._get_money_supply()
|
||||||
|
if money:
|
||||||
|
data["money_supply"] = money
|
||||||
|
print(" ✓ 货币供应数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"货币供应: {e}")
|
||||||
|
print(f" ✗ 货币供应获取失败: {e}")
|
||||||
|
|
||||||
|
# 5. 利率
|
||||||
|
print(" 5/9 获取利率数据...")
|
||||||
|
try:
|
||||||
|
rate = self._get_interest_rate()
|
||||||
|
if rate:
|
||||||
|
data["interest_rate"] = rate
|
||||||
|
print(" ✓ 利率数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"利率: {e}")
|
||||||
|
print(f" ✗ 利率获取失败: {e}")
|
||||||
|
|
||||||
|
# 6. 市场指数
|
||||||
|
print(" 6/9 获取市场指数...")
|
||||||
|
try:
|
||||||
|
indices = self._get_market_indices()
|
||||||
|
if indices:
|
||||||
|
data["market_indices"] = indices
|
||||||
|
print(" ✓ 市场指数获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"市场指数: {e}")
|
||||||
|
print(f" ✗ 市场指数获取失败: {e}")
|
||||||
|
|
||||||
|
# 7. 大宗商品
|
||||||
|
print(" 7/9 获取大宗商品数据...")
|
||||||
|
try:
|
||||||
|
commodities = self._get_commodities_data()
|
||||||
|
if commodities:
|
||||||
|
data["commodities"] = commodities
|
||||||
|
print(" ✓ 大宗商品数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"大宗商品: {e}")
|
||||||
|
print(f" ✗ 大宗商品获取失败: {e}")
|
||||||
|
|
||||||
|
# 8. 房地产
|
||||||
|
print(" 8/9 获取房地产数据...")
|
||||||
|
try:
|
||||||
|
real_estate = self._get_real_estate_data()
|
||||||
|
if real_estate:
|
||||||
|
data["real_estate"] = real_estate
|
||||||
|
print(" ✓ 房地产数据获取成功")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"房地产: {e}")
|
||||||
|
print(f" ✗ 房地产获取失败: {e}")
|
||||||
|
|
||||||
|
# 9. 财经新闻
|
||||||
|
print(" 9/9 获取财经新闻...")
|
||||||
|
try:
|
||||||
|
news = self._get_macro_news()
|
||||||
|
if news:
|
||||||
|
data["news"] = news
|
||||||
|
print(f" ✓ 获取{len(news)}条新闻")
|
||||||
|
except Exception as e:
|
||||||
|
data["errors"].append(f"新闻: {e}")
|
||||||
|
print(f" ✗ 新闻获取失败: {e}")
|
||||||
|
|
||||||
|
# 判断是否有足够数据
|
||||||
|
valid_count = sum(1 for k in ["gdp", "cpi_ppi", "pmi", "money_supply",
|
||||||
|
"interest_rate", "market_indices", "commodities"]
|
||||||
|
if data.get(k))
|
||||||
|
if valid_count >= 3:
|
||||||
|
data["success"] = True
|
||||||
|
print(f"\n[宏观周期] 数据采集完成,成功获取 {valid_count}/7 项核心数据")
|
||||||
|
else:
|
||||||
|
print(f"\n[宏观周期] 数据不足(仅 {valid_count}/7 项),分析可能不够准确")
|
||||||
|
data["success"] = True # 仍允许分析
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _get_gdp_data(self) -> dict:
|
||||||
|
"""获取GDP数据"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
# 中国GDP年度
|
||||||
|
df = self._safe_request(ak.macro_china_gdp)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(8)
|
||||||
|
result["yearly"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["yearly"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"GDP年度数据获取失败: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 季度GDP增速
|
||||||
|
df = self._safe_request(ak.macro_china_gdp_yearly)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["quarterly_growth"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["quarterly_growth"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"GDP季度数据获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_cpi_ppi_data(self) -> dict:
|
||||||
|
"""获取CPI和PPI数据"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
# CPI月度
|
||||||
|
df = self._safe_request(ak.macro_china_cpi_monthly)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["cpi_monthly"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["cpi_monthly"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"CPI数据获取失败: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# PPI月度
|
||||||
|
df = self._safe_request(ak.macro_china_ppi_yearly)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["ppi_monthly"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["ppi_monthly"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"PPI数据获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_pmi_data(self) -> dict:
|
||||||
|
"""获取PMI数据"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
# 制造业PMI
|
||||||
|
df = self._safe_request(ak.macro_china_pmi_yearly)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["manufacturing_pmi"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["manufacturing_pmi"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"制造业PMI获取失败: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 非制造业PMI(财新)
|
||||||
|
df = self._safe_request(ak.macro_china_cx_pmi_yearly)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["caixin_pmi"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["caixin_pmi"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"财新PMI获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_money_supply(self) -> dict:
|
||||||
|
"""获取货币供应量"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
df = self._safe_request(ak.macro_china_money_supply)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["m2_data"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["m2_data"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"货币供应数据获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_interest_rate(self) -> dict:
|
||||||
|
"""获取利率数据"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
# LPR利率
|
||||||
|
df = self._safe_request(ak.macro_china_lpr)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["lpr"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["lpr"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"LPR利率获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_market_indices(self) -> dict:
|
||||||
|
"""获取主要市场指数"""
|
||||||
|
result = {}
|
||||||
|
indices = {
|
||||||
|
"sh_index": "sh000001", # 上证指数
|
||||||
|
"sz_index": "sz399001", # 深证成指
|
||||||
|
"cyb_index": "sz399006", # 创业板指
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, code in indices.items():
|
||||||
|
try:
|
||||||
|
df = self._safe_request(
|
||||||
|
ak.stock_zh_index_daily,
|
||||||
|
symbol=code
|
||||||
|
)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
latest = df.tail(1).iloc[0]
|
||||||
|
prev = df.tail(2).iloc[0] if len(df) >= 2 else latest
|
||||||
|
|
||||||
|
change_pct = 0
|
||||||
|
if prev["close"] > 0:
|
||||||
|
change_pct = (latest["close"] - prev["close"]) / prev["close"] * 100
|
||||||
|
|
||||||
|
# 计算近期涨跌
|
||||||
|
recent_60 = df.tail(60)
|
||||||
|
pct_60d = 0
|
||||||
|
if len(recent_60) >= 60:
|
||||||
|
pct_60d = (latest["close"] - recent_60.iloc[0]["close"]) / recent_60.iloc[0]["close"] * 100
|
||||||
|
|
||||||
|
result[name] = {
|
||||||
|
"close": round(float(latest["close"]), 2),
|
||||||
|
"change_pct": round(change_pct, 2),
|
||||||
|
"pct_60d": round(pct_60d, 2),
|
||||||
|
"high_52w": round(float(df.tail(250)["high"].max()), 2) if len(df) >= 250 else None,
|
||||||
|
"low_52w": round(float(df.tail(250)["low"].min()), 2) if len(df) >= 250 else None,
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"指数{name}获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_commodities_data(self) -> dict:
|
||||||
|
"""获取大宗商品数据"""
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
# 黄金
|
||||||
|
try:
|
||||||
|
df = self._safe_request(ak.futures_main_sina, symbol="AU0", start_date=(datetime.now() - timedelta(days=365)).strftime("%Y%m%d"), end_date=datetime.now().strftime("%Y%m%d"))
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
latest = df.tail(1).iloc[0]
|
||||||
|
first = df.head(1).iloc[0]
|
||||||
|
ytd_pct = (float(latest["收盘价"]) - float(first["收盘价"])) / float(first["收盘价"]) * 100 if float(first["收盘价"]) > 0 else 0
|
||||||
|
result["gold"] = {
|
||||||
|
"price": round(float(latest["收盘价"]), 2),
|
||||||
|
"ytd_change_pct": round(ytd_pct, 2),
|
||||||
|
"name": "沪金主力"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"黄金数据获取失败: {e}")
|
||||||
|
|
||||||
|
# 原油
|
||||||
|
try:
|
||||||
|
df = self._safe_request(ak.futures_main_sina, symbol="SC0", start_date=(datetime.now() - timedelta(days=365)).strftime("%Y%m%d"), end_date=datetime.now().strftime("%Y%m%d"))
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
latest = df.tail(1).iloc[0]
|
||||||
|
first = df.head(1).iloc[0]
|
||||||
|
ytd_pct = (float(latest["收盘价"]) - float(first["收盘价"])) / float(first["收盘价"]) * 100 if float(first["收盘价"]) > 0 else 0
|
||||||
|
result["crude_oil"] = {
|
||||||
|
"price": round(float(latest["收盘价"]), 2),
|
||||||
|
"ytd_change_pct": round(ytd_pct, 2),
|
||||||
|
"name": "原油主力"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"原油数据获取失败: {e}")
|
||||||
|
|
||||||
|
# 铜
|
||||||
|
try:
|
||||||
|
df = self._safe_request(ak.futures_main_sina, symbol="CU0", start_date=(datetime.now() - timedelta(days=365)).strftime("%Y%m%d"), end_date=datetime.now().strftime("%Y%m%d"))
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
latest = df.tail(1).iloc[0]
|
||||||
|
first = df.head(1).iloc[0]
|
||||||
|
ytd_pct = (float(latest["收盘价"]) - float(first["收盘价"])) / float(first["收盘价"]) * 100 if float(first["收盘价"]) > 0 else 0
|
||||||
|
result["copper"] = {
|
||||||
|
"price": round(float(latest["收盘价"]), 2),
|
||||||
|
"ytd_change_pct": round(ytd_pct, 2),
|
||||||
|
"name": "沪铜主力"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"铜数据获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_real_estate_data(self) -> dict:
|
||||||
|
"""获取房地产相关数据"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
df = self._safe_request(ak.macro_china_real_estate)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
recent = df.tail(12)
|
||||||
|
result["data"] = []
|
||||||
|
for _, row in recent.iterrows():
|
||||||
|
item = {}
|
||||||
|
for col in df.columns:
|
||||||
|
item[col] = str(row[col])
|
||||||
|
result["data"].append(item)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"房地产数据获取失败: {e}")
|
||||||
|
|
||||||
|
return result if result else None
|
||||||
|
|
||||||
|
def _get_macro_news(self) -> list:
|
||||||
|
"""获取宏观经济相关新闻"""
|
||||||
|
news_list = []
|
||||||
|
try:
|
||||||
|
df = self._safe_request(ak.stock_info_global_em)
|
||||||
|
if df is not None and not df.empty:
|
||||||
|
for _, row in df.head(50).iterrows():
|
||||||
|
news_list.append({
|
||||||
|
"title": str(row.get("标题", "")),
|
||||||
|
"publish_time": str(row.get("发布时间", "")),
|
||||||
|
"content": str(row.get("概要", ""))[:300]
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"新闻获取失败: {e}")
|
||||||
|
|
||||||
|
return news_list
|
||||||
|
|
||||||
|
def format_data_for_ai(self, data: dict) -> str:
|
||||||
|
"""将数据格式化为AI分析所需的文本"""
|
||||||
|
parts = []
|
||||||
|
parts.append(f"===== 宏观经济数据报告 =====")
|
||||||
|
parts.append(f"数据采集时间: {data.get('timestamp', '未知')}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# GDP
|
||||||
|
if data.get("gdp"):
|
||||||
|
parts.append("【一、GDP数据】")
|
||||||
|
gdp = data["gdp"]
|
||||||
|
if gdp.get("yearly"):
|
||||||
|
parts.append("近年GDP:")
|
||||||
|
for item in gdp["yearly"][-4:]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
if gdp.get("quarterly_growth"):
|
||||||
|
parts.append("季度GDP增速:")
|
||||||
|
for item in gdp["quarterly_growth"][-8:]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# CPI/PPI
|
||||||
|
if data.get("cpi_ppi"):
|
||||||
|
parts.append("【二、CPI/PPI通胀数据】")
|
||||||
|
cp = data["cpi_ppi"]
|
||||||
|
if cp.get("cpi_monthly"):
|
||||||
|
parts.append("近12个月CPI:")
|
||||||
|
for item in cp["cpi_monthly"]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
if cp.get("ppi_monthly"):
|
||||||
|
parts.append("近12个月PPI:")
|
||||||
|
for item in cp["ppi_monthly"]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# PMI
|
||||||
|
if data.get("pmi"):
|
||||||
|
parts.append("【三、PMI景气指数】")
|
||||||
|
pmi = data["pmi"]
|
||||||
|
if pmi.get("manufacturing_pmi"):
|
||||||
|
parts.append("制造业PMI(50为荣枯线):")
|
||||||
|
for item in pmi["manufacturing_pmi"]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
if pmi.get("caixin_pmi"):
|
||||||
|
parts.append("财新PMI:")
|
||||||
|
for item in pmi["caixin_pmi"]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# 货币供应
|
||||||
|
if data.get("money_supply"):
|
||||||
|
parts.append("【四、货币供应量】")
|
||||||
|
ms = data["money_supply"]
|
||||||
|
if ms.get("m2_data"):
|
||||||
|
parts.append("M0/M1/M2数据:")
|
||||||
|
for item in ms["m2_data"]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# 利率
|
||||||
|
if data.get("interest_rate"):
|
||||||
|
parts.append("【五、利率数据】")
|
||||||
|
ir = data["interest_rate"]
|
||||||
|
if ir.get("lpr"):
|
||||||
|
parts.append("LPR利率:")
|
||||||
|
for item in ir["lpr"]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# 市场指数
|
||||||
|
if data.get("market_indices"):
|
||||||
|
parts.append("【六、市场指数】")
|
||||||
|
mi = data["market_indices"]
|
||||||
|
for name, info in mi.items():
|
||||||
|
label = {"sh_index": "上证指数", "sz_index": "深证成指", "cyb_index": "创业板指"}.get(name, name)
|
||||||
|
parts.append(f" {label}: {info['close']} (日涨跌: {info['change_pct']:+.2f}%, 60日涨跌: {info.get('pct_60d', 0):+.2f}%)")
|
||||||
|
if info.get("high_52w"):
|
||||||
|
parts.append(f" 52周最高: {info['high_52w']} 52周最低: {info['low_52w']}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# 大宗商品
|
||||||
|
if data.get("commodities"):
|
||||||
|
parts.append("【七、大宗商品】")
|
||||||
|
for name, info in data["commodities"].items():
|
||||||
|
parts.append(f" {info['name']}: {info['price']} (年涨跌: {info['ytd_change_pct']:+.2f}%)")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# 房地产
|
||||||
|
if data.get("real_estate"):
|
||||||
|
parts.append("【八、房地产数据】")
|
||||||
|
re_data = data["real_estate"]
|
||||||
|
if re_data.get("data"):
|
||||||
|
for item in re_data["data"][-4:]:
|
||||||
|
parts.append(f" {item}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
# 新闻
|
||||||
|
if data.get("news"):
|
||||||
|
parts.append("【九、近期宏观经济新闻】")
|
||||||
|
for idx, news in enumerate(data["news"][:20], 1):
|
||||||
|
parts.append(f" {idx}. [{news.get('publish_time', '')}] {news.get('title', '')}")
|
||||||
|
if news.get('content'):
|
||||||
|
parts.append(f" {news['content'][:150]}")
|
||||||
|
parts.append("")
|
||||||
|
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
# 测试
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("测试宏观周期数据采集")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
fetcher = MacroCycleDataFetcher()
|
||||||
|
data = fetcher.get_all_macro_data()
|
||||||
|
|
||||||
|
if data.get("success"):
|
||||||
|
formatted = fetcher.format_data_for_ai(data)
|
||||||
|
print(formatted[:5000])
|
||||||
|
print(f"\n... (总长度: {len(formatted)} 字符)")
|
||||||
|
else:
|
||||||
|
print(f"数据采集失败: {data.get('errors')}")
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
"""
|
||||||
|
宏观周期分析 - 综合研判引擎
|
||||||
|
协调数据采集与AI分析,生成完整的宏观周期分析报告
|
||||||
|
"""
|
||||||
|
|
||||||
|
from macro_cycle_agents import MacroCycleAgents
|
||||||
|
from macro_cycle_data import MacroCycleDataFetcher
|
||||||
|
from typing import Dict, Any
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import config
|
||||||
|
|
||||||
|
|
||||||
|
class MacroCycleEngine:
|
||||||
|
"""宏观周期综合研判引擎"""
|
||||||
|
|
||||||
|
def __init__(self, model=None):
|
||||||
|
self.model = model or config.DEFAULT_MODEL_NAME
|
||||||
|
self.agents = MacroCycleAgents(model=self.model)
|
||||||
|
self.data_fetcher = MacroCycleDataFetcher()
|
||||||
|
self.logger = logging.getLogger(__name__)
|
||||||
|
if not self.logger.handlers:
|
||||||
|
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s %(name)s: %(message)s')
|
||||||
|
print(f"[宏观周期引擎] 初始化完成 (模型: {self.model})")
|
||||||
|
|
||||||
|
def run_full_analysis(self, progress_callback=None) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
运行完整的宏观周期分析流程
|
||||||
|
|
||||||
|
Args:
|
||||||
|
progress_callback: 进度回调函数 (progress_pct, status_text)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
完整的分析结果
|
||||||
|
"""
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("🧭 宏观周期分析系统启动")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
results = {
|
||||||
|
"success": False,
|
||||||
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
"raw_data": {},
|
||||||
|
"formatted_data": "",
|
||||||
|
"agents_analysis": {},
|
||||||
|
"data_errors": []
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 阶段1:数据采集
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(5, "📊 正在采集宏观经济数据...")
|
||||||
|
print("\n[阶段1] 宏观经济数据采集...")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
raw_data = self.data_fetcher.get_all_macro_data()
|
||||||
|
results["raw_data"] = raw_data
|
||||||
|
results["data_errors"] = raw_data.get("errors", [])
|
||||||
|
|
||||||
|
if not raw_data.get("success"):
|
||||||
|
print("⚠ 数据采集未完全成功,尝试继续分析...")
|
||||||
|
|
||||||
|
# 格式化数据
|
||||||
|
formatted_text = self.data_fetcher.format_data_for_ai(raw_data)
|
||||||
|
results["formatted_data"] = formatted_text
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(15, "✓ 数据采集完成")
|
||||||
|
print("✓ 数据采集和格式化完成")
|
||||||
|
print(f" 数据文本长度: {len(formatted_text)} 字符")
|
||||||
|
|
||||||
|
# 阶段2:AI智能体分析
|
||||||
|
print("\n[阶段2] AI智能体分析集群工作中...")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
agents_results = {}
|
||||||
|
|
||||||
|
# 2.1 康波周期分析师
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(20, "🌊 康波周期分析师正在分析...")
|
||||||
|
print("1/4 康波周期分析师...")
|
||||||
|
kondratieff_result = self.agents.kondratieff_wave_agent(formatted_text)
|
||||||
|
agents_results["kondratieff"] = kondratieff_result
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(35, "✓ 康波分析完成")
|
||||||
|
|
||||||
|
# 2.2 美林时钟分析师
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(40, "⏰ 美林时钟分析师正在分析...")
|
||||||
|
print("2/4 美林时钟分析师...")
|
||||||
|
merrill_result = self.agents.merrill_lynch_clock_agent(formatted_text)
|
||||||
|
agents_results["merrill"] = merrill_result
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(55, "✓ 美林时钟分析完成")
|
||||||
|
|
||||||
|
# 2.3 中国政策分析师
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(60, "🏛️ 中国政策分析师正在分析...")
|
||||||
|
print("3/4 中国政策分析师...")
|
||||||
|
policy_result = self.agents.china_policy_agent(formatted_text)
|
||||||
|
agents_results["policy"] = policy_result
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(75, "✓ 政策分析完成")
|
||||||
|
|
||||||
|
# 2.4 首席宏观策略师(综合三位分析师的报告)
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(80, "👔 首席宏观策略师正在综合研判...")
|
||||||
|
print("4/4 首席宏观策略师综合研判...")
|
||||||
|
chief_result = self.agents.chief_macro_strategist_agent(
|
||||||
|
kondratieff_report=kondratieff_result.get("analysis", ""),
|
||||||
|
merrill_report=merrill_result.get("analysis", ""),
|
||||||
|
policy_report=policy_result.get("analysis", ""),
|
||||||
|
macro_data_text=formatted_text
|
||||||
|
)
|
||||||
|
agents_results["chief"] = chief_result
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(95, "✓ 综合研判完成")
|
||||||
|
|
||||||
|
results["agents_analysis"] = agents_results
|
||||||
|
results["success"] = True
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✓ 宏观周期分析完成!")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(100, "✅ 分析完成!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n✗ 分析过程出错: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
results["error"] = str(e)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
# 测试
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("测试宏观周期分析引擎")
|
||||||
|
print("=" * 60)
|
||||||
|
engine = MacroCycleEngine()
|
||||||
|
print("引擎初始化完成")
|
||||||
@@ -0,0 +1,427 @@
|
|||||||
|
"""
|
||||||
|
宏观周期分析 - PDF报告生成模块
|
||||||
|
生成康波周期 × 美林投资时钟 × 中国政策分析的完整PDF报告
|
||||||
|
"""
|
||||||
|
|
||||||
|
from reportlab.lib import colors
|
||||||
|
from reportlab.lib.pagesizes import A4
|
||||||
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||||
|
from reportlab.lib.units import inch
|
||||||
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
|
||||||
|
from reportlab.pdfbase import pdfmetrics
|
||||||
|
from reportlab.pdfbase.ttfonts import TTFont
|
||||||
|
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
|
||||||
|
from datetime import datetime
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class MacroCyclePDFGenerator:
|
||||||
|
"""宏观周期分析PDF报告生成器"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""初始化PDF生成器"""
|
||||||
|
self.setup_fonts()
|
||||||
|
|
||||||
|
def setup_fonts(self):
|
||||||
|
"""设置中文字体"""
|
||||||
|
try:
|
||||||
|
font_paths = [
|
||||||
|
'C:/Windows/Fonts/msyh.ttc', # 微软雅黑
|
||||||
|
'C:/Windows/Fonts/simsun.ttc', # 宋体
|
||||||
|
'C:/Windows/Fonts/simhei.ttf', # 黑体
|
||||||
|
'/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', # Linux
|
||||||
|
'/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf',
|
||||||
|
]
|
||||||
|
|
||||||
|
for font_path in font_paths:
|
||||||
|
if os.path.exists(font_path):
|
||||||
|
try:
|
||||||
|
pdfmetrics.registerFont(TTFont('ChineseFont', font_path))
|
||||||
|
self.chinese_font = 'ChineseFont'
|
||||||
|
print(f"[宏观PDF] 成功加载字体: {font_path}")
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.chinese_font = 'Helvetica'
|
||||||
|
print("[宏观PDF] 警告: 未找到中文字体,使用默认字体")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[宏观PDF] 字体设置失败: {e}")
|
||||||
|
self.chinese_font = 'Helvetica'
|
||||||
|
|
||||||
|
def generate_pdf(self, result_data: dict, output_path: str = None) -> str:
|
||||||
|
"""
|
||||||
|
生成宏观周期分析PDF报告
|
||||||
|
|
||||||
|
Args:
|
||||||
|
result_data: 分析结果数据
|
||||||
|
output_path: 输出路径,如果为None则生成临时文件
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
PDF文件路径
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if output_path is None:
|
||||||
|
temp_dir = tempfile.gettempdir()
|
||||||
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
output_path = os.path.join(temp_dir, f"宏观周期报告_{timestamp}.pdf")
|
||||||
|
|
||||||
|
doc = SimpleDocTemplate(
|
||||||
|
output_path,
|
||||||
|
pagesize=A4,
|
||||||
|
rightMargin=0.5*inch,
|
||||||
|
leftMargin=0.5*inch,
|
||||||
|
topMargin=0.5*inch,
|
||||||
|
bottomMargin=0.5*inch
|
||||||
|
)
|
||||||
|
|
||||||
|
story = []
|
||||||
|
|
||||||
|
# 1. 标题页
|
||||||
|
story.extend(self._create_title_page(result_data))
|
||||||
|
story.append(PageBreak())
|
||||||
|
|
||||||
|
# 2. 首席宏观策略师综合研判(最重要,放最前面)
|
||||||
|
story.extend(self._create_chief_section(result_data))
|
||||||
|
story.append(PageBreak())
|
||||||
|
|
||||||
|
# 3. 康波周期分析
|
||||||
|
story.extend(self._create_kondratieff_section(result_data))
|
||||||
|
story.append(PageBreak())
|
||||||
|
|
||||||
|
# 4. 美林投资时钟分析
|
||||||
|
story.extend(self._create_merrill_section(result_data))
|
||||||
|
story.append(PageBreak())
|
||||||
|
|
||||||
|
# 5. 中国政策分析
|
||||||
|
story.extend(self._create_policy_section(result_data))
|
||||||
|
|
||||||
|
# 6. 结束语
|
||||||
|
story.extend(self._create_ending())
|
||||||
|
|
||||||
|
# 生成PDF
|
||||||
|
doc.build(story)
|
||||||
|
|
||||||
|
print(f"[宏观PDF] 报告生成成功: {output_path}")
|
||||||
|
return output_path
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[宏观PDF] 生成失败: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
raise
|
||||||
|
|
||||||
|
def _clean_markdown(self, text: str) -> str:
|
||||||
|
"""清理Markdown标记,转换为适合PDF的纯文本/HTML"""
|
||||||
|
if not text:
|
||||||
|
return ""
|
||||||
|
# 移除markdown粗体 **text** → text
|
||||||
|
text = re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', text)
|
||||||
|
# 移除markdown斜体 *text* → text
|
||||||
|
text = re.sub(r'\*(.*?)\*', r'<i>\1</i>', text)
|
||||||
|
# 移除markdown标题 ## → 空
|
||||||
|
text = re.sub(r'^#{1,6}\s+', '', text, flags=re.MULTILINE)
|
||||||
|
# 移除markdown链接 [text](url) → text
|
||||||
|
text = re.sub(r'\[(.*?)\]\(.*?\)', r'\1', text)
|
||||||
|
# 移除markdown表格分隔线
|
||||||
|
text = re.sub(r'\|[-:]+\|[-:| ]+\|', '', text)
|
||||||
|
# 替换换行
|
||||||
|
text = text.replace('\n', '<br/>')
|
||||||
|
return text
|
||||||
|
|
||||||
|
def _split_text_to_paragraphs(self, text: str, styles: dict, max_chars: int = 0) -> list:
|
||||||
|
"""将长文本分段为多个Paragraph,避免单段过长溢出"""
|
||||||
|
elements = []
|
||||||
|
if not text:
|
||||||
|
return elements
|
||||||
|
|
||||||
|
if max_chars > 0 and len(text) > max_chars:
|
||||||
|
text = text[:max_chars] + "...(更多内容请查看网页版完整报告)"
|
||||||
|
|
||||||
|
# 按段落分割
|
||||||
|
paragraphs = text.split('\n\n')
|
||||||
|
for para in paragraphs:
|
||||||
|
para = para.strip()
|
||||||
|
if not para:
|
||||||
|
continue
|
||||||
|
# 清理markdown
|
||||||
|
cleaned = self._clean_markdown(para)
|
||||||
|
if cleaned:
|
||||||
|
try:
|
||||||
|
elements.append(Paragraph(cleaned, styles['Small']))
|
||||||
|
elements.append(Spacer(1, 0.08*inch))
|
||||||
|
except Exception:
|
||||||
|
# 如果格式化失败,用纯文本
|
||||||
|
plain = re.sub(r'<[^>]+>', '', cleaned)
|
||||||
|
elements.append(Paragraph(plain, styles['Small']))
|
||||||
|
elements.append(Spacer(1, 0.08*inch))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _create_title_page(self, data: dict) -> list:
|
||||||
|
"""创建标题页"""
|
||||||
|
styles = self._get_styles()
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
elements.append(Spacer(1, 1.5*inch))
|
||||||
|
|
||||||
|
# 主标题
|
||||||
|
elements.append(Paragraph("宏观周期分析报告", styles['Title']))
|
||||||
|
elements.append(Spacer(1, 0.3*inch))
|
||||||
|
|
||||||
|
# 副标题
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"康波周期 × 美林投资时钟 × 中国政策分析",
|
||||||
|
styles['Heading2']
|
||||||
|
))
|
||||||
|
elements.append(Spacer(1, 0.8*inch))
|
||||||
|
|
||||||
|
# 报告信息
|
||||||
|
timestamp = data.get('timestamp', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||||
|
info_text = f"""
|
||||||
|
<para align=center>
|
||||||
|
<b>生成时间:</b> {timestamp}<br/>
|
||||||
|
<b>分析框架:</b> 三维周期定位系统<br/>
|
||||||
|
<b>AI分析师:</b> 4位专业分析师协同研判<br/>
|
||||||
|
<b>分析维度:</b> 康波长周期 · 美林中短周期 · 中国政策环境<br/>
|
||||||
|
<b>数据来源:</b> AKShare宏观经济数据
|
||||||
|
</para>
|
||||||
|
"""
|
||||||
|
elements.append(Paragraph(info_text, styles['Normal']))
|
||||||
|
elements.append(Spacer(1, 0.5*inch))
|
||||||
|
|
||||||
|
# 分析师团队
|
||||||
|
team_text = """
|
||||||
|
<para align=center>
|
||||||
|
<b>AI分析师团队:</b><br/>
|
||||||
|
康波周期分析师 · 美林时钟分析师 · 中国政策分析师 · 首席宏观策略师
|
||||||
|
</para>
|
||||||
|
"""
|
||||||
|
elements.append(Paragraph(team_text, styles['Normal']))
|
||||||
|
elements.append(Spacer(1, 0.8*inch))
|
||||||
|
|
||||||
|
# 免责声明
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"<para align=center><i>本报告由AI系统自动生成,仅供学习研究参考,不构成投资建议。<br/>"
|
||||||
|
"周期理论是认知框架而非精确预测工具。投资有风险,入市需谨慎。</i></para>",
|
||||||
|
styles['Small']
|
||||||
|
))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _create_chief_section(self, data: dict) -> list:
|
||||||
|
"""创建首席宏观策略师综合研判部分"""
|
||||||
|
styles = self._get_styles()
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
elements.append(Paragraph("一、首席宏观策略师 — 综合研判", styles['Heading1']))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"<i>整合康波周期、美林投资时钟、中国政策三个维度,构建周期仪表盘,给出最终综合投资策略。</i>",
|
||||||
|
styles['Small']
|
||||||
|
))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
|
||||||
|
chief = data.get('agents_analysis', {}).get('chief', {})
|
||||||
|
analysis = chief.get('analysis', '暂无分析结果')
|
||||||
|
elements.extend(self._split_text_to_paragraphs(analysis, styles, max_chars=5000))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _create_kondratieff_section(self, data: dict) -> list:
|
||||||
|
"""创建康波周期分析部分"""
|
||||||
|
styles = self._get_styles()
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
elements.append(Paragraph("二、康波周期分析 — 60年长周期定位", styles['Heading1']))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"<i>基于康德拉季耶夫长波理论(周金涛\"人生发财靠康波\"),判断当前处于第五轮信息技术康波的阶段位置。</i>",
|
||||||
|
styles['Small']
|
||||||
|
))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
|
||||||
|
kondratieff = data.get('agents_analysis', {}).get('kondratieff', {})
|
||||||
|
analysis = kondratieff.get('analysis', '暂无分析结果')
|
||||||
|
elements.extend(self._split_text_to_paragraphs(analysis, styles, max_chars=5000))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _create_merrill_section(self, data: dict) -> list:
|
||||||
|
"""创建美林投资时钟分析部分"""
|
||||||
|
styles = self._get_styles()
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
elements.append(Paragraph("三、美林投资时钟 — 中短周期定位", styles['Heading1']))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"<i>基于经济增长与通胀两大维度,结合中国政策方向(第三维度),判断当前处于美林时钟的哪个象限。</i>",
|
||||||
|
styles['Small']
|
||||||
|
))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
|
||||||
|
merrill = data.get('agents_analysis', {}).get('merrill', {})
|
||||||
|
analysis = merrill.get('analysis', '暂无分析结果')
|
||||||
|
elements.extend(self._split_text_to_paragraphs(analysis, styles, max_chars=5000))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _create_policy_section(self, data: dict) -> list:
|
||||||
|
"""创建中国政策分析部分"""
|
||||||
|
styles = self._get_styles()
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
elements.append(Paragraph("四、中国政策环境分析", styles['Heading1']))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"<i>深度分析货币政策、财政政策、产业政策、房地产政策,评估政策对周期的影响和投资机会。</i>",
|
||||||
|
styles['Small']
|
||||||
|
))
|
||||||
|
elements.append(Spacer(1, 0.15*inch))
|
||||||
|
|
||||||
|
policy = data.get('agents_analysis', {}).get('policy', {})
|
||||||
|
analysis = policy.get('analysis', '暂无分析结果')
|
||||||
|
elements.extend(self._split_text_to_paragraphs(analysis, styles, max_chars=5000))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _create_ending(self) -> list:
|
||||||
|
"""创建结束语"""
|
||||||
|
styles = self._get_styles()
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
elements.append(Spacer(1, 0.5*inch))
|
||||||
|
elements.append(Paragraph(
|
||||||
|
"<para align=center><i>--- 报告结束 ---<br/>"
|
||||||
|
"本报告由宏观周期AI分析系统自动生成<br/>"
|
||||||
|
"康波是罗盘,美林是航海图,政策是季风<br/>"
|
||||||
|
"愿你在经济的海洋中,驶向属于自己的财富彼岸</i></para>",
|
||||||
|
styles['Normal']
|
||||||
|
))
|
||||||
|
|
||||||
|
return elements
|
||||||
|
|
||||||
|
def _get_styles(self) -> dict:
|
||||||
|
"""获取样式"""
|
||||||
|
styles = getSampleStyleSheet()
|
||||||
|
|
||||||
|
custom_styles = {
|
||||||
|
'Title': ParagraphStyle(
|
||||||
|
'MacroTitle',
|
||||||
|
parent=styles['Title'],
|
||||||
|
fontName=self.chinese_font,
|
||||||
|
fontSize=26,
|
||||||
|
textColor=colors.HexColor('#302b63'),
|
||||||
|
spaceAfter=30,
|
||||||
|
alignment=TA_CENTER
|
||||||
|
),
|
||||||
|
'Heading1': ParagraphStyle(
|
||||||
|
'MacroHeading1',
|
||||||
|
parent=styles['Heading1'],
|
||||||
|
fontName=self.chinese_font,
|
||||||
|
fontSize=16,
|
||||||
|
textColor=colors.HexColor('#0f0c29'),
|
||||||
|
spaceAfter=12,
|
||||||
|
spaceBefore=12
|
||||||
|
),
|
||||||
|
'Heading2': ParagraphStyle(
|
||||||
|
'MacroHeading2',
|
||||||
|
parent=styles['Heading2'],
|
||||||
|
fontName=self.chinese_font,
|
||||||
|
fontSize=14,
|
||||||
|
textColor=colors.HexColor('#302b63'),
|
||||||
|
spaceAfter=10,
|
||||||
|
spaceBefore=10,
|
||||||
|
alignment=TA_CENTER
|
||||||
|
),
|
||||||
|
'Normal': ParagraphStyle(
|
||||||
|
'MacroNormal',
|
||||||
|
parent=styles['Normal'],
|
||||||
|
fontName=self.chinese_font,
|
||||||
|
fontSize=11,
|
||||||
|
leading=16,
|
||||||
|
alignment=TA_JUSTIFY
|
||||||
|
),
|
||||||
|
'Small': ParagraphStyle(
|
||||||
|
'MacroSmall',
|
||||||
|
parent=styles['Normal'],
|
||||||
|
fontName=self.chinese_font,
|
||||||
|
fontSize=9,
|
||||||
|
leading=14,
|
||||||
|
alignment=TA_LEFT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return custom_styles
|
||||||
|
|
||||||
|
|
||||||
|
def generate_macro_cycle_markdown(result_data: dict) -> str:
|
||||||
|
"""生成宏观周期分析的Markdown报告"""
|
||||||
|
parts = []
|
||||||
|
timestamp = result_data.get('timestamp', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||||
|
|
||||||
|
parts.append("# 🧭 宏观周期分析报告\n")
|
||||||
|
parts.append(f"**生成时间**: {timestamp}\n")
|
||||||
|
parts.append("**分析框架**: 康波周期 × 美林投资时钟 × 中国政策分析\n")
|
||||||
|
parts.append("---\n")
|
||||||
|
|
||||||
|
agents = result_data.get('agents_analysis', {})
|
||||||
|
|
||||||
|
# 首席策略师
|
||||||
|
chief = agents.get('chief', {})
|
||||||
|
if chief:
|
||||||
|
parts.append("## 👔 一、首席宏观策略师 — 综合研判\n")
|
||||||
|
parts.append(chief.get('analysis', '暂无分析结果'))
|
||||||
|
parts.append("\n\n---\n")
|
||||||
|
|
||||||
|
# 康波周期
|
||||||
|
kondratieff = agents.get('kondratieff', {})
|
||||||
|
if kondratieff:
|
||||||
|
parts.append("## 🌊 二、康波周期分析 — 60年长周期定位\n")
|
||||||
|
parts.append(kondratieff.get('analysis', '暂无分析结果'))
|
||||||
|
parts.append("\n\n---\n")
|
||||||
|
|
||||||
|
# 美林时钟
|
||||||
|
merrill = agents.get('merrill', {})
|
||||||
|
if merrill:
|
||||||
|
parts.append("## ⏰ 三、美林投资时钟 — 中短周期定位\n")
|
||||||
|
parts.append(merrill.get('analysis', '暂无分析结果'))
|
||||||
|
parts.append("\n\n---\n")
|
||||||
|
|
||||||
|
# 政策分析
|
||||||
|
policy = agents.get('policy', {})
|
||||||
|
if policy:
|
||||||
|
parts.append("## 🏛️ 四、中国政策环境分析\n")
|
||||||
|
parts.append(policy.get('analysis', '暂无分析结果'))
|
||||||
|
parts.append("\n\n---\n")
|
||||||
|
|
||||||
|
# 免责声明
|
||||||
|
parts.append("\n> ⚠️ **免责声明**: 本报告由AI系统自动生成,仅供学习研究参考,不构成投资建议。")
|
||||||
|
parts.append("周期理论是认知框架而非精确预测工具。投资有风险,入市需谨慎。\n")
|
||||||
|
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
# 测试
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("测试宏观周期PDF生成器")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
test_data = {
|
||||||
|
"success": True,
|
||||||
|
"timestamp": "2026-02-27 14:00:00",
|
||||||
|
"agents_analysis": {
|
||||||
|
"chief": {"analysis": "综合研判测试内容..."},
|
||||||
|
"kondratieff": {"analysis": "康波分析测试内容..."},
|
||||||
|
"merrill": {"analysis": "美林时钟测试内容..."},
|
||||||
|
"policy": {"analysis": "政策分析测试内容..."},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generator = MacroCyclePDFGenerator()
|
||||||
|
output_path = generator.generate_pdf(test_data)
|
||||||
|
print(f"测试PDF生成: {output_path}")
|
||||||
@@ -0,0 +1,370 @@
|
|||||||
|
"""
|
||||||
|
宏观周期分析 - UI界面模块
|
||||||
|
展示康波周期 + 美林投资时钟 + 中国政策分析的综合结果
|
||||||
|
"""
|
||||||
|
|
||||||
|
import streamlit as st
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from macro_cycle_engine import MacroCycleEngine
|
||||||
|
from macro_cycle_pdf import MacroCyclePDFGenerator, generate_macro_cycle_markdown
|
||||||
|
|
||||||
|
|
||||||
|
def display_macro_cycle():
|
||||||
|
"""显示宏观周期分析主界面"""
|
||||||
|
st.markdown("""
|
||||||
|
<div style="background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
|
||||||
|
padding: 2rem; border-radius: 15px; margin-bottom: 1.5rem;
|
||||||
|
box-shadow: 0 8px 32px rgba(0,0,0,0.3);">
|
||||||
|
<h1 style="color: #fff; margin: 0; font-size: 2rem;">
|
||||||
|
🧭 宏观周期分析
|
||||||
|
</h1>
|
||||||
|
<p style="color: rgba(255,255,255,0.8); margin: 0.5rem 0 0 0; font-size: 1.1rem;">
|
||||||
|
康波周期 × 美林投资时钟 × 中国政策分析 — AI驱动的宏观经济周期研判
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
""", unsafe_allow_html=True)
|
||||||
|
|
||||||
|
# 标签页
|
||||||
|
tab1, tab2 = st.tabs(["📊 周期分析", "📚 理论介绍"])
|
||||||
|
|
||||||
|
with tab1:
|
||||||
|
display_analysis_tab()
|
||||||
|
|
||||||
|
with tab2:
|
||||||
|
display_theory_tab()
|
||||||
|
|
||||||
|
|
||||||
|
def display_analysis_tab():
|
||||||
|
"""显示分析标签页"""
|
||||||
|
# 简介
|
||||||
|
st.markdown("""
|
||||||
|
> **分析说明**:本模块基于视频[康波周期理论](https://www.bilibili.com/video/BV1QNcEzREzY)(50-60年长周期)和视频[美林投资时钟](https://www.bilibili.com/video/BV1Zuf5BUEhH)(3-5年中短周期),
|
||||||
|
> 结合中国政策环境(第三维度),由4位AI分析师协同研判当前宏观经济所处的周期位置,并给出资产配置建议。
|
||||||
|
""")
|
||||||
|
|
||||||
|
st.markdown("""
|
||||||
|
**🤖 AI分析师团队:**
|
||||||
|
- 🌊 **康波周期分析师** — 60年长周期战略定位(回升→繁荣→衰退→萧条)
|
||||||
|
- ⏰ **美林时钟分析师** — 3-5年中短周期战术定位(复苏→过热→滞胀→衰退)
|
||||||
|
- 🏛️ **中国政策分析师** — 政策第三维度(货币/财政/产业/房地产)
|
||||||
|
- 👔 **首席宏观策略师** — 三维综合研判,最终资产配置建议
|
||||||
|
""")
|
||||||
|
|
||||||
|
st.markdown("---")
|
||||||
|
|
||||||
|
# 操作按钮
|
||||||
|
col1, col2 = st.columns([2, 2])
|
||||||
|
|
||||||
|
with col1:
|
||||||
|
analyze_button = st.button("🚀 开始宏观周期分析", type="primary", key="macro_analyze")
|
||||||
|
|
||||||
|
with col2:
|
||||||
|
if st.button("🔄 清除结果", key="macro_clear"):
|
||||||
|
if 'macro_cycle_result' in st.session_state:
|
||||||
|
del st.session_state.macro_cycle_result
|
||||||
|
st.success("已清除分析结果")
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
st.markdown("---")
|
||||||
|
|
||||||
|
# 开始分析
|
||||||
|
if analyze_button:
|
||||||
|
if 'macro_cycle_result' in st.session_state:
|
||||||
|
del st.session_state.macro_cycle_result
|
||||||
|
|
||||||
|
run_macro_cycle_analysis()
|
||||||
|
|
||||||
|
# 显示结果
|
||||||
|
if 'macro_cycle_result' in st.session_state:
|
||||||
|
result = st.session_state.macro_cycle_result
|
||||||
|
if result.get("success"):
|
||||||
|
display_analysis_results(result)
|
||||||
|
else:
|
||||||
|
st.error(f"❌ 分析失败: {result.get('error', '未知错误')}")
|
||||||
|
|
||||||
|
|
||||||
|
def run_macro_cycle_analysis():
|
||||||
|
"""运行宏观周期分析"""
|
||||||
|
import config
|
||||||
|
model = config.DEFAULT_MODEL_NAME
|
||||||
|
|
||||||
|
progress_bar = st.progress(0)
|
||||||
|
status_text = st.empty()
|
||||||
|
|
||||||
|
def progress_callback(pct, text):
|
||||||
|
progress_bar.progress(pct)
|
||||||
|
status_text.text(text)
|
||||||
|
|
||||||
|
try:
|
||||||
|
engine = MacroCycleEngine(model=model)
|
||||||
|
result = engine.run_full_analysis(progress_callback=progress_callback)
|
||||||
|
|
||||||
|
if result.get("success"):
|
||||||
|
st.session_state.macro_cycle_result = result
|
||||||
|
time.sleep(1)
|
||||||
|
status_text.empty()
|
||||||
|
progress_bar.empty()
|
||||||
|
st.rerun()
|
||||||
|
else:
|
||||||
|
st.error(f"❌ 分析失败: {result.get('error', '未知错误')}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"❌ 分析过程出错: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
st.code(traceback.format_exc())
|
||||||
|
finally:
|
||||||
|
progress_bar.empty()
|
||||||
|
status_text.empty()
|
||||||
|
|
||||||
|
|
||||||
|
def display_analysis_results(result):
|
||||||
|
"""显示分析结果"""
|
||||||
|
agents = result.get("agents_analysis", {})
|
||||||
|
timestamp = result.get("timestamp", "")
|
||||||
|
|
||||||
|
st.success(f"✅ 分析完成于 {timestamp}")
|
||||||
|
|
||||||
|
# 数据采集状态
|
||||||
|
data_errors = result.get("data_errors", [])
|
||||||
|
if data_errors:
|
||||||
|
with st.expander("⚠️ 部分数据采集失败(不影响分析)"):
|
||||||
|
for err in data_errors:
|
||||||
|
st.warning(f"• {err}")
|
||||||
|
|
||||||
|
# 四个分析师报告
|
||||||
|
report_tabs = st.tabs([
|
||||||
|
"👔 综合策略",
|
||||||
|
"🌊 康波周期",
|
||||||
|
"⏰ 美林时钟",
|
||||||
|
"🏛️ 政策分析"
|
||||||
|
])
|
||||||
|
|
||||||
|
# Tab 1: 首席宏观策略师(综合)
|
||||||
|
with report_tabs[0]:
|
||||||
|
chief = agents.get("chief", {})
|
||||||
|
if chief:
|
||||||
|
st.markdown("""
|
||||||
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
padding: 1.2rem; border-radius: 12px; margin-bottom: 1rem;
|
||||||
|
color: white;">
|
||||||
|
<h3 style="margin: 0; color: white;">👔 首席宏观策略师 — 综合研判</h3>
|
||||||
|
<p style="margin: 0.3rem 0 0 0; opacity: 0.9; font-size: 0.95rem;">
|
||||||
|
整合康波周期 + 美林投资时钟 + 中国政策三维分析,给出最终投资策略
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
""", unsafe_allow_html=True)
|
||||||
|
st.markdown(chief.get("analysis", "暂无分析结果"))
|
||||||
|
else:
|
||||||
|
st.info("暂无综合策略分析结果")
|
||||||
|
|
||||||
|
# Tab 2: 康波周期分析师
|
||||||
|
with report_tabs[1]:
|
||||||
|
kondratieff = agents.get("kondratieff", {})
|
||||||
|
if kondratieff:
|
||||||
|
st.markdown("""
|
||||||
|
<div style="background: linear-gradient(135deg, #0575E6 0%, #021B79 100%);
|
||||||
|
padding: 1.2rem; border-radius: 12px; margin-bottom: 1rem;
|
||||||
|
color: white;">
|
||||||
|
<h3 style="margin: 0; color: white;">🌊 康波周期分析师 — 60年长周期定位</h3>
|
||||||
|
<p style="margin: 0.3rem 0 0 0; opacity: 0.9; font-size: 0.95rem;">
|
||||||
|
基于康德拉季耶夫长波理论,判断当前处于第五轮信息技术康波的哪个阶段
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
""", unsafe_allow_html=True)
|
||||||
|
st.markdown(kondratieff.get("analysis", "暂无分析结果"))
|
||||||
|
else:
|
||||||
|
st.info("暂无康波周期分析结果")
|
||||||
|
|
||||||
|
# Tab 3: 美林时钟分析师
|
||||||
|
with report_tabs[2]:
|
||||||
|
merrill = agents.get("merrill", {})
|
||||||
|
if merrill:
|
||||||
|
st.markdown("""
|
||||||
|
<div style="background: linear-gradient(135deg, #f5af19 0%, #f12711 100%);
|
||||||
|
padding: 1.2rem; border-radius: 12px; margin-bottom: 1rem;
|
||||||
|
color: white;">
|
||||||
|
<h3 style="margin: 0; color: white;">⏰ 美林投资时钟分析师 — 中短周期定位</h3>
|
||||||
|
<p style="margin: 0.3rem 0 0 0; opacity: 0.9; font-size: 0.95rem;">
|
||||||
|
基于经济增长+通胀+政策三维度,判断当前处于美林时钟的哪个象限
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
""", unsafe_allow_html=True)
|
||||||
|
st.markdown(merrill.get("analysis", "暂无分析结果"))
|
||||||
|
else:
|
||||||
|
st.info("暂无美林时钟分析结果")
|
||||||
|
|
||||||
|
# Tab 4: 中国政策分析师
|
||||||
|
with report_tabs[3]:
|
||||||
|
policy = agents.get("policy", {})
|
||||||
|
if policy:
|
||||||
|
st.markdown("""
|
||||||
|
<div style="background: linear-gradient(135deg, #e53935 0%, #b71c1c 100%);
|
||||||
|
padding: 1.2rem; border-radius: 12px; margin-bottom: 1rem;
|
||||||
|
color: white;">
|
||||||
|
<h3 style="margin: 0; color: white;">🏛️ 中国政策分析师 — 政策第三维度</h3>
|
||||||
|
<p style="margin: 0.3rem 0 0 0; opacity: 0.9; font-size: 0.95rem;">
|
||||||
|
深度分析货币政策、财政政策、产业政策、房地产政策对周期和投资的影响
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
""", unsafe_allow_html=True)
|
||||||
|
st.markdown(policy.get("analysis", "暂无分析结果"))
|
||||||
|
else:
|
||||||
|
st.info("暂无政策分析结果")
|
||||||
|
|
||||||
|
# 导出报告
|
||||||
|
st.markdown("---")
|
||||||
|
display_pdf_export_section(result)
|
||||||
|
|
||||||
|
|
||||||
|
def display_pdf_export_section(result):
|
||||||
|
"""显示PDF/Markdown导出部分"""
|
||||||
|
st.subheader("📄 导出报告")
|
||||||
|
|
||||||
|
col1, col2, col3, col4 = st.columns([2, 1, 1, 1])
|
||||||
|
|
||||||
|
with col1:
|
||||||
|
st.write("将宏观周期分析报告导出为PDF或Markdown文件,方便保存和分享")
|
||||||
|
|
||||||
|
with col2:
|
||||||
|
if st.button("📥 生成PDF报告", type="primary", width='content', key="macro_pdf_gen"):
|
||||||
|
with st.spinner("正在生成PDF报告..."):
|
||||||
|
try:
|
||||||
|
generator = MacroCyclePDFGenerator()
|
||||||
|
pdf_path = generator.generate_pdf(result)
|
||||||
|
|
||||||
|
with open(pdf_path, "rb") as f:
|
||||||
|
pdf_bytes = f.read()
|
||||||
|
|
||||||
|
st.session_state.macro_pdf_data = pdf_bytes
|
||||||
|
ts = result.get('timestamp', datetime.now().strftime('%Y%m%d_%H%M%S')).replace(':', '').replace(' ', '_')
|
||||||
|
st.session_state.macro_pdf_filename = f"宏观周期报告_{ts}.pdf"
|
||||||
|
|
||||||
|
st.success("✅ PDF报告生成成功!")
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"❌ PDF生成失败: {str(e)}")
|
||||||
|
|
||||||
|
with col3:
|
||||||
|
if st.button("📝 生成Markdown", type="secondary", width='content', key="macro_md_gen"):
|
||||||
|
with st.spinner("正在生成Markdown报告..."):
|
||||||
|
try:
|
||||||
|
markdown_content = generate_macro_cycle_markdown(result)
|
||||||
|
|
||||||
|
st.session_state.macro_md_data = markdown_content
|
||||||
|
ts = result.get('timestamp', datetime.now().strftime('%Y%m%d_%H%M%S')).replace(':', '').replace(' ', '_')
|
||||||
|
st.session_state.macro_md_filename = f"宏观周期报告_{ts}.md"
|
||||||
|
|
||||||
|
st.success("✅ Markdown报告生成成功!")
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"❌ Markdown生成失败: {str(e)}")
|
||||||
|
|
||||||
|
with col4:
|
||||||
|
if 'macro_pdf_data' in st.session_state:
|
||||||
|
st.download_button(
|
||||||
|
label="💾 下载PDF",
|
||||||
|
data=st.session_state.macro_pdf_data,
|
||||||
|
file_name=st.session_state.macro_pdf_filename,
|
||||||
|
mime="application/pdf",
|
||||||
|
width='content',
|
||||||
|
key="macro_pdf_dl"
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'macro_md_data' in st.session_state:
|
||||||
|
st.download_button(
|
||||||
|
label="💾 下载Markdown",
|
||||||
|
data=st.session_state.macro_md_data,
|
||||||
|
file_name=st.session_state.macro_md_filename,
|
||||||
|
mime="text/markdown",
|
||||||
|
width='content',
|
||||||
|
key="macro_md_dl"
|
||||||
|
)
|
||||||
|
|
||||||
|
def display_theory_tab():
|
||||||
|
"""显示理论介绍标签页"""
|
||||||
|
st.markdown("""
|
||||||
|
## 📖 两大周期理论简介
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🌊 康德拉季耶夫长波(康波周期)
|
||||||
|
|
||||||
|
**创始人**:苏联经济学家尼古拉·康德拉季耶夫(1920s)
|
||||||
|
**中国推广者**:周金涛("周期天王",中信建投首席经济学家)
|
||||||
|
|
||||||
|
**核心思想**:资本主义经济存在约 **50-60年** 的超长周期,由重大技术革命驱动。
|
||||||
|
|
||||||
|
**四个阶段**:
|
||||||
|
|
||||||
|
| 阶段 | 持续时间 | 特征 | 最优资产 |
|
||||||
|
|------|---------|------|---------|
|
||||||
|
| 🌱 **回升期** | ~15年 | 新技术商业化,经济从底部爬起 | 股票、新兴产业 |
|
||||||
|
| ☀️ **繁荣期** | ~15年 | 技术全面铺开,高速增长 | 几乎所有资产 |
|
||||||
|
| 🍂 **衰退期** | ~10年 | 泡沫破裂,增速放缓 | 大宗商品→现金 |
|
||||||
|
| ❄️ **萧条期** | ~10年 | 全面收缩,资产便宜 | 现金→布局未来 |
|
||||||
|
|
||||||
|
**历史五轮康波**:
|
||||||
|
1. **1780s-1840s**:蒸汽机革命
|
||||||
|
2. **1840s-1890s**:铁路与钢铁
|
||||||
|
3. **1890s-1940s**:电力与化工
|
||||||
|
4. **1940s-1990s**:汽车与计算机
|
||||||
|
5. **1990s-2050s?**:信息技术革命(当前)
|
||||||
|
|
||||||
|
> *"人生发财靠康波。每个人的财富积累,一定不要以为是你多有本事,财富积累完全来源于经济周期运动的时间给你的机会。"* — 周金涛
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ⏰ 美林投资时钟
|
||||||
|
|
||||||
|
**创始人**:美林证券分析师(2004年)
|
||||||
|
**核心指标**:经济增长 × 通货膨胀
|
||||||
|
|
||||||
|
**四个象限**:
|
||||||
|
|
||||||
|
| 象限 | 经济 | 通胀 | 最优资产 | 典型特征 |
|
||||||
|
|------|------|------|---------|---------|
|
||||||
|
| 🟢 **复苏期** | ↑ | ↓ | **股票** | 盈利改善,利率低 |
|
||||||
|
| 🔴 **过热期** | ↑ | ↑ | **大宗商品** | 需求旺盛,加息 |
|
||||||
|
| 🟡 **滞胀期** | ↓ | ↑ | **现金** | 成本上升,利润缩水 |
|
||||||
|
| 🔵 **衰退期** | ↓ | ↓ | **债券** | 降息,避险需求 |
|
||||||
|
|
||||||
|
**中国化改造**:
|
||||||
|
- 增加 **政策方向** 作为第三维度
|
||||||
|
- 缩短时钟转动周期(中国约1-3年一轮,美国3-5年)
|
||||||
|
- 增加 **房地产** 作为第五类资产
|
||||||
|
- 重视 **政策友好型** 资产
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🤝 两大理论的结合使用
|
||||||
|
|
||||||
|
| 维度 | 康波周期 | 美林时钟 |
|
||||||
|
|------|---------|---------|
|
||||||
|
| **时间尺度** | 50-60年 | 3-5年 |
|
||||||
|
| **驱动力** | 技术革命(供给侧) | 增长+通胀(需求侧) |
|
||||||
|
| **用途** | 人生战略决策 | 投资组合调整 |
|
||||||
|
| **比喻** | 🔭 望远镜 | 🔬 显微镜 |
|
||||||
|
| **角色** | 罗盘(大方向) | 航海图(风浪变化) |
|
||||||
|
|
||||||
|
**结合方法**:
|
||||||
|
- 康波定 **战略方向**(进攻/防守)
|
||||||
|
- 美林定 **战术节奏**(具体配什么)
|
||||||
|
- 政策作为 **催化剂**(加速/扭曲周期)
|
||||||
|
|
||||||
|
> *"双指针一致时信心更强,矛盾时要谨慎。"*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ⚠️ 免责声明
|
||||||
|
|
||||||
|
本分析仅供学习研究参考,不构成任何投资建议。周期理论是认知框架而非精确预测工具。
|
||||||
|
投资有风险,入市需谨慎。
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
# 主入口
|
||||||
|
if __name__ == "__main__":
|
||||||
|
display_macro_cycle()
|
||||||
Reference in New Issue
Block a user