Compare commits
	
		
			7 Commits
		
	
	
		
			d229c9cf2d
			...
			cae704b658
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cae704b658 | |||
| a69f3e495e | |||
| 40429fc70a | |||
| c7e955f91e | |||
| d0c087c3bf | |||
| 2367d1aef8 | |||
| 31abaa4052 | 
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -4,4 +4,7 @@ | ||||
| *egg-info | ||||
| __pycache__ | ||||
| .vscode | ||||
| .idea | ||||
| .idea | ||||
| build | ||||
| .coverage | ||||
| .DS_store | ||||
| @ -1,15 +0,0 @@ | ||||
| # Fincal | ||||
| This module simplified handling of time-series data | ||||
| 
 | ||||
| ## The problem | ||||
| Time series data often have missing data points. These missing points mess things up when you are trying to do a comparison between two sections of a time series. | ||||
| 
 | ||||
| To make things worse, most libraries don't allow comparison based on dates. Month to Month and year to year comparisons become difficult as they cannot be translated into number of days. However, these are commonly used metrics while looking at financial data. | ||||
| 
 | ||||
| ## The Solution | ||||
| Fincal aims to simplify things by allowing you to: | ||||
| * Compare time-series data based on dates | ||||
| * Easy way to work around missing dates by taking the closest data points | ||||
| * Completing series with missing data points using forward fill and backward fill | ||||
| 
 | ||||
| ## Examples | ||||
| @ -1,233 +0,0 @@ | ||||
| { | ||||
|  "cells": [ | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 1, | ||||
|    "id": "3f7938c0-98e3-43b8-86e8-4f000cda7ce5", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import datetime\n", | ||||
|     "import pandas as pd\n", | ||||
|     "\n", | ||||
|     "from fincal.fincal import TimeSeries\n", | ||||
|     "from fincal.core import Series" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "id": "4b8ccd5f-dfff-4202-82c4-f66a30c122b6", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "CPU times: user 152 ms, sys: 284 ms, total: 436 ms\n", | ||||
|       "Wall time: 61.3 ms\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "TimeSeries([(datetime.datetime(2021, 5, 28, 0, 0), 249.679993),\n", | ||||
|        "\t(datetime.datetime(2022, 1, 31, 0, 0), 310.980011)], frequency='D')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 2, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "%%time\n", | ||||
|     "dfd = pd.read_csv('test_files/msft.csv')\n", | ||||
|     "# dfd = dfd[dfd['amfi_code'] == 118825].reset_index(drop=True)\n", | ||||
|     "ts = TimeSeries([(i.date, i.nav) for i in dfd.itertuples()], frequency='D')\n", | ||||
|     "repr(ts)\n", | ||||
|     "ts[['2022-01-31', '2021-05-28']]" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 3, | ||||
|    "id": "a0232e05-27c7-4d2d-a4bc-5dcf42666983", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "ename": "TypeError", | ||||
|      "evalue": "Type List cannot be instantiated; use list() instead", | ||||
|      "output_type": "error", | ||||
|      "traceback": [ | ||||
|       "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | ||||
|       "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)", | ||||
|       "Input \u001b[0;32mIn [3]\u001b[0m, in \u001b[0;36m<cell line: 7>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfincal\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcore\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Frequency\n\u001b[1;32m      3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m List, Tuple\n\u001b[1;32m      5\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcreate_test_data\u001b[39m(\n\u001b[1;32m      6\u001b[0m     frequency: Frequency,\n\u001b[1;32m      7\u001b[0m     num: \u001b[38;5;28mint\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1000\u001b[39m,\n\u001b[1;32m      8\u001b[0m     skip_weekends: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m      9\u001b[0m     mu: \u001b[38;5;28mfloat\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.1\u001b[39m,\n\u001b[1;32m     10\u001b[0m     sigma: \u001b[38;5;28mfloat\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.05\u001b[39m,\n\u001b[1;32m     11\u001b[0m     eomonth: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[0;32m---> 12\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[43mList\u001b[49m\u001b[43m(\u001b[49m\u001b[43mTuple\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[1;32m     13\u001b[0m     \u001b[38;5;124;03m\"\"\"Creates TimeSeries data\u001b[39;00m\n\u001b[1;32m     14\u001b[0m \n\u001b[1;32m     15\u001b[0m \u001b[38;5;124;03m    Parameters:\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     35\u001b[0m \u001b[38;5;124;03m        Returns a TimeSeries object\u001b[39;00m\n\u001b[1;32m     36\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[1;32m     38\u001b[0m     start_date \u001b[38;5;241m=\u001b[39m datetime\u001b[38;5;241m.\u001b[39mdatetime(\u001b[38;5;241m2017\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m1\u001b[39m)\n", | ||||
|       "File \u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/typing.py:941\u001b[0m, in \u001b[0;36m_BaseGenericAlias.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m    939\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m    940\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inst:\n\u001b[0;32m--> 941\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mType \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m cannot be instantiated; \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m    942\u001b[0m                         \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124muse \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__origin__\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m() instead\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m    943\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__origin__(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m    944\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n", | ||||
|       "\u001b[0;31mTypeError\u001b[0m: Type List cannot be instantiated; use list() instead" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "from fincal.fincal import create_date_series\n", | ||||
|     "from fincal.core import Frequency\n", | ||||
|     "from typing import List, Tuple\n", | ||||
|     "\n", | ||||
|     "def create_test_data(\n", | ||||
|     "    frequency: Frequency,\n", | ||||
|     "    num: int = 1000,\n", | ||||
|     "    skip_weekends: bool = False,\n", | ||||
|     "    mu: float = 0.1,\n", | ||||
|     "    sigma: float = 0.05,\n", | ||||
|     "    eomonth: bool = False,\n", | ||||
|     ") -> List[Tuple]:\n", | ||||
|     "    \"\"\"Creates TimeSeries data\n", | ||||
|     "\n", | ||||
|     "    Parameters:\n", | ||||
|     "    -----------\n", | ||||
|     "    frequency: Frequency\n", | ||||
|     "        The frequency of the time series data to be generated.\n", | ||||
|     "\n", | ||||
|     "    num: int\n", | ||||
|     "        Number of date: value pairs to be generated.\n", | ||||
|     "\n", | ||||
|     "    skip_weekends: bool\n", | ||||
|     "        Whether weekends (saturday, sunday) should be skipped.\n", | ||||
|     "        Gets used only if the frequency is daily.\n", | ||||
|     "\n", | ||||
|     "    mu: float\n", | ||||
|     "        Mean return for the values.\n", | ||||
|     "\n", | ||||
|     "    sigma: float\n", | ||||
|     "        standard deviation of the values.\n", | ||||
|     "\n", | ||||
|     "    Returns:\n", | ||||
|     "    --------\n", | ||||
|     "        Returns a TimeSeries object\n", | ||||
|     "    \"\"\"\n", | ||||
|     "\n", | ||||
|     "    start_date = datetime.datetime(2017, 1, 1)\n", | ||||
|     "    timedelta_dict = {\n", | ||||
|     "        frequency.freq_type: int(\n", | ||||
|     "            frequency.value * num * (7 / 5 if frequency == AllFrequencies.D and skip_weekends else 1)\n", | ||||
|     "        )\n", | ||||
|     "    }\n", | ||||
|     "    end_date = start_date + relativedelta(**timedelta_dict)\n", | ||||
|     "    dates = create_date_series(start_date, end_date, frequency.symbol, skip_weekends=skip_weekends, eomonth=eomonth)\n", | ||||
|     "    values = create_prices(1000, mu, sigma, num)\n", | ||||
|     "    ts = list(zip(dates, values))\n", | ||||
|     "    return ts" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": null, | ||||
|    "id": "53dbc8a6-d7b1-4d82-ac3d-ee3908ff086d", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 1, | ||||
|    "id": "aa1584d5-1df0-4661-aeeb-5e8c424de06d", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "from fincal import fincal\n", | ||||
|     "from fincal.core import FincalOptions\n", | ||||
|     "import csv" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 8, | ||||
|    "id": "7d51fca1-f731-47c8-99c9-6e199cfeca92", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "['date', 'nav']\n", | ||||
|       "CPU times: user 47.7 ms, sys: 3.16 ms, total: 50.9 ms\n", | ||||
|       "Wall time: 50.3 ms\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "TimeSeries([(datetime.datetime(1992, 2, 19, 0, 0), '2.398438'),\n", | ||||
|        "\t    (datetime.datetime(1992, 2, 20, 0, 0), '2.447917'),\n", | ||||
|        "\t    (datetime.datetime(1992, 2, 21, 0, 0), '2.385417')\n", | ||||
|        "\t    ...\n", | ||||
|        "\t    (datetime.datetime(2022, 2, 16, 0, 0), '299.5'),\n", | ||||
|        "\t    (datetime.datetime(2022, 2, 17, 0, 0), '290.730011'),\n", | ||||
|        "\t    (datetime.datetime(2022, 2, 18, 0, 0), '287.929993')], frequency='M')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 8, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "%%time\n", | ||||
|     "FincalOptions.date_format = '%Y-%m-%d'\n", | ||||
|     "fincal.read_csv('test_files/msft.csv', frequency='M')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 9, | ||||
|    "id": "b689f64c-6764-45b5-bccf-f23b351f6419", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import pandas as pd" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 11, | ||||
|    "id": "6c9b2dd7-9983-40cd-8ac4-3530a3892f17", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "CPU times: user 61.4 ms, sys: 2.35 ms, total: 63.7 ms\n", | ||||
|       "Wall time: 62.6 ms\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "%%time\n", | ||||
|     "dfd = pd.read_csv(\"test_files/msft.csv\")\n", | ||||
|     "ts = fincal.TimeSeries([(i.date, i.nav) for i in dfd.itertuples()], frequency=\"D\")" | ||||
|    ] | ||||
|   } | ||||
|  ], | ||||
|  "metadata": { | ||||
|   "kernelspec": { | ||||
|    "display_name": "Python 3 (ipykernel)", | ||||
|    "language": "python", | ||||
|    "name": "python3" | ||||
|   }, | ||||
|   "language_info": { | ||||
|    "codemirror_mode": { | ||||
|     "name": "ipython", | ||||
|     "version": 3 | ||||
|    }, | ||||
|    "file_extension": ".py", | ||||
|    "mimetype": "text/x-python", | ||||
|    "name": "python", | ||||
|    "nbconvert_exporter": "python", | ||||
|    "pygments_lexer": "ipython3", | ||||
|    "version": "3.10.2" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 5 | ||||
| } | ||||
							
								
								
									
										21
									
								
								Check3.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								Check3.py
									
									
									
									
									
								
							| @ -1,21 +0,0 @@ | ||||
| import datetime | ||||
| import math | ||||
| import random | ||||
| import time | ||||
| from typing import List | ||||
| 
 | ||||
| from dateutil.relativedelta import relativedelta | ||||
| 
 | ||||
| import pyfacts as pft | ||||
| 
 | ||||
| data = [ | ||||
|     ("2021-01-01", 10), | ||||
|     ("2021-02-01", 12), | ||||
|     ("2021-03-01", 14), | ||||
|     ("2021-04-01", 16), | ||||
|     ("2021-05-01", 18), | ||||
|     ("2021-06-01", 20), | ||||
| ] | ||||
| 
 | ||||
| ts = pft.TimeSeries(data) | ||||
| print(repr(ts)) | ||||
							
								
								
									
										118
									
								
								check.py
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								check.py
									
									
									
									
									
								
							| @ -1,118 +0,0 @@ | ||||
| import datetime | ||||
| import math | ||||
| import random | ||||
| 
 | ||||
| # import time | ||||
| from typing import List | ||||
| 
 | ||||
| from dateutil.relativedelta import relativedelta | ||||
| 
 | ||||
| import pyfacts as pft | ||||
| 
 | ||||
| 
 | ||||
| def create_prices(s0: float, mu: float, sigma: float, num_prices: int) -> list: | ||||
|     """Generates a price following a geometric brownian motion process based on the input of the arguments. | ||||
| 
 | ||||
|         Since this function is used only to generate data for tests, the seed is fixed as 1234. | ||||
|         Many of the tests rely on exact values generated using this seed. | ||||
|         If the seed is changed, those tests will fail. | ||||
| 
 | ||||
|     Parameters: | ||||
|     ------------ | ||||
|     s0: float | ||||
|         Asset inital price. | ||||
| 
 | ||||
|     mu: float | ||||
|         Interest rate expressed annual terms. | ||||
| 
 | ||||
|     sigma: float | ||||
|         Volatility expressed annual terms. | ||||
| 
 | ||||
|     num_prices: int | ||||
|         number of prices to generate | ||||
| 
 | ||||
|     Returns: | ||||
|     -------- | ||||
|         Returns a list of values generated using GBM algorithm | ||||
|     """ | ||||
| 
 | ||||
|     random.seed(1234)  # WARNING! Changing the seed will cause most tests to fail | ||||
|     all_values = [] | ||||
|     for _ in range(num_prices): | ||||
|         s0 *= math.exp( | ||||
|             (mu - 0.5 * sigma**2) * (1.0 / 365.0) + sigma * math.sqrt(1.0 / 365.0) * random.gauss(mu=0, sigma=1) | ||||
|         ) | ||||
|         all_values.append(round(s0, 2)) | ||||
| 
 | ||||
|     return all_values | ||||
| 
 | ||||
| 
 | ||||
| def sample_data_generator( | ||||
|     frequency: pft.Frequency, | ||||
|     num: int = 1000, | ||||
|     skip_weekends: bool = False, | ||||
|     mu: float = 0.1, | ||||
|     sigma: float = 0.05, | ||||
|     eomonth: bool = False, | ||||
| ) -> List[tuple]: | ||||
|     """Creates TimeSeries data | ||||
| 
 | ||||
|     Parameters: | ||||
|     ----------- | ||||
|     frequency: Frequency | ||||
|         The frequency of the time series data to be generated. | ||||
| 
 | ||||
|     num: int | ||||
|         Number of date: value pairs to be generated. | ||||
| 
 | ||||
|     skip_weekends: bool | ||||
|         Whether weekends (saturday, sunday) should be skipped. | ||||
|         Gets used only if the frequency is daily. | ||||
| 
 | ||||
|     mu: float | ||||
|         Mean return for the values. | ||||
| 
 | ||||
|     sigma: float | ||||
|         standard deviation of the values. | ||||
| 
 | ||||
|     Returns: | ||||
|     -------- | ||||
|         Returns a TimeSeries object | ||||
|     """ | ||||
| 
 | ||||
|     start_date = datetime.datetime(2017, 1, 1) | ||||
|     timedelta_dict = { | ||||
|         frequency.freq_type: int( | ||||
|             frequency.value * num * (7 / 5 if frequency == pft.AllFrequencies.D and skip_weekends else 1) | ||||
|         ) | ||||
|     } | ||||
|     end_date = start_date + relativedelta(**timedelta_dict) | ||||
|     dates = pft.create_date_series(start_date, end_date, frequency.symbol, skip_weekends=skip_weekends, eomonth=eomonth) | ||||
|     values = create_prices(1000, mu, sigma, num) | ||||
|     ts = list(zip(dates, values)) | ||||
|     return ts | ||||
| 
 | ||||
| 
 | ||||
| market_data = sample_data_generator(num=3600, frequency=pft.AllFrequencies.D, skip_weekends=False) | ||||
| mts = pft.TimeSeries(market_data, "D") | ||||
| print(mts) | ||||
| 
 | ||||
| # print("Datediff=", (mts.end_date - mts.start_date).days) | ||||
| # stock_data = sample_data_generator(num=3600, frequency=pft.AllFrequencies.D, skip_weekends=False, mu=0.12, sigma=0.15) | ||||
| # sts = pft.TimeSeries(stock_data, "D") | ||||
| # print(sts) | ||||
| 
 | ||||
| # start = time.time() | ||||
| # alpha = pft.jensens_alpha( | ||||
| #     asset_data=sts, market_data=mts, risk_free_rate=0.052, return_period_unit="months", return_period_value=1 | ||||
| # ) | ||||
| 
 | ||||
| # print(alpha) | ||||
| 
 | ||||
| # print("Alpha calculation took", time.time() - start, "seconds") | ||||
| 
 | ||||
| # print("Correlation=", pft.correlation(sts, mts)) | ||||
| 
 | ||||
| rr = mts.calculate_rolling_returns(frequency="D") | ||||
| 
 | ||||
| print(117, rr[rr.values < 0.1]) | ||||
							
								
								
									
										100
									
								
								check2.py
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								check2.py
									
									
									
									
									
								
							| @ -1,100 +0,0 @@ | ||||
| import datetime | ||||
| import math | ||||
| import random | ||||
| import time | ||||
| from typing import List | ||||
| 
 | ||||
| from dateutil.relativedelta import relativedelta | ||||
| 
 | ||||
| import pyfacts as pft | ||||
| 
 | ||||
| 
 | ||||
| def create_prices(s0: float, mu: float, sigma: float, num_prices: int) -> list: | ||||
|     """Generates a price following a geometric brownian motion process based on the input of the arguments. | ||||
| 
 | ||||
|         Since this function is used only to generate data for tests, the seed is fixed as 1234. | ||||
|         Many of the tests rely on exact values generated using this seed. | ||||
|         If the seed is changed, those tests will fail. | ||||
| 
 | ||||
|     Parameters: | ||||
|     ------------ | ||||
|     s0: float | ||||
|         Asset inital price. | ||||
| 
 | ||||
|     mu: float | ||||
|         Interest rate expressed annual terms. | ||||
| 
 | ||||
|     sigma: float | ||||
|         Volatility expressed annual terms. | ||||
| 
 | ||||
|     num_prices: int | ||||
|         number of prices to generate | ||||
| 
 | ||||
|     Returns: | ||||
|     -------- | ||||
|         Returns a list of values generated using GBM algorithm | ||||
|     """ | ||||
| 
 | ||||
|     random.seed(1234)  # WARNING! Changing the seed will cause most tests to fail | ||||
|     all_values = [] | ||||
|     for _ in range(num_prices): | ||||
|         s0 *= math.exp( | ||||
|             (mu - 0.5 * sigma**2) * (1.0 / 365.0) + sigma * math.sqrt(1.0 / 365.0) * random.gauss(mu=0, sigma=1) | ||||
|         ) | ||||
|         all_values.append(round(s0, 2)) | ||||
| 
 | ||||
|     return all_values | ||||
| 
 | ||||
| 
 | ||||
| def sample_data_generator( | ||||
|     frequency: pft.Frequency, | ||||
|     num: int = 1000, | ||||
|     skip_weekends: bool = False, | ||||
|     mu: float = 0.1, | ||||
|     sigma: float = 0.05, | ||||
|     eomonth: bool = False, | ||||
| ) -> List[tuple]: | ||||
|     """Creates TimeSeries data | ||||
| 
 | ||||
|     Parameters: | ||||
|     ----------- | ||||
|     frequency: Frequency | ||||
|         The frequency of the time series data to be generated. | ||||
| 
 | ||||
|     num: int | ||||
|         Number of date: value pairs to be generated. | ||||
| 
 | ||||
|     skip_weekends: bool | ||||
|         Whether weekends (saturday, sunday) should be skipped. | ||||
|         Gets used only if the frequency is daily. | ||||
| 
 | ||||
|     mu: float | ||||
|         Mean return for the values. | ||||
| 
 | ||||
|     sigma: float | ||||
|         standard deviation of the values. | ||||
| 
 | ||||
|     Returns: | ||||
|     -------- | ||||
|         Returns a TimeSeries object | ||||
|     """ | ||||
| 
 | ||||
|     start_date = datetime.datetime(2017, 1, 1) | ||||
|     timedelta_dict = { | ||||
|         frequency.freq_type: int( | ||||
|             frequency.value * num * (7 / 5 if frequency == pft.AllFrequencies.D and skip_weekends else 1) | ||||
|         ) | ||||
|     } | ||||
|     end_date = start_date + relativedelta(**timedelta_dict) | ||||
|     dates = pft.create_date_series(start_date, end_date, frequency.symbol, skip_weekends=skip_weekends, eomonth=eomonth) | ||||
|     values = create_prices(1000, mu, sigma, num) | ||||
|     ts = list(zip(dates, values)) | ||||
|     return ts | ||||
| 
 | ||||
| 
 | ||||
| market_data = sample_data_generator(num=3600, frequency=pft.AllFrequencies.D, skip_weekends=False) | ||||
| mts = pft.TimeSeries(market_data, "D") | ||||
| print(mts) | ||||
| 
 | ||||
| sortino = pft.sortino_ratio(mts, risk_free_rate=0.05) | ||||
| print(sortino) | ||||
| @ -1,25 +0,0 @@ | ||||
| import datetime | ||||
| 
 | ||||
| from pyfacts.core import Series | ||||
| 
 | ||||
| s1 = Series([2.5, 6.2, 5.6, 8.4, 7.4, 1.5, 9.6, 5]) | ||||
| 
 | ||||
| dt_lst = [ | ||||
|     datetime.datetime(2020, 12, 4, 0, 0), | ||||
|     datetime.datetime(2019, 5, 16, 0, 0), | ||||
|     datetime.datetime(2019, 9, 25, 0, 0), | ||||
|     datetime.datetime(2016, 2, 18, 0, 0), | ||||
|     datetime.datetime(2017, 8, 14, 0, 0), | ||||
|     datetime.datetime(2018, 1, 4, 0, 0), | ||||
|     datetime.datetime(2017, 5, 21, 0, 0), | ||||
|     datetime.datetime(2018, 7, 17, 0, 0), | ||||
|     datetime.datetime(2016, 4, 8, 0, 0), | ||||
|     datetime.datetime(2020, 1, 7, 0, 0), | ||||
|     datetime.datetime(2016, 12, 24, 0, 0), | ||||
|     datetime.datetime(2020, 6, 19, 0, 0), | ||||
|     datetime.datetime(2016, 3, 16, 0, 0), | ||||
|     datetime.datetime(2017, 4, 25, 0, 0), | ||||
|     datetime.datetime(2016, 7, 10, 0, 0), | ||||
| ] | ||||
| 
 | ||||
| s2 = Series(dt_lst) | ||||
							
								
								
									
										29
									
								
								dict_iter.py
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								dict_iter.py
									
									
									
									
									
								
							| @ -1,29 +0,0 @@ | ||||
| import pandas | ||||
| 
 | ||||
| from fincal.fincal import TimeSeries | ||||
| 
 | ||||
| dfd = pandas.read_csv('test_files/nav_history_daily - Copy.csv') | ||||
| dfm = pandas.read_csv('test_files/nav_history_monthly.csv') | ||||
| 
 | ||||
| data_d = [(i.date, i.nav) for i in dfd.itertuples() if i.amfi_code == 118825] | ||||
| data_d.sort() | ||||
| data_m = [{'date': i.date, 'value': i.nav} for i in dfm.itertuples()] | ||||
| 
 | ||||
| tsd = TimeSeries(data_d, frequency='D') | ||||
| 
 | ||||
| md = dict(data_d) | ||||
| counter = 1 | ||||
| for i in iter(md): | ||||
|     print(i) | ||||
|     counter += 1 | ||||
|     if counter >= 5: break | ||||
| 
 | ||||
| print('\n') | ||||
| counter = 1 | ||||
| for i in reversed(md): | ||||
|     print('rev', i) | ||||
|     counter += 1 | ||||
|     if counter >= 5: break | ||||
| 
 | ||||
| x = [next(i) for i in iter(md)] | ||||
| print(x) | ||||
| @ -90,7 +90,7 @@ def sharpe_ratio( | ||||
|         If risk free data or risk free rate is not provided. | ||||
|     """ | ||||
| 
 | ||||
|     interval_days = int(_interval_to_years(return_period_unit, return_period_value) * 365 + 1) | ||||
|     interval_days = math.ceil(_interval_to_years(return_period_unit, return_period_value) * 365) | ||||
| 
 | ||||
|     if from_date is None: | ||||
|         from_date = time_series_data.start_date + datetime.timedelta(days=interval_days) | ||||
| @ -187,7 +187,7 @@ def beta( | ||||
|         The value of beta as a float. | ||||
|     """ | ||||
|     interval_years = _interval_to_years(return_period_unit, return_period_value) | ||||
|     interval_days = int(interval_years * 365 + 1) | ||||
|     interval_days = math.ceil(interval_years * 365) | ||||
| 
 | ||||
|     annual_compounded_returns = True if interval_years > 1 else False | ||||
| 
 | ||||
| @ -300,7 +300,7 @@ def jensens_alpha( | ||||
|     """ | ||||
| 
 | ||||
|     interval_years = _interval_to_years(return_period_unit, return_period_value) | ||||
|     interval_days = int(interval_years * 365 + 1) | ||||
|     interval_days = math.ceil(interval_years * 365) | ||||
| 
 | ||||
|     if from_date is None: | ||||
|         from_date = asset_data.start_date + datetime.timedelta(days=interval_days) | ||||
| @ -423,7 +423,7 @@ def correlation( | ||||
|         * If both time series do not have data between the from date and to date | ||||
|     """ | ||||
|     interval_years = _interval_to_years(return_period_unit, return_period_value) | ||||
|     interval_days = int(interval_years * 365 + 1) | ||||
|     interval_days = math.ceil(interval_years * 365) | ||||
| 
 | ||||
|     annual_compounded_returns = True if interval_years > 1 else False | ||||
| 
 | ||||
| @ -538,7 +538,7 @@ def sortino_ratio( | ||||
|         If risk free data or risk free rate is not provided. | ||||
|     """ | ||||
| 
 | ||||
|     interval_days = int(_interval_to_years(return_period_unit, return_period_value) * 365 + 1) | ||||
|     interval_days = math.ceil(_interval_to_years(return_period_unit, return_period_value) * 365) | ||||
| 
 | ||||
|     if from_date is None: | ||||
|         from_date = time_series_data.start_date + datetime.timedelta(days=interval_days) | ||||
|  | ||||
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ setup( | ||||
|     author="Gourav Kumar", | ||||
|     author_email="gouravkr@outlook.in", | ||||
|     url="https://gouravkumar.com", | ||||
|     description="A library to perform financial analytics on Time Series data", | ||||
|     description="A Python library to perform financial analytics on Time Series data", | ||||
|     long_description=open("README.md").read().strip(), | ||||
|     packages=find_packages(), | ||||
|     install_requires=["python-dateutil"], | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,139 +0,0 @@ | ||||
| amfi_code,date,nav | ||||
| 118825,01-11-2021,87.925 | ||||
| 119528,02-11-2021,378.51 | ||||
| 118825,02-11-2021,87.885 | ||||
| 119528,03-11-2021,377.79 | ||||
| 118825,03-11-2021,87.553 | ||||
| 119528,08-11-2021,383.13 | ||||
| 118825,08-11-2021,88.743 | ||||
| 119528,09-11-2021,383.06 | ||||
| 118825,09-11-2021,88.793 | ||||
| 119528,10-11-2021,382.71 | ||||
| 118825,10-11-2021,88.723 | ||||
| 118825,10-11-2021,88.78 | ||||
| 119528,11-11-2021,379.28 | ||||
| 118825,11-11-2021,88.205 | ||||
| 119528,12-11-2021,383.94 | ||||
| 118825,12-11-2021,89.025 | ||||
| 119528,15-11-2021,383.31 | ||||
| 118825,15-11-2021,89.182 | ||||
| 119528,16-11-2021,381.08 | ||||
| 118825,16-11-2021,88.569 | ||||
| 119528,17-11-2021,379.17 | ||||
| 118825,17-11-2021,88.09 | ||||
| 119528,18-11-2021,375.09 | ||||
| 118825,18-11-2021,87.202 | ||||
| 119528,22-11-2021,368.16 | ||||
| 118825,22-11-2021,85.382 | ||||
| 119528,23-11-2021,370.64 | ||||
| 118825,23-11-2021,85.978 | ||||
| 119528,24-11-2021,369.91 | ||||
| 118825,24-11-2021,85.635 | ||||
| 119528,25-11-2021,371.33 | ||||
| 118825,25-11-2021,86.212 | ||||
| 119528,26-11-2021,360.66 | ||||
| 118825,26-11-2021,83.748 | ||||
| 119528,29-11-2021,360.05 | ||||
| 118825,29-11-2021,83.523 | ||||
| 119528,30-11-2021,359.8 | ||||
| 118825,30-11-2021,83.475 | ||||
| 119528,01-12-2021,362.35 | ||||
| 118825,01-12-2021,84.269 | ||||
| 119528,02-12-2021,366.09 | ||||
| 118825,02-12-2021,85.105 | ||||
| 119528,03-12-2021,363.11 | ||||
| 118825,03-12-2021,84.507 | ||||
| 119528,06-12-2021,357.21 | ||||
| 118825,06-12-2021,83.113 | ||||
| 119528,07-12-2021,362.63 | ||||
| 118825,07-12-2021,84.429 | ||||
| 119528,08-12-2021,368.73 | ||||
| 118825,08-12-2021,85.935 | ||||
| 119528,09-12-2021,369.49 | ||||
| 118825,09-12-2021,86.045 | ||||
| 119528,10-12-2021,369.44 | ||||
| 118825,10-12-2021,86.058 | ||||
| 119528,13-12-2021,367.6 | ||||
| 118825,13-12-2021,85.632 | ||||
| 119528,14-12-2021,366.36 | ||||
| 118825,14-12-2021,85.502 | ||||
| 119528,15-12-2021,364.34 | ||||
| 118825,15-12-2021,84.989 | ||||
| 119528,16-12-2021,363.73 | ||||
| 118825,16-12-2021,84.972 | ||||
| 119528,17-12-2021,358.17 | ||||
| 118825,17-12-2021,83.83 | ||||
| 119528,20-12-2021,349.98 | ||||
| 118825,20-12-2021,81.817 | ||||
| 119528,21-12-2021,353.71 | ||||
| 118825,21-12-2021,82.746 | ||||
| 119528,22-12-2021,357.93 | ||||
| 118825,22-12-2021,83.776 | ||||
| 119528,23-12-2021,360.68 | ||||
| 118825,23-12-2021,84.297 | ||||
| 119528,24-12-2021,359.11 | ||||
| 118825,24-12-2021,83.903 | ||||
| 119528,27-12-2021,360.71 | ||||
| 118825,27-12-2021,84.227 | ||||
| 119528,28-12-2021,363.81 | ||||
| 118825,28-12-2021,85.044 | ||||
| 119528,29-12-2021,363.2 | ||||
| 118825,29-12-2021,85.03 | ||||
| 119528,30-12-2021,363.31 | ||||
| 118825,30-12-2021,85.047 | ||||
| 119528,31-12-2021,366.98 | ||||
| 118825,31-12-2021,85.759 | ||||
| 119528,03-01-2022,371.76 | ||||
| 118825,03-01-2022,87.111 | ||||
| 119528,04-01-2022,374.22 | ||||
| 118825,04-01-2022,87.804 | ||||
| 119528,05-01-2022,376.31 | ||||
| 118825,05-01-2022,88.162 | ||||
| 119528,06-01-2022,373.64 | ||||
| 118825,06-01-2022,87.541 | ||||
| 119528,07-01-2022,374.68 | ||||
| 118825,07-01-2022,87.818 | ||||
| 119528,10-01-2022,378.47 | ||||
| 118825,10-01-2022,88.622 | ||||
| 119528,11-01-2022,379.34 | ||||
| 118825,11-01-2022,88.678 | ||||
| 119528,12-01-2022,382.86 | ||||
| 118825,12-01-2022,89.332 | ||||
| 119528,13-01-2022,383.68 | ||||
| 118825,13-01-2022,89.553 | ||||
| 119528,14-01-2022,384.02 | ||||
| 118825,14-01-2022,89.729 | ||||
| 119528,17-01-2022,384.36 | ||||
| 118825,17-01-2022,89.733 | ||||
| 119528,18-01-2022,380 | ||||
| 118825,18-01-2022,88.781 | ||||
| 119528,19-01-2022,377.24 | ||||
| 118825,19-01-2022,88.059 | ||||
| 119528,20-01-2022,374.45 | ||||
| 118825,20-01-2022,87.361 | ||||
| 119528,21-01-2022,369.86 | ||||
| 118825,21-01-2022,86.22 | ||||
| 119528,24-01-2022,361.01 | ||||
| 118825,24-01-2022,83.907 | ||||
| 119528,25-01-2022,364.63 | ||||
| 118825,25-01-2022,84.763 | ||||
| 119528,27-01-2022,361.95 | ||||
| 118825,27-01-2022,83.876 | ||||
| 119528,28-01-2022,361.91 | ||||
| 118825,28-01-2022,83.829 | ||||
| 119528,31-01-2022,367.31 | ||||
| 118825,31-01-2022,85.18 | ||||
| 119528,04-02-2022,371.01 | ||||
| 118825,04-02-2022,86.079 | ||||
| 119528,07-02-2022,365.04 | ||||
| 118825,07-02-2022,84.867 | ||||
| 119528,08-02-2022,365.74 | ||||
| 118825,08-02-2022,84.945 | ||||
| 119528,09-02-2022,369.85 | ||||
| 118825,09-02-2022,85.977 | ||||
| 119528,10-02-2022,372.29 | ||||
| 118825,10-02-2022,86.5 | ||||
| 119528,11-02-2022,366.91 | ||||
| 118825,11-02-2022,85.226 | ||||
| 119528,14-02-2022,355.47 | ||||
| 118825,14-02-2022,82.533 | ||||
| 
 | 
| @ -1,11 +0,0 @@ | ||||
| amfi_code,date,nav | ||||
| 118825,31-03-2021,70.69 | ||||
| 118825,30-04-2021,70.39 | ||||
| 118825,31-05-2021,74.85 | ||||
| 118825,30-07-2021,78.335 | ||||
| 118825,31-08-2021,83.691 | ||||
| 118825,30-09-2021,86.128 | ||||
| 118825,29-10-2021,86.612 | ||||
| 118825,30-11-2021,83.475 | ||||
| 118825,31-01-2022,85.18 | ||||
| 118825,17-02-2022,84.33 | ||||
| 
 | 
							
								
								
									
										7560
									
								
								test_files/msft.csv
									
									
									
									
									
								
							
							
						
						
									
										7560
									
								
								test_files/msft.csv
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,139 +0,0 @@ | ||||
| amfi_code,date,nav | ||||
| 118825,01-11-2021,87.925 | ||||
| 119528,02-11-2021,378.51 | ||||
| 118825,02-11-2021,87.885 | ||||
| 119528,03-11-2021,377.79 | ||||
| 118825,03-11-2021,87.553 | ||||
| 119528,08-11-2021,383.13 | ||||
| 118825,08-11-2021,88.743 | ||||
| 119528,09-11-2021,383.06 | ||||
| 118825,09-11-2021,88.793 | ||||
| 119528,10-11-2021,382.71 | ||||
| 118825,10-11-2021,88.723 | ||||
| 118825,10-11-2021,88.78 | ||||
| 119528,11-11-2021,379.28 | ||||
| 118825,11-11-2021,88.205 | ||||
| 119528,12-11-2021,383.94 | ||||
| 118825,12-11-2021,89.025 | ||||
| 119528,15-11-2021,383.31 | ||||
| 118825,15-11-2021,89.182 | ||||
| 119528,16-11-2021,381.08 | ||||
| 118825,16-11-2021,88.569 | ||||
| 119528,17-11-2021,379.17 | ||||
| 118825,17-11-2021,88.09 | ||||
| 119528,18-11-2021,375.09 | ||||
| 118825,18-11-2021,87.202 | ||||
| 119528,22-11-2021,368.16 | ||||
| 118825,22-11-2021,85.382 | ||||
| 119528,23-11-2021,370.64 | ||||
| 118825,23-11-2021,85.978 | ||||
| 119528,24-11-2021,369.91 | ||||
| 118825,24-11-2021,85.635 | ||||
| 119528,25-11-2021,371.33 | ||||
| 118825,25-11-2021,86.212 | ||||
| 119528,26-11-2021,360.66 | ||||
| 118825,26-11-2021,83.748 | ||||
| 119528,29-11-2021,360.05 | ||||
| 118825,29-11-2021,83.523 | ||||
| 119528,30-11-2021,359.8 | ||||
| 118825,30-11-2021,83.475 | ||||
| 119528,01-12-2021,362.35 | ||||
| 118825,01-12-2021,84.269 | ||||
| 119528,02-12-2021,366.09 | ||||
| 118825,02-12-2021,85.105 | ||||
| 119528,03-12-2021,363.11 | ||||
| 118825,03-12-2021,84.507 | ||||
| 119528,06-12-2021,357.21 | ||||
| 118825,06-12-2021,83.113 | ||||
| 119528,07-12-2021,362.63 | ||||
| 118825,07-12-2021,84.429 | ||||
| 119528,08-12-2021,368.73 | ||||
| 118825,08-12-2021,85.935 | ||||
| 119528,09-12-2021,369.49 | ||||
| 118825,09-12-2021,86.045 | ||||
| 119528,10-12-2021,369.44 | ||||
| 118825,10-12-2021,86.058 | ||||
| 119528,13-12-2021,367.6 | ||||
| 118825,13-12-2021,85.632 | ||||
| 119528,14-12-2021,366.36 | ||||
| 118825,14-12-2021,85.502 | ||||
| 119528,15-12-2021,364.34 | ||||
| 118825,15-12-2021,84.989 | ||||
| 119528,16-12-2021,363.73 | ||||
| 118825,16-12-2021,84.972 | ||||
| 119528,17-12-2021,358.17 | ||||
| 118825,17-12-2021,83.83 | ||||
| 119528,20-12-2021,349.98 | ||||
| 118825,20-12-2021,81.817 | ||||
| 119528,21-12-2021,353.71 | ||||
| 118825,21-12-2021,82.746 | ||||
| 119528,22-12-2021,357.93 | ||||
| 118825,22-12-2021,83.776 | ||||
| 119528,23-12-2021,360.68 | ||||
| 118825,23-12-2021,84.297 | ||||
| 119528,24-12-2021,359.11 | ||||
| 118825,24-12-2021,83.903 | ||||
| 119528,27-12-2021,360.71 | ||||
| 118825,27-12-2021,84.227 | ||||
| 119528,28-12-2021,363.81 | ||||
| 118825,28-12-2021,85.044 | ||||
| 119528,29-12-2021,363.2 | ||||
| 118825,29-12-2021,85.03 | ||||
| 119528,30-12-2021,363.31 | ||||
| 118825,30-12-2021,85.047 | ||||
| 119528,31-12-2021,366.98 | ||||
| 118825,31-12-2021,85.759 | ||||
| 119528,03-01-2022,371.76 | ||||
| 118825,03-01-2022,87.111 | ||||
| 119528,04-01-2022,374.22 | ||||
| 118825,04-01-2022,87.804 | ||||
| 119528,05-01-2022,376.31 | ||||
| 118825,05-01-2022,88.162 | ||||
| 119528,06-01-2022,373.64 | ||||
| 118825,06-01-2022,87.541 | ||||
| 119528,07-01-2022,374.68 | ||||
| 118825,07-01-2022,87.818 | ||||
| 119528,10-01-2022,378.47 | ||||
| 118825,10-01-2022,88.622 | ||||
| 119528,11-01-2022,379.34 | ||||
| 118825,11-01-2022,88.678 | ||||
| 119528,12-01-2022,382.86 | ||||
| 118825,12-01-2022,89.332 | ||||
| 119528,13-01-2022,383.68 | ||||
| 118825,13-01-2022,89.553 | ||||
| 119528,14-01-2022,384.02 | ||||
| 118825,14-01-2022,89.729 | ||||
| 119528,17-01-2022,384.36 | ||||
| 118825,17-01-2022,89.733 | ||||
| 119528,18-01-2022,380 | ||||
| 118825,18-01-2022,88.781 | ||||
| 119528,19-01-2022,377.24 | ||||
| 118825,19-01-2022,88.059 | ||||
| 119528,20-01-2022,374.45 | ||||
| 118825,20-01-2022,87.361 | ||||
| 119528,21-01-2022,369.86 | ||||
| 118825,21-01-2022,86.22 | ||||
| 119528,24-01-2022,361.01 | ||||
| 118825,24-01-2022,83.907 | ||||
| 119528,25-01-2022,364.63 | ||||
| 118825,25-01-2022,84.763 | ||||
| 119528,27-01-2022,361.95 | ||||
| 118825,27-01-2022,83.876 | ||||
| 119528,28-01-2022,361.91 | ||||
| 118825,28-01-2022,83.829 | ||||
| 119528,31-01-2022,367.31 | ||||
| 118825,31-01-2022,85.18 | ||||
| 119528,04-02-2022,371.01 | ||||
| 118825,04-02-2022,86.079 | ||||
| 119528,07-02-2022,365.04 | ||||
| 118825,07-02-2022,84.867 | ||||
| 119528,08-02-2022,365.74 | ||||
| 118825,08-02-2022,84.945 | ||||
| 119528,09-02-2022,369.85 | ||||
| 118825,09-02-2022,85.977 | ||||
| 119528,10-02-2022,372.29 | ||||
| 118825,10-02-2022,86.5 | ||||
| 119528,11-02-2022,366.91 | ||||
| 118825,11-02-2022,85.226 | ||||
| 119528,14-02-2022,355.47 | ||||
| 118825,14-02-2022,82.533 | ||||
| 
 | 
| @ -1,219 +0,0 @@ | ||||
| "amfi_code","date","nav" | ||||
| 118825,2013-01-31,18.913 | ||||
| 118825,2013-02-28,17.723 | ||||
| 118825,2013-03-28,17.563 | ||||
| 118825,2013-04-30,18.272 | ||||
| 118825,2013-05-31,18.383 | ||||
| 118825,2013-06-28,17.802 | ||||
| 118825,2013-07-31,17.588 | ||||
| 118825,2013-08-30,16.993 | ||||
| 118825,2013-09-30,17.732 | ||||
| 118825,2013-10-31,19.665 | ||||
| 118825,2013-11-29,19.787 | ||||
| 118825,2013-12-31,20.499 | ||||
| 118825,2014-01-31,19.994 | ||||
| 118825,2014-02-28,20.942 | ||||
| 118825,2014-03-31,22.339 | ||||
| 118825,2014-04-30,22.599 | ||||
| 118825,2014-05-30,24.937 | ||||
| 118825,2014-06-30,27.011 | ||||
| 118825,2014-07-31,27.219 | ||||
| 118825,2014-08-28,28.625 | ||||
| 118825,2014-09-30,29.493 | ||||
| 118825,2014-10-31,30.685 | ||||
| 118825,2014-11-28,31.956 | ||||
| 118825,2014-12-31,31.646 | ||||
| 118825,2015-01-30,33.653 | ||||
| 118825,2015-02-27,33.581 | ||||
| 118825,2015-03-31,33.14 | ||||
| 118825,2015-04-30,32.181 | ||||
| 118825,2015-05-29,33.256 | ||||
| 118825,2015-06-30,33.227 | ||||
| 118825,2015-07-31,34.697 | ||||
| 118825,2015-08-31,32.833 | ||||
| 118825,2015-09-30,32.94 | ||||
| 118825,2015-10-30,33.071 | ||||
| 118825,2015-11-30,33.024 | ||||
| 118825,2015-12-31,33.267 | ||||
| 118825,2016-01-29,31.389 | ||||
| 118825,2016-02-29,28.751 | ||||
| 118825,2016-03-31,32.034 | ||||
| 118825,2016-04-29,32.848 | ||||
| 118825,2016-05-31,34.135 | ||||
| 118825,2016-06-30,35.006 | ||||
| 118825,2016-07-29,37.148 | ||||
| 118825,2016-08-31,38.005 | ||||
| 118825,2016-09-30,37.724 | ||||
| 118825,2016-10-28,38.722 | ||||
| 118825,2016-11-30,36.689 | ||||
| 118825,2016-12-30,36.239 | ||||
| 118825,2017-01-31,38.195 | ||||
| 118825,2017-02-28,39.873 | ||||
| 118825,2017-03-31,41.421 | ||||
| 118825,2017-04-28,42.525 | ||||
| 118825,2017-05-31,43.977 | ||||
| 118825,2017-06-30,43.979 | ||||
| 118825,2017-07-31,46.554 | ||||
| 118825,2017-08-31,46.383 | ||||
| 118825,2017-09-29,46.085 | ||||
| 118825,2017-10-31,48.668 | ||||
| 118825,2017-11-30,48.824 | ||||
| 118825,2017-12-29,50.579 | ||||
| 118825,2018-01-31,51.799 | ||||
| 118825,2018-02-28,49.041 | ||||
| 118825,2018-03-28,46.858 | ||||
| 118825,2018-04-30,49.636 | ||||
| 118825,2018-05-31,49.169 | ||||
| 118825,2018-06-29,48.716 | ||||
| 118825,2018-07-31,51.455 | ||||
| 118825,2018-08-31,53.494 | ||||
| 118825,2018-09-28,49.863 | ||||
| 118825,2018-10-31,48.538 | ||||
| 118825,2018-11-30,50.597 | ||||
| 118825,2018-12-31,50.691 | ||||
| 118825,2019-01-31,50.517 | ||||
| 118825,2019-02-28,50.176 | ||||
| 118825,2019-03-31,54.017 | ||||
| 118825,2019-04-30,54.402 | ||||
| 118825,2019-05-31,55.334 | ||||
| 118825,2019-06-28,55.181 | ||||
| 118825,2019-07-31,52.388 | ||||
| 118825,2019-08-30,52.214 | ||||
| 118825,2019-09-30,54.058 | ||||
| 118825,2019-10-31,56.514 | ||||
| 118825,2019-11-29,57.42 | ||||
| 118825,2019-12-31,57.771 | ||||
| 118825,2020-01-31,57.135 | ||||
| 118825,2020-02-28,54.034 | ||||
| 118825,2020-03-31,41.452 | ||||
| 118825,2020-04-30,47.326 | ||||
| 118825,2020-05-29,45.845 | ||||
| 118825,2020-06-30,49.526 | ||||
| 118825,2020-07-31,53.306000000000004 | ||||
| 118825,2020-08-19,55.747 | ||||
| 118825,2020-10-30,56.387 | ||||
| 118825,2020-11-27,62.001000000000005 | ||||
| 118825,2020-12-31,66.415 | ||||
| 118825,2021-01-29,65.655 | ||||
| 118825,2021-02-26,70.317 | ||||
| 118825,2021-03-31,70.69 | ||||
| 118825,2021-04-30,70.39 | ||||
| 118825,2021-05-31,74.85 | ||||
| 118825,2021-06-30,77.109 | ||||
| 118825,2021-07-30,78.335 | ||||
| 118825,2021-08-31,83.691 | ||||
| 118825,2021-09-30,86.128 | ||||
| 118825,2021-10-29,86.612 | ||||
| 118825,2021-11-30,83.475 | ||||
| 118825,2021-12-31,85.759 | ||||
| 118825,2022-01-31,85.18 | ||||
| 118825,2022-02-17,84.33 | ||||
| 119528,2013-01-31,101.36 | ||||
| 119528,2013-02-28,95.25 | ||||
| 119528,2013-03-28,94.81 | ||||
| 119528,2013-04-30,99.75 | ||||
| 119528,2013-05-31,99.73 | ||||
| 119528,2013-06-28,97.52 | ||||
| 119528,2013-07-31,95.37 | ||||
| 119528,2013-08-30,92.24 | ||||
| 119528,2013-09-30,97.45 | ||||
| 119528,2013-10-31,107.03 | ||||
| 119528,2013-11-29,105.91 | ||||
| 119528,2013-12-31,109.3 | ||||
| 119528,2014-01-31,105.09 | ||||
| 119528,2014-02-28,108.58 | ||||
| 119528,2014-03-31,117.28 | ||||
| 119528,2014-04-30,118.06 | ||||
| 119528,2014-05-30,131.33 | ||||
| 119528,2014-06-30,139.48 | ||||
| 119528,2014-07-31,140.49 | ||||
| 119528,2014-08-28,145.43 | ||||
| 119528,2014-09-30,147.4 | ||||
| 119528,2014-10-31,154.46 | ||||
| 119528,2014-11-28,161.93 | ||||
| 119528,2014-12-31,159.62 | ||||
| 119528,2015-01-30,170.46 | ||||
| 119528,2015-02-27,171.18 | ||||
| 119528,2015-03-31,166.8 | ||||
| 119528,2015-04-30,161.95 | ||||
| 119528,2015-05-29,166.78 | ||||
| 119528,2015-06-30,166.67 | ||||
| 119528,2015-07-31,172.33 | ||||
| 119528,2015-08-31,161.96 | ||||
| 119528,2015-09-30,162.25 | ||||
| 119528,2015-10-30,164.16 | ||||
| 119528,2015-11-30,162.7 | ||||
| 119528,2015-12-31,162.83 | ||||
| 119528,2016-01-29,155.87 | ||||
| 119528,2016-02-29,144.56 | ||||
| 119528,2016-03-31,159.88 | ||||
| 119528,2016-04-29,163.54 | ||||
| 119528,2016-05-31,170.01 | ||||
| 119528,2016-06-30,174.61 | ||||
| 119528,2016-07-29,184.36 | ||||
| 119528,2016-08-31,189.33 | ||||
| 119528,2016-09-30,187.16 | ||||
| 119528,2016-10-28,189.29 | ||||
| 119528,2016-11-30,178.19 | ||||
| 119528,2016-12-30,176.66 | ||||
| 119528,2017-01-31,185.76 | ||||
| 119528,2017-02-28,193.2 | ||||
| 119528,2017-03-31,200.54 | ||||
| 119528,2017-04-28,205.25 | ||||
| 119528,2017-05-31,208.22 | ||||
| 119528,2017-06-30,209.83 | ||||
| 119528,2017-07-31,221.15 | ||||
| 119528,2017-08-31,219.99 | ||||
| 119528,2017-09-29,217.7 | ||||
| 119528,2017-10-31,226.94 | ||||
| 119528,2017-11-30,225.24 | ||||
| 119528,2017-12-29,233.26 | ||||
| 119528,2018-01-31,237.57 | ||||
| 119528,2018-02-28,226.55 | ||||
| 119528,2018-03-28,219.73 | ||||
| 119528,2018-04-30,232.04 | ||||
| 119528,2018-05-31,228.49 | ||||
| 119528,2018-06-29,225.27 | ||||
| 119528,2018-07-31,237.11 | ||||
| 119528,2018-08-31,243.79 | ||||
| 119528,2018-09-28,223.83 | ||||
| 119528,2018-10-31,218.61 | ||||
| 119528,2018-11-30,226.99 | ||||
| 119528,2018-12-31,228.61 | ||||
| 119528,2019-01-31,224.26 | ||||
| 119528,2019-02-28,222.71 | ||||
| 119528,2019-03-29,240.21 | ||||
| 119528,2019-04-30,240.01 | ||||
| 119528,2019-05-31,243.72 | ||||
| 119528,2019-06-28,241.28 | ||||
| 119528,2019-07-31,229.54 | ||||
| 119528,2019-08-30,226.0 | ||||
| 119528,2019-09-30,234.75 | ||||
| 119528,2019-10-31,242.11 | ||||
| 119528,2019-11-29,246.75 | ||||
| 119528,2019-12-31,247.81 | ||||
| 119528,2020-01-31,246.14 | ||||
| 119528,2020-02-28,231.91 | ||||
| 119528,2020-03-31,175.98 | ||||
| 119528,2020-04-30,200.77 | ||||
| 119528,2020-05-29,196.75 | ||||
| 119528,2020-06-30,210.55 | ||||
| 119528,2020-07-31,224.93 | ||||
| 119528,2020-08-19,233.78 | ||||
| 119528,2020-10-30,235.83 | ||||
| 119528,2020-11-27,264.04 | ||||
| 119528,2020-12-31,285.02 | ||||
| 119528,2021-01-29,280.52 | ||||
| 119528,2021-02-26,300.56 | ||||
| 119528,2021-03-31,301.57 | ||||
| 119528,2021-04-30,301.1 | ||||
| 119528,2021-05-31,320.98 | ||||
| 119528,2021-06-30,327.64 | ||||
| 119528,2021-07-30,336.6 | ||||
| 119528,2021-08-31,360.75 | ||||
| 119528,2021-09-30,369.42 | ||||
| 119528,2021-10-29,372.89 | ||||
| 119528,2021-11-30,359.8 | ||||
| 119528,2021-12-31,366.98 | ||||
| 119528,2022-01-31,367.31 | ||||
| 119528,2022-02-17,363.56 | ||||
| 
 | 
| @ -1,15 +0,0 @@ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| amfi_code,date,nav | ||||
| 118825,31-03-2021,70.69 | ||||
| 118825,30-04-2021,70.39 | ||||
| 118825,31-05-2021,74.85 | ||||
| 118825,30-07-2021,78.335 | ||||
| 118825,31-08-2021,83.691 | ||||
| 118825,30-09-2021,86.128 | ||||
| 118825,29-10-2021,86.612 | ||||
| 118825,30-11-2021,83.475 | ||||
| 118825,31-01-2022,85.18 | ||||
| 118825,17-02-2022,84.33 | ||||
| 
 | 
| @ -1,71 +0,0 @@ | ||||
| "amfi_code","date","nav" | ||||
| 118825,2013-03-28,17.563 | ||||
| 118825,2013-06-28,17.802 | ||||
| 118825,2013-09-30,17.732 | ||||
| 118825,2013-12-31,20.499 | ||||
| 118825,2014-03-31,22.339 | ||||
| 118825,2014-06-30,27.011 | ||||
| 118825,2014-09-30,29.493 | ||||
| 118825,2014-12-31,31.646 | ||||
| 118825,2015-03-31,33.14 | ||||
| 118825,2015-06-30,33.227 | ||||
| 118825,2015-09-30,32.94 | ||||
| 118825,2015-12-31,33.267 | ||||
| 118825,2016-03-31,32.034 | ||||
| 118825,2016-06-30,35.006 | ||||
| 118825,2016-09-30,37.724 | ||||
| 118825,2016-12-30,36.239 | ||||
| 118825,2017-03-31,41.421 | ||||
| 118825,2017-06-30,43.979 | ||||
| 118825,2017-09-29,46.085 | ||||
| 118825,2017-12-29,50.579 | ||||
| 118825,2018-03-28,46.858 | ||||
| 118825,2018-06-29,48.716 | ||||
| 118825,2018-09-28,49.863 | ||||
| 118825,2018-12-31,50.691 | ||||
| 118825,2019-03-31,54.017 | ||||
| 118825,2019-06-28,55.181 | ||||
| 118825,2019-09-30,54.058 | ||||
| 118825,2019-12-31,57.771 | ||||
| 118825,2020-03-31,41.452 | ||||
| 118825,2020-06-30,49.526 | ||||
| 118825,2020-12-31,66.415 | ||||
| 118825,2021-03-31,70.69 | ||||
| 118825,2021-06-30,77.109 | ||||
| 118825,2021-09-30,86.128 | ||||
| 118825,2021-12-31,85.759 | ||||
| 119528,2013-03-28,94.81 | ||||
| 119528,2013-06-28,97.52 | ||||
| 119528,2013-09-30,97.45 | ||||
| 119528,2013-12-31,109.3 | ||||
| 119528,2014-03-31,117.28 | ||||
| 119528,2014-06-30,139.48 | ||||
| 119528,2014-09-30,147.4 | ||||
| 119528,2014-12-31,159.62 | ||||
| 119528,2015-03-31,166.8 | ||||
| 119528,2015-06-30,166.67 | ||||
| 119528,2015-09-30,162.25 | ||||
| 119528,2015-12-31,162.83 | ||||
| 119528,2016-03-31,159.88 | ||||
| 119528,2016-06-30,174.61 | ||||
| 119528,2016-09-30,187.16 | ||||
| 119528,2016-12-30,176.66 | ||||
| 119528,2017-03-31,200.54 | ||||
| 119528,2017-06-30,209.83 | ||||
| 119528,2017-09-29,217.7 | ||||
| 119528,2017-12-29,233.26 | ||||
| 119528,2018-03-28,219.73 | ||||
| 119528,2018-06-29,225.27 | ||||
| 119528,2018-09-28,223.83 | ||||
| 119528,2018-12-31,228.61 | ||||
| 119528,2019-03-29,240.21 | ||||
| 119528,2019-06-28,241.28 | ||||
| 119528,2019-09-30,234.75 | ||||
| 119528,2019-12-31,247.81 | ||||
| 119528,2020-03-31,175.98 | ||||
| 119528,2020-06-30,210.55 | ||||
| 119528,2020-12-31,285.02 | ||||
| 119528,2021-03-31,301.57 | ||||
| 119528,2021-06-30,327.64 | ||||
| 119528,2021-09-30,369.42 | ||||
| 119528,2021-12-31,366.98 | ||||
| 
 | 
| @ -1,9 +0,0 @@ | ||||
| amfi_code,date,nav | ||||
| 118825,31-03-2019,54.017 | ||||
| 118825,28-06-2019,55.181 | ||||
| 118825,31-12-2019,57.771 | ||||
| 118825,31-03-2020,41.452 | ||||
| 118825,30-06-2020,49.526 | ||||
| 118825,30-06-2021,77.109 | ||||
| 118825,30-09-2021,86.128 | ||||
| 118825,31-12-2021,85.759 | ||||
| 
 | 
							
								
								
									
										712
									
								
								testing.ipynb
									
									
									
									
									
								
							
							
						
						
									
										712
									
								
								testing.ipynb
									
									
									
									
									
								
							| @ -1,712 +0,0 @@ | ||||
| { | ||||
|  "cells": [ | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "id": "e40a5526-458a-4d11-8eaa-3b584f723738", | ||||
|    "metadata": { | ||||
|     "tags": [] | ||||
|    }, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import fincal as fc\n", | ||||
|     "import datetime\n", | ||||
|     "from dateutil.relativedelta import relativedelta" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "id": "a54bfbdf", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "data = [\n", | ||||
|     "    (\"2022-01-01\", 10),\n", | ||||
|     "    (\"2022-01-02\", 12),\n", | ||||
|     "    (\"2022-01-03\", 14),\n", | ||||
|     "    (\"2022-01-04\", 16)\n", | ||||
|     "    # (\"2022-01-06\", 18),\n", | ||||
|     "    # (\"2022-01-07\", 20),\n", | ||||
|     "    # (\"2022-01-09\", 22),\n", | ||||
|     "    # (\"2022-01-10\", 24),\n", | ||||
|     "    # (\"2022-01-11\", 26),\n", | ||||
|     "    # (\"2022-01-12\", 28),\n", | ||||
|     "    # (\"2023-01-01\", 30),\n", | ||||
|     "    # (\"2023-01-02\", 32),\n", | ||||
|     "    # (\"2023-01-03\", 34),\n", | ||||
|     "]" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 3, | ||||
|    "id": "fcc5f8f1", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "TimeSeries([(datetime.datetime(2022, 1, 1, 0, 0), 10.0),\n", | ||||
|        "\t(datetime.datetime(2022, 1, 2, 0, 0), 12.0),\n", | ||||
|        "\t(datetime.datetime(2022, 1, 3, 0, 0), 14.0),\n", | ||||
|        "\t(datetime.datetime(2022, 1, 4, 0, 0), 16.0)], frequency='D')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 3, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "ts = fc.TimeSeries(data, 'D')\n", | ||||
|     "ts2 = fc.TimeSeries(data, 'D')\n", | ||||
|     "ts" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 21, | ||||
|    "id": "c091da16-d3a2-4d5b-93da-099d67373932", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "Series([datetime.datetime(2021, 1, 1, 0, 0), datetime.datetime(2021, 1, 2, 0, 0)], data_type='datetime')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 21, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "fc.Series(['2021-01-01', '2021-01-02'], data_type='date')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 15, | ||||
|    "id": "77fc30d8-2843-40c4-9842-d943e6ef9813", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "Series([11.0, 14.0, 17.0, 20.0], data_type='float')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 15, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "ts.values + fc.Series([1, 2, 3, 4])" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 8, | ||||
|    "id": "8e812756", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "ename": "ValueError", | ||||
|      "evalue": "TimeSeries can be only expanded to a higher frequency", | ||||
|      "output_type": "error", | ||||
|      "traceback": [ | ||||
|       "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | ||||
|       "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)", | ||||
|       "Input \u001b[0;32mIn [8]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mts\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexpand\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mW\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mffill\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", | ||||
|       "File \u001b[0;32m~/Documents/projects/fincal/fincal/fincal.py:624\u001b[0m, in \u001b[0;36mTimeSeries.expand\u001b[0;34m(self, to_frequency, method, skip_weekends, eomonth)\u001b[0m\n\u001b[1;32m    621\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid argument for to_frequency \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mto_frequency\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m    623\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m to_frequency\u001b[38;5;241m.\u001b[39mdays \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfrequency\u001b[38;5;241m.\u001b[39mdays:\n\u001b[0;32m--> 624\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTimeSeries can be only expanded to a higher frequency\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m    626\u001b[0m new_dates \u001b[38;5;241m=\u001b[39m create_date_series(\n\u001b[1;32m    627\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstart_date,\n\u001b[1;32m    628\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mend_date,\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    632\u001b[0m     ensure_coverage\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m    633\u001b[0m )\n\u001b[1;32m    635\u001b[0m closest: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mprevious\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m method \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mffill\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnext\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", | ||||
|       "\u001b[0;31mValueError\u001b[0m: TimeSeries can be only expanded to a higher frequency" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "ts.expand('W', 'ffill')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 12, | ||||
|    "id": "55918da9-2df6-4773-9ca0-e19b52c3ece2", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "TimeSeries([(datetime.datetime(2022, 1, 1, 0, 0), 10),\n", | ||||
|        "\t(datetime.datetime(2022, 4, 1, 0, 0), 28),\n", | ||||
|        "\t(datetime.datetime(2022, 7, 1, 0, 0), 28),\n", | ||||
|        "\t(datetime.datetime(2022, 10, 1, 0, 0), 28),\n", | ||||
|        "\t(datetime.datetime(2023, 1, 1, 0, 0), 30)], frequency='Q')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 12, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "ts.shrink('Q', 'ffill')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "id": "9431eb8c", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "from fincal.utils import _is_eomonth" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 5, | ||||
|    "id": "36eefec7-7dbf-4a28-ac50-2e502d9d6864", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "weekly_data = [\n", | ||||
|     "    ('2018-01-31', 26),\n", | ||||
|     "    ('2018-02-28', 44),\n", | ||||
|     "    ('2018-03-30', 40),\n", | ||||
|     "    ('2018-04-30', 36),\n", | ||||
|     "    ('2018-05-31', 31),\n", | ||||
|     "    ('2018-06-30', 45),\n", | ||||
|     "    ('2018-07-30', 31),\n", | ||||
|     "    ('2018-08-31', 42),\n", | ||||
|     "    ('2018-09-30', 40),\n", | ||||
|     "    ('2018-10-30', 30),\n", | ||||
|     "    ('2018-11-30', 35),\n", | ||||
|     "    ('2018-12-31', 37),\n", | ||||
|     "    ('2019-01-31', 31),\n", | ||||
|     "    ('2019-02-28', 44),\n", | ||||
|     "    ('2019-03-31', 31),\n", | ||||
|     "    ('2019-04-29', 32),\n", | ||||
|     "    ('2019-05-30', 39),\n", | ||||
|     "    ('2019-06-30', 27),\n", | ||||
|     "    ('2019-07-31', 35),\n", | ||||
|     "    ('2019-08-31', 33),\n", | ||||
|     "    ('2019-09-30', 29),\n", | ||||
|     "    ('2019-10-30', 26),\n", | ||||
|     "    ('2019-11-30', 39),\n", | ||||
|     "    ('2019-12-30', 30),\n", | ||||
|     "    ('2020-01-30', 29)\n", | ||||
|     "]\n", | ||||
|     "week_ts = fc.TimeSeries(weekly_data, 'W')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 6, | ||||
|    "id": "e1071f90", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "False" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 6, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "_is_eomonth(week_ts.dates)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 22, | ||||
|    "id": "d64dd3c6-4295-4301-90e4-5c74ea23c4af", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "(datetime.datetime(2017, 1, 1, 0, 0), 67)\n", | ||||
|       "(datetime.datetime(2017, 2, 1, 0, 0), 85)\n", | ||||
|       "(datetime.datetime(2017, 3, 1, 0, 0), 76)\n", | ||||
|       "(datetime.datetime(2017, 4, 1, 0, 0), 78)\n", | ||||
|       "(datetime.datetime(2017, 5, 1, 0, 0), 65)\n", | ||||
|       "(datetime.datetime(2017, 6, 1, 0, 0), 74)\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "for i in week_ts.shrink('M', 'ffill', skip_weekends=True):\n", | ||||
|     "    print(i)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": null, | ||||
|    "id": "a549c5c0-c89a-4cc3-b396-c4afa77a9879", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "week_ts.sync(ts)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 1, | ||||
|    "id": "4755aea3-3655-4651-91d2-8e54c24303bc", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import fincal as fc" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "id": "bd9887b3-d98a-4c80-8f95-ef7b7f19ded4", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "['date', 'nav']\n", | ||||
|       "CPU times: user 57.5 ms, sys: 3.38 ms, total: 60.8 ms\n", | ||||
|       "Wall time: 60.5 ms\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "%%time\n", | ||||
|     "ts = fc.read_csv('test_files/msft.csv', frequency='D')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 7, | ||||
|    "id": "b7c176d4-d89f-4bda-9d67-75463eb90468", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "(datetime.datetime(2022, 2, 11, 0, 0), 295.040009)\n", | ||||
|       "(datetime.datetime(2022, 2, 12, 0, 0), 296.0)\n", | ||||
|       "(datetime.datetime(2022, 2, 13, 0, 0), 296.0)\n", | ||||
|       "(datetime.datetime(2022, 2, 14, 0, 0), 295.0)\n", | ||||
|       "(datetime.datetime(2022, 2, 15, 0, 0), 300.470001)\n", | ||||
|       "(datetime.datetime(2022, 2, 16, 0, 0), 299.5)\n", | ||||
|       "(datetime.datetime(2022, 2, 17, 0, 0), 290.730011)\n", | ||||
|       "(datetime.datetime(2022, 2, 18, 0, 0), 287.929993)\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "for i in ts.tail(8):\n", | ||||
|     "    print(i)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 6, | ||||
|    "id": "69c57754-a6fb-4881-9359-ba17c7fb8be5", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "CPU times: user 1.76 ms, sys: 123 µs, total: 1.88 ms\n", | ||||
|       "Wall time: 1.88 ms\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "%%time\n", | ||||
|     "ts['2022-02-12'] = 296" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 8, | ||||
|    "id": "7aa02023-406e-4700-801c-c06390ddf914", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "CPU times: user 3.61 ms, sys: 68 µs, total: 3.68 ms\n", | ||||
|       "Wall time: 3.7 ms\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "{'start_date': datetime.datetime(1999, 12, 27, 0, 0),\n", | ||||
|        " 'end_date': datetime.datetime(2009, 3, 9, 0, 0),\n", | ||||
|        " 'drawdown': -0.7456453305351521}" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 8, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "%%time\n", | ||||
|     "ts.max_drawdown()" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 9, | ||||
|    "id": "72cb4da4-1318-4b9b-b563-adac46accfb3", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "True" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 9, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "from typing import Mapping\n", | ||||
|     "isinstance(ts, Mapping)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 23, | ||||
|    "id": "96bbecbf", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import fincal as fc" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 24, | ||||
|    "id": "19199c92", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "['amfi_code', 'date', 'nav']\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "name": "stderr", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "/Users/gourav/Documents/projects/fincal/fincal/core.py:308: UserWarning: The input data contains duplicate dates which have been ignored.\n", | ||||
|       "  warnings.warn(\"The input data contains duplicate dates which have been ignored.\")\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "TimeSeries([(datetime.datetime(2013, 1, 2, 0, 0), 18.972),\n", | ||||
|        "\t    (datetime.datetime(2013, 1, 3, 0, 0), 19.011),\n", | ||||
|        "\t    (datetime.datetime(2013, 1, 4, 0, 0), 19.008)\n", | ||||
|        "\t    ...\n", | ||||
|        "\t    (datetime.datetime(2022, 2, 10, 0, 0), 86.5),\n", | ||||
|        "\t    (datetime.datetime(2022, 2, 11, 0, 0), 85.226),\n", | ||||
|        "\t    (datetime.datetime(2022, 2, 14, 0, 0), 82.533)], frequency='D')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 24, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "ts = fc.read_csv('test_files/nav_history_daily - copy.csv', col_index=(1, 2), frequency='D', date_format='%d-%m-%y')\n", | ||||
|     "ts" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 28, | ||||
|    "id": "51c9ae9a", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "0.12031455056454916" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 28, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "fc.sharpe_ratio(\n", | ||||
|     "    ts,\n", | ||||
|     "    risk_free_rate=0.06,\n", | ||||
|     "    from_date='2013-02-04',\n", | ||||
|     "    to_date='2022-02-14',\n", | ||||
|     "    return_period_unit='months',\n", | ||||
|     "    return_period_value=1\n", | ||||
|     ")" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "id": "b3fb7b59-eaa3-41a5-b1ab-89d63b69edb0", | ||||
|    "metadata": {}, | ||||
|    "source": [ | ||||
|     "# Data generator" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 1, | ||||
|    "id": "aead3e77-2670-4541-846a-5537b01f3d2e", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import random\n", | ||||
|     "import math\n", | ||||
|     "import pyfacts as pft\n", | ||||
|     "from typing import List\n", | ||||
|     "import datetime\n", | ||||
|     "from dateutil.relativedelta import relativedelta" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "id": "f287e05f", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "def create_prices(s0: float, mu: float, sigma: float, num_prices: int) -> list:\n", | ||||
|     "    \"\"\"Generates a price following a geometric brownian motion process based on the input of the arguments.\n", | ||||
|     "\n", | ||||
|     "        Since this function is used only to generate data for tests, the seed is fixed as 1234.\n", | ||||
|     "        Many of the tests rely on exact values generated using this seed.\n", | ||||
|     "        If the seed is changed, those tests will fail.\n", | ||||
|     "\n", | ||||
|     "    Parameters:\n", | ||||
|     "    ------------\n", | ||||
|     "    s0: float\n", | ||||
|     "        Asset inital price.\n", | ||||
|     "\n", | ||||
|     "    mu: float\n", | ||||
|     "        Interest rate expressed annual terms.\n", | ||||
|     "\n", | ||||
|     "    sigma: float\n", | ||||
|     "        Volatility expressed annual terms.\n", | ||||
|     "\n", | ||||
|     "    num_prices: int\n", | ||||
|     "        number of prices to generate\n", | ||||
|     "\n", | ||||
|     "    Returns:\n", | ||||
|     "    --------\n", | ||||
|     "        Returns a list of values generated using GBM algorithm\n", | ||||
|     "    \"\"\"\n", | ||||
|     "\n", | ||||
|     "    random.seed(1234)  # WARNING! Changing the seed will cause most tests to fail\n", | ||||
|     "    all_values = []\n", | ||||
|     "    for _ in range(num_prices):\n", | ||||
|     "        s0 *= math.exp(\n", | ||||
|     "            (mu - 0.5 * sigma**2) * (1.0 / 365.0) + sigma * math.sqrt(1.0 / 365.0) * random.gauss(mu=0, sigma=1)\n", | ||||
|     "        )\n", | ||||
|     "        all_values.append(round(s0, 2))\n", | ||||
|     "\n", | ||||
|     "    return all_values\n", | ||||
|     "\n", | ||||
|     "\n", | ||||
|     "def sample_data_generator(\n", | ||||
|     "    frequency: pft.Frequency,\n", | ||||
|     "    num: int = 1000,\n", | ||||
|     "    skip_weekends: bool = False,\n", | ||||
|     "    mu: float = 0.1,\n", | ||||
|     "    sigma: float = 0.05,\n", | ||||
|     "    eomonth: bool = False,\n", | ||||
|     ") -> List[tuple]:\n", | ||||
|     "    \"\"\"Creates TimeSeries data\n", | ||||
|     "\n", | ||||
|     "    Parameters:\n", | ||||
|     "    -----------\n", | ||||
|     "    frequency: Frequency\n", | ||||
|     "        The frequency of the time series data to be generated.\n", | ||||
|     "\n", | ||||
|     "    num: int\n", | ||||
|     "        Number of date: value pairs to be generated.\n", | ||||
|     "\n", | ||||
|     "    skip_weekends: bool\n", | ||||
|     "        Whether weekends (saturday, sunday) should be skipped.\n", | ||||
|     "        Gets used only if the frequency is daily.\n", | ||||
|     "\n", | ||||
|     "    mu: float\n", | ||||
|     "        Mean return for the values.\n", | ||||
|     "\n", | ||||
|     "    sigma: float\n", | ||||
|     "        standard deviation of the values.\n", | ||||
|     "\n", | ||||
|     "    Returns:\n", | ||||
|     "    --------\n", | ||||
|     "        Returns a TimeSeries object\n", | ||||
|     "    \"\"\"\n", | ||||
|     "\n", | ||||
|     "    start_date = datetime.datetime(2017, 1, 1)\n", | ||||
|     "    timedelta_dict = {\n", | ||||
|     "        frequency.freq_type: int(\n", | ||||
|     "            frequency.value * num * (7 / 5 if frequency == pft.AllFrequencies.D and skip_weekends else 1)\n", | ||||
|     "        )\n", | ||||
|     "    }\n", | ||||
|     "    end_date = start_date + relativedelta(**timedelta_dict)\n", | ||||
|     "    dates = pft.create_date_series(start_date, end_date, frequency.symbol, skip_weekends=skip_weekends, eomonth=eomonth)\n", | ||||
|     "    values = create_prices(1000, mu, sigma, num)\n", | ||||
|     "    ts = list(zip(dates, values))\n", | ||||
|     "    return ts\n" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 6, | ||||
|    "id": "c85b5dd9-9a88-4608-ac58-1a141295f63f", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "market_data = sample_data_generator(num=3600, frequency=pft.AllFrequencies.D)\n", | ||||
|     "mts = pft.TimeSeries(market_data, \"D\")\n", | ||||
|     "stock_data = sample_data_generator(num=3600, frequency=pft.AllFrequencies.D, mu=0.12, sigma=0.05)\n", | ||||
|     "sts = pft.TimeSeries(stock_data, 'D')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 8, | ||||
|    "id": "0488a4d0-bca1-4341-9fae-1fd254adc0dc", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "1.020217253491451" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 8, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "pft.beta(sts, mts)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 14, | ||||
|    "id": "04624145-4fce-484c-aa69-0d17d159b598", | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "tst = ts.transform('Q', 'mean', False)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 16, | ||||
|    "id": "75ed1666-5fc8-4707-bf42-62d44adcae18", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "20" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 16, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "len(tst)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 15, | ||||
|    "id": "bccd7d1c-2d57-444c-af68-290f476f2b05", | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "(datetime.datetime(2017, 1, 1, 0, 0), 1010.4553846153846)\n", | ||||
|       "(datetime.datetime(2017, 4, 1, 0, 0), 1019.34)\n", | ||||
|       "(datetime.datetime(2017, 7, 1, 0, 0), 1015.3515384615384)\n", | ||||
|       "(datetime.datetime(2017, 10, 1, 0, 0), 1031.2892857142858)\n", | ||||
|       "(datetime.datetime(2018, 1, 1, 0, 0), 1054.7216666666666)\n", | ||||
|       "(datetime.datetime(2018, 4, 1, 0, 0), 1059.736153846154)\n", | ||||
|       "(datetime.datetime(2018, 7, 1, 0, 0), 1049.1100000000001)\n", | ||||
|       "(datetime.datetime(2018, 10, 1, 0, 0), 1051.663076923077)\n", | ||||
|       "(datetime.datetime(2019, 1, 1, 0, 0), 1062.2869230769231)\n", | ||||
|       "(datetime.datetime(2019, 4, 1, 0, 0), 1059.7423076923076)\n", | ||||
|       "(datetime.datetime(2019, 7, 1, 0, 0), 1050.7661538461539)\n", | ||||
|       "(datetime.datetime(2019, 10, 1, 0, 0), 1045.2061538461537)\n", | ||||
|       "(datetime.datetime(2020, 1, 1, 0, 0), 1046.11)\n", | ||||
|       "(datetime.datetime(2020, 4, 1, 0, 0), 1053.126923076923)\n", | ||||
|       "(datetime.datetime(2020, 7, 1, 0, 0), 1053.273846153846)\n", | ||||
|       "(datetime.datetime(2020, 10, 1, 0, 0), 1064.2384615384615)\n", | ||||
|       "(datetime.datetime(2021, 1, 1, 0, 0), 1073.1538461538462)\n", | ||||
|       "(datetime.datetime(2021, 4, 1, 0, 0), 1094.3215384615385)\n", | ||||
|       "(datetime.datetime(2021, 7, 1, 0, 0), 1104.3584615384616)\n", | ||||
|       "(datetime.datetime(2021, 10, 1, 0, 0), 1112.806923076923)\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "for i in tst:\n", | ||||
|     "    print(i)" | ||||
|    ] | ||||
|   } | ||||
|  ], | ||||
|  "metadata": { | ||||
|   "interpreter": { | ||||
|    "hash": "71e6a8e087576f7c2a714460e6ef0339bac111b70cc81e9aa980fde63219ab06" | ||||
|   }, | ||||
|   "kernelspec": { | ||||
|    "display_name": "Python 3 (ipykernel)", | ||||
|    "language": "python", | ||||
|    "name": "python3" | ||||
|   }, | ||||
|   "language_info": { | ||||
|    "codemirror_mode": { | ||||
|     "name": "ipython", | ||||
|     "version": 3 | ||||
|    }, | ||||
|    "file_extension": ".py", | ||||
|    "mimetype": "text/x-python", | ||||
|    "name": "python", | ||||
|    "nbconvert_exporter": "python", | ||||
|    "pygments_lexer": "ipython3", | ||||
|    "version": "3.10.4" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 5 | ||||
| } | ||||
							
								
								
									
										42
									
								
								tests/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								tests/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| # Testing Guidelines | ||||
| PyFacts uses Pytest for unit testing. | ||||
| 
 | ||||
| All high level functions are expected to have tests written for them. Each file in the pyfacts module has a dedicated test file. All tests related to that file go within the respective test files. | ||||
| 
 | ||||
| Since this module needs test data for testing, a Pytest fixture has been defined to generate test data. Use this fixture to generate test data. The fixture uses the random module to generate random test data. A seed has been hardcoded for the random data generator to ensure it generates the same data all the time (if it didn't, tests for specific values would never pass). | ||||
| WARNING! Do not change the seed for the random data generator. This will cause most tests to fail. | ||||
| 
 | ||||
| To use the fixture, just pass `create_test_data` as an argument to the test function and then use it within the function. Pytest will automatically locate the relevant function (it need not be imported into the test file). | ||||
| 
 | ||||
| ## Writing tests | ||||
| Tests are organised as follows: | ||||
| - Each broad function/method has a Test Class | ||||
| - All variations should be tested within this class using one or more functions | ||||
| 
 | ||||
| All test files should be named `test_<module_file_name>.py`. | ||||
| For instance, test file for `core.py` is named `test_core.py` | ||||
| 
 | ||||
| All class names should begin with the word `Test`. | ||||
| All function names should begin with the word `test_`. | ||||
| 
 | ||||
| It needs to be ensured that all test functions are independent of each other. | ||||
| ## Running tests | ||||
| Skip this part if you already know how to run pytest. | ||||
| 
 | ||||
| Open the terminal. Make sure you are in the root pyfacts folder. Then run the following command: | ||||
| `pytest tests` | ||||
| 
 | ||||
| This will run the entire test suite. This can take some time depending on the number of tests and speed of your computer. Hence you might want to run only a few tests. | ||||
| 
 | ||||
| To run tests within a particular file, say test_core.py, type the following command: | ||||
| `pytest tests/test_core.py` | ||||
| 
 | ||||
| If you want to run only a particular class within a file, for instance `TestSetitem` within the `test_core.py` file, run them as follows: | ||||
| `pytest tests/test_core.py::TestSetitem` | ||||
| 
 | ||||
| This will run only the specified class, making sure your tests don't take too long. | ||||
| 
 | ||||
| If you're using VS Code, you can make this whole process easier by configuring pytest within VS Code. It will identify all tests and allow you to run them individually from the testing pane on the left. | ||||
| 
 | ||||
| ### Before you push your code | ||||
| Before you push your code or raise a PR, ensure that all tests are passing. PRs where any of the tests are failing will not be merged. Any modifications to the code which require a modification to existing tests should be accompanied with a note in the PR as to the reasons existing tests had to be modified. | ||||
| @ -86,47 +86,25 @@ class TestSharpe: | ||||
| 
 | ||||
| class TestSortino: | ||||
|     def test_sortino_daily_freq(self, create_test_data): | ||||
|         data = create_test_data(num=1305, frequency=pft.AllFrequencies.D, skip_weekends=True) | ||||
|         data = create_test_data(num=3600, frequency=pft.AllFrequencies.D, mu=0.12, sigma=0.12) | ||||
|         ts = pft.TimeSeries(data, "D") | ||||
|         sortino_ratio = pft.sortino_ratio( | ||||
|             ts, | ||||
|             risk_free_rate=0.06, | ||||
|             risk_free_rate=0.06 / 12, | ||||
|             from_date="2017-02-02", | ||||
|             to_date="2021-12-31", | ||||
|             return_period_unit="months", | ||||
|             return_period_value=1, | ||||
|         ) | ||||
|         assert round(sortino_ratio, 4) == 2.5377 | ||||
|         assert round(sortino_ratio, 4) == 1.625 | ||||
| 
 | ||||
|     #     sharpe_ratio = pft.sharpe_ratio( | ||||
|     #         ts, | ||||
|     #         risk_free_rate=0.06, | ||||
|     #         from_date="2017-01-09", | ||||
|     #         to_date="2021-12-31", | ||||
|     #         return_period_unit="days", | ||||
|     #         return_period_value=7, | ||||
|     #     ) | ||||
|     #     assert round(sharpe_ratio, 4) == 1.0701 | ||||
| 
 | ||||
|     #     sharpe_ratio = pft.sharpe_ratio( | ||||
|     #         ts, | ||||
|     #         risk_free_rate=0.06, | ||||
|     #         from_date="2018-01-02", | ||||
|     #         to_date="2021-12-31", | ||||
|     #         return_period_unit="years", | ||||
|     #         return_period_value=1, | ||||
|     #     ) | ||||
|     #     assert round(sharpe_ratio, 4) == 1.4374 | ||||
| 
 | ||||
|     #     sharpe_ratio = pft.sharpe_ratio( | ||||
|     #         ts, | ||||
|     #         risk_free_rate=0.06, | ||||
|     #         from_date="2017-07-03", | ||||
|     #         to_date="2021-12-31", | ||||
|     #         return_period_unit="months", | ||||
|     #         return_period_value=6, | ||||
|     #     ) | ||||
|     #     assert round(sharpe_ratio, 4) == 0.8401 | ||||
|         sortino_ratio = pft.sortino_ratio( | ||||
|             ts, | ||||
|             risk_free_rate=0.06, | ||||
|             from_date="2018-01-02", | ||||
|             return_period_unit="years", | ||||
|             return_period_value=1, | ||||
|         ) | ||||
|         assert round(sortino_ratio, 4) == 1.2564 | ||||
| 
 | ||||
|     # def test_sharpe_weekly_freq(self, create_test_data): | ||||
|     #     data = create_test_data(num=261, frequency=pft.AllFrequencies.W, mu=0.6, sigma=0.7) | ||||
| @ -185,7 +163,7 @@ class TestBeta: | ||||
|         sts = pft.TimeSeries(stock_data, "D") | ||||
|         mts = pft.TimeSeries(market_data, "D") | ||||
|         beta = pft.beta(sts, mts, frequency="M") | ||||
|         assert round(beta, 4) == 1.6137 | ||||
|         assert round(beta, 4) == 1.6131 | ||||
| 
 | ||||
|     def test_beta_monthly_freq_monthly_returns(self, create_test_data): | ||||
|         market_data = create_test_data(num=3600, frequency=pft.AllFrequencies.D) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user