v1.7.0: 每日定时报告(工作日9:00盘前分析/15:30盘后总结) - 全球市场数据+报告引擎(简版邮件正文+详细版HTML附件)+cron定时+手动触发+发送日志; 修复模拟数据换手率失真

This commit is contained in:
2026-08-20 00:08:39 +08:00
parent 7d8ed3d7de
commit adc54d509f
8 changed files with 631 additions and 6 deletions
+32 -2
View File
@@ -15,6 +15,7 @@
"""
import argparse
import datetime as dt
import json
import math
import random
import sys
@@ -238,7 +239,8 @@ def gen_daily(dates):
drift = {0: 0.0011, 1: 0.00025, 2: -0.00085}[trend]
# 最近30天加速(制造趋势分化,让荐股有区分度)
recent_drift = {0: 0.0045, 1: 0.0001, 2: -0.0045}[trend]
base_vol = float_shares * 10000 * random.uniform(0.8, 2.2) # 基准成交量(万股)
# 基准成交量(万股= 流通盘 × 0.4%~1.5% 日换手(贴近真实市场
base_vol = float_shares * 10000 * random.uniform(0.004, 0.015)
for i, d in enumerate(dates):
phase = max(0, i - (len(dates) - 30))
dr = drift + (recent_drift if phase > 0 else 0)
@@ -250,7 +252,7 @@ def gen_daily(dates):
open_p = prev * (1 + random.gauss(0, vol * 0.5))
high = max(open_p, p) * (1 + abs(random.gauss(0, vol * 0.35)))
low = min(open_p, p) * (1 - abs(random.gauss(0, vol * 0.35)))
volume = base_vol * (1 + 3 * abs(r) / vol) * random.uniform(0.6, 1.4)
volume = base_vol * (1 + 1.5 * abs(r) / vol) * random.uniform(0.6, 1.4)
amount = volume * (open_p + p) / 2 # 万元
chg = (p - prev) / prev * 100
daily.append((code, d, round(open_p, 2), round(high, 2), round(low, 2),
@@ -339,6 +341,30 @@ def _recent_days(n):
return dates
GLOBAL_INDICES = [
("dji", "道琼斯", 34000), ("nasdaq", "纳斯达克", 12800), ("sp500", "标普500", 4400),
("hsi", "恒生指数", 17500), ("nikkei", "日经225", 33000), ("kospi", "韩国KOSPI", 2500),
("dax", "德国DAX", 16000), ("cac", "法国CAC40", 7000), ("ftse", "英国FTSE100", 7500),
]
def _gen_global(dates):
"""生成全球主要指数模拟序列(随机游走,chg 基于前一交易日)"""
vals = {k: v for k, _, v in GLOBAL_INDICES}
prev = dict(vals)
out = {}
for d in dates:
row = {}
for k, label, _v in GLOBAL_INDICES:
vals[k] *= (1 + random.gauss(0.0002, 0.009))
row[k] = {"label": label, "value": round(vals[k], 2),
"chg": round((vals[k] - prev[k]) / prev[k] * 100, 2)}
for k in prev:
prev[k] = vals[k]
out[d] = row
return out
def gen_holdings(price, dates):
"""基金季度持仓:2025Q4 / 2026Q1 / 2026Q2"""
rows = []
@@ -424,6 +450,10 @@ def main():
"VALUES(?,?,?,?,?,?,?,?,?)", daily)
executemany("INSERT OR REPLACE INTO market_index(date,sh,sz,cy) VALUES(?,?,?,?)",
[(d, v["sh"], v["sz"], v["cy"]) for d, v in index.items()])
# 全球市场指数(模拟)
gm = _gen_global(dates)
executemany("INSERT OR REPLACE INTO global_markets(date,data) VALUES(?,?)",
[(d, json.dumps(v, ensure_ascii=False)) for d, v in gm.items()])
# 回填市值
for code, name, industry, board, base, fs, trend, vol, biz in STOCKS:
from database import execute as ex