现金更正 + 法拉电子清仓记录

截图确认:
- 可用资金 92,664.20(含天添利)
- 冻结 39,481.40
- 总现金 132,145.60
- 总资产 = 持仓市值1,107,670 + 现金132,145.60 = 1,239,815.60

法拉电子 189.20卖出100股已记录
This commit is contained in:
知微
2026-06-29 12:40:50 +08:00
parent 13b4dcbcf0
commit 6a97d93018
34 changed files with 14336 additions and 30071 deletions
+12 -3
View File
@@ -5,11 +5,13 @@ import_holding_xls.py — 从 holding.xls 导入持仓到全系统
用法:
python3 import_holding_xls.py [--cash 现金] [--total 总资产] [--mv 市值]
--cash 必传!holding文件不含现金行,不传则现金=0。
不传 --total/--mv 则从 holding.xls 计算(可能有价格时差误差)。
建议传截图上的真实数字。
示例:
python3 import_holding_xls.py --cash 20230.10 --total 1008860.62 --mv 988512.96
python3 import_holding_xls.py --cash 73758.0 --total 874598.90 --mv 800840.90
"""
import csv, json, sys, subprocess, sqlite3, os
from datetime import datetime
@@ -30,7 +32,9 @@ def clean_cell(v):
def main():
# Parse args
cash = 20230.10
# ⚠️ 现金不从holding文件读取。holding只有股票持仓,现金必须单独提供(截图)。
# 不传 --cash 则默认为0,会在后面警告。
cash = 0.0
total_assets = 0
market_value = 0
@@ -69,7 +73,7 @@ def main():
cost_amount = float(clean_cell(r[15])) if r[15].strip() and r[15].strip() != '--' else 0
rate_str = clean_cell(r[16])
rate = float(rate_str) if rate_str and rate_str != '--' else 0.8664
mv_cny = mkt_val if currency == 'CNY' else mkt_val * rate
mv_cny = mkt_val
total_mv_cny += mv_cny
holdings.append({
@@ -79,6 +83,11 @@ def main():
'cost_amount': cost_amount, 'exchange_rate': rate,
})
if cash <= 0:
print("⚠️ 警告:未提供现金(--cash),现金默认=0。Dad可能给了截图现金数!")
print(" holding文件不含现金行,必须手动提供。可以用:")
print(f" python3 import_holding_xls.py --cash 73758.0")
# Use provided values or calculate
if total_assets <= 0:
total_assets = total_mv_cny + cash
+65 -19
View File
@@ -71,25 +71,61 @@ def check_xiaoguo():
check_http("http://192.168.1.122:18003/v1/models")
PORTFOLIO_PATH = str(DATA / "portfolio.json")
def check_price_monitor():
"""价格监控:进程在跑 + 最近有数据"""
# 进程检查
r = subprocess.run(["pgrep", "-f", "price_monitor"], capture_output=True, timeout=5)
process_alive = r.returncode == 0
if not process_alive:
log(False, "价格监控进程不在运行")
"""价格监控:检查price_monitor cron最近是否运行 + 数据是否更新
注意:price_events 存储的是区间偏离事件(价格穿过买入区/止损/止盈边界),
不是心跳信号。横盘期/无操作信号时自然不会有新事件。因此不检查event数,
改为检查 cron 最后运行时间和 portfolio.json 数据新鲜度。
"""
# 检查cron最近运行记录
cron_ok = False
try:
with open(str(CRON_JOBS)) as f:
data = json.load(f)
jobs_list = data.get("jobs", []) if isinstance(data.get("jobs"), list) else []
if not jobs_list:
jobs_list = list(data.get("jobs", {}).values())
for job in jobs_list:
if not job:
continue
script = job.get("script") or ""
name = job.get("name") or ""
if "price_monitor" in script or "价格监控" in name:
last_run = job.get("last_run_at")
if last_run:
last_dt = datetime.fromisoformat(last_run)
# 兼容带时区和无时区两种格式
ref_now = datetime.now(last_dt.tzinfo) if last_dt.tzinfo else datetime.now()
elapsed = (ref_now - last_dt).total_seconds()
if elapsed < 600: # 10分钟内运行过
cron_ok = True
break
except Exception:
pass
if not cron_ok:
log(False, "价格监控cron无最近运行记录(>10分钟未运行)")
return
# 数据新鲜度(最近10分钟是否有事件)
# 检查portfolio.json数据新鲜度
try:
conn = sqlite3.connect(str(DB_PATH))
recent = conn.execute(
"SELECT COUNT(*) FROM price_events WHERE created_at > datetime('now', '-10 minutes')"
).fetchone()[0]
conn.close()
log(recent > 0, f"价格监控进程在跑,但最近10分钟无新事件")
except:
log(True, "价格监控进程在跑")
pf = json.load(open(PORTFOLIO_PATH))
pf_updated = pf.get("updated_at", "")
if pf_updated:
pf_dt = datetime.strptime(pf_updated, "%Y-%m-%d %H:%M")
seconds_ago = (datetime.now() - pf_dt).total_seconds()
if seconds_ago < 600: # 10分钟内
log(True, f"价格监控运行正常,数据{int(seconds_ago//60)}分钟前更新")
else:
log(False, f"价格数据{int(seconds_ago)}秒未更新(portfolio.json")
else:
log(False, "portfolio.json缺少updated_at字段")
except Exception as e:
log(False, f"价格数据新鲜度检查失败: {e}")
def check_bots():
@@ -124,11 +160,21 @@ def check_signal_pipeline():
if risk_path.exists():
risk = json.loads(risk_path.read_text())
level = risk.get("level", "none")
reason = risk.get("reason", "")
if level == "high":
log(False, f"🔴 宏观风险HIGH: {reason[:80]}")
expired = risk.get("expired", False)
# 提取摘要做原因描述(state.json用signals数组,不是reason字段)
signals = risk.get("signals", [])
reason = ""
if signals and isinstance(signals, list) and len(signals) > 0:
first_sig = signals[0]
summary = first_sig.get("summary", "")
if summary:
reason = summary[:80].replace("\n", " ")
if level == "high" and not expired:
log(False, f"🔴 宏观风险HIGH: {reason}")
elif level == "high" and expired:
log(True, f"⏳ 宏观风险HIGH已过期(无新信号超过15分钟)")
elif level == "medium":
log(True, f"⚠️ 宏观风险MEDIUM: {reason[:80]}")
log(True, f"⚠️ 宏观风险MEDIUM: {reason}")
else:
log(True, "无宏观风险状态文件(可能未生成)")
except:
+9 -7
View File
@@ -29,30 +29,32 @@ STATE_PATH = DATA_DIR / "macro_risk_state.json"
# HIGH: 任何一条匹配 → 立即 HIGH 预警
HIGH_PATTERNS = [
# 全球巨头+核心产业
r"苹果.*(?:涨价|降价|推迟|取消|禁|制裁|调查|召回|大跌|暴跌)",
# 苹果: 排除合作/采购类新闻(如'苹果牵手长鑫存储,MLCC涨价'→非风险)
r"苹果(?!.*?(?:牵手|合作|联合|携手|助力|入驻|投资|设立|引入)).*?(?:涨价|降价|推迟|取消|禁|制裁|调查|召回|大跌|暴跌)",
r"openai.*(?:推迟|取消|风险|调查|起诉|倒闭|ipo)",
r"英伟达|nvidia.*(?:跌|调查|制裁|推迟|禁令)",
r"(?:英伟达|nvidia).*(?:跌|调查|制裁|推迟|禁令)",
r"台积电.*(?:跌|推迟|取消|地震|火灾|禁)",
r"特斯拉.*(?:暴跌|召回|调查|破产|禁)",
# 美联储/央行意外
r"美联储.*(?:意外|紧急|缩表|风暴|警告|超预期|加息\s*50|降息\s*50|紧急\s*(?:会议|声明))",
r"美联储.*(?:利率|决议).*(?:超预期|意外|紧急)",
r"fed.*(?:emergency|unexpected|surprise|hike|cut)",
# 指数暴跌
r"指数.*(?:跌幅|暴跌|熔断|闪崩|重挫)",
r"(?:暴跌|重挫|熔断).*[5-9]%",
# 指数暴跌(针对主要指数,避免'板块指数跌幅居前'等非风险匹配)
r"(?:上证|深证|创业板|科创|恒生指数|恒指|日经|KOSPI|道指|纳指|标普500|沪深300).*(?:暴跌|重挫|熔断|闪崩|跳水|跌幅(?!.*?居前))",
r"指数.*(?:暴跌|熔断|闪崩)",
r"熔断|闪崩",
# 地缘+贸易
r"关税.*(?:升级|新|报复|制裁)",
r"制裁.*(?:新|升级|全面)",
r"战争|开战|入侵|核|导弹.*发射",
# 战争/地缘: 移除过宽的'核'/'战争'独立匹配,避免'核聚变''硬核科技''核心''贸易战'误触
r"(?:地缘|边境|朝鲜|伊朗).*(?:冲突|风险|升级|紧张|军事行动|交火)|开战|开火|空袭|轰炸|入侵|击落|军事(?:冲突|行动|升级|打击|对抗|演习|部署)|核(?:威胁|武器|弹头|试验|攻击|冲突|导弹|战争|潜艇|问题|危机|设施)|导弹.*(?:发射|试射|打击)",
# 系统性能源
r"原油.*(?:跌破|暴跌|崩盘|断供)",
r"石油.*(?:禁运|制裁|断供)",
r"能源危机|粮食危机",
# 系统金融
r"银行.*(?:倒闭|挤兑|破产|接管|危机)",
r"金融危机|债务危机|违约潮|系统性",
r"金融危机|债务危机|违约潮|系统性(?:风险|危机|金融|下跌|崩塌)",
# AI/科技板块重挫
r"半导体.*(?:暴跌|熔断|崩盘|跌幅)",
r"科技股.*(?:暴跌|熔断|崩盘|重挫)",
+4
View File
@@ -708,6 +708,7 @@ def main():
sig = d.get("timing_signal", "")
sector = d.get("sector_context", "")
tech = d.get("tech_snapshot", "")
mtf_ctx = d.get("multi_tf_context", "")
note = d.get("note", "")
d_factors = d.get("signal_factors", [])
cat = d.get("stock_category", "")
@@ -807,6 +808,9 @@ def main():
f" 仓位:理论{theo_pct}%×总资产 | 建议{actual_pct}%{details}"
)
if mtf_ctx:
lines[-1] += f"\n 均线{mtf_ctx}"
if swap_text:
lines[-1] += f"\n {swap_text}"