新增建材价格指数趋势监控仪表盘

This commit is contained in:
fish
2026-07-24 12:01:08 +08:00
parent 4b4469528f
commit f6c54971e4
3 changed files with 585 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
"""拉取建材价格指数,更新 data.json 并刷新 index.html。"""
import json
import pandas as pd
import akshare as ak
df = ak.macro_china_construction_index()
df['日期'] = pd.to_datetime(df['日期'])
df = df.sort_values('日期').reset_index(drop=True)
for w in [5, 10, 20, 60]:
df[f'MA{w}'] = df['最新值'].rolling(w).mean().round(1)
df[f'MA{w}_dir'] = df[f'MA{w}'].diff().apply(lambda x: 'up' if x > 0 else ('down' if x < 0 else 'flat'))
latest = df.iloc[-1]
signals = []
if latest['最新值'] > latest['MA5']:
signals.append(('短期', '偏多', '价格 > MA5'))
else:
signals.append(('短期', '偏空', '价格 < MA5'))
if latest['MA5'] > latest['MA20']:
signals.append(('中期', '偏多', 'MA5 > MA20'))
else:
signals.append(('中期', '偏空', 'MA5 < MA20'))
if latest['MA20'] > latest['MA60']:
signals.append(('长期', '偏多', 'MA20 > MA60'))
else:
signals.append(('长期', '偏空', 'MA20 < MA60'))
momentum_5d = latest['最新值'] - df.iloc[-6]['最新值']
signals.append(('动量(5日)', '偏多' if momentum_5d > 0 else '偏空', f"{momentum_5d:+d}"))
bull_count = sum(1 for _, s, _ in signals if s == '偏多')
if bull_count >= 3:
overall = ('偏多', '#16a34a')
elif bull_count <= 1:
overall = ('偏空', '#dc2626')
else:
overall = ('震荡', '#d97706')
summary = {
'date': latest['日期'].strftime('%Y-%m-%d'),
'value': int(latest['最新值']),
'change': round(float(latest['涨跌幅']), 4),
'chg_3m': round(float(latest['近3月涨跌幅']), 4),
'chg_6m': round(float(latest['近6月涨跌幅']), 4),
'chg_1y': round(float(latest['近1年涨跌幅']), 4),
}
mas = {}
for w in [5, 10, 20, 60]:
mas[f'MA{w}'] = {
'value': float(latest[f'MA{w}']),
'direction': latest[f'MA{w}_dir'],
'price_vs_ma': 'above' if latest['最新值'] > latest[f'MA{w}'] else 'below'
}
rows = []
for _, r in df.tail(30).iterrows():
rows.append({
'date': r['日期'].strftime('%m-%d'),
'value': int(r['最新值']),
'chg': round(float(r['涨跌幅']), 4),
'MA5': None if pd.isna(r['MA5']) else round(float(r['MA5']), 1),
'MA20': None if pd.isna(r['MA20']) else round(float(r['MA20']), 1),
'MA60': None if pd.isna(r['MA60']) else round(float(r['MA60']), 1),
})
output = {
'summary': summary,
'mas': mas,
'signals': [{'period': p, 'signal': s, 'detail': d} for p, s, d in signals],
'overall': {'signal': overall[0], 'color': overall[1]},
'recent': rows,
}
with open('data.json', 'w') as f:
json.dump(output, f, ensure_ascii=False, indent=2)
SENTINEL = '/*__DATA_SENTINEL__*/{}'
html = open('index.html').read()
html = html.replace(SENTINEL, json.dumps(output, ensure_ascii=False))
open('index.html', 'w').write(html)
print(f"刷新完成: {summary['date']}{summary['value']} (日涨跌 {summary['change']:+.2f}%)")
print(f"综合信号: {overall[0]}")
print("信号明细:")
for p, s, d in signals:
print(f" {p}: {s} ({d})")