diff --git a/BharatFinTrack/__init__.py b/BharatFinTrack/__init__.py
index 4986bbf..29c5764 100644
--- a/BharatFinTrack/__init__.py
+++ b/BharatFinTrack/__init__.py
@@ -10,4 +10,4 @@
]
-__version__ = '0.1.2'
+__version__ = '0.1.3'
diff --git a/BharatFinTrack/core.py b/BharatFinTrack/core.py
index 6fd7e08..b83806d 100644
--- a/BharatFinTrack/core.py
+++ b/BharatFinTrack/core.py
@@ -125,7 +125,8 @@ def _download_nse_tri(
response = requests.post(
url=self.url_nse_index_tri_data,
headers=headers,
- data=payload
+ data=payload,
+ timeout=30
)
response_data = response.json()
records = json.loads(response_data['d'])
diff --git a/BharatFinTrack/data/equity_indices.xlsx b/BharatFinTrack/data/equity_indices.xlsx
index 99ebf97..c9467f5 100644
Binary files a/BharatFinTrack/data/equity_indices.xlsx and b/BharatFinTrack/data/equity_indices.xlsx differ
diff --git a/BharatFinTrack/nse_index.py b/BharatFinTrack/nse_index.py
index c7ee03d..12ca375 100644
--- a/BharatFinTrack/nse_index.py
+++ b/BharatFinTrack/nse_index.py
@@ -7,7 +7,6 @@
import requests
import bs4
import matplotlib
-import warnings
from .nse_product import NSEProduct
from .core import Core
@@ -19,29 +18,29 @@ class NSEIndex:
(excluding dividend reinvestment).
'''
- def equity_cagr_from_launch(
+ def download_daily_summary_report(
self,
- http_headers: typing.Optional[dict[str, str]] = None,
- untracked_indices: bool = False
+ folder_path: str,
+ http_headers: typing.Optional[dict[str, str]] = None
) -> pandas.DataFrame:
'''
- Returns a DataFrame with the CAGR(%) of all NSE equity indices from inception.
+ Download the daily summary for all NSE indices and save it as the
+ 'daily_summary_report.csv' file in the specified folder path.
Parameters
----------
+ folder_path: str
+ Folder path to save the CSV file of the daily summary for all NSE indices.
+
http_headers : dict, optional
HTTP headers for the web request. Defaults to
:attr:`BharatFinTrack.core.Core.default_http_headers` if not provided.
- untracked_indices : bool, optional
- Defaults to False. If True, print two lists of untracked indices
- from downloaded and based files.
-
Returns
-------
DataFrame
- A DataFrame with the CAGR(%) for all NSE equity indices from inception.
+ A DataFrame containing the daily summary for all NSE indices.
'''
# web request headers
@@ -66,14 +65,47 @@ def equity_cagr_from_launch(
url=csv_link,
headers=headers
)
- with tempfile.TemporaryDirectory() as tmp_dir:
- download_file = os.path.join(tmp_dir, 'daily.csv')
+ if os.path.isdir(folder_path):
+ download_file = os.path.join(folder_path, 'daily_summary_report.csv')
with open(download_file, 'wb') as download_data:
download_data.write(response.content)
- download_df = pandas.read_csv(download_file)
+ output = pandas.read_csv(download_file)
+ else:
+ raise Exception('The folder path does not exist.')
else:
pass
+ return output
+
+ def equity_cagr_from_launch(
+ self,
+ http_headers: typing.Optional[dict[str, str]] = None,
+ untracked_indices: bool = False
+ ) -> pandas.DataFrame:
+
+ '''
+ Returns the CAGR (%) since launch for all NSE equity indices.
+
+ Parameters
+ ----------
+ http_headers : dict, optional
+ HTTP headers for the web request. Defaults to
+ :attr:`BharatFinTrack.core.Core.default_http_headers` if not provided.
+
+ untracked_indices : bool, optional
+ Defaults to False. If True, print two lists of untracked indices
+ from downloaded and based files.
+
+ Returns
+ -------
+ DataFrame
+ A DataFrame with the CAGR (%) since launch for all NSE equity indices.
+ '''
+
+ # downlod daily summary of NSE indices
+ with tempfile.TemporaryDirectory() as tmp_dir:
+ download_df = self.download_daily_summary_report(tmp_dir)
+
# processing downloaded data
date_string = datetime.datetime.strptime(
download_df.loc[0, 'Index Date'], '%d-%m-%Y'
@@ -82,9 +114,9 @@ def equity_cagr_from_launch(
download_df = download_df[
['Index Name', 'Index Date', 'Closing Index Value']
]
- download_df.columns = ['Index Name', 'Date', 'Close']
+ download_df.columns = ['Index Name', 'Close Date', 'Close Value']
download_df['Index Name'] = download_df['Index Name'].apply(lambda x: x.upper())
- download_df['Date'] = download_date
+ download_df['Close Date'] = download_date
# processing base DataFrame
base_df = NSEProduct()._dataframe_equity_index
@@ -104,7 +136,7 @@ def equity_cagr_from_launch(
# computing CAGR(%)
cagr_df = base_df.merge(download_df)
- cagr_df['Close/Base Value'] = cagr_df['Close'] / cagr_df['Base Value']
+ cagr_df['Close/Base'] = cagr_df['Close Value'] / cagr_df['Base Value']
cagr_df['Years'] = list(
map(
lambda x: dateutil.relativedelta.relativedelta(download_date, x).years, cagr_df['Base Date']
@@ -116,7 +148,7 @@ def equity_cagr_from_launch(
)
)
total_years = cagr_df['Years'] + (cagr_df['Days'] / 365)
- cagr_df['CAGR(%)'] = 100 * (pow(cagr_df['Close'] / cagr_df['Base Value'], 1 / total_years) - 1)
+ cagr_df['CAGR(%)'] = 100 * (pow(cagr_df['Close Value'] / cagr_df['Base Value'], 1 / total_years) - 1)
# output
if untracked_indices is False:
@@ -138,8 +170,7 @@ def sort_equity_cagr_from_launch(
) -> pandas.DataFrame:
'''
- Returns a DataFrame where equity indices are sorted
- in descending order of CAGR(%).
+ Returns equity indices sorted in descending order by CAGR (%) since launch.
Parameters
----------
@@ -153,8 +184,7 @@ def sort_equity_cagr_from_launch(
Returns
-------
DataFrame
- A DataFrame with the CAGR(%) for all NSE equity indices from inception,
- sorted in descending order by CAGR(%).
+ A DataFrame sorted in descending order by CAGR (%) since launch for all NSE equity indices.
'''
# DataFrame of CAGR(%)
@@ -171,7 +201,7 @@ def sort_equity_cagr_from_launch(
)
output = cagr_df.reset_index(drop=True)
- # saving the DataFrame
+ # saving DataFrame
excel_ext = Core()._excel_file_extension(excel_file)
if excel_ext != '.xlsx':
raise Exception(
@@ -183,15 +213,20 @@ def sort_equity_cagr_from_launch(
workbook = excel_writer.book
worksheet = excel_writer.sheets['Sheet1']
# format columns
- for col_num, df_col in enumerate(output.columns):
- if df_col == 'Index Name':
+ for col_num, col_df in enumerate(output.columns):
+ if col_df == 'Index Name':
worksheet.set_column(col_num, col_num, 60)
- elif df_col == 'Close/Base Value':
+ elif col_df == 'Close Value':
+ worksheet.set_column(
+ col_num, col_num, 15,
+ workbook.add_format({'num_format': '#,##0'})
+ )
+ elif col_df == 'Close/Base':
worksheet.set_column(
col_num, col_num, 15,
workbook.add_format({'num_format': '#,##0.0'})
)
- elif df_col == 'CAGR(%)':
+ elif col_df == 'CAGR(%)':
worksheet.set_column(
col_num, col_num, 15,
workbook.add_format({'num_format': '#,##0.00'})
@@ -208,8 +243,8 @@ def category_sort_equity_cagr_from_launch(
) -> pandas.DataFrame:
'''
- Returns a multi-index DataFrame where equity indices are sorted
- in descending order of CAGR(%) from inception within each category.
+ Returns equity indices sorted in descending order by CAGR (%)
+ since launch within each index category.
Parameters
----------
@@ -223,8 +258,8 @@ def category_sort_equity_cagr_from_launch(
Returns
-------
DataFrame
- A multi-index DataFrame with the CAGR(%) for all NSE equity indices from inception,
- sorted in descending order by CAGR(%) within each index category.
+ A multi-index DataFrame sorted in descending order by CAGR (%)
+ since launch within each index category.
'''
# DataFrame of CAGR(%)
@@ -240,13 +275,11 @@ def category_sort_equity_cagr_from_launch(
ordered=True
)
- # Sort the dataframe
+ # Sorting Dataframe
cagr_df = cagr_df.sort_values(
by=['Category', 'CAGR(%)', 'Years', 'Days'],
ascending=[True, False, False, False]
)
-
- # output
dataframes = []
for category in categories:
category_df = cagr_df[cagr_df['Category'] == category]
@@ -273,15 +306,20 @@ def category_sort_equity_cagr_from_launch(
index_cols = len(output.index.names)
# format columns
worksheet.set_column(0, index_cols - 1, 15)
- for col_num, df_col in enumerate(output.columns):
- if df_col == 'Index Name':
+ for col_num, col_df in enumerate(output.columns):
+ if col_df == 'Index Name':
worksheet.set_column(index_cols + col_num, index_cols + col_num, 60)
- elif df_col == 'Close/Base Value':
+ elif col_df == 'Close Value':
+ worksheet.set_column(
+ index_cols + col_num, index_cols + col_num, 15,
+ workbook.add_format({'num_format': '#,##0'})
+ )
+ elif col_df == 'Close/Base':
worksheet.set_column(
index_cols + col_num, index_cols + col_num, 15,
workbook.add_format({'num_format': '#,##0.0'})
)
- elif df_col == 'CAGR(%)':
+ elif col_df == 'CAGR(%)':
worksheet.set_column(
index_cols + col_num, index_cols + col_num, 15,
workbook.add_format({'num_format': '#,##0.00'})
@@ -310,32 +348,3 @@ def category_sort_equity_cagr_from_launch(
start_row = end_row + 1
return output
-
- def all_equity_index_cagr_from_inception(
- self,
- excel_file: str,
- http_headers: typing.Optional[dict[str, str]] = None
- ) -> pandas.DataFrame:
-
- '''
- .. warning::
- :meth:`NSEIndex.all_equity_index_cagr_from_inception` is deprecated and will be removed in version 0.1.3.
- Use :meth:`NSEIndex.category_sort_equity_cagr_from_launch` instead.
- '''
-
- message = '''Use the method category_sort_equity_cagr_from_launch(excel_file)
- instead of the deprecated method all_equity_index_cagr_from_inception(excel_file),
- which will be removed in version 0.1.3.
- '''
- warnings.warn(
- message,
- DeprecationWarning,
- stacklevel=2
- )
-
- output = self.category_sort_equity_cagr_from_launch(
- excel_file=excel_file,
- http_headers=http_headers
- )
-
- return output
diff --git a/BharatFinTrack/nse_tri.py b/BharatFinTrack/nse_tri.py
index 1eff518..8f09c1e 100644
--- a/BharatFinTrack/nse_tri.py
+++ b/BharatFinTrack/nse_tri.py
@@ -1,6 +1,8 @@
import typing
import datetime
+import dateutil.relativedelta
import pandas
+import matplotlib
from .nse_product import NSEProduct
from .core import Core
@@ -83,7 +85,7 @@ def download_historical_daily_data(
'''
Downloads historical daily closing values for the specified index
- between the given start and end dates, both inclusive, and returns them in a DataFrame.
+ between the given start and end dates, both inclusive.
Parameters
----------
@@ -165,3 +167,339 @@ def download_historical_daily_data(
worksheet.set_column(0, 1, 12)
return df
+
+ def download_equity_indices_updated_value(
+ self,
+ excel_file: str,
+ http_headers: typing.Optional[dict[str, str]] = None
+ ) -> pandas.DataFrame:
+
+ '''
+ Returns updated TRI values for all NSE indices.
+
+ Parameters
+ ----------
+ excel_file : str, optional
+ Path to an Excel file to save the DataFrame.
+
+ http_headers : dict, optional
+ HTTP headers for the web request. Defaults to
+ :attr:`BharatFinTrack.core.Core.default_http_headers` if not provided.
+
+ Returns
+ -------
+ DataFrame
+ A DataFrame containing updated TRI values for all NSE indices.
+ '''
+
+ # processing base DataFrame
+ base_df = NSEProduct()._dataframe_equity_index
+ base_df = base_df.reset_index()
+ base_df = base_df[base_df['API TRI'] != 'NON OPEN SOURCE'].reset_index(drop=True)
+ base_df = base_df.drop(columns=['ID', 'API TRI'])
+ base_df['Base Date'] = base_df['Base Date'].apply(lambda x: x.date())
+
+ # check the Excel file extension first
+ excel_ext = Core()._excel_file_extension(excel_file)
+ if excel_ext == '.xlsx':
+ pass
+ else:
+ raise Exception(f'Input file extension "{excel_ext}" does not match the required ".xlsx".')
+
+ # downloading data
+ today = datetime.date.today()
+ week_ago = today - datetime.timedelta(days=7)
+ end_date = today.strftime('%d-%b-%Y')
+ start_date = week_ago.strftime('%d-%b-%Y')
+ for base_index in base_df.index:
+ index_df = self.download_historical_daily_data(
+ index=base_df.loc[base_index, 'Index Name'],
+ start_date=start_date,
+ end_date=end_date
+ )
+ base_df.loc[base_index, 'Close Date'] = index_df.iloc[-1, 0]
+ base_df.loc[base_index, 'Close Value'] = index_df.iloc[-1, -1]
+
+ # saving the DataFrame
+ with pandas.ExcelWriter(excel_file, engine='xlsxwriter') as excel_writer:
+ base_df.to_excel(excel_writer, index=False)
+ worksheet = excel_writer.sheets['Sheet1']
+ # format columns
+ for col_num, df_col in enumerate(base_df.columns):
+ if df_col == 'Index Name':
+ worksheet.set_column(col_num, col_num, 60)
+ else:
+ worksheet.set_column(col_num, col_num, 15)
+
+ return base_df
+
+ def sort_equity_value_from_launch(
+ self,
+ input_excel: str,
+ output_excel: str,
+ ) -> pandas.DataFrame:
+
+ '''
+ Returns equity indices sorted in descending order by TRI values since launch.
+
+ Parameters
+ ----------
+ inout_excel : str
+ Path to the input Excel file.
+
+ output_excel : str
+ Path to an output Excel file to save the output DataFrame.
+
+ Returns
+ -------
+ DataFrame
+ A DataFrame sorted in descending order by TRI values since launch.
+ '''
+
+ # sorting DataFrame by TRI values
+ df = pandas.read_excel(input_excel)
+ df = df.drop(columns=['Category'])
+ df = df.sort_values(
+ by=['Close Value'],
+ ascending=[False]
+ )
+ df = df.reset_index(drop=True)
+ for col_df in df.columns:
+ if 'Date' in col_df:
+ df[col_df] = df[col_df].apply(lambda x: x.date())
+ else:
+ pass
+
+ # saving the DataFrame
+ excel_ext = Core()._excel_file_extension(output_excel)
+ if excel_ext != '.xlsx':
+ raise Exception(
+ f'Input file extension "{excel_ext}" does not match the required ".xlsx".'
+ )
+ else:
+ with pandas.ExcelWriter(output_excel, engine='xlsxwriter') as excel_writer:
+ df.to_excel(excel_writer, index=False)
+ worksheet = excel_writer.sheets['Sheet1']
+ # format columns
+ for col_num, col_df in enumerate(df.columns):
+ if col_df == 'Index Name':
+ worksheet.set_column(col_num, col_num, 60)
+ else:
+ worksheet.set_column(col_num, col_num, 15)
+
+ return df
+
+ def sort_equity_cagr_from_launch(
+ self,
+ input_excel: str,
+ output_excel: str,
+ ) -> pandas.DataFrame:
+
+ '''
+ Returns equity indices sorted in descending order by CAGR (%) since launch.
+
+ Parameters
+ ----------
+ inout_excel : str
+ Path to the input Excel file.
+
+ output_excel : str
+ Path to an output Excel file to save the output DataFrame.
+
+ Returns
+ -------
+ DataFrame
+ A DataFrame sorted in descending order by CAGR (%) values since launch.
+ '''
+
+ # DataFrame processing
+ df = pandas.read_excel(input_excel)
+ df = df.drop(columns=['Category'])
+ for col_df in df.columns:
+ if 'Date' in col_df:
+ df[col_df] = df[col_df].apply(lambda x: x.date())
+ else:
+ pass
+ df['Close/Base'] = df['Close Value'] / df['Base Value']
+ df['Years'] = list(
+ map(
+ lambda x, y: dateutil.relativedelta.relativedelta(x, y).years, df['Close Date'], df['Base Date']
+ )
+ )
+ df['Days'] = list(
+ map(
+ lambda x, y, z: (x - y.replace(year=y.year + z)).days, df['Close Date'], df['Base Date'], df['Years']
+ )
+ )
+ total_years = df['Years'] + (df['Days'] / 365)
+ df['CAGR(%)'] = 100 * (pow(df['Close Value'] / df['Base Value'], 1 / total_years) - 1)
+
+ # sorting DataFrame by CAGR (%) values
+ df = df.sort_values(
+ by=['CAGR(%)', 'Years', 'Days'],
+ ascending=[False, False, False]
+ )
+ df = df.reset_index(drop=True)
+
+ # saving the DataFrame
+ excel_ext = Core()._excel_file_extension(output_excel)
+ if excel_ext != '.xlsx':
+ raise Exception(
+ f'Input file extension "{excel_ext}" does not match the required ".xlsx".'
+ )
+ else:
+ with pandas.ExcelWriter(output_excel, engine='xlsxwriter') as excel_writer:
+ df.to_excel(excel_writer, index=False)
+ workbook = excel_writer.book
+ worksheet = excel_writer.sheets['Sheet1']
+ # format columns
+ for col_num, col_df in enumerate(df.columns):
+ if col_df == 'Index Name':
+ worksheet.set_column(col_num, col_num, 60)
+ elif col_df == 'Close Value':
+ worksheet.set_column(
+ col_num, col_num, 15,
+ workbook.add_format({'num_format': '#,##0'})
+ )
+ elif col_df == 'Close/Base':
+ worksheet.set_column(
+ col_num, col_num, 15,
+ workbook.add_format({'num_format': '#,##0.0'})
+ )
+ elif col_df == 'CAGR(%)':
+ worksheet.set_column(
+ col_num, col_num, 15,
+ workbook.add_format({'num_format': '#,##0.00'})
+ )
+ else:
+ worksheet.set_column(col_num, col_num, 15)
+
+ return df
+
+ def category_sort_equity_cagr_from_launch(
+ self,
+ input_excel: str,
+ output_excel: str,
+ ) -> pandas.DataFrame:
+
+ '''
+ Returns equity indices sorted in descending order by CAGR (%) since launch
+ within each index category.
+
+ Parameters
+ ----------
+ inout_excel : str
+ Path to the input Excel file.
+
+ output_excel : str
+ Path to an output Excel file to save the output DataFrame.
+
+ Returns
+ -------
+ DataFrame
+ A multi-index DataFrame sorted in descending order by CAGR (%) values since launch
+ within each index category.
+ '''
+
+ # DataFrame processing
+ df = pandas.read_excel(input_excel)
+ for col_df in df.columns:
+ if 'Date' in col_df:
+ df[col_df] = df[col_df].apply(lambda x: x.date())
+ else:
+ pass
+ df['Close/Base'] = df['Close Value'] / df['Base Value']
+ df['Years'] = list(
+ map(
+ lambda x, y: dateutil.relativedelta.relativedelta(x, y).years, df['Close Date'], df['Base Date']
+ )
+ )
+ df['Days'] = list(
+ map(
+ lambda x, y, z: (x - y.replace(year=y.year + z)).days, df['Close Date'], df['Base Date'], df['Years']
+ )
+ )
+ total_years = df['Years'] + (df['Days'] / 365)
+ df['CAGR(%)'] = 100 * (pow(df['Close Value'] / df['Base Value'], 1 / total_years) - 1)
+
+ # Convert 'Category' column to categorical data types with a defined order
+ categories = list(df['Category'].unique())
+ df['Category'] = pandas.Categorical(
+ df['Category'],
+ categories=categories,
+ ordered=True
+ )
+
+ # Sorting Dataframe
+ df = df.sort_values(
+ by=['Category', 'CAGR(%)', 'Years', 'Days'],
+ ascending=[True, False, False, False]
+ )
+ dataframes = []
+ for category in categories:
+ category_df = df[df['Category'] == category]
+ category_df = category_df.drop(columns=['Category']).reset_index(drop=True)
+ dataframes.append(category_df)
+ output = pandas.concat(
+ dataframes,
+ keys=[word.upper() for word in categories],
+ names=['Category', 'ID']
+ )
+
+ # saving the DataFrame
+ excel_ext = Core()._excel_file_extension(output_excel)
+ if excel_ext != '.xlsx':
+ raise Exception(
+ f'Input file extension "{excel_ext}" does not match the required ".xlsx".'
+ )
+ else:
+ with pandas.ExcelWriter(output_excel, engine='xlsxwriter') as excel_writer:
+ output.to_excel(excel_writer, index=True)
+ workbook = excel_writer.book
+ worksheet = excel_writer.sheets['Sheet1']
+ # number of columns for DataFrame indices
+ index_cols = len(output.index.names)
+ # format columns
+ worksheet.set_column(0, index_cols - 1, 15)
+ for col_num, col_df in enumerate(output.columns):
+ if col_df == 'Index Name':
+ worksheet.set_column(index_cols + col_num, index_cols + col_num, 60)
+ elif col_df == 'Close Value':
+ worksheet.set_column(
+ index_cols + col_num, index_cols + col_num, 15,
+ workbook.add_format({'num_format': '#,##0'})
+ )
+ elif col_df == 'Close/Base':
+ worksheet.set_column(
+ index_cols + col_num, index_cols + col_num, 15,
+ workbook.add_format({'num_format': '#,##0.0'})
+ )
+ elif col_df == 'CAGR(%)':
+ worksheet.set_column(
+ index_cols + col_num, index_cols + col_num, 15,
+ workbook.add_format({'num_format': '#,##0.00'})
+ )
+ else:
+ worksheet.set_column(index_cols + col_num, index_cols + col_num, 15)
+ # Dataframe colors
+ get_colormap = matplotlib.colormaps.get_cmap('Pastel2')
+ colors = [
+ get_colormap(count / len(dataframes)) for count in range(len(dataframes))
+ ]
+ hex_colors = [
+ '{:02X}{:02X}{:02X}'.format(*[int(num * 255) for num in color]) for color in colors
+ ]
+ # coloring of DataFrames
+ start_col = index_cols - 1
+ end_col = index_cols + len(output.columns) - 1
+ start_row = 1
+ for df, color in zip(dataframes, hex_colors):
+ color_format = workbook.add_format({'bg_color': color})
+ end_row = start_row + len(df) - 1
+ worksheet.conditional_format(
+ start_row, start_col, end_row, end_col,
+ {'type': 'no_blanks', 'format': color_format}
+ )
+ start_row = end_row + 1
+
+ return output
diff --git a/docs/changelog.rst b/docs/changelog.rst
index f6bf38c..a3e165a 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -3,6 +3,19 @@ Release Notes
===============
+Version 0.1.3
+--------------
+
+* **Release date:** 06-Oct-2024
+
+* **Feature Additions:**
+
+ * Fetches updated Total Return Index values for all NSE equity indices.
+ * Sorts the CAGR (%) of all NSE equity TRI values since launch.
+
+* **Bug Fixes:** Issues with the API used to fetch Total Return Index data.
+
+
Version 0.1.2
--------------
@@ -11,8 +24,9 @@ Version 0.1.2
* **Changes:**
* Deprecated :meth:`BharatFinTrack.NSEIndex.all_equity_index_cagr_from_inception` and introduced :meth:`BharatFinTrack.NSEIndex.category_sort_equity_cagr_from_launch`.
- * Added functionality for sorting the CAGR (%) of all NSE equity indices from launch.
- * Introduced sorting of the CAGR (%) of NSE equity indices from launch while maintaining fixed index categories.
+
+* **Feature Additions:** Added functionality for sorting the CAGR (%) of all NSE equity indices since launch.
+
* **Development Status:** Upgraded from Alpha to Beta.
@@ -35,7 +49,7 @@ Version 0.1.0
* **Release date:** 30-Sep-2024.
-* **Feature Additions:** Introduced :class:`BharatFinTrack.NSETRI` class, which facilitates downloading Total Return Index (TRI) data for all NSE equity indices.
+* **Feature Additions:** Introduced :class:`BharatFinTrack.NSETRI` class, which facilitates downloading Total Return Index data for all NSE equity indices.
* **Changes:**
diff --git a/docs/functionality.rst b/docs/functionality.rst
index fe7a359..ab148e7 100644
--- a/docs/functionality.rst
+++ b/docs/functionality.rst
@@ -14,8 +14,6 @@ This feature helps users make informed decisions about investments in passive fu
.. code-block:: python
- import BharatFinTrack
- nse_index = BharatFinTrack.NSEIndex()
nse_index.sort_equity_cagr_from_launch(
excel_file=r"C:\Users\Username\Folder\sort_cagr.xlsx"
)
@@ -30,6 +28,39 @@ better understand the difference in index returns across various categories.
nse_index.category_sort_equity_cagr_from_launch(
excel_file=r"C:\Users\Username\Folder\category_sort_cagr.xlsx"
)
+
+
+Equity Total Return Index (TRI) Summary
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Download the updated TRI values for all NSE indices. These values are not updated on the website on a daily basis.
+It is recommended to use this function at night when web traffic to the website is lower. The function sends several web requests to collect the required values.
+
+.. code-block:: python
+
+ excel_file = r"C:\Users\Username\Folder\tri_updated_value.xlsx"
+
+ # updated TRI value
+ nse_tri.download_equity_indices_updated_value(
+ excel_file=excel_file
+ )
+
+ # sort equity indices by updated value since launch
+ nse_tri.sort_equity_value_from_launch(
+ input_excel=excel_file,
+ output_excel=r"C:\Users\Username\Folder\sorted_tri_value.xlsx"
+ )
+
+ # sort equity indices by CAGR (%) since launch
+ nse_tri.sort_equity_cagr_from_launch(
+ input_excel=excel_file,
+ output_excel=r"C:\Users\Username\Folder\sorted_tri_cagr.xlsx"
+ )
+
+ # sort equity indices by CAGR (%) since launch within each category
+ nse_tri.category_sort_equity_cagr_from_launch(
+ input_excel=excel_file,
+ output_excel=r"C:\Users\Username\Folder\category_sort_tri_cagr.xlsx"
+ )
diff --git a/docs/introduction.rst b/docs/introduction.rst
index ad0eee4..c145785 100644
--- a/docs/introduction.rst
+++ b/docs/introduction.rst
@@ -8,6 +8,12 @@ BharatFinTrack is a Python package designed to simplify the process of downloadi
* `Nifty Indices `_
- Provides access to the characteristics of NSE equity indices.
- - Calculates the CAGR(%) of all NSE equity indices (excluding dividend reinvestment) from inception.
- - Facilitates downloading Total Return Index, including both price and dividend reinvestment, data for all NSE equity indices.
+ - Fetches updated values of prices (excluding dividend reinvestment) and Total Return Index (TRI) for all NSE equity indices.
+ - Facilitates downloading TRI data for all NSE equity indices between the specified start and end dates, inclusive.
+
+
+* Analysis
+
+ - Calculates the updated CAGR (%) of all NSE equity index prices and TRI since their inception.
+ - Sorts equity indices by CAGR (%) values since inception.
\ No newline at end of file
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index 622cf1e..331093d 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -13,6 +13,8 @@ Ensure successful installation by running the following commands:
import BharatFinTrack
nse_product = BharatFinTrack.NSEProduct()
+ nse_index = BharatFinTrack.NSEIndex()
+ nse_tri = BharatFinTrack.NSETRI()
NSE Equity Index Characteristics
@@ -36,7 +38,7 @@ Expected output:
Index List
-^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^
Get the list of all NSE equity indices:
@@ -97,28 +99,27 @@ Expected output:
Download Data
---------------
+NSE Indices Summary
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+Download the daily summary report for all NSE indices, which is uploaded daily on the `Nifty Indices Reports `_, and save
+as 'daily_summary_report.csv' in the specified folder path.
+
+.. code-block:: python
+
+ nse_index.download_daily_summary_report(
+ folder_path=r"C:\Users\Username\Folder"
+ )
+
+
Total Return Index (TRI)
^^^^^^^^^^^^^^^^^^^^^^^^^^
-Download historical daily TRI data, including both price and dividend reinvestment, for the NIFTY 50 index:
+Download historical daily TRI data, including both price and dividend reinvestment, for the NIFTY 50 index.
+Currently, the function supports only equity indices.
.. code-block:: python
- import BharatFinTrack
- nse_tri = BharatFinTrack.NSETRI()
nse_tri.download_historical_daily_data(
index='NIFTY 50',
start_date='23-Sep-2024',
end_date='27-Sep-2024'
)
-
-
-Expected output:
-
-.. code-block:: text
-
- Date Close
- 0 2024-09-23 38505.51
- 1 2024-09-24 38507.55
- 2 2024-09-25 38602.21
- 3 2024-09-26 38916.76
- 4 2024-09-27 38861.64
\ No newline at end of file
diff --git a/tests/test_bharatfintrack.py b/tests/test_bharatfintrack.py
index 4369f94..6e7f13e 100644
--- a/tests/test_bharatfintrack.py
+++ b/tests/test_bharatfintrack.py
@@ -39,6 +39,7 @@ def message():
'error_date2': "time data '20-Se-2024' does not match format '%d-%b-%Y'",
'error_date3': 'Start date 27-Sep-2024 cannot be later than end date 26-Sep-2024.',
'error_excel': 'Input file extension ".xl" does not match the required ".xlsx".',
+ 'error_folder': 'The folder path does not exist.',
'error_index1': '"INVALID" index does not exist.',
'error_index2': '"NIFTY50 USD" index data is not available as open-source.'
@@ -249,6 +250,19 @@ def test_index_download_historical_daily_data(
assert float(df.iloc[-1, -1]) == expected_value
+def test_download_daily_summary_report(
+ nse_index,
+ message
+):
+
+ # test for error when the input is a invalid folder path
+ with tempfile.TemporaryDirectory() as tmp_dir:
+ pass
+ with pytest.raises(Exception) as exc_info:
+ nse_index.download_daily_summary_report(tmp_dir)
+ assert exc_info.value.args[0] == message['error_folder']
+
+
def test_equity_cagr_from_launch(
nse_index,
capsys
@@ -287,8 +301,7 @@ def test_sort_equity_cagr_from_launch(
assert exc_info.value.args[0] == message['error_excel']
-@pytest.mark.filterwarnings('ignore::DeprecationWarning')
-def test_all_index_cagr_from_inception(
+def test_category_sort_equity_cagr_from_launch(
nse_index,
message
):
@@ -296,7 +309,7 @@ def test_all_index_cagr_from_inception(
# pass test
with tempfile.TemporaryDirectory() as tmp_dir:
excel_file = os.path.join(tmp_dir, 'equity.xlsx')
- nse_index.all_equity_index_cagr_from_inception(
+ nse_index.category_sort_equity_cagr_from_launch(
excel_file=excel_file
)
df = pandas.read_excel(excel_file, index_col=[0, 1])
@@ -305,7 +318,73 @@ def test_all_index_cagr_from_inception(
# error test for invalid Excel file input
with pytest.raises(Exception) as exc_info:
- nse_index.all_equity_index_cagr_from_inception(
+ nse_index.category_sort_equity_cagr_from_launch(
excel_file='equily.xl'
)
assert exc_info.value.args[0] == message['error_excel']
+
+
+def test_download_equity_indices_updated_value(
+ nse_tri,
+ message
+):
+
+ with tempfile.TemporaryDirectory() as tmp_dir:
+ excel_file = os.path.join(tmp_dir, 'equity.xlsx')
+ # pass test for downloading updated TRI values of NSE equity indices
+ nse_tri.download_equity_indices_updated_value(
+ excel_file=excel_file
+ )
+ df = pandas.read_excel(excel_file)
+ assert df.shape[1] == 6
+ # error test for invalid Excel file input
+ with pytest.raises(Exception) as exc_info:
+ nse_tri.download_equity_indices_updated_value(
+ excel_file='output.xl'
+ )
+ assert exc_info.value.args[0] == message['error_excel']
+ # pass test for sorting of NSE equity indices by TRI values
+ output_excel = os.path.join(tmp_dir, 'sorted_tri_value.xlsx')
+ nse_tri.sort_equity_value_from_launch(
+ input_excel=excel_file,
+ output_excel=output_excel
+ )
+ df = pandas.read_excel(output_excel)
+ assert df.shape[1] == 5
+ # error test for invalid Excel file input
+ with pytest.raises(Exception) as exc_info:
+ nse_tri.sort_equity_value_from_launch(
+ input_excel=excel_file,
+ output_excel='output.xl'
+ )
+ assert exc_info.value.args[0] == message['error_excel']
+ # pass test for sorting of NSE equity indices by CAGR (%) value
+ output_excel = os.path.join(tmp_dir, 'sorted_tri_cagr.xlsx')
+ nse_tri.sort_equity_cagr_from_launch(
+ input_excel=excel_file,
+ output_excel=output_excel
+ )
+ df = pandas.read_excel(output_excel)
+ assert df.shape[1] == 9
+ # error test for invalid Excel file input
+ with pytest.raises(Exception) as exc_info:
+ nse_tri.sort_equity_cagr_from_launch(
+ input_excel=excel_file,
+ output_excel='output.xl'
+ )
+ assert exc_info.value.args[0] == message['error_excel']
+ # pass test for categorical sorting NSE equity indices by CAGR (%) value
+ output_excel = os.path.join(tmp_dir, 'categorical_sorted_tri_cagr.xlsx')
+ nse_tri.category_sort_equity_cagr_from_launch(
+ input_excel=excel_file,
+ output_excel=output_excel
+ )
+ df = pandas.read_excel(output_excel, index_col=[0, 1])
+ assert len(df.index.get_level_values('Category').unique()) == 5
+ # error test for invalid Excel file input
+ with pytest.raises(Exception) as exc_info:
+ nse_tri.category_sort_equity_cagr_from_launch(
+ input_excel=excel_file,
+ output_excel='output.xl'
+ )
+ assert exc_info.value.args[0] == message['error_excel']