Building An Market-Weight Adjusted N50 Index Fund – Part II

The N50 Index Fund

Our goal is to make an index fund that will allocate the fund towards buying equities in the same ratio it is present in the NIFTY 50.  The stock’s weight changes each day in NIFTY. What is the correct allocation of the shares to buy is the agenda of this entire discussion. 

Framing the Data Source to Dataframe

The most comprehensive data for the NIFTY and its components are available in the  website of NIFTY Indices.
Inspecting the network requests we land in the URL https://iislliveblob.niftyindices.com/jsonfiles/HeatmapDetail/FinalHeatmapNIFTY%2050.json from where the data is coming. So Let’s run a small patch of code that fetches the data –
				
					import pandas as pd
df=pd.read_json('https://iislliveblob.niftyindices.com/jsonfiles/HeatmapDetail/FinalHeatmapNIFTY%2050.json')
df.head()
				
			

Output – 

				
					
per	ptsC	change	high	low	previousClose	sector	time	iislPtsChange	iislPercChange	...	indexDivisor	sharesOutstanding	symbol	investableWeightFactor	Indexmcap_yst	Indexmcap_today	priceperchange	NewIndexValue	pointchange	perchange
0	1.19	18.70	18.70	1588.00	1562.00	1568.20	Information Technology	Nov 22, 2022 16:00:24	16.85	1.07	...	4.422462e+09	4207753474	INFY	0.87	5740781128196	5802464690248	1.19	18173.916251	13.95	0.08
1	0.55	14.00	14.00	2568.50	2536.50	2550.90	Oil Gas & Consumable Fuels	Nov 22, 2022 16:00:24	14.15	0.55	...	4.422462e+09	6765355933	RELIANCE	0.51	8801450689240	8850272880330	0.55	18171.008059	11.04	0.06
2	0.84	27.50	27.50	3318.95	3255.25	3283.50	Information Technology	Nov 22, 2022 16:00:24	31.45	0.96	...	4.422462e+09	3659051373	TCS	0.28	3364058651309	3396280257699	0.84	18167.254361	7.29	0.04
3	0.83	2.80	2.80	341.00	335.70	337.20	Fast Moving Consumer Goods	Nov 22, 2022 16:00:24	3.05	0.90	...	4.422462e+09	12399178702	ITC	0.71	2968512171403	2995362592882	0.83	18166.039838	6.07	0.03
4	0.82	16.55	16.55	2033.15	2019.60	2011.45	Construction	Nov 22, 2022 16:00:24	18.35	0.91	...	4.422462e+09	1405191199	LT	0.86	2430765780017	2452941102328	0.82	18164.982712	5.01	0.03
5 rows × 24 columns
				
			

Another small code to list the name of the columns here – 

				
					df.columns
				
			

Output – 

				
					Index(['per', 'ptsC', 'change', 'high', 'low', 'previousClose', 'sector',
       'time', 'iislPtsChange', 'iislPercChange', 'ltP', 'cappingFactor',
       'adjustedClosePrice', 'dayEndClose', 'indexDivisor',
       'sharesOutstanding', 'symbol', 'investableWeightFactor',
       'Indexmcap_yst', 'Indexmcap_today', 'priceperchange', 'NewIndexValue',
       'pointchange', 'perchange'],
      dtype='object')
				
			

You can see it provides with the data of  IWF i.e. Investable Weight Factor too which was discussed in the last article. 

Defining "Index Weight"

As you can see above, in the list of the column names, there is an entry named
Indexmcap_today.

Now we can easily reverse engineer this data to check the exact % of allocation of any stock in the index today. Lets define that variable as IndexWeight.

				
					Net_Indexmcap_today = df['Indexmcap_today'].sum()
df['IndexWeight']=(df['Indexmcap_today']*100)/(Net_Indexmcap_today)
				
			
Now We are just printing three columns from the DataFrame with sorting in IndexWeight.
				
					
symbol	ltP	IndexWeight
17	IOC	116.85	0.435662
27	COALINDIA	156.00	0.480076
35	SBILIFE	980.75	0.561291
24	EICHERMOT	2761.00	0.565857
31	SHREECEM	28847.00	0.567727
26	HEROMOTOCO	3057.90	0.582835
12	BRITANNIA	3597.35	0.624342
15	TATACONSUM	709.05	0.625029
16	BPCL	489.50	0.667793
29	ONGC	125.00	0.668707
22	UPL	853.00	0.689627
11	CIPLA	954.00	0.711691
23	DIVISLAB	4245.05	0.793737
28	NTPC	116.40	0.810883
21	BAJAJ-AUTO	4268.95	0.816606
41	HINDALCO	388.00	0.831650
10	HDFCLIFE	691.50	0.839328
25	GRASIM	1502.05	0.842475
32	INDUSINDBK	1019.10	0.845643
36	POWERGRID	234.10	0.881194
30	NESTLEIND	17484.00	0.915986
7	TATAMOTORS	356.50	0.928907
34	ADANIPORTS	874.90	0.939112
14	DRREDDY	5287.00	0.940484
6	TECHM	1058.00	0.962694
39	JSWSTEEL	706.35	1.004699
37	BAJAJFINSV	11725.40	1.042082
8	TITAN	1710.00	1.049470
19	SUNPHARMA	679.70	1.076333
18	M&M	807.75	1.135777
38	ULTRACEMCO	6789.00	1.152134
20	WIPRO	551.30	1.196309
43	TATASTEEL	1110.00	1.269242
9	MARUTI	7336.95	1.432227
3	HCLTECH	967.00	1.541934
33	ASIANPAINT	2925.00	1.937540
1	BHARTIARTL	547.50	1.940650
13	BAJFINANCE	5746.85	2.241205
44	SBIN	427.40	2.407811
2	ITC	213.80	2.742063
40	LT	1549.95	2.748065
42	AXISBANK	745.45	2.753537
4	HINDUNILVR	2358.00	3.093373
45	KOTAKBANK	1792.00	3.862774
5	TCS	3199.35	4.868017
46	ICICIBANK	642.95	6.524685
48	HDFC	2555.00	6.757776
0	INFY	1414.00	7.690907
49	HDFCBANK	1483.00	9.486076
47	RELIANCE	2211.50	10.515982
				
			

The Base Value of our Fund

The goal here is to make the fund in a way that the minimum quantity of each stock is at least one.
  • The fat way of doing this is to start the program allocation from df['ltP].total() and keep increasing 1 INR till the “Qty” of all stocks is at least one.
  • The other approach which I have followed here is similar of LCM method which we have learnt in the elementary school
				
					MinCapital = max(df['ltP']/df['IndexWeight'])*50
MinCapital
				
			

Output – 

				
					1130084.2519603972
				
			

Now, Lets find the allocatable quantity of the stocks – 

				
					df['Qty'] = round((max(df['ltP']/df['IndexWeight']))/df['ltP'])
df['Value'] = df['Qty']*df['ltP']
				
			

Sorting the dataframe and printing it – 

				
					df[['symbol','ltP','IndexWeight','Qty','Value']].sort_values('IndexWeight', ascending=False)
				
			

The Final Output of Our Index Fund

Running the above code will result in the following output – 

				
						symbol	ltP	IndexWeight	Qty	Value
1	RELIANCE	2564.90	10.969006	9.0	23084.10
49	HDFCBANK	1597.00	8.698620	14.0	22358.00
6	ICICIBANK	922.65	7.976526	24.0	22143.60
0	INFY	1586.90	7.191560	14.0	22216.60
10	HDFC	2630.00	5.901042	9.0	23670.00
2	TCS	3311.00	4.209341	7.0	23177.00
3	ITC	340.00	3.712445	66.0	22440.00
47	KOTAKBANK	1936.00	3.532555	12.0	23232.00
4	LT	2028.00	3.040169	11.0	22308.00
29	SBIN	599.00	2.849494	38.0	22762.00
38	AXISBANK	869.80	2.848814	26.0	22614.80
8	HINDUNILVR	2511.00	2.783847	9.0	22599.00
48	BHARTIARTL	847.00	2.571469	27.0	22869.00
30	BAJFINANCE	6696.00	2.207147	3.0	20088.00
28	ASIANPAINT	3104.80	1.734273	7.0	21733.60
32	MARUTI	8887.15	1.461815	3.0	26661.45
13	M&M	1234.00	1.457462	18.0	22212.00
15	HCLTECH	1105.35	1.447320	20.0	22107.00
14	ADANIENT	4034.90	1.367927	6.0	24209.40
18	SUNPHARMA	1011.00	1.351694	22.0	22242.00
7	TITAN	2607.50	1.347797	9.0	23467.50
26	BAJAJFINSV	1645.05	1.232792	14.0	23030.70
17	TATASTEEL	105.35	1.051682	215.0	22650.25
9	NTPC	167.10	0.983729	135.0	22558.50
12	ULTRACEMCO	6855.00	0.979321	3.0	20565.00
21	TATAMOTORS	424.50	0.944014	53.0	22498.50
5	INDUSINDBK	1172.45	0.943802	19.0	22276.55
45	POWERGRID	218.25	0.922650	104.0	22698.00
46	NESTLEIND	19600.00	0.867192	1.0	19600.00
11	JSWSTEEL	709.70	0.827519	32.0	22710.40
23	TECHM	1051.85	0.823694	21.0	22088.85
20	GRASIM	1700.00	0.790482	13.0	22100.00
16	ADANIPORTS	881.25	0.785507	26.0	22912.50
37	HINDALCO	430.45	0.779624	53.0	22813.85
40	CIPLA	1103.95	0.739892	20.0	22079.00
36	WIPRO	389.00	0.713697	58.0	22562.00
33	SBILIFE	1232.00	0.685966	18.0	22176.00
31	DRREDDY	4383.00	0.656975	5.0	21915.00
43	ONGC	135.25	0.653490	167.0	22586.75
19	HDFCLIFE	540.00	0.632797	42.0	22680.00
27	BRITANNIA	4151.00	0.608176	5.0	20755.00
42	COALINDIA	229.40	0.594960	99.0	22710.60
41	EICHERMOT	3378.00	0.583375	7.0	23646.00
39	BAJAJ-AUTO	3619.00	0.575055	6.0	21714.00
35	TATACONSUM	772.00	0.572621	29.0	22388.00
22	APOLLOHOSP	4479.00	0.565548	5.0	22395.00
24	DIVISLAB	3306.00	0.522054	7.0	23142.00
25	UPL	768.00	0.507770	29.0	22272.00
34	HEROMOTOCO	2676.90	0.432300	8.0	21415.20
44	BPCL	306.50	0.362994	74.0	22681.00
				
			

The net allocated capital will be slightly less because we have rounded down the quantity when it became fractions. 

				
					AllocatedCapital = df['Value'].sum()
AllocatedCapital 
				
			

It will come around – 

				
					1123815.7000000002

				
			

To be Continued...

This is a part of the live discussion that happened on Unofficed Discussion Forum. Feel free to participate and engage in future discussions. Here are some agenda to be discussed later –

  • Would be able to calculate the NIFTY Value directly from the prices of the stocks in real-time?
  • And, Will there be an arbitrage opportunity if there is a difference in the value?

Let’s discuss this further in the next part of this discussion. Don’t shy away to share your code snippets or variations in the forum if You trying something 🙂

Post a comment

Leave a Comment

Your email address will not be published. Required fields are marked *

×Close