e728dcd226
① D11 HTML 报告 RustFS 单源化(TECH_DEBT P2 清偿):可视化产物写任务临时目录后
裸传报告键 html/reports/{filename}(文件名寻址),/html StaticFiles 挂载删除,
新增 html_report_router 根路径代理(报告键→遗留 JSON 包装→本地卷兜底→404,
防穿越);URL 形状 /html/{filename} 不变,持久化引用零迁移;celery 摘除
html_data 卷,镜像不再烤入陈旧报告;顺带删除 get_stp_file_with_data 死数据块
② OCC 方案 B(D10 清偿):run_occ(op_name, payload) 契约 + 常驻工作进程池
(occ_process_pool + occ_worker 操作注册表),超时/崩溃 terminate 换新补位、
任务级超时 recover 整体重建,残留线程泄漏根治;TopoDS 不跨进程(generate_cavity
分模 + 方案 STEP 持久化全在子进程内,返回 export_manifest);删除内存形状缓存链、
CADExporter.export_mold_results、shape_loader(→ stp_materializer)
③ OCC 方案 A 部署参数:CELERY_CONCURRENCY / CELERY_MAX_TASKS_PER_CHILD 进
Dockerfile.celery + compose + .env.example
④ D2 诚实标注:铝价响应带 source: "simulated",前端按来源渲染标注(原硬编码
"上海期货交易所"属虚假声明),死代码 getAluminumPrice 删除
⑤ CI 门禁:.gitea/workflows/ci.yml 三 job(pytest / 前端构建含 vue-tsc /
openapi 漂移检测)
接口变更三件套随批完成(openapi 76→77 paths + gen:api + 前端构建通过;方案 B
接口面零变化)。测试基线 143 passed, 0 skipped(新增 16 项)。文档六处同步。
Co-Authored-By: Claude Code <noreply@anthropic.com>
98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
"""
|
|
铝金属价格数据服务
|
|
|
|
提供铝金属的当前价格和历史价格走势数据。
|
|
数据来源优先级:
|
|
1. 外部API(预留接口)
|
|
2. 模拟真实走势数据(当前使用)
|
|
|
|
数据基于上海期货交易所(SHFE)铝期货价格走势特征生成。
|
|
"""
|
|
import random
|
|
import hashlib
|
|
from datetime import datetime, timedelta
|
|
from typing import List, Dict, Optional
|
|
|
|
|
|
BASE_PRICE = 18950.0
|
|
PRICE_VOLATILITY = 120.0
|
|
TREND_DRIFT = 0.3
|
|
|
|
|
|
def _daily_seed(date_str: str) -> float:
|
|
h = hashlib.md5(date_str.encode()).hexdigest()
|
|
seed = int(h[:8], 16) / (16 ** 8)
|
|
return seed
|
|
|
|
|
|
def get_aluminum_current_price() -> Dict:
|
|
today = datetime.now().strftime("%Y-%m-%d")
|
|
seed = _daily_seed(today)
|
|
random.seed(int(seed * 1_000_000))
|
|
|
|
price = BASE_PRICE + (seed - 0.5) * PRICE_VOLATILITY * 2
|
|
price = round(price, 0)
|
|
|
|
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
|
|
prev_seed = _daily_seed(yesterday)
|
|
prev_price = BASE_PRICE + (prev_seed - 0.5) * PRICE_VOLATILITY * 2
|
|
prev_price = round(prev_price, 0)
|
|
|
|
change = price - prev_price
|
|
change_percent = round((change / prev_price) * 100, 2)
|
|
|
|
week_ago = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
|
|
week_seed = _daily_seed(week_ago)
|
|
week_price = BASE_PRICE + (week_seed - 0.5) * PRICE_VOLATILITY * 2
|
|
|
|
random.seed()
|
|
|
|
return {
|
|
"price": price,
|
|
"unit": "元/吨",
|
|
"currency": "CNY",
|
|
"date": today,
|
|
"change": round(change, 0),
|
|
"change_percent": change_percent,
|
|
"open": round(price - random.uniform(10, 50), 0),
|
|
"high": round(price + random.uniform(10, 60), 0),
|
|
"low": round(price - random.uniform(10, 60), 0),
|
|
"prev_close": prev_price,
|
|
"week_ago_price": round(week_price, 0),
|
|
# D2:数据为模拟走势(见模块 docstring),必须显式声明来源,
|
|
# 前端按此字段展示"模拟/参考"标注,防止被当作实时行情
|
|
"source": "simulated",
|
|
}
|
|
|
|
|
|
def get_aluminum_price_history(days: int = 30) -> List[Dict]:
|
|
history = []
|
|
random.seed(42)
|
|
|
|
price_line = BASE_PRICE
|
|
for i in range(days, -1, -1):
|
|
date = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
|
|
date_seed = _daily_seed(date)
|
|
|
|
drift = (date_seed - 0.5) * TREND_DRIFT
|
|
noise = (date_seed - 0.5) * PRICE_VOLATILITY * 1.5
|
|
price_line = price_line + drift + noise * 0.3
|
|
price_line = max(18200, min(19800, price_line))
|
|
|
|
open_price = round(price_line + (date_seed - 0.5) * 80, 0)
|
|
high_price = round(open_price + abs(date_seed - 0.5) * 160, 0)
|
|
low_price = round(open_price - abs(date_seed - 0.5) * 140, 0)
|
|
close_price = round(price_line, 0)
|
|
|
|
history.append({
|
|
"date": date,
|
|
"open": open_price,
|
|
"high": high_price,
|
|
"low": low_price,
|
|
"close": close_price,
|
|
"source": "simulated", # D2:与 current 一致,逐项显式声明模拟来源
|
|
})
|
|
|
|
random.seed()
|
|
return history
|