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