feat: 增加不同地区各渠道收入占比图

This commit is contained in:
R524809
2026-09-08 16:53:44 +08:00
parent 44c6437b64
commit bab02e1efd
25 changed files with 888 additions and 29 deletions
+76
View File
@@ -0,0 +1,76 @@
year,company,shares
1988,大都会/ABC(Capital Cities/ABC),3000000
1988,房地美(Freddie Mac),2400000
1988,盖可保险(GEICO),6850000
1988,华盛顿邮报(Washington Post),1727765
1988,可口可乐(Coca-Cola),14172500
1989,大都会/ABC(Capital Cities/ABC),3000000
1989,房地美(Freddie Mac),2400000
1989,盖可保险(GEICO),6850000
1989,华盛顿邮报(Washington Post),1727765
1989,可口可乐(Coca-Cola),23350000
1990,大都会/ABC(Capital Cities/ABC),3000000
1990,房地美(Freddie Mac),2400000
1990,富国银行(Wells Fargo),5000000
1990,盖可保险(GEICO),6850000
1990,华盛顿邮报(Washington Post),1727765
1990,可口可乐(Coca-Cola),46700000
1991,大都会/ABC(Capital Cities/ABC),3000000
1991,房地美(Freddie Mac),2495200
1991,富国银行(Wells Fargo),5000000
1991,盖可保险(GEICO),6850000
1991,华盛顿邮报(Washington Post),1727765
1991,吉列(Gillette),24000000
1991,健力士(Guinness),31247000
1991,可口可乐(Coca-Cola),46700000
1992,大都会/ABC(Capital Cities/ABC),3000000
1992,房地美(Freddie Mac),16196700
1992,富国银行(Wells Fargo),6358418
1992,盖可保险(GEICO),34250000
1992,华盛顿邮报(Washington Post),1727765
1992,吉列(Gillette),24000000
1992,健力士(Guinness),38335000
1992,可口可乐(Coca-Cola),93400000
1992,通用动力(General Dynamics),4350000
1993,大都会/ABC(Capital Cities/ABC),2000000
1993,房地美(Freddie Mac),13654600
1993,富国银行(Wells Fargo),6791218
1993,盖可保险(GEICO),34250000
1993,华盛顿邮报(Washington Post),1727765
1993,吉列(Gillette),24000000
1993,健力士(Guinness),38335000
1993,可口可乐(Coca-Cola),93400000
1993,通用动力(General Dynamics),4350000
1994,大都会/ABC(Capital Cities/ABC),20000000
1994,房地美(Freddie Mac),12761200
1994,富国银行(Wells Fargo),6791218
1994,盖可保险(GEICO),34250000
1994,甘尼特(Gannett),6854500
1994,华盛顿邮报(Washington Post),1727765
1994,吉列(Gillette),24000000
1994,可口可乐(Coca-Cola),100000000
1994,美国运通(American Express),27759941
1994,PNC 银行(PNC Bank),19453300
1995,大都会/ABC(Capital Cities/ABC),20000000
1995,房地美(Freddie Mac),12502500
1995,富国银行(Wells Fargo),6791218
1995,盖可保险(GEICO),34250000
1995,吉列(Gillette),48000000
1995,可口可乐(Coca-Cola),100000000
1995,美国运通(American Express),49456900
1996,房地美(Freddie Mac),64246000
1996,富国银行(Wells Fargo),7291418
1996,华盛顿邮报(Washington Post),1727765
1996,华特迪士尼(Walt Disney),24614214
1996,吉列(Gillette),48000000
1996,可口可乐(Coca-Cola),200000000
1996,麦当劳(McDonald's),30156600
1996,美国运通(American Express),49456900
1997,房地美(Freddie Mac),63977600
1997,富国银行(Wells Fargo),6690218
1997,华盛顿邮报(Washington Post),1727765
1997,华特迪士尼(Walt Disney),21563414
1997,吉列(Gillette),48000000
1997,可口可乐(Coca-Cola),200000000
1997,旅行家集团(Travelers Group),23733198
1997,美国运通(American Express),49456900
1 year company shares
2 1988 大都会/ABC(Capital Cities/ABC) 3000000
3 1988 房地美(Freddie Mac) 2400000
4 1988 盖可保险(GEICO) 6850000
5 1988 华盛顿邮报(Washington Post) 1727765
6 1988 可口可乐(Coca-Cola) 14172500
7 1989 大都会/ABC(Capital Cities/ABC) 3000000
8 1989 房地美(Freddie Mac) 2400000
9 1989 盖可保险(GEICO) 6850000
10 1989 华盛顿邮报(Washington Post) 1727765
11 1989 可口可乐(Coca-Cola) 23350000
12 1990 大都会/ABC(Capital Cities/ABC) 3000000
13 1990 房地美(Freddie Mac) 2400000
14 1990 富国银行(Wells Fargo) 5000000
15 1990 盖可保险(GEICO) 6850000
16 1990 华盛顿邮报(Washington Post) 1727765
17 1990 可口可乐(Coca-Cola) 46700000
18 1991 大都会/ABC(Capital Cities/ABC) 3000000
19 1991 房地美(Freddie Mac) 2495200
20 1991 富国银行(Wells Fargo) 5000000
21 1991 盖可保险(GEICO) 6850000
22 1991 华盛顿邮报(Washington Post) 1727765
23 1991 吉列(Gillette) 24000000
24 1991 健力士(Guinness) 31247000
25 1991 可口可乐(Coca-Cola) 46700000
26 1992 大都会/ABC(Capital Cities/ABC) 3000000
27 1992 房地美(Freddie Mac) 16196700
28 1992 富国银行(Wells Fargo) 6358418
29 1992 盖可保险(GEICO) 34250000
30 1992 华盛顿邮报(Washington Post) 1727765
31 1992 吉列(Gillette) 24000000
32 1992 健力士(Guinness) 38335000
33 1992 可口可乐(Coca-Cola) 93400000
34 1992 通用动力(General Dynamics) 4350000
35 1993 大都会/ABC(Capital Cities/ABC) 2000000
36 1993 房地美(Freddie Mac) 13654600
37 1993 富国银行(Wells Fargo) 6791218
38 1993 盖可保险(GEICO) 34250000
39 1993 华盛顿邮报(Washington Post) 1727765
40 1993 吉列(Gillette) 24000000
41 1993 健力士(Guinness) 38335000
42 1993 可口可乐(Coca-Cola) 93400000
43 1993 通用动力(General Dynamics) 4350000
44 1994 大都会/ABC(Capital Cities/ABC) 20000000
45 1994 房地美(Freddie Mac) 12761200
46 1994 富国银行(Wells Fargo) 6791218
47 1994 盖可保险(GEICO) 34250000
48 1994 甘尼特(Gannett) 6854500
49 1994 华盛顿邮报(Washington Post) 1727765
50 1994 吉列(Gillette) 24000000
51 1994 可口可乐(Coca-Cola) 100000000
52 1994 美国运通(American Express) 27759941
53 1994 PNC 银行(PNC Bank) 19453300
54 1995 大都会/ABC(Capital Cities/ABC) 20000000
55 1995 房地美(Freddie Mac) 12502500
56 1995 富国银行(Wells Fargo) 6791218
57 1995 盖可保险(GEICO) 34250000
58 1995 吉列(Gillette) 48000000
59 1995 可口可乐(Coca-Cola) 100000000
60 1995 美国运通(American Express) 49456900
61 1996 房地美(Freddie Mac) 64246000
62 1996 富国银行(Wells Fargo) 7291418
63 1996 华盛顿邮报(Washington Post) 1727765
64 1996 华特迪士尼(Walt Disney) 24614214
65 1996 吉列(Gillette) 48000000
66 1996 可口可乐(Coca-Cola) 200000000
67 1996 麦当劳(McDonald's) 30156600
68 1996 美国运通(American Express) 49456900
69 1997 房地美(Freddie Mac) 63977600
70 1997 富国银行(Wells Fargo) 6690218
71 1997 华盛顿邮报(Washington Post) 1727765
72 1997 华特迪士尼(Walt Disney) 21563414
73 1997 吉列(Gillette) 48000000
74 1997 可口可乐(Coca-Cola) 200000000
75 1997 旅行家集团(Travelers Group) 23733198
76 1997 美国运通(American Express) 49456900
@@ -0,0 +1,105 @@
1997/12/31,,,,,,,,,,,
公司名称,股份数量,成本(截至1997/12/31)(百万美元)*,市值(截至1997/12/31)(百万美元),,,,,,,,
美国运通 (American Express),"49,456,900 ","1,392.70 ","4,414.00 ",,,,,,,,
可口可乐 (The Coca-Cola Company),"200,000,000 ","1,298.90 ","13,337.50 ",,,,,,,,
迪士尼 (The Walt Disney Company),"21,563,414 ",381,"2,134.80 ",,,,,,,,
房地美 (Freddie Mac),"63,977,600 ",329,"2,683.10 ",,,,,,,,
吉列 (The Gillette Company),"48,000,000 ",600,"4,821.00 ",,,,,,,,
旅行家集团 (Travelers Group Inc.),"23,733,198 ",604,"1,278.60 ",,,,,,,,
华盛顿邮报 (The Washington Post Company),"1,727,765 ",11,841,,,,,,,,
富国银行 (Wells Fargo & Company),"6,690,218 ",413,"2,270.90 ",,,,,,,,
,,,,,,,,,,,
1996/12/31,,,,,,,,,,,
公司,股数,成本\*(百万美元,截至1996/12/31),市值(百万美元,截至1996/12/31),,,,,,,,
美国运通,"49,456,900 ","1,392.70 ","2,794.30 ",,,,,,,,
可口可乐,"200,000,000 ","1,298.90 ","10,525.00 ",,,,,,,,
华特迪士尼,"24,614,214 ",577,"1,716.80 ",,,,,,,,
房地美,"64,246,000 ",333,"1,772.80 ",,,,,,,,
吉列,"48,000,000 ",600,"3,732.00 ",,,,,,,,
麦当劳,"30,156,600 ","1,265.30 ","1,368.40 ",,,,,,,,
华盛顿邮报,"1,727,765 ",11,579,,,,,,,,
富国银行,"7,291,418 ",498,"1,966.90 ",,,,,,,,
,,,,,,,,,,,
1995/12/31,,,,,,,,,,,
公司,股数,成本 1995/12/31(百万美元),市值 1995/12/31(百万美元),,,,,,,,
美国运通 (American Express),"49,456,900 ","1,392.70 ","2,046.30 ",,,,,,,,
大都会/ABC (Capital Cities/ABC),"20,000,000 ",345,"2,467.50 ",,,,,,,,
可口可乐 (The Coca-Cola Company),"100,000,000 ","1,298.90 ","7,425.00 ",,,,,,,,
房地美 (Freddie Mac),"12,502,500 ",260,"1,044.00 ",,,,,,,,
盖可保险 (GEICO Corp.),"34,250,000 ",46,"2,393.20 ",,,,,,,,
吉列 (The Gillette Company),"48,000,000 ",600,"2,502.00 ",,,,,,,,
富国银行 (Wells Fargo & Company),"6,791,218 ",424,"1,466.90 ",,,,,,,,
,,,,,,,,,,,
1994/12/31,,,,,,,,,,,
公司,股份数量,成本 (千美元),市值(千美元),,,,,,,,
美国运通 ,"27,759,941 ","US$723,919 ","US$818,918 ",,,,,,,,
大都会/ABC,"20,000,000 ","345,000 ","1,705,000 ",,,,,,,,
可口可乐,"100,000,000 ","1,298,888 ","5,150,000 ",,,,,,,,
房地美,"12,761,200 ","270,468 ","644,441 ",,,,,,,,
甘尼特公司,"6,854,500 ","335,216 ","365,002 ",,,,,,,,
盖可保险 (GEICO),"34,250,000 ","45,713 ","1,678,250 ",,,,,,,,
吉列 (Gillette),"24,000,000 ","600,000 ","1,797,000 ",,,,,,,,
PNC银行 (PNC Bank),"19,453,300 ","503,046 ","410,951 ",,,,,,,,
华盛顿邮报,"1,727,765 ","9,731 ","418,983 ",,,,,,,,
富国银行 ,"6,791,218 ","423,680 ","984,727 ",,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
1993/12/31,,,,,,,,,,,
公司名称,股份数量,成本(千美元),市值(千美元),,,,,,,,
大都会/ABC ,"2,000,000 ","US$345,000 ","US$1,239,000 ",,,,,,,,
可口可乐 ,"93,400,000 ","1,023,920 ","4,167,975 ",,,,,,,,
房地美 ,"13,654,600 ","307,505 ","681,023 ",,,,,,,,
盖可保险 ,"34,250,000 ","45,713 ","1,759,594 ",,,,,,,,
通用动力 ,"4,350,000 ","94,938 ","401,287 ",,,,,,,,
吉列 ,"24,000,000 ","600,000 ","1,431,000 ",,,,,,,,
健力士,"38,335,000 ","333,019 ","270,822 ",,,,,,,,
华盛顿邮报 ,"1,727,765 ","9,731 ","440,148 ",,,,,,,,
富国银行,"6,791,218 ","423,680 ","878,614 ",,,,,,,,
,,,,,,,,,,,
1992/12/31,,,,,,,,,,,
公司名称,股份数量,成本 (千美元),市值(千美元),,,,,,,,
大都会/ABC,"3,000,000 ","US$517,500 ","US$1,523,500 ",,,,,,,,
可口可乐,"93,400,000 ","1,023,920 ","3,911,125 ",,,,,,,,
房地美 ,"16,196,700 ","414,257 ","783,515 ",,,,,,,,
盖可保险 ,"34,250,000 ","45,713 ","2,226,250 ",,,,,,,,
通用动力,"4,350,000 ","312,438 ","450,769 ",,,,,,,,
吉列 ,"24,000,000 ","600,000 ","1,365,000 ",,,,,,,,
健力士,"38,335,000 ","333,019 ","299,581 ",,,,,,,,
华盛顿邮报 ,"1,727,765 ","9,731 ","396,954 ",,,,,,,,
富国银行,"6,358,418 ","380,983 ","485,624 ",,,,,,,,
,,,,,,,,,,,
1991/12/31,,,,,,,,,,,
公司,股数,成本(千美元),市值(千美元),,,,,,,,
大都会/ABC,"3,000,000 ","US$517,500 ","US$1,300,500 ",,,,,,,,
可口可乐,"46,700,000 ","1,023,920 ","3,747,675 ",,,,,,,,
房地美,"2,495,200 ","77,245 ","343,090 ",,,,,,,,
盖可保险,"6,850,000 ","45,713 ","1,363,150 ",,,,,,,,
吉列,"24,000,000 ","600,000 ","1,347,000 ",,,,,,,,
健力士 ,"31,247,000 ","264,782 ","296,755 ",,,,,,,,
华盛顿邮报,"1,727,765 ","9,731 ","336,050 ",,,,,,,,
富国银行,"5,000,000 ","289,431 ","290,000 ",,,,,,,,
,,,,,,,,,,,
1990/12/31,,,,,,,,,,,
公司,持股数量,成本(千美元),市值(千美元),,,,,,,,
大都会/ABC公司,"3,000,000 ","US$517,500 ","US$1,377,375 ",,,,,,,,
可口可乐公司,"46,700,000 ","1,023,920 ","2,171,550 ",,,,,,,,
联邦住房贷款抵押公司,"2,400,000 ","71,729 ","117,000 ",,,,,,,,
盖可保险公司,"6,850,000 ","45,713 ","1,110,556 ",,,,,,,,
华盛顿邮报公司,"1,727,765 ","9,731 ","342,097 ",,,,,,,,
富国银行,"5,000,000 ","289,431 ","289,375 ",,,,,,,,
,,,,,,,,,,,
1989/12/31,,,,,,,,,,,
股份数量,公司名称,成本(千美元),市值(千美元),,,,,,,,
"3,000,000 ",大都会/ABC,"US$517,500 ","US$1,692,375 ",,,,,,,,
"23,350,000 ",可口可乐,"1,023,920 ","1,803,787 ",,,,,,,,
"2,400,000 ",房地美优先股,"71,729 ","161,100 ",,,,,,,,
"6,850,000 ",盖可保险,"45,713 ","1,044,625 ",,,,,,,,
"1,727,765 ",华盛顿邮报 ,"9,731 ","486,366 ",,,,,,,,
,,,,,,,,,,,
1988/12/31,,,,,,,,,,,
股份数量,公司名称,成本(千美元),市值(千美元),,,,,,,,
"3,000,000 ",大都会/ABC,"US$517,500 ","US$1,086,750 ",,,,,,,,
"14,172,500 ",可口可乐公司,"592,540 ","632,448 ",,,,,,,,
"2,400,000 ",联邦住宅贷款抵押公司优先股\*,"71,729 ","121,200 ",,,,,,,,
"6,850,000 ",盖可保险,"45,713 ","849,400 ",,,,,,,,
"1,727,765 ",华盛顿邮报公司,"9,731 ","364,126 ",,,,,,,,
1 1997/12/31
2 公司名称 股份数量 成本(截至1997/12/31)(百万美元)* 市值(截至1997/12/31)(百万美元)
3 美国运通 (American Express) 49,456,900 1,392.70 4,414.00
4 可口可乐 (The Coca-Cola Company) 200,000,000 1,298.90 13,337.50
5 迪士尼 (The Walt Disney Company) 21,563,414 381 2,134.80
6 房地美 (Freddie Mac) 63,977,600 329 2,683.10
7 吉列 (The Gillette Company) 48,000,000 600 4,821.00
8 旅行家集团 (Travelers Group Inc.) 23,733,198 604 1,278.60
9 华盛顿邮报 (The Washington Post Company) 1,727,765 11 841
10 富国银行 (Wells Fargo & Company) 6,690,218 413 2,270.90
11
12 1996/12/31
13 公司 股数 成本\*(百万美元,截至1996/12/31) 市值(百万美元,截至1996/12/31)
14 美国运通 49,456,900 1,392.70 2,794.30
15 可口可乐 200,000,000 1,298.90 10,525.00
16 华特迪士尼 24,614,214 577 1,716.80
17 房地美 64,246,000 333 1,772.80
18 吉列 48,000,000 600 3,732.00
19 麦当劳 30,156,600 1,265.30 1,368.40
20 华盛顿邮报 1,727,765 11 579
21 富国银行 7,291,418 498 1,966.90
22
23 1995/12/31
24 公司 股数 成本 1995/12/31(百万美元) 市值 1995/12/31(百万美元)
25 美国运通 (American Express) 49,456,900 1,392.70 2,046.30
26 大都会/ABC (Capital Cities/ABC) 20,000,000 345 2,467.50
27 可口可乐 (The Coca-Cola Company) 100,000,000 1,298.90 7,425.00
28 房地美 (Freddie Mac) 12,502,500 260 1,044.00
29 盖可保险 (GEICO Corp.) 34,250,000 46 2,393.20
30 吉列 (The Gillette Company) 48,000,000 600 2,502.00
31 富国银行 (Wells Fargo & Company) 6,791,218 424 1,466.90
32
33 1994/12/31
34 公司 股份数量 成本 (千美元) 市值(千美元)
35 美国运通 27,759,941 US$723,919 US$818,918
36 大都会/ABC 20,000,000 345,000 1,705,000
37 可口可乐 100,000,000 1,298,888 5,150,000
38 房地美 12,761,200 270,468 644,441
39 甘尼特公司 6,854,500 335,216 365,002
40 盖可保险 (GEICO) 34,250,000 45,713 1,678,250
41 吉列 (Gillette) 24,000,000 600,000 1,797,000
42 PNC银行 (PNC Bank) 19,453,300 503,046 410,951
43 华盛顿邮报 1,727,765 9,731 418,983
44 富国银行 6,791,218 423,680 984,727
45
46
47 1993/12/31
48 公司名称 股份数量 成本(千美元) 市值(千美元)
49 大都会/ABC 2,000,000 US$345,000 US$1,239,000
50 可口可乐 93,400,000 1,023,920 4,167,975
51 房地美 13,654,600 307,505 681,023
52 盖可保险 34,250,000 45,713 1,759,594
53 通用动力 4,350,000 94,938 401,287
54 吉列 24,000,000 600,000 1,431,000
55 健力士 38,335,000 333,019 270,822
56 华盛顿邮报 1,727,765 9,731 440,148
57 富国银行 6,791,218 423,680 878,614
58
59 1992/12/31
60 公司名称 股份数量 成本 (千美元) 市值(千美元)
61 大都会/ABC 3,000,000 US$517,500 US$1,523,500
62 可口可乐 93,400,000 1,023,920 3,911,125
63 房地美 16,196,700 414,257 783,515
64 盖可保险 34,250,000 45,713 2,226,250
65 通用动力 4,350,000 312,438 450,769
66 吉列 24,000,000 600,000 1,365,000
67 健力士 38,335,000 333,019 299,581
68 华盛顿邮报 1,727,765 9,731 396,954
69 富国银行 6,358,418 380,983 485,624
70
71 1991/12/31
72 公司 股数 成本(千美元) 市值(千美元)
73 大都会/ABC 3,000,000 US$517,500 US$1,300,500
74 可口可乐 46,700,000 1,023,920 3,747,675
75 房地美 2,495,200 77,245 343,090
76 盖可保险 6,850,000 45,713 1,363,150
77 吉列 24,000,000 600,000 1,347,000
78 健力士 31,247,000 264,782 296,755
79 华盛顿邮报 1,727,765 9,731 336,050
80 富国银行 5,000,000 289,431 290,000
81
82 1990/12/31
83 公司 持股数量 成本(千美元) 市值(千美元)
84 大都会/ABC公司 3,000,000 US$517,500 US$1,377,375
85 可口可乐公司 46,700,000 1,023,920 2,171,550
86 联邦住房贷款抵押公司 2,400,000 71,729 117,000
87 盖可保险公司 6,850,000 45,713 1,110,556
88 华盛顿邮报公司 1,727,765 9,731 342,097
89 富国银行 5,000,000 289,431 289,375
90
91 1989/12/31
92 股份数量 公司名称 成本(千美元) 市值(千美元)
93 3,000,000 大都会/ABC US$517,500 US$1,692,375
94 23,350,000 可口可乐 1,023,920 1,803,787
95 2,400,000 房地美优先股 71,729 161,100
96 6,850,000 盖可保险 45,713 1,044,625
97 1,727,765 华盛顿邮报 9,731 486,366
98
99 1988/12/31
100 股份数量 公司名称 成本(千美元) 市值(千美元)
101 3,000,000 大都会/ABC US$517,500 US$1,086,750
102 14,172,500 可口可乐公司 592,540 632,448
103 2,400,000 联邦住宅贷款抵押公司优先股\* 71,729 121,200
104 6,850,000 盖可保险 45,713 849,400
105 1,727,765 华盛顿邮报公司 9,731 364,126
@@ -0,0 +1,8 @@
period,retail,robot_store,own_app,tiktok,amazon,online_other,wholesale,total_revenue
2024H1,47.5,7.1,15.8,8.2,0.0,10.9,10.4,1.83
2024H2,41.0,4.0,26.3,15.0,0.0,7.3,6.3,6.19
2024FY,42.5,4.7,23.9,13.5,0.0,8.1,7.2,8.02
2025H1,32.5,4.6,39.2,13.9,0.0,5.5,4.2,22.65
2025H2,27.9,2.8,43.7,16.0,0.0,7.0,2.7,45.42
2025FY,29.4,3.4,42.2,15.3,0.0,6.5,3.2,68.07
2026H1,47.8,5.5,26.0,0.0,8.9,3.3,8.6,18.91
1 period retail robot_store own_app tiktok amazon online_other wholesale total_revenue
2 2024H1 47.5 7.1 15.8 8.2 0.0 10.9 10.4 1.83
3 2024H2 41.0 4.0 26.3 15.0 0.0 7.3 6.3 6.19
4 2024FY 42.5 4.7 23.9 13.5 0.0 8.1 7.2 8.02
5 2025H1 32.5 4.6 39.2 13.9 0.0 5.5 4.2 22.65
6 2025H2 27.9 2.8 43.7 16.0 0.0 7.0 2.7 45.42
7 2025FY 29.4 3.4 42.2 15.3 0.0 6.5 3.2 68.07
8 2026H1 47.8 5.5 26.0 0.0 8.9 3.3 8.6 18.91
@@ -0,0 +1,3 @@
period,retail,robot_store,own_app,tiktok,amazon,online_other,wholesale,total_revenue
2024FY,42.5,4.7,23.9,13.5,0.0,8.1,7.2,8.02
2025FY,29.4,3.4,42.2,15.3,0.0,6.5,3.2,68.07
1 period retail robot_store own_app tiktok amazon online_other wholesale total_revenue
2 2024FY 42.5 4.7 23.9 13.5 0.0 8.1 7.2 8.02
3 2025FY 29.4 3.4 42.2 15.3 0.0 6.5 3.2 68.07
@@ -0,0 +1,6 @@
period,retail,robot_store,own_app,tiktok,amazon,online_other,wholesale,total_revenue
2024H1,47.5,7.1,15.8,8.2,0.0,10.9,10.4,1.83
2024H2,41.0,4.0,26.3,15.0,0.0,7.3,6.3,6.19
2025H1,32.5,4.6,39.2,13.9,0.0,5.5,4.2,22.65
2025H2,27.9,2.8,43.7,16.0,0.0,7.0,2.7,45.42
2026H1,47.8,5.5,26.0,0.0,8.9,3.3,8.6,18.91
1 period retail robot_store own_app tiktok amazon online_other wholesale total_revenue
2 2024H1 47.5 7.1 15.8 8.2 0.0 10.9 10.4 1.83
3 2024H2 41.0 4.0 26.3 15.0 0.0 7.3 6.3 6.19
4 2025H1 32.5 4.6 39.2 13.9 0.0 5.5 4.2 22.65
5 2025H2 27.9 2.8 43.7 16.0 0.0 7.0 2.7 45.42
6 2026H1 47.8 5.5 26.0 0.0 8.9 3.3 8.6 18.91
+8
View File
@@ -0,0 +1,8 @@
period,retail,robot_store,own_app,shopee,online_other,wholesale,total_revenue
2024H1,60.9,2.1,5.0,5.1,10.7,16.2,7.97
2024H2,51.1,1.0,11.5,10.5,12.8,13.0,23.13
2024FY,53.6,1.3,9.8,9.2,12.3,13.8,31.10
2025H1,52.4,1.2,11.0,9.9,16.7,9.0,28.51
2025H2,54.8,1.2,22.2,5.6,10.7,5.6,51.60
2025FY,53.9,1.2,18.2,7.1,12.8,6.8,80.11
2026H1,66.6,2.2,13.1,4.2,7.7,6.2,25.76
1 period retail robot_store own_app shopee online_other wholesale total_revenue
2 2024H1 60.9 2.1 5.0 5.1 10.7 16.2 7.97
3 2024H2 51.1 1.0 11.5 10.5 12.8 13.0 23.13
4 2024FY 53.6 1.3 9.8 9.2 12.3 13.8 31.10
5 2025H1 52.4 1.2 11.0 9.9 16.7 9.0 28.51
6 2025H2 54.8 1.2 22.2 5.6 10.7 5.6 51.60
7 2025FY 53.9 1.2 18.2 7.1 12.8 6.8 80.11
8 2026H1 66.6 2.2 13.1 4.2 7.7 6.2 25.76
@@ -0,0 +1,3 @@
period,retail,robot_store,own_app,shopee,online_other,wholesale,total_revenue
2024FY,53.6,1.3,9.8,9.2,12.3,13.8,31.10
2025FY,53.9,1.2,18.2,7.1,12.8,6.8,80.11
1 period retail robot_store own_app shopee online_other wholesale total_revenue
2 2024FY 53.6 1.3 9.8 9.2 12.3 13.8 31.10
3 2025FY 53.9 1.2 18.2 7.1 12.8 6.8 80.11
@@ -0,0 +1,6 @@
period,retail,robot_store,own_app,shopee,online_other,wholesale,total_revenue
2024H1,60.9,2.1,5.0,5.1,10.7,16.2,7.97
2024H2,51.1,1.0,11.5,10.5,12.8,13.0,23.13
2025H1,52.4,1.2,11.0,9.9,16.7,9.0,28.51
2025H2,54.8,1.2,22.2,5.6,10.7,5.6,51.60
2026H1,66.6,2.2,13.1,4.2,7.7,6.2,25.76
1 period retail robot_store own_app shopee online_other wholesale total_revenue
2 2024H1 60.9 2.1 5.0 5.1 10.7 16.2 7.97
3 2024H2 51.1 1.0 11.5 10.5 12.8 13.0 23.13
4 2025H1 52.4 1.2 11.0 9.9 16.7 9.0 28.51
5 2025H2 54.8 1.2 22.2 5.6 10.7 5.6 51.60
6 2026H1 66.6 2.2 13.1 4.2 7.7 6.2 25.76
+8
View File
@@ -0,0 +1,8 @@
period,retail,robot_store,roboshop,tmall,douyin,online_other,wholesale,total_revenue
2024H1,56.9,9.6,11.3,5.7,5.9,3.8,6.8,35.22
2024H2,48.4,7.7,13.3,8.0,7.3,5.5,9.8,53.65
2024FY,51.8,8.5,12.5,7.1,6.8,4.8,8.6,88.87
2025H1,53.2,8.2,13.6,7.9,6.8,7.2,3.2,82.82
2025H2,45.1,5.3,18.3,9.0,8.2,9.0,5.1,125.69
2025FY,48.3,6.5,16.4,8.6,7.6,8.3,4.4,208.51
2026H1,49.9,6.4,16.9,7.4,8.0,6.9,4.5,122.00
1 period retail robot_store roboshop tmall douyin online_other wholesale total_revenue
2 2024H1 56.9 9.6 11.3 5.7 5.9 3.8 6.8 35.22
3 2024H2 48.4 7.7 13.3 8.0 7.3 5.5 9.8 53.65
4 2024FY 51.8 8.5 12.5 7.1 6.8 4.8 8.6 88.87
5 2025H1 53.2 8.2 13.6 7.9 6.8 7.2 3.2 82.82
6 2025H2 45.1 5.3 18.3 9.0 8.2 9.0 5.1 125.69
7 2025FY 48.3 6.5 16.4 8.6 7.6 8.3 4.4 208.51
8 2026H1 49.9 6.4 16.9 7.4 8.0 6.9 4.5 122.00
@@ -0,0 +1,3 @@
period,retail,robot_store,roboshop,tmall,douyin,online_other,wholesale,total_revenue
2024FY,51.8,8.5,12.5,7.1,6.8,4.8,8.6,88.87
2025FY,48.3,6.5,16.4,8.6,7.6,8.3,4.4,208.51
1 period retail robot_store roboshop tmall douyin online_other wholesale total_revenue
2 2024FY 51.8 8.5 12.5 7.1 6.8 4.8 8.6 88.87
3 2025FY 48.3 6.5 16.4 8.6 7.6 8.3 4.4 208.51
@@ -0,0 +1,6 @@
period,retail,robot_store,roboshop,tmall,douyin,online_other,wholesale,total_revenue
2024H1,56.9,9.6,11.3,5.7,5.9,3.8,6.8,35.22
2024H2,48.4,7.7,13.3,8.0,7.3,5.5,9.8,53.65
2025H1,53.2,8.2,13.6,7.9,6.8,7.2,3.2,82.82
2025H2,45.1,5.3,18.3,9.0,8.2,9.0,5.1,125.69
2026H1,49.9,6.4,16.9,7.4,8.0,6.9,4.5,122.00
1 period retail robot_store roboshop tmall douyin online_other wholesale total_revenue
2 2024H1 56.9 9.6 11.3 5.7 5.9 3.8 6.8 35.22
3 2024H2 48.4 7.7 13.3 8.0 7.3 5.5 9.8 53.65
4 2025H1 53.2 8.2 13.6 7.9 6.8 7.2 3.2 82.82
5 2025H2 45.1 5.3 18.3 9.0 8.2 9.0 5.1 125.69
6 2026H1 49.9 6.4 16.9 7.4 8.0 6.9 4.5 122.00
+8
View File
@@ -0,0 +1,8 @@
period,retail,robot_store,own_app,online_other,wholesale,total_revenue
2024H1,70.7,1.7,1.7,17.2,8.6,0.58
2024H2,64.1,0.6,11.0,13.3,11.0,1.81
2024FY,65.7,0.8,8.8,14.2,10.5,2.39
2025H1,57.0,0.8,17.8,16.8,7.5,4.77
2025H2,60.0,1.3,23.7,11.2,3.8,9.74
2025FY,59.0,1.2,21.8,13.0,5.0,14.51
2026H1,79.6,2.2,10.5,3.0,4.7,5.06
1 period retail robot_store own_app online_other wholesale total_revenue
2 2024H1 70.7 1.7 1.7 17.2 8.6 0.58
3 2024H2 64.1 0.6 11.0 13.3 11.0 1.81
4 2024FY 65.7 0.8 8.8 14.2 10.5 2.39
5 2025H1 57.0 0.8 17.8 16.8 7.5 4.77
6 2025H2 60.0 1.3 23.7 11.2 3.8 9.74
7 2025FY 59.0 1.2 21.8 13.0 5.0 14.51
8 2026H1 79.6 2.2 10.5 3.0 4.7 5.06
@@ -0,0 +1,3 @@
period,retail,robot_store,own_app,online_other,wholesale,total_revenue
2024FY,65.7,0.8,8.8,14.2,10.5,2.39
2025FY,59.0,1.2,21.8,13.0,5.0,14.51
1 period retail robot_store own_app online_other wholesale total_revenue
2 2024FY 65.7 0.8 8.8 14.2 10.5 2.39
3 2025FY 59.0 1.2 21.8 13.0 5.0 14.51
@@ -0,0 +1,6 @@
period,retail,robot_store,own_app,online_other,wholesale,total_revenue
2024H1,70.7,1.7,1.7,17.2,8.6,0.58
2024H2,64.1,0.6,11.0,13.3,11.0,1.81
2025H1,57.0,0.8,17.8,16.8,7.5,4.77
2025H2,60.0,1.3,23.7,11.2,3.8,9.74
2026H1,79.6,2.2,10.5,3.0,4.7,5.06
1 period retail robot_store own_app online_other wholesale total_revenue
2 2024H1 70.7 1.7 1.7 17.2 8.6 0.58
3 2024H2 64.1 0.6 11.0 13.3 11.0 1.81
4 2025H1 57.0 0.8 17.8 16.8 7.5 4.77
5 2025H2 60.0 1.3 23.7 11.2 3.8 9.74
6 2026H1 79.6 2.2 10.5 3.0 4.7 5.06
+65
View File
@@ -14,6 +14,26 @@ region,channel,period,revenue
中国,线上渠道,2025H1,29.37 中国,线上渠道,2025H1,29.37
中国,线上渠道,2025FY,85.22 中国,线上渠道,2025FY,85.22
中国,线上渠道,2026H1,47.79 中国,线上渠道,2026H1,47.79
中国,泡泡玛特抽盒机,2024H1,3.99
中国,泡泡玛特抽盒机,2024FY,11.14
中国,泡泡玛特抽盒机,2025H1,11.25
中国,泡泡玛特抽盒机,2025FY,34.23
中国,泡泡玛特抽盒机,2026H1,20.63
中国,天猫旗舰店,2024H1,1.99
中国,天猫旗舰店,2024FY,6.28
中国,天猫旗舰店,2025H1,6.58
中国,天猫旗舰店,2025FY,17.85
中国,天猫旗舰店,2026H1,9.01
中国,抖音平台,2024H1,2.09
中国,抖音平台,2024FY,6.01
中国,抖音平台,2025H1,5.61
中国,抖音平台,2025FY,15.90
中国,抖音平台,2026H1,9.76
中国,其他线上渠道,2024H1,1.34
中国,其他线上渠道,2024FY,4.29
中国,其他线上渠道,2025H1,5.93
中国,其他线上渠道,2025FY,17.24
中国,其他线上渠道,2026H1,8.38
中国,批发及其他,2024H1,2.39 中国,批发及其他,2024H1,2.39
中国,批发及其他,2024FY,7.63 中国,批发及其他,2024FY,7.63
中国,批发及其他,2025H1,2.61 中国,批发及其他,2025H1,2.61
@@ -34,6 +54,21 @@ region,channel,period,revenue
亚太,线上渠道,2025H1,10.69 亚太,线上渠道,2025H1,10.69
亚太,线上渠道,2025FY,30.53 亚太,线上渠道,2025FY,30.53
亚太,线上渠道,2026H1,6.44 亚太,线上渠道,2026H1,6.44
亚太,自研APP及官方网站,2024H1,0.40
亚太,自研APP及官方网站,2024FY,3.05
亚太,自研APP及官方网站,2025H1,3.13
亚太,自研APP及官方网站,2025FY,14.58
亚太,自研APP及官方网站,2026H1,3.38
亚太,Shopee,2024H1,0.41
亚太,Shopee,2024FY,2.85
亚太,Shopee,2025H1,2.81
亚太,Shopee,2025FY,5.69
亚太,Shopee,2026H1,1.07
亚太,其他线上渠道,2024H1,0.85
亚太,其他线上渠道,2024FY,3.82
亚太,其他线上渠道,2025H1,4.75
亚太,其他线上渠道,2025FY,10.26
亚太,其他线上渠道,2026H1,1.99
亚太,批发及其他,2024H1,1.29 亚太,批发及其他,2024H1,1.29
亚太,批发及其他,2024FY,4.30 亚太,批发及其他,2024FY,4.30
亚太,批发及其他,2025H1,2.56 亚太,批发及其他,2025H1,2.56
@@ -54,6 +89,26 @@ region,channel,period,revenue
美洲,线上渠道,2025H1,13.27 美洲,线上渠道,2025H1,13.27
美洲,线上渠道,2025FY,43.54 美洲,线上渠道,2025FY,43.54
美洲,线上渠道,2026H1,7.22 美洲,线上渠道,2026H1,7.22
美洲,自研APP及官方网站,2024H1,0.29
美洲,自研APP及官方网站,2024FY,1.92
美洲,自研APP及官方网站,2025H1,8.87
美洲,自研APP及官方网站,2025FY,28.70
美洲,自研APP及官方网站,2026H1,4.91
美洲,TikTok,2024H1,0.15
美洲,TikTok,2024FY,1.08
美洲,TikTok,2025H1,3.15
美洲,TikTok,2025FY,10.40
美洲,TikTok,2026H1,0.00
美洲,亚马逊,2024H1,0.00
美洲,亚马逊,2024FY,0.00
美洲,亚马逊,2025H1,0.00
美洲,亚马逊,2025FY,0.00
美洲,亚马逊,2026H1,1.68
美洲,其他线上渠道,2024H1,0.20
美洲,其他线上渠道,2024FY,0.65
美洲,其他线上渠道,2025H1,1.25
美洲,其他线上渠道,2025FY,4.44
美洲,其他线上渠道,2026H1,0.63
美洲,批发及其他,2024H1,0.19 美洲,批发及其他,2024H1,0.19
美洲,批发及其他,2024FY,0.58 美洲,批发及其他,2024FY,0.58
美洲,批发及其他,2025H1,0.96 美洲,批发及其他,2025H1,0.96
@@ -74,6 +129,16 @@ region,channel,period,revenue
欧洲及其他,线上渠道,2025H1,1.65 欧洲及其他,线上渠道,2025H1,1.65
欧洲及其他,线上渠道,2025FY,5.05 欧洲及其他,线上渠道,2025FY,5.05
欧洲及其他,线上渠道,2026H1,0.68 欧洲及其他,线上渠道,2026H1,0.68
欧洲及其他,自研APP及官方网站,2024H1,0.01
欧洲及其他,自研APP及官方网站,2024FY,0.21
欧洲及其他,自研APP及官方网站,2025H1,0.85
欧洲及其他,自研APP及官方网站,2025FY,3.16
欧洲及其他,自研APP及官方网站,2026H1,0.53
欧洲及其他,其他线上渠道,2024H1,0.10
欧洲及其他,其他线上渠道,2024FY,0.34
欧洲及其他,其他线上渠道,2025H1,0.80
欧洲及其他,其他线上渠道,2025FY,1.89
欧洲及其他,其他线上渠道,2026H1,0.15
欧洲及其他,批发及其他,2024H1,0.05 欧洲及其他,批发及其他,2024H1,0.05
欧洲及其他,批发及其他,2024FY,0.25 欧洲及其他,批发及其他,2024FY,0.25
欧洲及其他,批发及其他,2025H1,0.36 欧洲及其他,批发及其他,2025H1,0.36
1 region channel period revenue
14 中国 线上渠道 2025H1 29.37
15 中国 线上渠道 2025FY 85.22
16 中国 线上渠道 2026H1 47.79
17 中国 泡泡玛特抽盒机 2024H1 3.99
18 中国 泡泡玛特抽盒机 2024FY 11.14
19 中国 泡泡玛特抽盒机 2025H1 11.25
20 中国 泡泡玛特抽盒机 2025FY 34.23
21 中国 泡泡玛特抽盒机 2026H1 20.63
22 中国 天猫旗舰店 2024H1 1.99
23 中国 天猫旗舰店 2024FY 6.28
24 中国 天猫旗舰店 2025H1 6.58
25 中国 天猫旗舰店 2025FY 17.85
26 中国 天猫旗舰店 2026H1 9.01
27 中国 抖音平台 2024H1 2.09
28 中国 抖音平台 2024FY 6.01
29 中国 抖音平台 2025H1 5.61
30 中国 抖音平台 2025FY 15.90
31 中国 抖音平台 2026H1 9.76
32 中国 其他线上渠道 2024H1 1.34
33 中国 其他线上渠道 2024FY 4.29
34 中国 其他线上渠道 2025H1 5.93
35 中国 其他线上渠道 2025FY 17.24
36 中国 其他线上渠道 2026H1 8.38
37 中国 批发及其他 2024H1 2.39
38 中国 批发及其他 2024FY 7.63
39 中国 批发及其他 2025H1 2.61
54 亚太 线上渠道 2025H1 10.69
55 亚太 线上渠道 2025FY 30.53
56 亚太 线上渠道 2026H1 6.44
57 亚太 自研APP及官方网站 2024H1 0.40
58 亚太 自研APP及官方网站 2024FY 3.05
59 亚太 自研APP及官方网站 2025H1 3.13
60 亚太 自研APP及官方网站 2025FY 14.58
61 亚太 自研APP及官方网站 2026H1 3.38
62 亚太 Shopee 2024H1 0.41
63 亚太 Shopee 2024FY 2.85
64 亚太 Shopee 2025H1 2.81
65 亚太 Shopee 2025FY 5.69
66 亚太 Shopee 2026H1 1.07
67 亚太 其他线上渠道 2024H1 0.85
68 亚太 其他线上渠道 2024FY 3.82
69 亚太 其他线上渠道 2025H1 4.75
70 亚太 其他线上渠道 2025FY 10.26
71 亚太 其他线上渠道 2026H1 1.99
72 亚太 批发及其他 2024H1 1.29
73 亚太 批发及其他 2024FY 4.30
74 亚太 批发及其他 2025H1 2.56
89 美洲 线上渠道 2025H1 13.27
90 美洲 线上渠道 2025FY 43.54
91 美洲 线上渠道 2026H1 7.22
92 美洲 自研APP及官方网站 2024H1 0.29
93 美洲 自研APP及官方网站 2024FY 1.92
94 美洲 自研APP及官方网站 2025H1 8.87
95 美洲 自研APP及官方网站 2025FY 28.70
96 美洲 自研APP及官方网站 2026H1 4.91
97 美洲 TikTok 2024H1 0.15
98 美洲 TikTok 2024FY 1.08
99 美洲 TikTok 2025H1 3.15
100 美洲 TikTok 2025FY 10.40
101 美洲 TikTok 2026H1 0.00
102 美洲 亚马逊 2024H1 0.00
103 美洲 亚马逊 2024FY 0.00
104 美洲 亚马逊 2025H1 0.00
105 美洲 亚马逊 2025FY 0.00
106 美洲 亚马逊 2026H1 1.68
107 美洲 其他线上渠道 2024H1 0.20
108 美洲 其他线上渠道 2024FY 0.65
109 美洲 其他线上渠道 2025H1 1.25
110 美洲 其他线上渠道 2025FY 4.44
111 美洲 其他线上渠道 2026H1 0.63
112 美洲 批发及其他 2024H1 0.19
113 美洲 批发及其他 2024FY 0.58
114 美洲 批发及其他 2025H1 0.96
129 欧洲及其他 线上渠道 2025H1 1.65
130 欧洲及其他 线上渠道 2025FY 5.05
131 欧洲及其他 线上渠道 2026H1 0.68
132 欧洲及其他 自研APP及官方网站 2024H1 0.01
133 欧洲及其他 自研APP及官方网站 2024FY 0.21
134 欧洲及其他 自研APP及官方网站 2025H1 0.85
135 欧洲及其他 自研APP及官方网站 2025FY 3.16
136 欧洲及其他 自研APP及官方网站 2026H1 0.53
137 欧洲及其他 其他线上渠道 2024H1 0.10
138 欧洲及其他 其他线上渠道 2024FY 0.34
139 欧洲及其他 其他线上渠道 2025H1 0.80
140 欧洲及其他 其他线上渠道 2025FY 1.89
141 欧洲及其他 其他线上渠道 2026H1 0.15
142 欧洲及其他 批发及其他 2024H1 0.05
143 欧洲及其他 批发及其他 2024FY 0.25
144 欧洲及其他 批发及其他 2025H1 0.36
+174
View File
@@ -0,0 +1,174 @@
import {
PALETTE, FONT, categoryAxis, titleStyle,
standardLegend, footnote, watermarks, LAYOUT,
} from '../theme.js';
const STATE_LABELS = {
initial: '期初持有',
added: '新建仓',
held: '持续持有',
sold: '清仓',
};
const STATE_COLORS = {
initial: PALETTE.sand,
added: PALETTE.green,
sold: PALETTE.coral,
};
const SHORT_NAMES = {
'美国运通(American Express)': '美国运通',
'可口可乐(Coca-Cola)': '可口可乐',
'华特迪士尼(Walt Disney)': '迪士尼',
'房地美(Freddie Mac)': '房地美',
'吉列(Gillette)': '吉列',
'旅行家集团(Travelers Group)': '旅行家集团',
'华盛顿邮报(Washington Post)': '华盛顿邮报',
'富国银行(Wells Fargo)': '富国银行',
'大都会/ABC(Capital Cities/ABC)': '大都会/ABC',
'盖可保险(GEICO)': '盖可保险',
'甘尼特(Gannett)': '甘尼特',
'PNC 银行(PNC Bank)': 'PNC 银行',
'通用动力(General Dynamics)': '通用动力',
'健力士(Guinness)': '健力士',
"麦当劳(McDonald's)": '麦当劳',
};
function formatShares(value) {
return Number(value).toLocaleString('en-US');
}
function quantityChange(current, previous) {
if (!Number.isFinite(previous)) return '无可比上年数据';
const change = current - previous;
const sign = change > 0 ? '+' : '';
return `${sign}${formatShares(change)} 股`;
}
export function brkHoldingsChart(rows, { width, height }) {
const years = [...new Set(rows.map((row) => row.year))].sort((a, b) => a - b);
const holdingsByYear = new Map(years.map((year) => [year, new Map()]));
const firstYearByCompany = new Map();
const maxSharesByCompany = new Map();
rows.forEach((row) => {
holdingsByYear.get(row.year).set(row.company, row.shares);
firstYearByCompany.set(row.company, Math.min(firstYearByCompany.get(row.company) ?? row.year, row.year));
maxSharesByCompany.set(row.company, Math.max(maxSharesByCompany.get(row.company) ?? 0, row.shares));
});
const companies = [...firstYearByCompany.keys()].sort((a, b) => (
firstYearByCompany.get(a) - firstYearByCompany.get(b) || a.localeCompare(b, 'zh-CN')
));
const dataByState = { initial: [], added: [], held: [], sold: [] };
years.forEach((year, yearIndex) => {
const current = holdingsByYear.get(year);
const previous = yearIndex > 0 ? holdingsByYear.get(years[yearIndex - 1]) : new Map();
companies.forEach((company, companyIndex) => {
const shares = current.get(company);
const priorShares = previous.get(company);
let state;
if (Number.isFinite(shares)) {
state = yearIndex === 0 ? 'initial' : (Number.isFinite(priorShares) ? 'held' : 'added');
} else if (yearIndex > 0 && Number.isFinite(priorShares)) {
state = 'sold';
} else {
return;
}
const relativeSize = Number.isFinite(shares)
? Math.sqrt(shares / maxSharesByCompany.get(company))
: 1;
const color = state === 'held'
? `rgba(59, 110, 165, ${(0.38 + relativeSize * 0.62).toFixed(2)})`
: STATE_COLORS[state];
const labelColor = state === 'initial' || (state === 'held' && relativeSize < 0.55)
? PALETTE.ink
: '#fff';
dataByState[state].push({
value: [yearIndex, companyIndex, shares ?? 0],
shares,
priorShares,
state,
shortName: SHORT_NAMES[company] || company,
itemStyle: { color, borderColor: '#fff', borderWidth: 3 },
label: { color: labelColor },
});
});
});
return {
backgroundColor: '#fff',
title: {
...titleStyle,
text: '伯克希尔主要持仓变动(1988–1997)',
subtext: '每格标注公司简称;持续持有的蓝色越深,表示相对持股数量越大',
},
legend: standardLegend([
STATE_LABELS.initial,
STATE_LABELS.added,
STATE_LABELS.held,
STATE_LABELS.sold,
], { selectedMode: false, itemGap: 20 }),
tooltip: {
trigger: 'item',
textStyle: { fontFamily: FONT },
formatter: (params) => {
const data = params.data;
const company = companies[data.value[1]];
const year = years[data.value[0]];
const lines = [`<b>${year} · ${company}</b>`, `状态:${STATE_LABELS[data.state]}`];
if (Number.isFinite(data.shares)) {
lines.push(`年末持股:${formatShares(data.shares)} 股`);
if (data.state !== 'initial') lines.push(`较上年:${quantityChange(data.shares, data.priorShares)}`);
} else {
lines.push(`上年末持股:${formatShares(data.priorShares)} 股`);
}
return lines.join('<br/>');
},
},
// ECharts 的 heatmap 组件要求声明 visualMap;实际颜色由每个状态单元格的 itemStyle 控制。
visualMap: {
show: false,
min: 0,
max: Math.max(...rows.map((row) => row.shares)),
dimension: 2,
inRange: { color: ['#ffffff'] },
},
grid: { left: 258, right: 48, top: LAYOUT.gridTop, bottom: 72 },
xAxis: {
...categoryAxis,
type: 'category',
data: years.map(String),
splitArea: { show: true, areaStyle: { color: ['#fbfbfa'] } },
},
yAxis: {
...categoryAxis,
type: 'category',
inverse: true,
data: companies,
axisLabel: { ...categoryAxis.axisLabel, fontSize: 12, margin: 14 },
splitArea: { show: true, areaStyle: { color: ['#fbfbfa'] } },
},
series: Object.entries(dataByState).map(([state, data]) => ({
name: STATE_LABELS[state],
type: 'heatmap',
data,
label: {
show: true,
position: 'inside',
fontFamily: FONT,
fontSize: 12,
fontWeight: 600,
formatter: (params) => params.data.shortName,
},
emphasis: { itemStyle: { borderColor: PALETTE.ink, borderWidth: 2 } },
})),
graphic: [
...watermarks(width, height),
footnote('绿色=相对上一年新增;红色=相对上一年清仓;蓝色深浅=相对持股数量 | @思考的Joey'),
],
};
}
+7
View File
@@ -26,6 +26,7 @@ import { workingCapitalDaysChart } from './ppmt_working_capital_days.js';
import { expenseStructureChart } from './ppmt_expense_structure.js'; import { expenseStructureChart } from './ppmt_expense_structure.js';
import { channelRevenueChart } from './ppmt_channel_revenue.js'; import { channelRevenueChart } from './ppmt_channel_revenue.js';
import { channelShareChart } from './ppmt_channel_share.js'; import { channelShareChart } from './ppmt_channel_share.js';
import { makeRegionChannelShareChart } from './ppmt_channel_share_region.js';
import { storesRetailChart } from './ppmt_stores_retail.js'; import { storesRetailChart } from './ppmt_stores_retail.js';
import { storesRobotChart } from './ppmt_stores_robot.js'; import { storesRobotChart } from './ppmt_stores_robot.js';
import { regionShareChart } from './ppmt_region_share.js'; import { regionShareChart } from './ppmt_region_share.js';
@@ -33,6 +34,7 @@ import { inventoryBalanceChart } from './ppmt_inventory.js';
import { storesRetailShareChart } from './ppmt_stores_retail_share.js'; import { storesRetailShareChart } from './ppmt_stores_retail_share.js';
import { retailStoreRevenueChart } from './ppmt_retail_store_revenue.js'; import { retailStoreRevenueChart } from './ppmt_retail_store_revenue.js';
import { robotStoreRevenueChart } from './ppmt_robot_store_revenue.js'; import { robotStoreRevenueChart } from './ppmt_robot_store_revenue.js';
import { brkHoldingsChart } from './brk_holdings.js';
/** 图表构建函数注册表。manifest 只引用这里的 key,不直接引用 JS 函数。 */ /** 图表构建函数注册表。manifest 只引用这里的 key,不直接引用 JS 函数。 */
export const chartRegistry = { export const chartRegistry = {
@@ -64,6 +66,10 @@ export const chartRegistry = {
'ppmt-expense-structure': expenseStructureChart, 'ppmt-expense-structure': expenseStructureChart,
'ppmt-channel-revenue': channelRevenueChart, 'ppmt-channel-revenue': channelRevenueChart,
'ppmt-channel-share': channelShareChart, 'ppmt-channel-share': channelShareChart,
'ppmt-channel-share-china': makeRegionChannelShareChart('china'),
'ppmt-channel-share-apac': makeRegionChannelShareChart('apac'),
'ppmt-channel-share-americas': makeRegionChannelShareChart('americas'),
'ppmt-channel-share-europe': makeRegionChannelShareChart('europe'),
'ppmt-stores-retail': storesRetailChart, 'ppmt-stores-retail': storesRetailChart,
'ppmt-stores-robot': storesRobotChart, 'ppmt-stores-robot': storesRobotChart,
'ppmt-region-share': regionShareChart, 'ppmt-region-share': regionShareChart,
@@ -71,6 +77,7 @@ export const chartRegistry = {
'ppmt-stores-retail-share': storesRetailShareChart, 'ppmt-stores-retail-share': storesRetailShareChart,
'ppmt-retail-store-revenue': retailStoreRevenueChart, 'ppmt-retail-store-revenue': retailStoreRevenueChart,
'ppmt-robot-store-revenue': robotStoreRevenueChart, 'ppmt-robot-store-revenue': robotStoreRevenueChart,
'brk-holdings': brkHoldingsChart,
}; };
export function getChartBuilder(key) { export function getChartBuilder(key) {
+11 -14
View File
@@ -1,7 +1,7 @@
import { col } from '../csv.js'; import { col } from '../csv.js';
import { import {
CHANNEL_COLORS, PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, standardLegend, CHANNEL_COLORS, PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, standardLegend,
financialViewLabel, barSeries, footnote, watermarks, LAYOUT, financialViewLabel, barSeries, stackedSharePoint, fanTinyLabelOffsets, footnote, watermarks, LAYOUT,
} from '../theme.js'; } from '../theme.js';
const CHANNELS = [ const CHANNELS = [
@@ -11,21 +11,14 @@ const CHANNELS = [
{ key: 'wholesale', name: '批发及其他', color: CHANNEL_COLORS.wholesale, labelColor: PALETTE.ink }, { key: 'wholesale', name: '批发及其他', color: CHANNEL_COLORS.wholesale, labelColor: PALETTE.ink },
]; ];
function sharePoint(value, labelColor) {
if (!Number.isFinite(value) || value === 0) return null;
// 3.5% 以下的段放不下 11px 段内标签;当前数据最小为 3.7%(2025H2 机器人商店)
return {
value,
label: value >= 3.5
? { position: 'inside', color: labelColor }
: { show: false },
};
}
/** 泡泡玛特全渠道收入占比:全部地区合并,每根柱按当期总收入归一化为 100%。 */ /** 泡泡玛特全渠道收入占比:全部地区合并,每根柱按当期总收入归一化为 100%。 */
export function channelShareChart(rows, { width, height, view = 'all' }) { export function channelShareChart(rows, { width, height, view = 'all' }) {
const periods = col(rows, 'period'); const periods = col(rows, 'period');
const barWidth = view === 'all' ? 48 : 80; const barWidth = view === 'all' ? 48 : 80;
// 绘图区像素高:画布高 − grid top 145 − grid bottom 100;轴固定 0–100%
const pxPerUnit = (height - LAYOUT.gridTop - 100) / 100;
const seriesKeys = CHANNELS.map((item) => item.key);
const rowOffsets = fanTinyLabelOffsets(rows, seriesKeys, pxPerUnit);
return { return {
backgroundColor: '#fff', backgroundColor: '#fff',
@@ -59,9 +52,13 @@ export function channelShareChart(rows, { width, height, view = 'all' }) {
interval: 20, interval: 20,
axisLabel: { ...axisCommon.axisLabel, formatter: '{value}%' }, axisLabel: { ...axisCommon.axisLabel, formatter: '{value}%' },
}, },
series: CHANNELS.map((item) => barSeries({ series: CHANNELS.map((item, ci) => barSeries({
name: item.name, name: item.name,
data: rows.map((row) => sharePoint(row[item.key], item.labelColor)), data: rows.map((row, ri) => stackedSharePoint(row[item.key], {
pxPerUnit,
labelColor: item.labelColor,
dy: rowOffsets[ri][ci] ?? 0,
})),
color: item.color, color: item.color,
barWidth, barWidth,
stack: 'channel-share', stack: 'channel-share',
+122
View File
@@ -0,0 +1,122 @@
import { col } from '../csv.js';
import {
CHANNEL_COLORS, PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, standardLegend,
financialViewLabel, barSeries, stackedSharePoint, fanTinyLabelOffsets, footnote, watermarks, LAYOUT,
} from '../theme.js';
/**
* 四地区共用同一套渠道语义色:零售店/机器人商店/批发及其他沿用渠道色板;
* 线上细分逐平台一色,抖音与 TikTok 同属一条生态线共用青色,其他线上为中性灰。
* 各图 5~7 个系列,图内两两 ΔE 已验算 > 25(最紧:抖音青 vs 中性灰 25.1)。
*/
const SERIES = {
retail: { name: '零售店', color: CHANNEL_COLORS.retail, labelColor: '#fff' },
robot_store: { name: '机器人商店', color: CHANNEL_COLORS.robotStore, labelColor: '#fff' },
wholesale: { name: '批发及其他', color: CHANNEL_COLORS.wholesale, labelColor: PALETTE.ink },
online_other: { name: '其他线上', color: PALETTE.grey, labelColor: '#fff' },
roboshop: { name: '抽盒机', color: CHANNEL_COLORS.online, labelColor: '#fff' },
tmall: { name: '天猫旗舰店', color: '#8256B2', labelColor: '#fff' },
douyin: { name: '抖音平台', color: '#4E9EA7', labelColor: '#fff' },
own_app: { name: '自研APP及官网', color: '#C05B76', labelColor: '#fff' },
shopee: { name: 'Shopee', color: PALETTE.brown, labelColor: '#fff' },
tiktok: { name: 'TikTok', color: '#4E9EA7', labelColor: '#fff' },
amazon: { name: '亚马逊', color: PALETTE.red, labelColor: '#fff' },
};
const REGIONS = {
china: {
title: '中国区',
source: '中国(含港澳台)',
series: ['retail', 'robot_store', 'roboshop', 'tmall', 'douyin', 'online_other', 'wholesale'],
footnote: '数据来源:泡泡玛特中国区(含港澳台)分渠道收入披露;H2为单半年(全年−H1)\n线上渠道按财报披露拆分为抽盒机、天猫旗舰店、抖音平台与其他线上 | @思考的Joey',
},
apac: {
title: '亚太区',
source: '亚太区',
series: ['retail', 'robot_store', 'own_app', 'shopee', 'online_other', 'wholesale'],
footnote: '数据来源:泡泡玛特亚太区分渠道收入披露;H2为单半年(全年−H1)\n线上渠道按财报披露拆分为自研APP及官网、Shopee与其他线上 | @思考的Joey',
},
americas: {
title: '美洲区',
source: '美洲区',
series: ['retail', 'robot_store', 'own_app', 'tiktok', 'amazon', 'online_other', 'wholesale'],
footnote: '数据来源:泡泡玛特美洲区分渠道收入披露;H2为单半年(全年−H1)\n2026H1起TikTok无收入,亚马逊为2026年新开渠道 | @思考的Joey',
},
europe: {
title: '欧洲及其他区',
source: '欧洲及其他地区',
series: ['retail', 'robot_store', 'own_app', 'online_other', 'wholesale'],
footnote: '数据来源:泡泡玛特欧洲及其他地区分渠道收入披露;H2为单半年(全年−H1)\n线上渠道按财报披露拆分为自研APP及官网与其他线上 | @思考的Joey',
},
};
/** 分地区渠道收入占比:线上渠道拆分披露的细分平台,每根柱按当期该地区总收入归一化。 */
export function makeRegionChannelShareChart(regionKey) {
const region = REGIONS[regionKey];
if (!region) throw new Error(`未配置的地区渠道占比图:${regionKey}`);
return function regionChannelShareChart(rows, { width, height, view = 'all' }) {
const periods = col(rows, 'period');
const barWidth = view === 'all' ? 48 : 80;
// 绘图区像素高:画布高 − grid top 145 − grid bottom 100;轴固定 0–100%
const pxPerUnit = (height - LAYOUT.gridTop - 100) / 100;
const rowOffsets = fanTinyLabelOffsets(rows, region.series, pxPerUnit);
return {
backgroundColor: '#fff',
title: {
...titleStyle,
text: `泡泡玛特${region.title}渠道收入占比(${financialViewLabel(view)})`,
subtext: '归一化堆叠:每根柱为当期该地区总收入的 100%;线上渠道按披露细分拆分',
},
legend: standardLegend(region.series.map((key) => SERIES[key].name)),
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
textStyle: { fontFamily: FONT },
formatter: (params) => {
const row = rows[periods.indexOf(params[0].axisValue)];
return `<b>${params[0].axisValue}</b> ${region.source}总收入 ${row.total_revenue.toFixed(2)} 亿元<br/>${params
.filter((item) => item.value !== null)
.slice()
.reverse()
.map((item) => `${item.marker}${item.seriesName}: ${item.value.toFixed(1)}%`)
.join('<br/>')}`;
},
},
grid: { left: 78, right: 42, top: LAYOUT.gridTop, bottom: 100 },
xAxis: { ...standalonePeriodAxis, data: periods },
yAxis: {
...axisCommon,
type: 'value',
min: 0,
max: 100,
interval: 20,
axisLabel: { ...axisCommon.axisLabel, formatter: '{value}%' },
},
series: region.series.map((key, ci) => barSeries({
name: SERIES[key].name,
data: rows.map((row, ri) => stackedSharePoint(row[key], {
pxPerUnit,
labelColor: SERIES[key].labelColor,
dy: rowOffsets[ri][ci] ?? 0,
})),
color: SERIES[key].color,
barWidth,
stack: `channel-share-${regionKey}`,
label: {
show: true,
position: 'inside',
fontSize: 11,
fontFamily: FONT,
fontWeight: 500,
formatter: (point) => `${point.value.toFixed(1)}%`,
},
emphasis: { focus: 'series' },
})),
graphic: [
...watermarks(width, height),
footnote(region.footnote),
],
};
};
}
+11 -13
View File
@@ -1,7 +1,7 @@
import { col } from '../csv.js'; import { col } from '../csv.js';
import { import {
PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, standardLegend, PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, standardLegend,
financialViewLabel, barSeries, footnote, watermarks, LAYOUT, financialViewLabel, barSeries, stackedSharePoint, fanTinyLabelOffsets, footnote, watermarks, LAYOUT,
} from '../theme.js'; } from '../theme.js';
/** 泡泡玛特分地区零售门店占比:每根柱标准化为各期末全球门店数的 100%。 */ /** 泡泡玛特分地区零售门店占比:每根柱标准化为各期末全球门店数的 100%。 */
@@ -13,19 +13,13 @@ const REGIONS = [
{ key: 'other', name: '其他', color: PALETTE.sand, labelColor: PALETTE.ink }, { key: 'other', name: '其他', color: PALETTE.sand, labelColor: PALETTE.ink },
]; ];
function sharePoint(value, labelColor) {
if (!Number.isFinite(value) || value === 0) return null;
return {
value,
label: value >= 5
? { position: 'inside', color: labelColor }
: { show: false },
};
}
export function storesRetailShareChart(rows, { width, height, view = 'all' }) { export function storesRetailShareChart(rows, { width, height, view = 'all' }) {
const periods = col(rows, 'period'); const periods = col(rows, 'period');
const barWidth = view === 'all' ? 48 : 80; const barWidth = view === 'all' ? 48 : 80;
// 绘图区像素高:画布高 − grid top 145 − grid bottom 100;轴固定 0–100%
const pxPerUnit = (height - LAYOUT.gridTop - 100) / 100;
const seriesKeys = REGIONS.map((item) => item.key);
const rowOffsets = fanTinyLabelOffsets(rows, seriesKeys, pxPerUnit);
return { return {
backgroundColor: '#fff', backgroundColor: '#fff',
@@ -59,9 +53,13 @@ export function storesRetailShareChart(rows, { width, height, view = 'all' }) {
interval: 20, interval: 20,
axisLabel: { ...axisCommon.axisLabel, formatter: '{value}%' }, axisLabel: { ...axisCommon.axisLabel, formatter: '{value}%' },
}, },
series: REGIONS.map((item) => barSeries({ series: REGIONS.map((item, ci) => barSeries({
name: item.name, name: item.name,
data: rows.map((row) => sharePoint(row[item.key], item.labelColor)), data: rows.map((row, ri) => stackedSharePoint(row[item.key], {
pxPerUnit,
labelColor: item.labelColor,
dy: rowOffsets[ri][ci] ?? 0,
})),
color: item.color, color: item.color,
barWidth, barWidth,
stack: 'stores-retail-share', stack: 'stores-retail-share',
+61
View File
@@ -291,6 +291,67 @@ export function barSeries({ name, data, color, barWidth, formatter, ...rest }) {
}; };
} }
/**
* 归一化堆叠占比图的矮段标签外置偏移。
* 段高不足(< minInsidePx 像素)放不下段内标签时,标签标到柱体右侧;
* 同一根柱里有多个矮段时,柱侧标签自下而上按 gap 像素扇形排开避免重叠
* (先例:ppmt_channel_revenue 的 fanOutsideLabels、ppmt_region_share 的柱侧标签)。
* 返回 { 行序号: { 系列序号: dy } },dy 为 ECharts label.offset 的纵向偏移。
*/
export function fanTinyLabelOffsets(rows, seriesKeys, pxPerUnit, { minInsidePx = 15, gap = 13 } = {}) {
return rows.map((row) => {
const centers = [];
let cum = 0;
seriesKeys.forEach((key) => {
const value = Number.isFinite(row[key]) ? row[key] : 0;
centers.push((cum + value / 2) * pxPerUnit);
cum += value;
});
const tinyIdx = seriesKeys
.map((_, index) => index)
.filter((index) => Number.isFinite(row[seriesKeys[index]])
&& row[seriesKeys[index]] > 0
&& row[seriesKeys[index]] * pxPerUnit < minInsidePx);
if (tinyIdx.length === 0) return {};
const ys = tinyIdx.map((index) => centers[index]);
for (let k = 1; k < ys.length; k += 1) ys[k] = Math.max(ys[k], ys[k - 1] + gap);
if (tinyIdx.length === seriesKeys.length) {
// 整根柱都是矮段:扇形整体对中到柱身中部,避免标签飘离柱顶
const shift = cum * pxPerUnit / 2 - (ys[0] + ys[ys.length - 1]) / 2;
for (let k = 0; k < ys.length; k += 1) ys[k] += shift;
if (ys[0] < 2) {
for (let k = 0; k < ys.length; k += 1) ys[k] += 2 - ys[0];
}
}
const offsets = {};
tinyIdx.forEach((index, k) => { offsets[index] = centers[index] - ys[k]; });
return offsets;
});
}
/**
* 归一化堆叠占比图的逐点标签:段高够时段内显示(用系列的段内配色),
* 矮段外置到柱体右侧(深字白描边),保证每个分类的占比数值都可见。
* 必须配合 fanTinyLabelOffsets 计算的 dy 使用;value 为空或 0 时不渲染该段。
*/
export function stackedSharePoint(value, { pxPerUnit, labelColor, dy = 0, minInsidePx = 15 }) {
if (!Number.isFinite(value) || value === 0) return null;
if (value * pxPerUnit >= minInsidePx) {
return { value, label: { position: 'inside', color: labelColor } };
}
return {
value,
label: {
position: 'right',
color: PALETTE.ink,
distance: 3,
offset: [0, dy],
textBorderColor: '#fff',
textBorderWidth: 2,
},
};
}
/** 底部注释 */ /** 底部注释 */
export function footnote(text) { export function footnote(text) {
return { return {
+15 -1
View File
@@ -28,6 +28,10 @@
"ppmt-expense-structure": { "key": "ppmt-expense-structure", "title": "费用结构与费用率", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_expense_structure.csv", "annual": "data/ppmt/ppmt_expense_structure_annual.csv", "halfyear": "data/ppmt/ppmt_expense_structure_halfyear.csv" }, "height": 700, "filename": "泡泡玛特费用结构与费用率" }, "ppmt-expense-structure": { "key": "ppmt-expense-structure", "title": "费用结构与费用率", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_expense_structure.csv", "annual": "data/ppmt/ppmt_expense_structure_annual.csv", "halfyear": "data/ppmt/ppmt_expense_structure_halfyear.csv" }, "height": 700, "filename": "泡泡玛特费用结构与费用率" },
"ppmt-channel-revenue": { "key": "ppmt-channel-revenue", "title": "渠道收入结构与增速", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_revenue.csv", "annual": "data/ppmt/ppmt_channel_revenue_annual.csv", "halfyear": "data/ppmt/ppmt_channel_revenue_halfyear.csv" }, "height": 720, "filename": "泡泡玛特渠道收入结构与增速" }, "ppmt-channel-revenue": { "key": "ppmt-channel-revenue", "title": "渠道收入结构与增速", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_revenue.csv", "annual": "data/ppmt/ppmt_channel_revenue_annual.csv", "halfyear": "data/ppmt/ppmt_channel_revenue_halfyear.csv" }, "height": 720, "filename": "泡泡玛特渠道收入结构与增速" },
"ppmt-channel-share": { "key": "ppmt-channel-share", "title": "渠道收入占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_share.csv", "annual": "data/ppmt/ppmt_channel_share_annual.csv", "halfyear": "data/ppmt/ppmt_channel_share_halfyear.csv" }, "height": 680, "filename": "泡泡玛特渠道收入占比" }, "ppmt-channel-share": { "key": "ppmt-channel-share", "title": "渠道收入占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_share.csv", "annual": "data/ppmt/ppmt_channel_share_annual.csv", "halfyear": "data/ppmt/ppmt_channel_share_halfyear.csv" }, "height": 680, "filename": "泡泡玛特渠道收入占比" },
"ppmt-channel-share-china": { "key": "ppmt-channel-share-china", "title": "中国区渠道收入占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_share_china.csv", "annual": "data/ppmt/ppmt_channel_share_china_annual.csv", "halfyear": "data/ppmt/ppmt_channel_share_china_halfyear.csv" }, "height": 680, "filename": "泡泡玛特中国区渠道收入占比" },
"ppmt-channel-share-apac": { "key": "ppmt-channel-share-apac", "title": "亚太区渠道收入占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_share_apac.csv", "annual": "data/ppmt/ppmt_channel_share_apac_annual.csv", "halfyear": "data/ppmt/ppmt_channel_share_apac_halfyear.csv" }, "height": 680, "filename": "泡泡玛特亚太区渠道收入占比" },
"ppmt-channel-share-americas": { "key": "ppmt-channel-share-americas", "title": "美洲区渠道收入占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_share_americas.csv", "annual": "data/ppmt/ppmt_channel_share_americas_annual.csv", "halfyear": "data/ppmt/ppmt_channel_share_americas_halfyear.csv" }, "height": 680, "filename": "泡泡玛特美洲区渠道收入占比" },
"ppmt-channel-share-europe": { "key": "ppmt-channel-share-europe", "title": "欧洲及其他区渠道收入占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_channel_share_europe.csv", "annual": "data/ppmt/ppmt_channel_share_europe_annual.csv", "halfyear": "data/ppmt/ppmt_channel_share_europe_halfyear.csv" }, "height": 680, "filename": "泡泡玛特欧洲及其他区渠道收入占比" },
"ppmt-stores-retail": { "key": "ppmt-stores-retail", "title": "分地区零售门店数量与同比增速", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_stores_retail.csv", "annual": "data/ppmt/ppmt_stores_retail_annual.csv", "halfyear": "data/ppmt/ppmt_stores_retail_halfyear.csv" }, "height": 680, "filename": "泡泡玛特分地区零售门店数量与同比增速" }, "ppmt-stores-retail": { "key": "ppmt-stores-retail", "title": "分地区零售门店数量与同比增速", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_stores_retail.csv", "annual": "data/ppmt/ppmt_stores_retail_annual.csv", "halfyear": "data/ppmt/ppmt_stores_retail_halfyear.csv" }, "height": 680, "filename": "泡泡玛特分地区零售门店数量与同比增速" },
"ppmt-stores-retail-share": { "key": "ppmt-stores-retail-share", "title": "分地区零售门店数量占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_stores_retail_share.csv", "annual": "data/ppmt/ppmt_stores_retail_share_annual.csv", "halfyear": "data/ppmt/ppmt_stores_retail_share_halfyear.csv" }, "height": 680, "filename": "泡泡玛特分地区零售门店数量占比" }, "ppmt-stores-retail-share": { "key": "ppmt-stores-retail-share", "title": "分地区零售门店数量占比", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_stores_retail_share.csv", "annual": "data/ppmt/ppmt_stores_retail_share_annual.csv", "halfyear": "data/ppmt/ppmt_stores_retail_share_halfyear.csv" }, "height": 680, "filename": "泡泡玛特分地区零售门店数量占比" },
"ppmt-retail-store-revenue": { "key": "ppmt-retail-store-revenue", "title": "各地区零售店单店收入", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_retail_store_revenue.csv", "annual": "data/ppmt/ppmt_retail_store_revenue_annual.csv", "halfyear": "data/ppmt/ppmt_retail_store_revenue_halfyear.csv" }, "height": 680, "filename": "泡泡玛特各地区零售店单店收入" }, "ppmt-retail-store-revenue": { "key": "ppmt-retail-store-revenue", "title": "各地区零售店单店收入", "defaultView": "all", "views": { "all": "data/ppmt/ppmt_retail_store_revenue.csv", "annual": "data/ppmt/ppmt_retail_store_revenue_annual.csv", "halfyear": "data/ppmt/ppmt_retail_store_revenue_halfyear.csv" }, "height": 680, "filename": "泡泡玛特各地区零售店单店收入" },
@@ -41,10 +45,20 @@
{ "id": "expense", "name": "费用率", "chartRefs": ["ppmt-margins", "ppmt-expense-structure"] }, { "id": "expense", "name": "费用率", "chartRefs": ["ppmt-margins", "ppmt-expense-structure"] },
{ "id": "balance-sheet", "name": "资产负债", "chartRefs": ["ppmt-assets", "ppmt-inventory", "ppmt-liquidity-working-capital", "ppmt-working-capital-days"] }, { "id": "balance-sheet", "name": "资产负债", "chartRefs": ["ppmt-assets", "ppmt-inventory", "ppmt-liquidity-working-capital", "ppmt-working-capital-days"] },
{ "id": "ip-category", "name": "IP 与品类", "chartRefs": ["ppmt-ip", "ppmt-ip-share", "ppmt-ip-share-history", "ppmt-ip-ex-monsters", "ppmt-category"] }, { "id": "ip-category", "name": "IP 与品类", "chartRefs": ["ppmt-ip", "ppmt-ip-share", "ppmt-ip-share-history", "ppmt-ip-ex-monsters", "ppmt-category"] },
{ "id": "region-channel", "name": "区域渠道", "chartRefs": ["ppmt-region-channel", "ppmt-region-yoy", "ppmt-region-yoy-timeseries", "ppmt-channel-revenue", "ppmt-channel-share", "ppmt-stores-retail", "ppmt-stores-retail-share", "ppmt-stores-robot", "ppmt-region-share"] }, { "id": "region-channel", "name": "区域渠道", "chartRefs": ["ppmt-region-channel", "ppmt-region-yoy", "ppmt-region-yoy-timeseries", "ppmt-channel-revenue", "ppmt-channel-share", "ppmt-channel-share-china", "ppmt-channel-share-apac", "ppmt-channel-share-americas", "ppmt-channel-share-europe", "ppmt-stores-retail", "ppmt-stores-retail-share", "ppmt-stores-robot", "ppmt-region-share"] },
{ "id": "store-revenue", "name": "单店收入", "chartRefs": ["ppmt-retail-store-revenue", "ppmt-robot-store-revenue"] } { "id": "store-revenue", "name": "单店收入", "chartRefs": ["ppmt-retail-store-revenue", "ppmt-robot-store-revenue"] }
] ]
}, },
{
"id": "brk",
"name": "巴菲特致股东信",
"chartCatalog": {
"brk-holdings": { "key": "brk-holdings", "title": "1988–1997 年主要持仓变动", "csv": "data/brk/brk_holdings.csv", "height": 860, "filename": "伯克希尔1988-1997主要持仓变动" }
},
"tabs": [
{ "id": "holdings", "name": "主要持仓", "chartRefs": ["brk-holdings"] }
]
},
{ {
"id": "demo", "id": "demo",
"name": "示例", "name": "示例",
+95
View File
@@ -0,0 +1,95 @@
import fs from 'node:fs/promises';
import path from 'node:path';
const sourcePath = path.resolve('data/brk/rawData/brk_holdings_1988_1997_export.csv');
const outputPath = path.resolve('data/brk/brk_holdings.csv');
const COMPANY_NAMES = [
['american express|美国运通', '美国运通(American Express)'],
['coca-cola|可口可乐', '可口可乐(Coca-Cola)'],
['disney|迪士尼', '华特迪士尼(Walt Disney)'],
['freddie mac|房地美|联邦住', '房地美(Freddie Mac)'],
['gillette|吉列', '吉列(Gillette)'],
['travelers|旅行家', '旅行家集团(Travelers Group)'],
['washington post|华盛顿邮报', '华盛顿邮报(Washington Post)'],
['wells fargo|富国银行', '富国银行(Wells Fargo)'],
['capital cities|大都会', '大都会/ABC(Capital Cities/ABC)'],
['geico|盖可', '盖可保险(GEICO)'],
['gannett|甘尼特', '甘尼特(Gannett)'],
['pnc', 'PNC 银行(PNC Bank)'],
['general dynamics|通用动力', '通用动力(General Dynamics)'],
['guinness|健力士', '健力士(Guinness)'],
["mcdonald|麦当劳", '麦当劳(McDonald\'s)'],
].map(([pattern, name]) => ({ pattern: new RegExp(pattern, 'i'), name }));
function parseCSV(text) {
const rows = [];
let row = [];
let value = '';
let quoted = false;
for (let i = 0; i < text.length; i += 1) {
const char = text[i];
if (char === '"') {
if (quoted && text[i + 1] === '"') {
value += '"';
i += 1;
} else {
quoted = !quoted;
}
} else if (char === ',' && !quoted) {
row.push(value.trim());
value = '';
} else if ((char === '\n' || char === '\r') && !quoted) {
if (char === '\r' && text[i + 1] === '\n') i += 1;
row.push(value.trim());
rows.push(row);
row = [];
value = '';
} else {
value += char;
}
}
if (value || row.length) rows.push([...row, value.trim()]);
return rows;
}
function canonicalName(value) {
return COMPANY_NAMES.find(({ pattern }) => pattern.test(value))?.name || value.trim();
}
function parseShares(value) {
const digits = value.replace(/[^\d]/g, '');
return digits ? Number(digits) : NaN;
}
const rows = parseCSV(await fs.readFile(sourcePath, 'utf8'));
const holdings = [];
for (let index = 0; index < rows.length; index += 1) {
const dateMatch = rows[index][0]?.match(/^(\d{4})\/12\/31$/);
if (!dateMatch) continue;
const year = Number(dateMatch[1]);
const header = rows[index + 1] || [];
const sharesFirst = /股(份)?数量|股数|持股数量/.test(header[0] || '');
const companyIndex = sharesFirst ? 1 : 0;
const sharesIndex = sharesFirst ? 0 : 1;
for (let rowIndex = index + 2; rowIndex < rows.length; rowIndex += 1) {
const record = rows[rowIndex];
if (!record.some(Boolean)) break;
if (/^\d{4}\/12\/31$/.test(record[0] || '')) break;
const company = record[companyIndex];
const shares = parseShares(record[sharesIndex] || '');
if (!company || !Number.isFinite(shares)) continue;
holdings.push({ year, company: canonicalName(company), shares });
}
}
holdings.sort((a, b) => a.year - b.year || a.company.localeCompare(b.company, 'zh-CN'));
const lines = ['year,company,shares', ...holdings.map((row) => `${row.year},${row.company},${row.shares}`)];
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, `${lines.join('\n')}\n`, 'utf8');
console.log(`Normalized ${holdings.length} holdings across ${new Set(holdings.map((row) => row.year)).size} years.`);
+78 -1
View File
@@ -714,10 +714,24 @@ const CHANNEL_NAME_TO_KEY = {
线上渠道: 'online', 线上渠道: 'online',
批发及其他: 'wholesale', 批发及其他: 'wholesale',
}; };
const ONLINE_SUB_NAME_TO_KEY = {
泡泡玛特抽盒机: 'roboshop',
天猫旗舰店: 'tmall',
抖音平台: 'douyin',
自研APP及官方网站: 'own_app',
Shopee: 'shopee',
TikTok: 'tiktok',
亚马逊: 'amazon',
其他线上渠道: 'online_other',
};
const channelRevenueByPeriod = new Map(); const channelRevenueByPeriod = new Map();
readCsvRows(RAWDATA_DIR, '地区渠道收入.csv').forEach(({ region, channel, period, revenue }) => { readCsvRows(RAWDATA_DIR, '地区渠道收入.csv').forEach(({ region, channel, period, revenue }) => {
const key = CHANNEL_NAME_TO_KEY[channel]; const key = CHANNEL_NAME_TO_KEY[channel];
if (!key) throw new Error(`地区渠道收入底表存在未知渠道:${channel}`); if (!key) {
// 线上细分行只进分地区图;未知渠道仍视为底表错误。
if (!ONLINE_SUB_NAME_TO_KEY[channel]) throw new Error(`地区渠道收入底表存在未知渠道:${channel}`);
return;
}
if (!period || !Number.isFinite(revenue)) throw new Error(`地区渠道收入底表行不完整:${region} ${channel} ${period} ${revenue}`); if (!period || !Number.isFinite(revenue)) throw new Error(`地区渠道收入底表行不完整:${region} ${channel} ${period} ${revenue}`);
if (!channelRevenueByPeriod.has(period)) { if (!channelRevenueByPeriod.has(period)) {
channelRevenueByPeriod.set(period, { retail: 0, online: 0, robot_store: 0, wholesale: 0 }); channelRevenueByPeriod.set(period, { retail: 0, online: 0, robot_store: 0, wholesale: 0 });
@@ -745,3 +759,66 @@ writeRuntimeViews('ppmt_channel_share', ['period', 'retail', 'online', 'robot_st
}); });
console.log('已生成渠道收入占比的全部、年度、半年 CSV。'); console.log('已生成渠道收入占比的全部、年度、半年 CSV。');
// 分地区渠道收入占比:线上渠道按披露细分拆开,各地区细分不同。
// 底表中「线上渠道」合计行仅作核对值;细分空缺期已按 0 录入并核对
// (美洲区 2026H1 起 TikTok 未再产生收入、亚马逊 2026 年起开售,与线上合计勾稽一致)。
const REGION_KEY_BY_NAME = { 中国: 'china', 亚太: 'apac', 美洲: 'americas', 欧洲及其他: 'europe' };
const REGION_SERIES = {
china: ['retail', 'robot_store', 'roboshop', 'tmall', 'douyin', 'online_other', 'wholesale'],
apac: ['retail', 'robot_store', 'own_app', 'shopee', 'online_other', 'wholesale'],
americas: ['retail', 'robot_store', 'own_app', 'tiktok', 'amazon', 'online_other', 'wholesale'],
europe: ['retail', 'robot_store', 'own_app', 'online_other', 'wholesale'],
};
const TOP_AND_SUB_NAME_TO_KEY = { ...CHANNEL_NAME_TO_KEY, ...ONLINE_SUB_NAME_TO_KEY };
const regionAmounts = new Map();
const regionOnlineDisclosed = new Map();
readCsvRows(RAWDATA_DIR, '地区渠道收入.csv').forEach(({ region, channel, period, revenue }) => {
const regionKey = REGION_KEY_BY_NAME[region];
if (!regionKey) throw new Error(`地区渠道收入底表存在未知地区:${region}`);
if (channel === '线上渠道') {
regionOnlineDisclosed.set(`${regionKey}:${period}`, revenue);
return;
}
const key = TOP_AND_SUB_NAME_TO_KEY[channel];
if (!key) throw new Error(`地区渠道收入底表存在未知渠道:${channel}`);
if (!period || !Number.isFinite(revenue)) throw new Error(`地区渠道收入底表行不完整:${region} ${channel} ${period} ${revenue}`);
const bucketKey = `${regionKey}:${period}`;
if (!regionAmounts.has(bucketKey)) regionAmounts.set(bucketKey, {});
const bucket = regionAmounts.get(bucketKey);
bucket[key] = (bucket[key] ?? 0) + revenue;
});
regionOnlineDisclosed.forEach((disclosed, bucketKey) => {
const bucket = regionAmounts.get(bucketKey);
if (!bucket) throw new Error(`地区渠道收入底表缺少线上合计对应的期间:${bucketKey}`);
const subSum = Object.values(ONLINE_SUB_NAME_TO_KEY).reduce((sum, key) => sum + (bucket[key] ?? 0), 0);
if (Math.abs(subSum - disclosed) > 0.05) {
throw new Error(`${bucketKey} 线上细分合计 ${subSum.toFixed(2)} ≠ 披露线上渠道 ${disclosed.toFixed(2)}`);
}
});
Object.entries(REGION_SERIES).forEach(([regionKey, seriesKeys]) => {
const amountViews = buildViews((year, type) => {
const bucket = regionAmounts.get(`${regionKey}:${type === 'H1' ? `${year}H1` : `${year}FY`}`);
if (!bucket) return null;
const values = Object.fromEntries(seriesKeys.map((key) => [key, bucket[key] ?? 0]));
return isComplete(values) ? values : null;
});
const shareViews = Object.fromEntries(Object.entries(amountViews).map(([view, rows]) => [
view,
rows.map(({ period, ...amounts }) => {
const total = Object.values(amounts).reduce((sum, value) => sum + value, 0);
return {
period,
...Object.fromEntries(Object.entries(amounts).map(([key, value]) => [key, value / total * 100])),
total_revenue: total,
};
}),
]));
writeRuntimeViews(`ppmt_channel_share_${regionKey}`, ['period', ...seriesKeys, 'total_revenue'], shareViews, {
...Object.fromEntries(seriesKeys.map((key) => [key, 1])),
total_revenue: 2,
});
});
console.log('已生成四地区渠道收入占比(线上细分)的全部、年度、半年 CSV。');