sgfixedincome_pkg.analysis ========================== .. py:module:: sgfixedincome_pkg.analysis Functions --------- .. autoapisummary:: sgfixedincome_pkg.analysis.filter_df sgfixedincome_pkg.analysis.best_returns sgfixedincome_pkg.analysis.best_rates sgfixedincome_pkg.analysis.products sgfixedincome_pkg.analysis.plot_rates_vs_tenure sgfixedincome_pkg.analysis.plot_best_rates sgfixedincome_pkg.analysis.plot_bank_offerings_with_fuzz sgfixedincome_pkg.analysis.better_allocation sgfixedincome_pkg.analysis.plot_better_allocation_strategy sgfixedincome_pkg.analysis.plot_pure_and_better_allocation_strategy_rates Module Contents --------------- .. py:function:: filter_df(combined_df, investment_amount=None, min_tenure=0, max_tenure=999, min_rate=None, consider_tbills=True, consider_ssbs=True, consider_fd=True, include_providers=None, exclude_providers=None) Filters the combined_df based on provided criteria, including investment amount, tenure, rate, product provider, product, and whether to consider T-bills and SSBs. :param combined_df: DataFrame containing columns 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Required multiples', 'Product provider', 'Product'. :type combined_df: pd.DataFrame :param investment_amount: The investment amount to filter available rates and products for that amount. :type investment_amount: float, optional :param min_tenure: The minimum tenure (in months) to filter. Default is 0. :type min_tenure: int, optional :param max_tenure: The maximum tenure (in months) to filter. Default is 999. :type max_tenure: int, optional :param min_rate: The minimum rate (% p.a.) to filter. Default is None (no filtering). :type min_rate: float, optional :param consider_tbills: Whether to consider T-bills. Default is True. :type consider_tbills: bool, optional :param consider_ssbs: Whether to consider SSBs. Default is True. :type consider_ssbs: bool, optional :param consider_fd: Whether to consider fixed deposits. Default is True. :type consider_fd: bool, optional :param include_providers: Exclusive list of providers to include. Default is None. :type include_providers: list, optional :param exclude_providers: List of providers to exclude. Default is None. :type exclude_providers: list, optional :returns: The filtered DataFrame based on the provided criteria. :rtype: pd.DataFrame .. py:function:: best_returns(combined_df, investment_amount, min_tenure=0, max_tenure=999) Calculate the highest total dollar return achievable for each possible tenure, considering that the offered rates and available products differ across invested amounts. This function assumes you only can select one product to invest in, and finds the highest dollar return attainable for each tenure. For products which only accept investment in specific multiples, we allocate the maximum amount of investment to them given the investment amount, and assume the remaining cash earns no return. As such, for each tenure, the product delivering the best return (our concern here) may differ from the product with the highest rates. For example, product 'A' with a higher rate but which has required multiples of investment may produce lower total dollar return compared to product 'B' with a lower rate but no required multiples, as the full amount of cash cannot be invested in product 'A' but can be fully invested into product 'B'. :param combined_df: DataFrame containing columns 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Required multiples', 'Product provider', 'Product'. :type combined_df: pd.DataFrame :param investment_amount: The investment amount to filter available rates and products for that amount. :type investment_amount: float :param min_tenure: The minimum tenure (in months) to consider. Default is 0. :type min_tenure: int, optional :param max_tenure: The maximum tenure (in months) to consider. Default is 999. :type max_tenure: int, optional :returns: A DataFrame with products that deliver the highest dollar return for each tenure, product details, and total dollar return from the investment. :rtype: pd.DataFrame .. py:function:: best_rates(combined_df, investment_amount, min_tenure=0, max_tenure=999) Display the highest rates offered for each possible tenure given an investment amount. :param combined_df: DataFrame containing columns 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Required multiples', 'Product provider', 'Product'. :type combined_df: pd.DataFrame :param investment_amount: The investment amount to filter available rates and products for that amount. :type investment_amount: float :param min_tenure: The minimum tenure (in months) to consider. Default is 0. :type min_tenure: int, optional :param max_tenure: The maximum tenure (in months) to consider. Default is 999. :type max_tenure: int, optional :returns: A DataFrame with the products offering the best rate (in % p.a.) for each tenure. :rtype: pd.DataFrame .. py:function:: products(combined_df) Returns a list of unique products in the dataset by joining the 'Product provider' and 'Product' columns. It considers unique combinations of these joined strings. :param combined_df: DataFrame containing the columns 'Product provider' and 'Product'. :type combined_df: pd.DataFrame :returns: A list of unique product combinations in the format 'Product provider - Product'. :rtype: list .. py:function:: plot_rates_vs_tenure(df, investment_amount, min_tenure=0, max_tenure=999) Plots a graph of Rate (% p.a.) vs Tenure (in months) for a given investment amount with optional filtering by tenure range. Each unique 'Product provider - Product' pair is plotted as a separate line. :param df: DataFrame containing the data to plot. Must include columns: 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Product provider', 'Product'. :type df: pd.DataFrame :param investment_amount: The investment amount to filter rows for the plot. :type investment_amount: float :param min_tenure: Minimum tenure (in months) to include. Default is 0. :type min_tenure: int, optional :param max_tenure: Maximum tenure (in months) to include. Default is 999. :type max_tenure: int or float, optional :raises ValueError: If no valid rows remain after filtering based on the investment amount and tenure. .. py:function:: plot_best_rates(df, investment_amount, min_tenure=0, max_tenure=999) Plot of best rates (% p.a.) for each tenure for a given investment amount, across available products. The plot color-codes the points by provider-product pair. :param df: DataFrame containing columns 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Required multiples', 'Product provider', 'Product'. :type df: pd.DataFrame :param investment_amount: The investment amount to filter available rates and products for that amount and to calculate the total return. :type investment_amount: float :param min_tenure: The minimum tenure (in months) to consider. Default is 0. :type min_tenure: int, optional :param max_tenure: The maximum tenure (in months) to consider. Default is 999. :type max_tenure: int, optional .. py:function:: plot_bank_offerings_with_fuzz(df, product_provider, fuzz_factor=0.02) Plots a graph of Rate (% p.a.) vs Tenure (in months) for a given bank, where each line represents a different deposit range (created by joining 'Deposit lower bound' and 'Deposit upper bound'). Adds small fuzz to the points to avoid overlap. :param df: DataFrame containing columns 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Product provider'. :type df: pd.DataFrame :param product_provider: The bank name (Product provider) to filter the data for. :type product_provider: str :param fuzz_factor: The amount of fuzz (random noise) to add to the points. Default is 0.02. :type fuzz_factor: float, optional :raises ValueError: If no data is available for the given product_provider. .. py:function:: better_allocation(df, investment_amount, tenure) Returns a better strategy to improve effective rate by allocating investment across different products. Strategy: 1. First sorts all available products by interest rate in descending order 2. For each provider-product pair, only allows investment in one deposit range (the one with highest rate that we can afford given remaining funds) 3. Allocates maximum possible amount to each product while respecting: deposit range bounds (lower and upper limits), required multiples (if any), and available remaining investment amount 4. Continues allocation until either the entire investment amount is allocated, or no more valid products are available Note that while this strategy often produces returns at least as good as investing in any single product, it may sometimes produce lower returns, and may also be different from the globally optimal allocation. For example, consider the case where we 'use up' a provider-product pair by allocating the full amount to a low deposit range with high rates, and because of that forfeit the ability to invest in the same provider-product at a higher deposit range but a slightly lower rate. The overall return may be higher by allocating more to a slightly lower rate deposit range. :param df: DataFrame containing 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Product provider', 'Product'. :type df: pd.DataFrame :param investment_amount: The total investment amount to allocate across different products. :type investment_amount: float :param tenure: The tenure in months for the investment. :type tenure: int :returns: A DataFrame containing: - Product provider: Provider offering the product - Product: Type of investment product - Allocated amount: Amount invested in this product - Rate (% p.a.): Annual interest rate as percentage - Expected return ($): Expected dollar return from this allocation Plus a summary row with totals and effective overall rate :rtype: pd.DataFrame .. py:function:: plot_better_allocation_strategy(df, investment_amount, min_tenure=0, max_tenure=999) Plot the Rate (% p.a.) against Tenure (Months) for the better allocation strategy across all tenures available in the dataframe. :param df: DataFrame containing 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Product provider', 'Product'. :type df: pd.DataFrame :param investment_amount: The total investment amount to allocate across different products. :type investment_amount: float :param min_tenure: The minimum tenure (in months) to include. Default is 0. :type min_tenure: int, optional :param max_tenure: The maximum tenure (in months) to include. Default is 999. :type max_tenure: int, optional .. py:function:: plot_pure_and_better_allocation_strategy_rates(df, investment_amount, min_tenure=0, max_tenure=999) Overlay plot for best rates (% p.a.) and effective better allocation strategy rates for each tenure. :param df: DataFrame containing 'Tenure', 'Rate', 'Deposit lower bound', 'Deposit upper bound', 'Product provider', 'Product'. :type df: pd.DataFrame :param investment_amount: The investment amount to filter available rates and products. :type investment_amount: float :param min_tenure: The minimum tenure (in months) to include. Default is 0. :type min_tenure: int, optional :param max_tenure: The maximum tenure (in months) to include. Default is 999. :type max_tenure: int, optional