自选正反自动同步
clean_watchlist.py 双向: 买入→持仓→移出自选 ✅ (已完成) 清仓→自动加回自选 ✅ (新增) 每日09:05 cron自动执行
This commit is contained in:
@@ -28,36 +28,6 @@
|
|||||||
"take_profit_zone": "0~49.62"
|
"take_profit_zone": "0~49.62"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "01888",
|
|
||||||
"name": "建滔积层板",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "01088",
|
|
||||||
"name": "中国神华",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "01211",
|
|
||||||
"name": "比亚迪股份",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"code": "002594",
|
"code": "002594",
|
||||||
"name": "比亚迪",
|
"name": "比亚迪",
|
||||||
@@ -254,16 +224,6 @@
|
|||||||
"take_profit_zone": "0~2.13"
|
"take_profit_zone": "0~2.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "06869",
|
|
||||||
"name": "长飞光纤",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"code": "02318",
|
"code": "02318",
|
||||||
"name": "中国平安",
|
"name": "中国平安",
|
||||||
@@ -292,26 +252,6 @@
|
|||||||
"take_profit_zone": "0~59.32"
|
"take_profit_zone": "0~59.32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "688639",
|
|
||||||
"name": "华恒生物",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "300548",
|
|
||||||
"name": "博创科技",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"code": "300124",
|
"code": "300124",
|
||||||
"name": "汇川技术",
|
"name": "汇川技术",
|
||||||
@@ -396,46 +336,6 @@
|
|||||||
"take_profit_zone": "0~94.69"
|
"take_profit_zone": "0~94.69"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "00700",
|
|
||||||
"name": "腾讯控股",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "02202",
|
|
||||||
"name": "万科企业",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "688981",
|
|
||||||
"name": "中芯国际",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "01478",
|
|
||||||
"name": "丘钛科技",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"code": "001309",
|
"code": "001309",
|
||||||
"name": "德明利",
|
"name": "德明利",
|
||||||
@@ -492,26 +392,6 @@
|
|||||||
"take_profit_zone": "0~180.44"
|
"take_profit_zone": "0~180.44"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "688411",
|
|
||||||
"name": "海博思创",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "000700",
|
|
||||||
"name": "模塑科技",
|
|
||||||
"added_at": "2026-06-21 02:51:30",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"code": "000711",
|
"code": "000711",
|
||||||
"name": "ST京蓝",
|
"name": "ST京蓝",
|
||||||
@@ -596,16 +476,6 @@
|
|||||||
"take_profit_zone": "0~113.41"
|
"take_profit_zone": "0~113.41"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "300308",
|
|
||||||
"name": "中际旭创",
|
|
||||||
"added_at": "2026-06-22 09:22:26",
|
|
||||||
"stop_loss": null,
|
|
||||||
"take_profit": null,
|
|
||||||
"entry_low": null,
|
|
||||||
"entry_high": null,
|
|
||||||
"action": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"code": "600519",
|
"code": "600519",
|
||||||
"name": "贵州茅台",
|
"name": "贵州茅台",
|
||||||
|
|||||||
@@ -54,4 +54,47 @@ if dec_changed:
|
|||||||
else:
|
else:
|
||||||
print(f"\ndecisions.json: 无需更新")
|
print(f"\ndecisions.json: 无需更新")
|
||||||
|
|
||||||
|
# ── 反过程:清仓股自动加回自选 ──
|
||||||
|
# 找出曾持仓但现已不在 portfolio 的股票
|
||||||
|
prev_held = {} # code → last_execution info
|
||||||
|
for d in dec.get("decisions", []):
|
||||||
|
code = d.get("code", "")
|
||||||
|
exec_info = d.get("execution", {})
|
||||||
|
if exec_info and exec_info.get("status") in ("executing", "partial_exit"):
|
||||||
|
# 当前仍持仓但不在 portfolio?说明 portfolio 数据落后,跳过
|
||||||
|
pass
|
||||||
|
elif exec_info and exec_info.get("status") in ("sold", "closed") and code not in holding_codes:
|
||||||
|
prev_held[code] = {
|
||||||
|
"name": d.get("name", code),
|
||||||
|
"entry_low": d.get("entry_low", 0),
|
||||||
|
"entry_high": d.get("entry_high", 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev_held:
|
||||||
|
wl_stock_codes = set(s.get("code", "") for s in new_stocks)
|
||||||
|
added = 0
|
||||||
|
for code, info in sorted(prev_held.items()):
|
||||||
|
if code not in wl_stock_codes and code not in holding_codes:
|
||||||
|
# 确保买入区有值
|
||||||
|
entry_low = info.get("entry_low", 0) or 0
|
||||||
|
entry_high = info.get("entry_high", 0) or 0
|
||||||
|
new_stocks.append({
|
||||||
|
"code": code,
|
||||||
|
"name": info["name"],
|
||||||
|
"entry_low": entry_low,
|
||||||
|
"entry_high": entry_high,
|
||||||
|
"stop_loss": 0,
|
||||||
|
"tag": "recovered_from_sold",
|
||||||
|
})
|
||||||
|
added += 1
|
||||||
|
print(f" ← 已清仓→加回自选: {code} {info['name']}")
|
||||||
|
if added:
|
||||||
|
wl["stocks"] = new_stocks
|
||||||
|
json.dump(wl, open(WL, "w"), indent=2, ensure_ascii=False)
|
||||||
|
print(f"\n反过程: {added} 只清仓股已加回自选")
|
||||||
|
else:
|
||||||
|
print("\n反过程: 无清仓股需加回")
|
||||||
|
else:
|
||||||
|
print("\n反过程: 无已清仓记录")
|
||||||
|
|
||||||
print("\nDONE")
|
print("\nDONE")
|
||||||
|
|||||||
Reference in New Issue
Block a user