pyfinq


Namepyfinq JSON
Version 0.4.0 PyPI version JSON
download
home_pagehttps://github.com/wilhelmagren/finq
Summary🔬 Quantitative analysis and management for financial applications.
upload_time2023-11-10 20:06:36
maintainer
docs_urlNone
authorWilhelm Ã…gren
requires_python>=3.9,<3.13
licenseMIT
keywords finance nasdaq investment yahoo-finance data-science time-series analysis optimization data-analysis quantiative-finance portfolio-optimization portfolio-management
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">
<br/>
<div align="left">
<br/>
<p align="center">
<a href="https://github.com/wilhelmagren/finq">
<img align="center" width=75% src="https://github.com/wilhelmagren/finq/blob/6636192f668e45f51d2092b4b0e861e1a61a9af7/docs/images/finq-banner.png"></img>
</a>
</p>
</div>

[![PyPI - Version](https://img.shields.io/pypi/v/pyfinq)](https://pypi.org/project/pyfinq)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![codecov](https://codecov.io/gh/wilhelmagren/finq/graph/badge.svg?token=9QTX90NYYG)](https://codecov.io/gh/wilhelmagren/finq)
[![CI](https://github.com/wilhelmagren/finq/actions/workflows/ci.yml/badge.svg)](https://github.com/wilhelmagren/finq/actions/workflows/ci.yml)
[![CD](https://github.com/wilhelmagren/finq/actions/workflows/cd.yml/badge.svg)](https://github.com/wilhelmagren/finq/actions/workflows/cd.yml)
[![Tests](https://github.com/wilhelmagren/finq/actions/workflows/tests.yml/badge.svg)](https://github.com/wilhelmagren/finq/actions/workflows/tests.yml)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Lint style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)

</div>

## 🔎 Overview
The goal of *finq* is to provide an all-in-one Python library for **quantitative portfolio analysis and optimization** on historical and real-time financial data.

**NOTE:** Features are currently being determined and developed continuously. The repo is undergoing heavy modifications and could introduce **breaking changes** up until first major release. Current version is **v0.4.0**.

## 📦 Installation
Either clone this repository and perform a local install with [poetry](https://github.com/python-poetry/poetry/tree/master) accordingly
```
git clone https://github.com/wilhelmagren/finq.git
cd finq
poetry install
```
or install the most recent release from the Python Package Index (PyPI).
```
pip install pyfinq
```

## 🚀 Example usage
*finq* supports a large number of major world indices which can be used through their respective `Dataset` implementation. To download all ticker OHLC data for a period and saving it locally for the `OMXS30` index, you can do the following:
```python
from finq.datasets import OMXS30

dataset = OMXS30(save=True)
dataset.run("2y")

```

The `.run(period)` function is a convenient wrapper for three other functions. The alternative way would be by running:
```python
dataset.fetch_data("2y").fix_missing_data().verify_data()
```

and for a full list of all implemented indices, please take a look at the following [link](https://github.com/wilhelmagren/finq/blob/ade0e4ca064b08190131d013d6230c4d74be4986/finq/datasets/__init__.py).

You can also define custom datasets, which may not be an already available major world index. To do that you need to use the `CustomDataset` and provide both a list of security names and their ticker symbols
which are to be included in your dataset. Furthermore, you need to specify what market the ticker symbols are available on, e.g., `NASDAQ` or `OMX`. In code it can look like this:

```python
from finq.datasets import CustomDataset

names = ["Alfa Laval", "Boliden", "SEB A", "Sv. Handelsbanken A"]
symbols = ["ALFA.ST", "BOL.ST", "SEB-A.ST", "SHB-A.ST"]

dataset = CustomDataset(names, symbols, market="OMX", save=False)
dataset = dataset.run("6mo")
...

```

The `Dataset` class supports visualizing any OHLC historical data for all considered tickers. Calling the `.visualize(price_type="Close")` function on the OMXS30 index would yield the following plot:
<details>
<summary>Show dataset plot</summary>
    
![OMXS30 Visualization 6 months](./docs/images/OMXS30_visualization.png)
    
</details>

and the majority of labels and styles for the plot can be customized regularly with [matplotlib](https://matplotlib.org/) styling. You can also choose to visualize more advanced plots, but only for individual assets,
through the [mplfinance](https://github.com/matplotlib/mplfinance) library. The below image is a `candle` plot of the **BOL.ST** ticker from the **OMXS30** index, with three moving averages.

<details>
    <summary>Show ticker plot</summary>

![BOL.ST Candle plot](./docs/images/OMXS30_BOL_visualization.png)
    
</details>

---
You can create a `Portfolio` in a large number of ways. The most convenient way is to first initialize a `Dataset` like above, and then pass that dataset to the portfolio class constructor. The class also supports passing in
a list of `Asset` objects, or a `np.ndarray`, or a `pd.DataFrame`. But for the latter three alternatives you need to also provide the security names and ticker symbols from which the data came from.
All different methods are showed in the snipper below:

```python
from finq import Portfolio

# All four alternatives are equally viable.
# The latter three are implemented for whenever
# you preferably only want to work with local data.
from_dataset = Portfolio(dataset)
from_assets = Portfolio(assets, names=["SEB-A.ST", ...], symbols=...)
from_numpy = Portfolio(np_arr, names=["SEB-A.ST", ...], symbols=...)
from_pandas = Portfolio(pd_df, names=["SEB-A.ST", ...], symbols=...)
...

```

To optimize your portfolio against some objective function, you use the `optimize(...)` function. Optimizing the mean variance expression (maximizing sharpe ratio) requires you to specify the 
objective function that you want to *minimize*, the initial weights of your portfolio, optionally the bounds and constraints of the portfolio weights. You can do it in the following way:

```python
from finq import Portfolio
from finq.datasets import OMXS30
from finq.formulas import mean_variance

dataset = OMXS30(save=True)
dataset = dataset.run("2y")

portfolio = Portfolio(dataset)
portfolio.initialize_random_weights(
    "lognormal",
    size=(len(dataset), 1),
)

risk_tolerance = 1

portfolio.set_objective_function(
    mean_variance,
    risk_tolerance * portfolio.daily_covariance(),
    portfolio.daily_returns_mean(),
)

portfolio.set_objective_bounds(
    [(0, 0.2) for _ in range(len(dataset))],
)

portfolio.optimize(
    method="COBYLA",
    options={"maxiter": 1000},
)

portfolio.plot_mean_variance(n_samples=10000, figsize=(8, 5))
```

The above code is directly taken from one of the scripts available in the [examples](./examples) directory in this repo. Running it can yield the following comparative plot of the sharpe ratios for: your *optimized* portfolio weights,
and randomly sampled portfolio weights.

<details>
    <summary>Show sharpe ratio plot</summary>

![OMXS30 sharpe ratio plot](./docs/images/OMXS30_sharpe-ratio_COBYLA.png)
    
</details>

## 📋 License
All code is to be held under a general MIT license, please see [LICENSE](https://github.com/wilhelmagren/finq/blob/main/LICENSE) for specific information.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/wilhelmagren/finq",
    "name": "pyfinq",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9,<3.13",
    "maintainer_email": "",
    "keywords": "finance,nasdaq,investment,yahoo-finance,data-science,time-series,analysis,optimization,data-analysis,quantiative-finance,portfolio-optimization,portfolio-management",
    "author": "Wilhelm \u00c5gren",
    "author_email": "wilhelmagren98@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/9b/7f/880a25ce2bd88262e8fee9505db8fff20b915ba31edb45e2f66ea3229abc/pyfinq-0.4.0.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n<br/>\n<div align=\"left\">\n<br/>\n<p align=\"center\">\n<a href=\"https://github.com/wilhelmagren/finq\">\n<img align=\"center\" width=75% src=\"https://github.com/wilhelmagren/finq/blob/6636192f668e45f51d2092b4b0e861e1a61a9af7/docs/images/finq-banner.png\"></img>\n</a>\n</p>\n</div>\n\n[![PyPI - Version](https://img.shields.io/pypi/v/pyfinq)](https://pypi.org/project/pyfinq)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![codecov](https://codecov.io/gh/wilhelmagren/finq/graph/badge.svg?token=9QTX90NYYG)](https://codecov.io/gh/wilhelmagren/finq)\n[![CI](https://github.com/wilhelmagren/finq/actions/workflows/ci.yml/badge.svg)](https://github.com/wilhelmagren/finq/actions/workflows/ci.yml)\n[![CD](https://github.com/wilhelmagren/finq/actions/workflows/cd.yml/badge.svg)](https://github.com/wilhelmagren/finq/actions/workflows/cd.yml)\n[![Tests](https://github.com/wilhelmagren/finq/actions/workflows/tests.yml/badge.svg)](https://github.com/wilhelmagren/finq/actions/workflows/tests.yml)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Lint style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)\n\n</div>\n\n## \ud83d\udd0e Overview\nThe goal of *finq* is to provide an all-in-one Python library for **quantitative portfolio analysis and optimization** on historical and real-time financial data.\n\n**NOTE:** Features are currently being determined and developed continuously. The repo is undergoing heavy modifications and could introduce **breaking changes** up until first major release. Current version is **v0.4.0**.\n\n## \ud83d\udce6 Installation\nEither clone this repository and perform a local install with [poetry](https://github.com/python-poetry/poetry/tree/master) accordingly\n```\ngit clone https://github.com/wilhelmagren/finq.git\ncd finq\npoetry install\n```\nor install the most recent release from the Python Package Index (PyPI).\n```\npip install pyfinq\n```\n\n## \ud83d\ude80 Example usage\n*finq* supports a large number of major world indices which can be used through their respective `Dataset` implementation. To download all ticker OHLC data for a period and saving it locally for the `OMXS30` index, you can do the following:\n```python\nfrom finq.datasets import OMXS30\n\ndataset = OMXS30(save=True)\ndataset.run(\"2y\")\n\n```\n\nThe `.run(period)` function is a convenient wrapper for three other functions. The alternative way would be by running:\n```python\ndataset.fetch_data(\"2y\").fix_missing_data().verify_data()\n```\n\nand for a full list of all implemented indices, please take a look at the following [link](https://github.com/wilhelmagren/finq/blob/ade0e4ca064b08190131d013d6230c4d74be4986/finq/datasets/__init__.py).\n\nYou can also define custom datasets, which may not be an already available major world index. To do that you need to use the `CustomDataset` and provide both a list of security names and their ticker symbols\nwhich are to be included in your dataset. Furthermore, you need to specify what market the ticker symbols are available on, e.g., `NASDAQ` or `OMX`. In code it can look like this:\n\n```python\nfrom finq.datasets import CustomDataset\n\nnames = [\"Alfa Laval\", \"Boliden\", \"SEB A\", \"Sv. Handelsbanken A\"]\nsymbols = [\"ALFA.ST\", \"BOL.ST\", \"SEB-A.ST\", \"SHB-A.ST\"]\n\ndataset = CustomDataset(names, symbols, market=\"OMX\", save=False)\ndataset = dataset.run(\"6mo\")\n...\n\n```\n\nThe `Dataset` class supports visualizing any OHLC historical data for all considered tickers. Calling the `.visualize(price_type=\"Close\")` function on the OMXS30 index would yield the following plot:\n<details>\n<summary>Show dataset plot</summary>\n    \n![OMXS30 Visualization 6 months](./docs/images/OMXS30_visualization.png)\n    \n</details>\n\nand the majority of labels and styles for the plot can be customized regularly with [matplotlib](https://matplotlib.org/) styling. You can also choose to visualize more advanced plots, but only for individual assets,\nthrough the [mplfinance](https://github.com/matplotlib/mplfinance) library. The below image is a `candle` plot of the **BOL.ST** ticker from the **OMXS30** index, with three moving averages.\n\n<details>\n    <summary>Show ticker plot</summary>\n\n![BOL.ST Candle plot](./docs/images/OMXS30_BOL_visualization.png)\n    \n</details>\n\n---\nYou can create a `Portfolio` in a large number of ways. The most convenient way is to first initialize a `Dataset` like above, and then pass that dataset to the portfolio class constructor. The class also supports passing in\na list of `Asset` objects, or a `np.ndarray`, or a `pd.DataFrame`. But for the latter three alternatives you need to also provide the security names and ticker symbols from which the data came from.\nAll different methods are showed in the snipper below:\n\n```python\nfrom finq import Portfolio\n\n# All four alternatives are equally viable.\n# The latter three are implemented for whenever\n# you preferably only want to work with local data.\nfrom_dataset = Portfolio(dataset)\nfrom_assets = Portfolio(assets, names=[\"SEB-A.ST\", ...], symbols=...)\nfrom_numpy = Portfolio(np_arr, names=[\"SEB-A.ST\", ...], symbols=...)\nfrom_pandas = Portfolio(pd_df, names=[\"SEB-A.ST\", ...], symbols=...)\n...\n\n```\n\nTo optimize your portfolio against some objective function, you use the `optimize(...)` function. Optimizing the mean variance expression (maximizing sharpe ratio) requires you to specify the \nobjective function that you want to *minimize*, the initial weights of your portfolio, optionally the bounds and constraints of the portfolio weights. You can do it in the following way:\n\n```python\nfrom finq import Portfolio\nfrom finq.datasets import OMXS30\nfrom finq.formulas import mean_variance\n\ndataset = OMXS30(save=True)\ndataset = dataset.run(\"2y\")\n\nportfolio = Portfolio(dataset)\nportfolio.initialize_random_weights(\n    \"lognormal\",\n    size=(len(dataset), 1),\n)\n\nrisk_tolerance = 1\n\nportfolio.set_objective_function(\n    mean_variance,\n    risk_tolerance * portfolio.daily_covariance(),\n    portfolio.daily_returns_mean(),\n)\n\nportfolio.set_objective_bounds(\n    [(0, 0.2) for _ in range(len(dataset))],\n)\n\nportfolio.optimize(\n    method=\"COBYLA\",\n    options={\"maxiter\": 1000},\n)\n\nportfolio.plot_mean_variance(n_samples=10000, figsize=(8, 5))\n```\n\nThe above code is directly taken from one of the scripts available in the [examples](./examples) directory in this repo. Running it can yield the following comparative plot of the sharpe ratios for: your *optimized* portfolio weights,\nand randomly sampled portfolio weights.\n\n<details>\n    <summary>Show sharpe ratio plot</summary>\n\n![OMXS30 sharpe ratio plot](./docs/images/OMXS30_sharpe-ratio_COBYLA.png)\n    \n</details>\n\n## \ud83d\udccb License\nAll code is to be held under a general MIT license, please see [LICENSE](https://github.com/wilhelmagren/finq/blob/main/LICENSE) for specific information.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\ud83d\udd2c Quantitative analysis and management for financial applications. ",
    "version": "0.4.0",
    "project_urls": {
        "Bug tracker": "https://github.com/wilhelmagren/finq/issues",
        "Homepage": "https://github.com/wilhelmagren/finq",
        "Repository": "https://github.com/wilhelmagren/finq"
    },
    "split_keywords": [
        "finance",
        "nasdaq",
        "investment",
        "yahoo-finance",
        "data-science",
        "time-series",
        "analysis",
        "optimization",
        "data-analysis",
        "quantiative-finance",
        "portfolio-optimization",
        "portfolio-management"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9cd97dc776c0c02da3e15cf654fbbe0847665e6f0355c0388c4162a4661ebb17",
                "md5": "79c0f8ea2c722b97b4cddd8251ff73e4",
                "sha256": "efdcc3a96fee3d273ccd11a1c44115340815640b5565a6a7e32439a2117ea3f3"
            },
            "downloads": -1,
            "filename": "pyfinq-0.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "79c0f8ea2c722b97b4cddd8251ff73e4",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<3.13",
            "size": 42708,
            "upload_time": "2023-11-10T20:06:35",
            "upload_time_iso_8601": "2023-11-10T20:06:35.070892Z",
            "url": "https://files.pythonhosted.org/packages/9c/d9/7dc776c0c02da3e15cf654fbbe0847665e6f0355c0388c4162a4661ebb17/pyfinq-0.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9b7f880a25ce2bd88262e8fee9505db8fff20b915ba31edb45e2f66ea3229abc",
                "md5": "02198b00440868598f88f8089c8409b0",
                "sha256": "3b75f8882b128b91ee848a86ce99ca3319260e8a9fdbf337261df5563d43fd27"
            },
            "downloads": -1,
            "filename": "pyfinq-0.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "02198b00440868598f88f8089c8409b0",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<3.13",
            "size": 29177,
            "upload_time": "2023-11-10T20:06:36",
            "upload_time_iso_8601": "2023-11-10T20:06:36.469097Z",
            "url": "https://files.pythonhosted.org/packages/9b/7f/880a25ce2bd88262e8fee9505db8fff20b915ba31edb45e2f66ea3229abc/pyfinq-0.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-10 20:06:36",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "wilhelmagren",
    "github_project": "finq",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyfinq"
}
        
Elapsed time: 0.14081s