A Python library for working with time series data. It comes with common financial functions built-in.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

390 lines
13 KiB

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "e1ecfa55",
"metadata": {},
"outputs": [],
"source": [
"import fincal as fc"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ccac3896",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"fincal.fincal.TimeSeries"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fc.TimeSeries"
]
},
{
"cell_type": "code",
"execution_count": 3,
"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": 5,
"id": "fcc5f8f1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TimeSeries([(datetime.datetime(2022, 1, 1, 0, 0), 10),\n",
"\t(datetime.datetime(2022, 1, 2, 0, 0), 12),\n",
"\t(datetime.datetime(2022, 1, 3, 0, 0), 14)], frequency='M')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts = fc.TimeSeries(data, 'M')\n",
"ts"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "c9e9cb1b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TimeSeries([(datetime.datetime(2022, 1, 1, 0, 0), 10),\n",
"\t(datetime.datetime(2022, 1, 2, 0, 0), 12),\n",
"\t(datetime.datetime(2022, 1, 3, 0, 0), 14),\n",
"\t(datetime.datetime(2022, 1, 4, 0, 0), 15),\n",
"\t(datetime.datetime(2022, 1, 5, 0, 0), 16)], frequency='M')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts['2022-01-04'] = 15\n",
"ts"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "8e812756",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TimeSeries([(datetime.datetime(2022, 1, 1, 0, 0), 10),\n",
"\t (datetime.datetime(2022, 1, 8, 0, 0), 20),\n",
"\t (datetime.datetime(2022, 1, 15, 0, 0), 28)\n",
"\t ...\n",
"\t (datetime.datetime(2022, 12, 17, 0, 0), 28),\n",
"\t (datetime.datetime(2022, 12, 24, 0, 0), 28),\n",
"\t (datetime.datetime(2022, 12, 31, 0, 0), 28)], frequency='W')"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"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": 13,
"id": "36eefec7-7dbf-4a28-ac50-2e502d9d6864",
"metadata": {},
"outputs": [],
"source": [
"weekly_data = [('2017-01-01', 67),\n",
"('2017-01-08', 79),\n",
"('2017-01-15', 73),\n",
"('2017-01-22', 63),\n",
"('2017-01-29', 85),\n",
"('2017-02-05', 66),\n",
"('2017-02-12', 78),\n",
"('2017-02-19', 75),\n",
"('2017-02-26', 76),\n",
"('2017-03-05', 82),\n",
"('2017-03-12', 85),\n",
"('2017-03-19', 63),\n",
"('2017-03-26', 78),\n",
"('2017-04-02', 65),\n",
"('2017-04-09', 85),\n",
"('2017-04-16', 86),\n",
"('2017-04-23', 67),\n",
"('2017-04-30', 65),\n",
"('2017-05-07', 82),\n",
"('2017-05-14', 73),\n",
"('2017-05-21', 78),\n",
"('2017-05-28', 74),\n",
"('2017-06-04', 62),\n",
"('2017-06-11', 84),\n",
"('2017-06-18', 83)]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "39bd8598-ab0f-4c81-8428-ad8248e686d3",
"metadata": {},
"outputs": [],
"source": [
"week_ts = fc.TimeSeries(weekly_data, 'W')"
]
},
{
"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": 23,
"id": "a549c5c0-c89a-4cc3-b396-c4afa77a9879",
"metadata": {},
"outputs": [
{
"ename": "OverflowError",
"evalue": "date value out of range",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
"File \u001b[0;32m~/Documents/projects/fincal/fincal/core.py:405\u001b[0m, in \u001b[0;36mTimeSeriesCore.get\u001b[0;34m(self, date, default, closest)\u001b[0m\n\u001b[1;32m 404\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 405\u001b[0m item \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_item_from_date\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdate\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 406\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m item\n",
"File \u001b[0;32m~/Documents/projects/fincal/fincal/core.py:69\u001b[0m, in \u001b[0;36mdate_parser.<locals>.parse_dates.<locals>.wrapper_func\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 68\u001b[0m args[j] \u001b[38;5;241m=\u001b[39m parsed_date\n\u001b[0;32m---> 69\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/Documents/projects/fincal/fincal/core.py:328\u001b[0m, in \u001b[0;36mTimeSeriesCore._get_item_from_date\u001b[0;34m(self, date)\u001b[0m\n\u001b[1;32m 326\u001b[0m \u001b[38;5;129m@date_parser\u001b[39m(\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m 327\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_get_item_from_date\u001b[39m(\u001b[38;5;28mself\u001b[39m, date: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m|\u001b[39m datetime\u001b[38;5;241m.\u001b[39mdatetime):\n\u001b[0;32m--> 328\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m date, \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdata\u001b[49m\u001b[43m[\u001b[49m\u001b[43mdate\u001b[49m\u001b[43m]\u001b[49m\n",
"\u001b[0;31mKeyError\u001b[0m: datetime.datetime(1, 1, 1, 0, 0)",
"\nDuring handling of the above exception, another exception occurred:\n",
"\u001b[0;31mOverflowError\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [23]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mweek_ts\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msync\u001b[49m\u001b[43m(\u001b[49m\u001b[43mts\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/Documents/projects/fincal/fincal/fincal.py:733\u001b[0m, in \u001b[0;36mTimeSeries.sync\u001b[0;34m(self, other, fill_method)\u001b[0m\n\u001b[1;32m 731\u001b[0m new_other[dt] \u001b[38;5;241m=\u001b[39m other[dt][\u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 732\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 733\u001b[0m new_other[dt] \u001b[38;5;241m=\u001b[39m other\u001b[38;5;241m.\u001b[39mget(dt, closest\u001b[38;5;241m=\u001b[39mclosest)[\u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 735\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m(new_other, frequency\u001b[38;5;241m=\u001b[39mother\u001b[38;5;241m.\u001b[39mfrequency\u001b[38;5;241m.\u001b[39msymbol)\n",
"File \u001b[0;32m~/Documents/projects/fincal/fincal/core.py:69\u001b[0m, in \u001b[0;36mdate_parser.<locals>.parse_dates.<locals>.wrapper_func\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m args[j] \u001b[38;5;241m=\u001b[39m parsed_date\n\u001b[0;32m---> 69\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/Documents/projects/fincal/fincal/core.py:408\u001b[0m, in \u001b[0;36mTimeSeriesCore.get\u001b[0;34m(self, date, default, closest)\u001b[0m\n\u001b[1;32m 406\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m item\n\u001b[1;32m 407\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[0;32m--> 408\u001b[0m date \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m delta\n",
"\u001b[0;31mOverflowError\u001b[0m: date value out of range"
]
}
],
"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 56.9 ms, sys: 3.3 ms, total: 60.2 ms\n",
"Wall time: 60.2 ms\n"
]
}
],
"source": [
"%%time\n",
"ts = fc.read_csv('test_files/msft.csv', frequency='D')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "b7c176d4-d89f-4bda-9d67-75463eb90468",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(datetime.datetime(2022, 2, 9, 0, 0), 311.209991)\n",
"(datetime.datetime(2022, 2, 10, 0, 0), 302.380005)\n",
"(datetime.datetime(2022, 2, 11, 0, 0), 295.040009)\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": 4,
"id": "69c57754-a6fb-4881-9359-ba17c7fb8be5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1.85 ms, sys: 143 µs, total: 1.99 ms\n",
"Wall time: 2 ms\n"
]
}
],
"source": [
"%%time\n",
"ts['2022-02-12'] = 295"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "7aa02023-406e-4700-801c-c06390ddf914",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 3.7 ms, sys: 121 µs, total: 3.82 ms\n",
"Wall time: 3.84 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": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"ts.max_drawdown()"
]
}
],
"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
}