246 lines
9.1 KiB
Python
246 lines
9.1 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
股票投研体系学习执行器
|
||
======================
|
||
根据当前阶段推进学习内容,输出本周学习任务和进度。
|
||
|
||
用法:
|
||
python3 stock_learning.py report → 输出本周学习报告
|
||
python3 stock_learning.py advance → 进入下一阶段
|
||
python3 stock_learning.py status → 查看当前状态
|
||
"""
|
||
|
||
import json, os, sys
|
||
from datetime import datetime, timezone
|
||
|
||
HOME = os.path.expanduser("~")
|
||
HERMES = HOME + "/.hermes"
|
||
TOPICS_FILE = HERMES + "/proactive_learning/topics.json"
|
||
PROGRESS_FILE = HERMES + "/proactive_learning/stock_progress.json"
|
||
os.makedirs(HERMES + "/proactive_learning", exist_ok=True)
|
||
|
||
|
||
def load():
|
||
if os.path.exists(TOPICS_FILE):
|
||
data = json.load(open(TOPICS_FILE))
|
||
for t in data.get("topics", []):
|
||
if t["name"] == "股票投研体系":
|
||
return t
|
||
return None
|
||
|
||
|
||
def load_progress():
|
||
if os.path.exists(PROGRESS_FILE):
|
||
return json.load(open(PROGRESS_FILE))
|
||
return {"current_phase": 1, "current_item": 0, "learning_notes": [], "test_results": []}
|
||
|
||
|
||
def save_progress(p):
|
||
with open(PROGRESS_FILE, "w") as f:
|
||
json.dump(p, f, ensure_ascii=False, indent=2)
|
||
|
||
|
||
# ===================== 学习内容库 =====================
|
||
|
||
PHASES = {
|
||
1: {
|
||
"title": "股票基础概念",
|
||
"items": [
|
||
("A股交易规则", [
|
||
"A股实行T+1制度:当天买,次日才能卖",
|
||
"涨跌幅限制:主板±10%,创业板/科创板±20%",
|
||
"集合竞价:9:15-9:25申报,9:25-9:30不接受新申报",
|
||
"连续竞价:9:30-11:30、13:00-15:00",
|
||
"ST股(特别处理)涨跌±5%",
|
||
"注册制新股:上市前5日无涨跌幅限制",
|
||
]),
|
||
("K线基础", [
|
||
"阳线(红/实心):收盘价>开盘价,代表上涨",
|
||
"阴线(绿/空心):收盘价<开盘价,代表下跌",
|
||
"十字星:收盘≈开盘,多空力量均衡",
|
||
"上影线:最高价到收盘/开盘的距离,上涨受阻",
|
||
"下影线:最低价到收盘/开盘的距离,底部支撑",
|
||
]),
|
||
("核心指标", [
|
||
"市盈率(PE):股价/每股收益,越低越便宜但也可能是陷阱",
|
||
"换手率:当日成交股数/总股本,高换手=活跃但高波动",
|
||
"成交量:当日成交股数,量增价涨=健康上涨",
|
||
"量比:当日每分钟平均成交量/历史平均,>1.5为放量",
|
||
]),
|
||
("均线系统", [
|
||
"MA5:5日均线,短期趋势",
|
||
"MA10:10日均线",
|
||
"MA20:月线,中期趋势",
|
||
"MA60:季线,重要支撑/压力位",
|
||
"均线多头排列:短>长>短,价格强势",
|
||
"均线空头排列:短<长<短,价格弱势",
|
||
]),
|
||
],
|
||
},
|
||
2: {
|
||
"title": "技术分析框架",
|
||
"items": [
|
||
("MACD", [
|
||
"MACD = 12日EMA - 26日EMA",
|
||
"Signal线 = MACD的9日EMA",
|
||
"金叉:MACD上穿Signal线,看涨信号",
|
||
"死叉:MACD下穿Signal线,看跌信号",
|
||
"柱状图:MACD-Signal线,红柱=多头,绿柱=空头",
|
||
"顶背离:价格新高但MACD没新高,警惕回调",
|
||
"底背离:价格新低但MACD没新低,警惕反弹",
|
||
]),
|
||
("KDJ", [
|
||
"由RSV(未成熟随机值)计算得出",
|
||
"K值:快速指标,对价格敏感",
|
||
"D值:慢速指标,更稳定",
|
||
"J值:3*K-2*D,波动最大",
|
||
"KDJ金叉(K上穿D)+ 在20以下 = 超卖区买入信号",
|
||
"KDJ死叉(K下穿D)+ 在80以上 = 超买区卖出信号",
|
||
]),
|
||
("成交量与价格", [
|
||
"放量上涨:健康,看涨信号",
|
||
"缩量上涨:可能见顶,动力不足",
|
||
"放量下跌:恐慌抛售,可能见底",
|
||
"缩量下跌:观望情绪,可能盘整",
|
||
"地量见地价:极度缩量后可能反转",
|
||
]),
|
||
],
|
||
},
|
||
3: {
|
||
"title": "基本面分析",
|
||
"items": [
|
||
("三张报表", [
|
||
"利润表:展示收入、成本、利润",
|
||
"资产负债表:展示资产、负债、净资产",
|
||
"现金流量表:展示现金流入流出",
|
||
"经营现金流>净利润:利润质量好",
|
||
"商誉过高:警惕减值风险",
|
||
]),
|
||
("估值方法", [
|
||
"PE(市盈率):适合稳定增长的行业",
|
||
"PB(市净率):适合金融、周期行业",
|
||
"PEG = PE/增长率,<1为低估",
|
||
"DCF(现金流折现):适合高确定性企业",
|
||
]),
|
||
],
|
||
},
|
||
4: {
|
||
"title": "小唯量化工具链",
|
||
"items": [
|
||
("数据获取", [
|
||
"akshare:免费,A股数据全面",
|
||
"tushare:需要积分,接口更稳定",
|
||
]),
|
||
("技术指标计算", [
|
||
"pandas/numpy处理行情数据",
|
||
"TA-Lib计算MACD/KDJ/BOLL",
|
||
"matplotlib可视化",
|
||
]),
|
||
],
|
||
},
|
||
5: {
|
||
"title": "模拟交易与策略验证",
|
||
"items": [],
|
||
},
|
||
}
|
||
|
||
|
||
def load_industry_momentum():
|
||
"""读取行业扫描结果(stock_industry_scan.py 生成)"""
|
||
f = HERMES + "/stock_backtest/industry_scan.json"
|
||
if not os.path.exists(f):
|
||
return None
|
||
try:
|
||
return json.load(open(f))
|
||
except Exception:
|
||
return None
|
||
|
||
|
||
def generate_report(progress, topic):
|
||
phase = progress["current_phase"]
|
||
item_idx = progress["current_item"]
|
||
phase_data = PHASES.get(phase, {})
|
||
|
||
report = f"**📈 股票投研体系学习报告**\n"
|
||
report += f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}\n"
|
||
report += f"当前阶段: Phase {phase} - {phase_data.get('title', '完成')}\n\n"
|
||
|
||
# 市场实时情报(2026-08-01 新增:行业动量 + 关注池机会)
|
||
scan = load_industry_momentum()
|
||
if scan and scan.get("industries"):
|
||
report += "**🔭 市场行业动量(学术因子)**\n"
|
||
try:
|
||
mom_map = scan["industries"].get("avg_mom", {})
|
||
ranked = sorted(mom_map.items(), key=lambda kv: kv[1], reverse=True)
|
||
strong = [f"{ind}({mom:+.0%})" for ind, mom in ranked[:3] if mom > 0]
|
||
weak = [f"{ind}({mom:+.0%})" for ind, mom in ranked[-3:]]
|
||
if strong:
|
||
report += f"🟢 强势行业: {' '.join(strong)}\n"
|
||
if weak:
|
||
report += f"🔴 弱势行业: {' '.join(weak)} (金叉硬拦截)\n"
|
||
except Exception:
|
||
pass
|
||
report += "\n"
|
||
|
||
if phase == 5:
|
||
report += "**✅ 理论学习完成,开始模拟交易阶段**\n\n"
|
||
report += "下一步:选择模拟平台(小唯推荐聚宽/掘金),搭建回测环境\n"
|
||
return report
|
||
|
||
items = phase_data.get("items", [])
|
||
total_items = len(items)
|
||
|
||
if item_idx < total_items:
|
||
concept, points = items[item_idx]
|
||
report += f"**本周主题:{concept}**\n"
|
||
for i, p in enumerate(points, 1):
|
||
report += f"{i}. {p}\n"
|
||
report += f"\n📝 进度: {item_idx+1}/{total_items} 个概念\n"
|
||
report += f"阶段进度: {item_idx*100//total_items}%\n"
|
||
else:
|
||
report += f"**阶段 {phase} 完成!**\n"
|
||
report += f"\n✅ 已掌握:\n"
|
||
for concept, points in items:
|
||
report += f" - {concept}\n"
|
||
report += f"\n下一阶段:Phase {phase+1} - {PHASES.get(phase+1, {}).get('title', '完成')}\n"
|
||
report += f"\n回复「下一阶段」推进学习\n"
|
||
|
||
# 历史学习记录
|
||
if progress.get("learning_notes"):
|
||
report += f"\n**📖 学习笔记** ({len(progress['learning_notes'])}条)\n"
|
||
for note in progress["learning_notes"][-3:]:
|
||
report += f" - {note[:60]}\n"
|
||
|
||
return report
|
||
|
||
|
||
if __name__ == "__main__":
|
||
topic = load()
|
||
progress = load_progress()
|
||
|
||
cmd = sys.argv[1] if len(sys.argv) > 1 else "report"
|
||
|
||
if cmd == "report":
|
||
print(generate_report(progress, topic))
|
||
elif cmd == "advance":
|
||
# 推进到下一项或下一阶段
|
||
phase = progress["current_phase"]
|
||
phase_data = PHASES.get(phase, {})
|
||
items = phase_data.get("items", [])
|
||
item_idx = progress["current_item"]
|
||
|
||
if item_idx + 1 < len(items):
|
||
progress["current_item"] += 1
|
||
elif phase + 1 in PHASES:
|
||
progress["current_phase"] = phase + 1
|
||
progress["current_item"] = 0
|
||
else:
|
||
print("全部阶段已完成!")
|
||
sys.exit(0)
|
||
|
||
save_progress(progress)
|
||
print(generate_report(progress, topic))
|
||
elif cmd == "status":
|
||
print(json.dumps(progress, ensure_ascii=False, indent=2))
|
||
else:
|
||
print("用法: stock_learning.py [report|advance|status]") |