{"id":2480,"date":"2021-12-28T02:43:45","date_gmt":"2021-12-28T02:43:45","guid":{"rendered":"https:\/\/www.tejwin.com\/en\/insights\/brinson-model-performance-attribution\/"},"modified":"2021-12-28T02:43:45","modified_gmt":"2021-12-28T02:43:45","slug":"brinson-model-performance-attribution","status":"publish","type":"insight","link":"https:\/\/www.tejwin.com\/en\/insights\/brinson-model-performance-attribution\/","title":{"rendered":"Brinson Model Performance attribution"},"content":{"rendered":"<p class=\"wp-block-paragraph\" id=\"14bc\">Analyze the source of portfolio performance<\/p>\n<figure class=\"wp-block-image aligncenter is-resized caption-align-center\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1DKke3ihQwr8-Irk6FaeWng.jpg\" style=\"width:841px;height:557px\"\/><figcaption class=\"wp-element-caption\">Photo by\u00a0<a href=\"https:\/\/unsplash.com\/@adeolueletu?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\" rel=\"noreferrer noopener\" target=\"_blank\">Adeolu Eletu<\/a>\u00a0on\u00a0<a href=\"https:\/\/unsplash.com\/s\/photos\/finance?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\" rel=\"noreferrer noopener\" target=\"_blank\">Unsplash<\/a><\/figcaption><\/figure>\n<h2 class=\"wp-block-heading\" id=\"1df4\"><strong>Highlights<\/strong><\/h2>\n<ul class=\"wp-block-list\">\n<li>Difficulty\uff1a\u2605\u2605\u2606\u2606\u2606<\/li>\n<li>Performance attribution refers to the excess return between portfolio and its assigned benchmark into the detail return. The detail return can be used to quantify the impact of the portfolio\u2019s industries, stock-selection timing and stock selection ability on return and risk.<\/li>\n<li>Linking to\u00a0<a href=\"https:\/\/gist.github.com\/tej87681088\/05668fae34ee4c3458aa9c17191dc847#file-tejapi_medium-9-ipynb\" rel=\"noreferrer noopener\" target=\"_blank\">code<\/a><\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\" id=\"baae\"><strong>Preface<\/strong><\/h2>\n<p class=\"wp-block-paragraph\" id=\"3e99\">Portfolio\u2019s performance is affected by many factors. It is not easy for us to clearly distinguish whether the performance is due to the rise in the market, the stock selection ability of traders, or the proper allocation of assets or industries? Therefore, we can use the performance attribution proposed by Brinson (1985) to disassemble the excess return between the investment portfolio and its assigned benchmark into the selection effect, the interaction effect and the allocation effect. Moreover, performance attribution allows us to look across a specific time horizon and identify which investment decisions have either added or detracted value from the portfolio, relative to its benchmark.<\/p>\n<p class=\"wp-block-paragraph\" id=\"a344\">This article use the Taiwan 50 Index as the benchmark of the 00881 ETF, and analyze the performance attribution of the 00881 ETF through the Brinson model.<\/p>\n<h2 class=\"wp-block-heading\" id=\"8c4b\"><strong>The Editing Environment and Modules Required<\/strong><\/h2>\n<p class=\"wp-block-paragraph\" id=\"f8a9\">Windows OS and Jupyter Notebook<\/p>\n<pre class=\"wp-block-preformatted\"># \u529f\u80fd\u6a21\u7d44<br\/>import pandas as pd<br\/>import numpy as np<br\/>import statsmodels.api as sm<br\/>import matplotlib.pyplot as plt<br\/>from scipy.stats import wilcoxon# TEJ API<br\/>import tejapi<br\/>tejapi<strong>.<\/strong>ApiConfig<strong>.<\/strong>api_key <strong>=<\/strong> 'Your key'<\/pre>\n<h2 class=\"wp-block-heading\" id=\"9272\"><strong>Database Used<\/strong><\/h2>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/api.tej.com.tw\/columns.html?idCode=TWN%2FAEHOLD\" rel=\"noreferrer noopener\" target=\"_blank\">List of ETF companies<\/a>: the code of the database is (TWN\/AEHOLD)<\/li>\n<li><a href=\"https:\/\/api.tej.com.tw\/columns.html?idCode=TWN%2FAIDXS\" rel=\"noreferrer noopener\" target=\"_blank\">List of Index companies<\/a>: the code of the database is (TWN\/AIDXS)<\/li>\n<li><a href=\"https:\/\/api.tej.com.tw\/columns.html?idCode=TWN%2FANPRCSTD\" rel=\"noreferrer noopener\" target=\"_blank\">Security Characteristics Document<\/a>: the code of the database is (TWN\/EWNPRCSTD)<\/li>\n<li><a href=\"https:\/\/api.tej.com.tw\/columns.html?idCode=TWN%2FAPRCD1\" rel=\"noreferrer noopener\" target=\"_blank\">Adjusted daily stock price<\/a>: the code of the database is (TWN\/APRCD1)<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\" id=\"87ab\"><strong>Data Processing<\/strong><\/h2>\n<p class=\"wp-block-paragraph\" id=\"de5c\"><strong>Step 1.\u00a0<\/strong>Import ETF companies and Taiwan 50 Index companies<\/p>\n<p class=\"wp-block-paragraph\" id=\"d158\">We import the 00881 ETF and Taiwan 50 Index stocks updated daily from September to November 2021 from the TEJ database, which can save us a lot of time to inquiry from\u00a0<a aria-label=\" (opens in a new tab)\" class=\"ek-link\" href=\"https:\/\/www.cathaysite.com.tw\/ETF\/detail\/ECR?tab=etf3\" rel=\"noreferrer noopener\" target=\"_blank\">securities investment trust<\/a>\u00a0that issued the ETF. If you want to use a large number of ETF stocks, the advantage of using TEJ database is more obvious.<\/p>\n<pre class=\"wp-block-preformatted\">#%% \u532f\u5165 TEJ\u8cc7\u6599<br\/>etf = tejapi.get('TWN\/AEHOLD',<br\/>                 coid = '00881',<br\/>                 mdate= {'gte': '2021-09-01','lte':'2021-11-30'},<br\/>                 opts={'columns':['mdate', 'no','pct']},<br\/>                 chinese_column_name=True,paginate=True)# \u6a19\u7aff\u6307\u6578\uff1a\u81fa50\u6307\u6578<br\/>benchmark = tejapi.get('TWN\/AIDXS',<br\/>                       coid = 'TWN50',<br\/>                       mdate= {'gte': '2021-09-01','lte':'2021-11-30'},<br\/>                       opts={'columns':['mdate','key3','mv_pct']},<br\/>                       chinese_column_name=True,paginate=True)etf = etf[~etf['\u6a19\u7684\u540d\u7a31'].isin(['\u7533\u8d16\u61c9\u4ed8\u6b3e','\u4fdd\u8b49\u91d1','\u73fe\u91d1'])]<br\/>etf['\u8b49\u5238\u78bc'] = etf['\u6a19\u7684\u540d\u7a31'].str[0:4]<br\/>etf['\u8b49\u5238\u78bc'] = np.where(etf['\u8b49\u5238\u78bc'] == 'TX \u53f0','Y9999',etf['\u8b49\u5238\u78bc'])<br\/>etf['\u5e74'] = etf['\u65e5\u671f'].dt.year<br\/>etf['\u6708'] = etf['\u65e5\u671f'].dt.month<br\/>etf = etf.drop_duplicates(subset=['\u5e74','\u6708','\u8b49\u5238\u78bc'], keep='first')benchmark['\u8b49\u5238\u78bc'] = benchmark['\u6210\u4efd\u80a1'].str[0:4]<br\/>benchmark['\u5e74'] = benchmark['\u5e74\u6708\u65e5'].dt.year<br\/>benchmark['\u6708'] = benchmark['\u5e74\u6708\u65e5'].dt.month<br\/>benchmark = benchmark.drop_duplicates(subset=['\u5e74','\u6708','\u8b49\u5238\u78bc'], keep='first')etf.head(10)<\/pre>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1zwOxVMNv3PzqnMm_O-Mq4Q.png\"\/><\/figure>\n<p class=\"wp-block-paragraph\" id=\"94aa\"><strong>Step 2.\u00a0<\/strong>Import ETF industries belong by companies and the unadjusted stock price<\/p>\n<p class=\"wp-block-paragraph\" id=\"d91a\">We organize the 00881 ETF and Taiwan 50 Index stocks into a\u00a0<code>list<\/code>\u00a0data type, and retrieve the adjusted stock price and name of the industry of required stocks from the TEJ database.<\/p>\n<pre class=\"wp-block-preformatted\"># \u7372\u5f97 etf\u8207 benchmark\u7684\u4ee3\u78bc<br\/>coid_list = etf['\u8b49\u5238\u78bc'].unique().tolist()<br\/>coid_list.append('Y9999')<br\/>coid_list = coid_list + benchmark['\u8b49\u5238\u78bc'].unique().tolist()# \u6293\u53d6\u516c\u53f8\u7684\u7522\u696d\u540d\u7a31<br\/>code = tejapi.get(\"TWN\/EWNPRCSTD\",<br\/>                  coid = coid_list,<br\/>                  paginate=True,<br\/>                  opts={'columns':['coid', 'coid_name','tseindnm']},<br\/>                  chinese_column_name=True)code.head(5)<\/pre>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1SMRJogMPmKRs65P2ePcE5A.png\"\/><\/figure>\n<p class=\"wp-block-paragraph\" id=\"6ec0\">We directly get stock monthly return through TEJ database.<\/p>\n<pre class=\"wp-block-preformatted\"># \u80a1\u50f9<br\/>price = tejapi.get('TWN\/AAPRCM1',<br\/>                   coid = coid_list,<br\/>                   mdate= {'gte': '2021-09-01','lte':'2021-11-30'},<br\/>                   opts={'columns':['coid', 'mdate','roi']},<br\/>                   chinese_column_name=True,<br\/>                   paginate=True)price['\u5e74'] = price['\u5e74\u6708'].dt.year<br\/>price['\u6708'] = price['\u5e74\u6708'].dt.monthprice.head(5)<\/pre>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1nz7-QN81IfBYLw3SDNi4MQ.png\"\/><\/figure>\n<p class=\"wp-block-paragraph\" id=\"c18f\"><strong>Step 3.\u00a0<\/strong>Combine data by industry name<\/p>\n<p class=\"wp-block-paragraph\" id=\"bac5\">We merge the industry names into the Dataframe of 00881 ETF and Taiwan 50 Index. If there is a difference between the industry of the 00881 ETF and the stocks of the Taiwan 50 Index, we replace the industry name of the industry difference between the stocks of the 00881 ETF and the Taiwan 50 Index to ensure the 00881 ETF stocks industry names corresponding completely to the stocks of the Taiwan 50 Index.<\/p>\n<pre class=\"wp-block-preformatted\"># \u5408\u4f75\u7522\u696d\u540d\u7a31<br\/>etf = pd.merge(etf ,code , how = 'left' , on = ['\u8b49\u5238\u78bc'])<br\/>etf = pd.merge(etf ,price ,how = 'left' , left_on=['\u5e74','\u6708','\u8b49\u5238\u78bc'], right_on=['\u5e74','\u6708','\u8b49\u5238\u4ee3\u78bc'])benchmark = pd.merge(benchmark ,code , how = 'left' , on = ['\u8b49\u5238\u78bc'])<br\/>benchmark = pd.merge(benchmark ,price ,how = 'left' ,<br\/>                     left_on=['\u5e74','\u6708','\u5e74\u6708\u65e5','\u8b49\u5238\u78bc'], right_on=['\u5e74','\u6708','\u5e74\u6708\u65e5','\u8b49\u5238\u4ee3\u78bc'])# \u8655\u7406\u7522\u696d\u4e0d\u4e00\u81f4\u554f\u984c<br\/># \u82e5 benchmark\u7684\u7522\u696d\u7a2e\u985e\u6c92\u6709\u5728 etf\u7684\u7522\u696d\u7a2e\u985e\u4e2d\u627e\u5230\uff0c\u5247 benchmark\u4e2d\u7279\u6b8a\u7684\u7522\u696d\u6539\u6210\u5176\u4ed6<br\/>benchmark['TSE\u7522\u696d\u540d'] = np.where(benchmark['TSE\u7522\u696d\u540d'].isin(etf['TSE\u7522\u696d\u540d'].unique().tolist()),<br\/>                               benchmark['TSE\u7522\u696d\u540d'],'\u5176\u4ed6')# \u82e5 etf\u7684\u7522\u696d\u7a2e\u985e\u6c92\u6709\u5728 benchmark\u7684\u7522\u696d\u7a2e\u985e\u4e2d\u627e\u5230\uff0c\u5247 etf\u4e2d\u7279\u6b8a\u7684\u7522\u696d\u6539\u6210\u5176\u4ed6<br\/>etf['TSE\u7522\u696d\u540d'] = np.where(etf['TSE\u7522\u696d\u540d'].isin(benchmark['TSE\u7522\u696d\u540d'].unique().tolist()),<br\/>                          etf['TSE\u7522\u696d\u540d'],'\u5176\u4ed6')<\/pre>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1PdSyJnSozcL40_FzW11YLQ.png\"\/><\/figure>\n<p class=\"wp-block-paragraph\" id=\"d47f\"><strong>Step 4.<\/strong>\u00a0Caculate 00881 ETF and Taiwan 50 Index\u2019s monthly return<\/p>\n<p class=\"wp-block-paragraph\" id=\"7aaa\">We calculate the industry monthly return and industry weight for each industry in the 00881 ETF and Taiwan 50 Index.<\/p>\n<pre class=\"wp-block-preformatted\">etf = etf.sort_values(by=['\u5e74','\u6708','TSE\u7522\u696d\u540d','\u8b49\u5238\u4ee3\u78bc']).reset_index(drop=True) # \u6392\u5e8f\u5e74\u6708\u65e5<br\/>etf['TSE\u7522\u696d\u540d'] = np.where(etf['TSE\u7522\u696d\u540d'].isna(),'\u5176\u4ed6' ,etf['TSE\u7522\u696d\u540d'])etf['\u6b0a\u91cd'] = etf['\u6b0a\u91cd'] * 0.01etf['\u7522\u696d\u6b0a\u91cd'] = etf.groupby(['TSE\u7522\u696d\u540d','\u5e74','\u6708'])['\u6b0a\u91cd'].transform('sum')<br\/>etf['\u5be6\u969b\u7576\u6708\u5831\u916c\u7387'] = etf['\u6b0a\u91cd'] * etf['\u7576\u6708\u5831\u916c\u7387']<br\/>etf['\u7522\u696d\u7576\u6708\u5831\u916c\u7387'] = etf.groupby(['TSE\u7522\u696d\u540d','\u5e74','\u6708'])['\u5be6\u969b\u7576\u6708\u5831\u916c\u7387'].transform('sum') \/ etf['\u7522\u696d\u6b0a\u91cd']etf['\u5be6\u969b\u7522\u696d\u7576\u6708\u5831\u916c\u7387'] = etf['\u7522\u696d\u7576\u6708\u5831\u916c\u7387'] * etf['\u7522\u696d\u6b0a\u91cd']<br\/>etf['ETF \u7576\u6708\u5831\u916c\u7387'] = etf.groupby(['\u5e74','\u6708'])['\u5be6\u969b\u7576\u6708\u5831\u916c\u7387'].transform('sum')etf = etf[['\u5e74','\u6708','TSE\u7522\u696d\u540d','\u6a19\u7684\u540d\u7a31','\u6b0a\u91cd','\u7576\u6708\u5831\u916c\u7387','\u7522\u696d\u6b0a\u91cd','\u7522\u696d\u7576\u6708\u5831\u916c\u7387']]benchmark = benchmark.sort_values(by=['\u5e74','\u6708','TSE\u7522\u696d\u540d','\u8b49\u5238\u4ee3\u78bc']).reset_index(drop=True) # \u6392\u5e8f\u5e74\u6708\u65e5<br\/>benchmark = benchmark[['\u5e74\u6708\u65e5','TSE\u7522\u696d\u540d','\u6210\u4efd\u80a1','\u8b49\u5238\u4ee3\u78bc','\u5e74','\u6708','\u524d\u65e5\u5e02\u503c\u6bd4\u91cd','\u7576\u6708\u5831\u916c\u7387']]benchmark['\u524d\u65e5\u5e02\u503c\u6bd4\u91cd'] = benchmark['\u524d\u65e5\u5e02\u503c\u6bd4\u91cd'] * 0.01<br\/>benchmark['\u7522\u696d\u6b0a\u91cd'] = benchmark.groupby(['TSE\u7522\u696d\u540d','\u5e74','\u6708'])['\u524d\u65e5\u5e02\u503c\u6bd4\u91cd'].transform('sum')benchmark['\u5be6\u969b\u7576\u6708\u5831\u916c\u7387'] = benchmark['\u524d\u65e5\u5e02\u503c\u6bd4\u91cd'] * benchmark['\u7576\u6708\u5831\u916c\u7387']<br\/>benchmark['\u7522\u696d\u7576\u6708\u5831\u916c\u7387'] = benchmark.groupby(['TSE\u7522\u696d\u540d','\u5e74','\u6708'])['\u5be6\u969b\u7576\u6708\u5831\u916c\u7387'].transform('sum') \\<br\/>    \/ benchmark['\u7522\u696d\u6b0a\u91cd']benchmark['\u5be6\u969b\u7522\u696d\u7576\u6708\u5831\u916c\u7387'] = benchmark['\u7522\u696d\u7576\u6708\u5831\u916c\u7387'] * benchmark['\u7522\u696d\u6b0a\u91cd']<br\/>benchmark['ETF \u7576\u6708\u5831\u916c\u7387'] = benchmark.groupby(['\u5e74','\u6708'])['\u5be6\u969b\u7576\u6708\u5831\u916c\u7387'].transform('sum')benchmark.head(5)<\/pre>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1zlIi1ArQ3zLRU8LgQyc0uw.png\"\/><\/figure>\n<h2 class=\"wp-block-heading\" id=\"3795\"><strong>Performance attribution<\/strong><\/h2>\n<p class=\"wp-block-paragraph\" id=\"7c5b\">As shown in the table below, we can attribute excess return to allocation effects (Q2-Q1), selection effects (Q3-Q1), and interaction effects (Q4-Q3+Q2-Q1). Allocation effect mainly measures the impact of asset category, country, and industry contribution on excess return; selection effect mainly measures the impact selecting indivisual security with respect to a benchmark; and interactive effects are often incorporated into allocation effect or selection effect.<\/p>\n<figure class=\"wp-block-image aligncenter caption-align-center\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1AqvPgB9n8iNyRKwZX4mUVA.png\"\/><figcaption class=\"wp-element-caption\">Carl R. Bacon, CIPM, and Marc A. Wright, CFA<\/figcaption><\/figure>\n<pre class=\"wp-block-preformatted\">table = pd.merge(etf ,benchmark ,how = 'left' , on=['\u5e74','\u6708','TSE\u7522\u696d\u540d'])table['\u914d\u7f6e\u6548\u679c'] = (table['\u6295\u7d44\u6b0a\u91cd'] - table['\u6a19\u7aff\u6b0a\u91cd']) * \\<br\/>    (table['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'] - sum(table[:7]['\u6a19\u7aff\u6b0a\u91cd'] * table[:7]['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387']))table['\u9078\u64c7\u6548\u679c'] = table['\u6a19\u7aff\u6b0a\u91cd'] * (table['\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'] - table['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'])<br\/>table['\u4ea4\u4e92\u6548\u679c'] = (table['\u6295\u7d44\u6b0a\u91cd'] - table['\u6a19\u7aff\u6b0a\u91cd']) * (table['\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'] - table['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'])<br\/>table['\u4e3b\u52d5\u5831\u916c'] = table['\u914d\u7f6e\u6548\u679c'] + table['\u9078\u64c7\u6548\u679c'] + table['\u4ea4\u4e92\u6548\u679c']table.loc['\u5408\u8a08',:] = table.sum(axis=0)<br\/>table.loc['\u5408\u8a08','\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'] = sum(table[:7]['\u6295\u7d44\u6b0a\u91cd'] * table[:7]['\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'])<br\/>table.loc['\u5408\u8a08','\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'] = sum(table[:7]['\u6a19\u7aff\u6b0a\u91cd'] * table[:7]['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'])table = (table * 100).round(2)<br\/>table<\/pre>\n<p class=\"wp-block-paragraph\" id=\"5f23\">We calculated the performance attribution in November and found the 00881 ETF has a more precise stock selection ability, and its selection effect have 1.61%. However, the 00881 ETF aims for semiconductor, Internet, and electric vehicle stocks, the 00881 ETF and the Taiwan 50 Index are both nearly 60% of the weight is in the semiconductor industry, and the industry overlap is high. Therefore, the allocation effect have only 0.47%.<\/p>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1nE9RkNYxei3z6Jtj3rYHAQ.png\"\/><\/figure>\n<h2 class=\"wp-block-heading\" id=\"489d\"><strong>Visualization<\/strong><\/h2>\n<p class=\"wp-block-paragraph\" id=\"81a6\">We draw a three-month radar chart of the excess return of each industry, and analyze the excess return contributed by each industry every month, and find that the industry\u2019s contribution to the excess return of the investment group will fluctuate over time. However, return fluctuation is normal, we should pay attention to whether the excess return of the portfolio can be greater than 0 consistently.<\/p>\n<pre class=\"wp-block-preformatted\">fig = go.Figure()for date in etf['\u6708'].unique():<br\/>    table = pd.merge(etf ,benchmark ,how = 'left' , on=['\u5e74','\u6708','TSE\u7522\u696d\u540d'])<br\/>    table = table[table['\u6708'] == date]<br\/>    table = table.drop(['\u5e74','\u6708'], axis=1)<br\/>    table = table.set_index(['TSE\u7522\u696d\u540d'])<br\/>    table = table.sort_values(by=['\u6295\u7d44\u6b0a\u91cd'], ascending=False)<br\/>    table = table.fillna(0)<br\/>    <br\/>    table['\u914d\u7f6e\u6548\u679c'] = (table['\u6295\u7d44\u6b0a\u91cd'] - table['\u6a19\u7aff\u6b0a\u91cd']) * \\<br\/>        (table['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'] - sum(table[:7]['\u6a19\u7aff\u6b0a\u91cd'] * table[:7]['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387']))<br\/>        <br\/>    table['\u9078\u64c7\u6548\u679c'] = table['\u6a19\u7aff\u6b0a\u91cd'] * (table['\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'] - table['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'])<br\/>    table['\u4ea4\u4e92\u6548\u679c'] = (table['\u6295\u7d44\u6b0a\u91cd'] - table['\u6a19\u7aff\u6b0a\u91cd']) * (table['\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'] - table['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'])<br\/>    table['\u4e3b\u52d5\u5831\u916c'] = table['\u914d\u7f6e\u6548\u679c'] + table['\u9078\u64c7\u6548\u679c'] + table['\u4ea4\u4e92\u6548\u679c']<br\/>    <br\/>    table.loc['\u5408\u8a08',:] = table.sum(axis=0)<br\/>    table.loc['\u5408\u8a08','\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'] = sum(table[:7]['\u6295\u7d44\u6b0a\u91cd'] * table[:7]['\u6295\u7d44\u7576\u6708\u5831\u916c\u7387'])<br\/>    table.loc['\u5408\u8a08','\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'] = sum(table[:7]['\u6a19\u7aff\u6b0a\u91cd'] * table[:7]['\u6a19\u7aff\u7576\u6708\u5831\u916c\u7387'])<br\/>    <br\/>    table = (table * 100).round(2)<br\/>    <br\/>    fig.add_trace(go.Scatterpolar(r= table.loc['\u534a\u5c0e\u9ad4':'\u5176\u4ed6','\u4e3b\u52d5\u5831\u916c'].tolist(),<br\/>                                  theta= table.drop(['\u5408\u8a08']).index,<br\/>                                  fill='toself',<br\/>                                  name=str(date) + '\u6708'))fig.show()<\/pre>\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/1my_J5rm4z6sE8IFxi6uumA.png\"\/><\/figure>\n<h2 class=\"wp-block-heading\" id=\"f1f8\"><strong>Conclusion<\/strong><\/h2>\n<p class=\"wp-block-paragraph\" id=\"6d26\">Performance attribution can be uesd to clarify whether the stock selection and industry allocation are right, and can be used as a reference for future investment analysis and investment decisions. Finally, we recommend readers to use the ETF and index companies provided by the TEJ database, so that we can obtain the list stocks of the index in different periods and match the industries to which the constituent stocks belong, and analyze the performance attribution of different investment portfolios.<\/p>\n<p class=\"wp-block-paragraph\" id=\"b8b0\">It is for learning purposes only and does not take into account your individual needs, investment objectives and specific financial circumstances. Investment involves risk. Past performance is not indicative of future performance. Readers are requested to use their personal independent thinking skills to make investment decisions on their own. If losses are incurred due to relevant suggestions, it will not be involved with the author.<\/p>\n<h2 class=\"wp-block-heading\" id=\"b2ec\"><strong>Source Code<\/strong><\/h2>\n<ul class=\"wp-block-list\">\n<li><a class=\"ek-link\" href=\"https:\/\/gist.github.com\/tej87681088\/05668fae34ee4c3458aa9c17191dc847#file-tejapi_medium-9-ipynb\" rel=\"noopener\" target=\"_blank\">Click here to go Github<\/a><\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\" id=\"a336\"><strong>Related Link<\/strong><\/h2>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/api.tej.com.tw\/index.html\" rel=\"noreferrer noopener\" target=\"_blank\">TEJ API<\/a><\/li>\n<li><a href=\"https:\/\/eshop.tej.com.tw\/E-Shop\/Edata_intro\" rel=\"noreferrer noopener\" target=\"_blank\">TEJ E-Shop<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Analyze the source of portfolio performance Highlights Preface Portfolio\u2019s performance is affected by many factors. It is not easy for us to clearly distinguish whether the performance is due to the rise in the market, the stock selection ability of traders, or the proper allocation of assets or industries? Therefore, we can use the performance [\u2026]<\/p>\n","protected":false},"featured_media":2471,"template":"","tags":[50,65,70,71],"insight_category":[13],"class_list":["post-2480","insight","type-insight","status-publish","has-post-thumbnail","hentry","tag-market-data","tag-python","tag-tej-api","tag-quantitative-strategy","insight_category-quant-research"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight\/2480","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight"}],"about":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/types\/insight"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/media\/2471"}],"wp:attachment":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/media?parent=2480"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/tags?post=2480"},{"taxonomy":"insight_category","embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight_category?post=2480"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}