-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreview_pk.py
More file actions
139 lines (114 loc) · 6.1 KB
/
Copy pathreview_pk.py
File metadata and controls
139 lines (114 loc) · 6.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Portfolio Performance Review - PK between AI vs User
Date: 2026-05-19 (Tuesday)
"""
import sys
sys.path.insert(0, 'd:/trandingagent/deer-flow/skills/custom/factor-analysis')
from tools.local_data_store import _read_csv, _build_csv_ticker_map
import pandas as pd
AI_PORTFOLIO = {
"600000": {"name": "浦发银行", "allocation": 47500},
"601800": {"name": "中国交建", "allocation": 47500},
"000877": {"name": "天山股份", "allocation": 47500},
"601186": {"name": "中国铁建", "allocation": 47500},
"600373": {"name": "中文传媒", "allocation": 47500},
"600997": {"name": "开滦股份", "allocation": 47500},
"601686": {"name": "友发集团", "allocation": 47500},
"601166": {"name": "兴业银行", "allocation": 47500},
}
USER_PORTFOLIO = {
"002050": {"name": "三花智控", "allocation": 41250},
"002938": {"name": "鹏鼎控股", "allocation": 41250},
"600584": {"name": "长电科技", "allocation": 41250},
"688820": {"name": "盛合晶微", "allocation": 41250},
"688212": {"name": "澳华内镜", "allocation": 50000},
"003031": {"name": "中瓷电子", "allocation": 41250},
"600941": {"name": "中国移动", "allocation": 41250},
"600373": {"name": "中文传媒", "allocation": 41250},
"600406": {"name": "国电南瑞", "allocation": 41250},
}
INITIAL_CAPITAL_AI = sum(p["allocation"] for p in AI_PORTFOLIO.values())
INITIAL_CAPITAL_USER = sum(p["allocation"] for p in USER_PORTFOLIO.values())
def get_latest_price(ticker):
try:
df = _read_csv(ticker)
if df.empty:
return None
df["date"] = pd.to_datetime(df["date"])
df = df.sort_values("date")
return df["close"].iloc[-1]
except Exception as e:
return None
def calculate_portfolio(portfolio, name):
print(f"\n{'='*80}")
print(f" {name}组合")
print(f"{'='*80}")
total_current = 0
total_allocation = 0
details = []
print(f"\n {'股票':<12} {'代码':<8} {'配置(万)':>10} {'现价':>8} {'持仓(股)':>10} {'市值(万)':>10} {'涨跌幅':>10}")
print(f" {'-'*12} {'-'*8} {'-'*10} {'-'*8} {'-'*10} {'-'*10} {'-'*10}")
for ticker, info in portfolio.items():
price = get_latest_price(ticker)
allocation = info["allocation"]
total_allocation += allocation
if price is None:
print(f" {info['name']:<12} {ticker:<8} {allocation/10000:>9.2f}万 {'N/A':>8} {'N/A':>10} {'N/A':>10} {'N/A':>10}")
details.append({"name": info["name"], "ticker": ticker, "allocation": allocation, "price": None, "current_value": 0, "return_pct": None})
else:
shares = int(allocation / price / 100) * 100
current_value = shares * price
total_current += current_value
ret_pct = (price / (allocation / shares) - 1) * 100 if shares > 0 else 0
print(f" {info['name']:<12} {ticker:<8} {allocation/10000:>9.2f}万 {price:>8.2f} {shares:>10} {current_value/10000:>9.2f}万 {ret_pct:>+10.2f}%")
details.append({"name": info["name"], "ticker": ticker, "allocation": allocation, "price": price, "current_value": current_value, "return_pct": ret_pct})
total_return = (total_current / total_allocation - 1) * 100
print(f"\n {'总计':<12} {'':<8} {total_allocation/10000:>9.2f}万 {'':>8} {'':>10} {total_current/10000:>9.2f}万 {total_return:>+10.2f}%")
return {
"total_initial": total_allocation,
"total_current": total_current,
"total_return": total_return,
"details": details
}
def main():
print(f"📊 持仓PK复盘 - 2026-05-19")
print(f"初始日期: 2026-05-17")
print(f"复盘日期: 2026-05-19")
print(f"持股天数: 2天")
ai_result = calculate_portfolio(AI_PORTFOLIO, "🤖 AI (S1纯价值)")
user_result = calculate_portfolio(USER_PORTFOLIO, "👤 用户 (成长+价值混合)")
print(f"\n{'='*80}")
print(f" 🎯 PK结果对比")
print(f"{'='*80}")
print(f"\n {'组合':<20} {'初始资金':>12} {'当前市值':>12} {'收益率':>12}")
print(f" {'-'*20} {'-'*12} {'-'*12} {'-'*12}")
print(f" AI (价值) {'':<9} {ai_result['total_initial']/10000:>11.2f}万 {ai_result['total_current']/10000:>12.2f}万 {ai_result['total_return']:>+12.2f}%")
print(f" 用户 (混合) {'':<7} {user_result['total_initial']/10000:>11.2f}万 {user_result['total_current']/10000:>12.2f}万 {user_result['total_return']:>+12.2f}%")
diff = user_result["total_return"] - ai_result["total_return"]
winner = "用户" if user_result["total_return"] > ai_result["total_return"] else "AI"
print(f"\n 领先: {'用户' if diff > 0 else 'AI'} (+{abs(diff):.2f}%)")
print(f" 当前赢家: {winner} 🎉")
print(f"\n{'='*80}")
print(f" 📈 表现最好的股票")
print(f"{'='*80}")
all_stocks = []
for d in ai_result["details"]:
if d["return_pct"] is not None:
all_stocks.append({"name": d["name"], "ticker": d["ticker"], "return_pct": d["return_pct"], "portfolio": "AI"})
for d in user_result["details"]:
if d["return_pct"] is not None:
all_stocks.append({"name": d["name"], "ticker": d["ticker"], "return_pct": d["return_pct"], "portfolio": "用户"})
all_stocks.sort(key=lambda x: x["return_pct"], reverse=True)
print(f"\n {'排名':<6} {'股票':<12} {'代码':<8} {'所属组合':<8} {'涨幅':>10}")
print(f" {'-'*6} {'-'*12} {'-'*8} {'-'*8} {'-'*10}")
for i, s in enumerate(all_stocks[:5], 1):
print(f" #{i:<5} {s['name']:<12} {s['ticker']:<8} {s['portfolio']:<8} {s['return_pct']:>+10.2f}%")
print(f"\n{'='*80}")
print(f" 📉 表现最差的股票")
print(f"{'='*80}")
all_stocks.sort(key=lambda x: x["return_pct"])
print(f"\n {'排名':<6} {'股票':<12} {'代码':<8} {'所属组合':<8} {'跌幅':>10}")
print(f" {'-'*6} {'-'*12} {'-'*8} {'-'*8} {'-'*10}")
for i, s in enumerate(all_stocks[:5], 1):
print(f" #{i:<5} {s['name']:<12} {s['ticker']:<8} {s['portfolio']:<8} {s['return_pct']:>+10.2f}%")
if __name__ == "__main__":
main()