Skip to content

Commit

Permalink
Refactor/asset stock market index (#107)
Browse files Browse the repository at this point in the history
Refactoring the code:
Instead of having almost identical classes for Stock and Market, we now
introduce a parent class Asset for both.
  • Loading branch information
fmilthaler committed Jul 19, 2023
1 parent 13217b5 commit 184c014
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 152 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<img src="https://img.shields.io/github/stars/fmilthaler/FinQuant.svg?style=social&label=Star" alt='pypi'>
</a>
<a href="https://pypi.org/project/FinQuant">
<img src="https://img.shields.io/badge/pypi-v0.3.1-brightgreen.svg?style=popout" alt='pypi'>
<img src="https://img.shields.io/badge/pypi-v0.3.2-brightgreen.svg?style=popout" alt='pypi'>
</a>
<a href="https://github.com/fmilthaler/FinQuant">
<img src="https://github.com/fmilthaler/finquant/actions/workflows/pytest.yml/badge.svg?branch=master" alt='GitHub Actions'>
Expand Down
2 changes: 1 addition & 1 deletion README.tex.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<img src="https://img.shields.io/github/stars/fmilthaler/FinQuant.svg?style=social&label=Star" alt='pypi'>
</a>
<a href="https://pypi.org/project/FinQuant">
<img src="https://img.shields.io/badge/pypi-v0.3.1-brightgreen.svg?style=popout" alt='pypi'>
<img src="https://img.shields.io/badge/pypi-v0.3.2-brightgreen.svg?style=popout" alt='pypi'>
</a>
<a href="https://github.com/fmilthaler/FinQuant">
<img src="https://github.com/fmilthaler/finquant/actions/workflows/pytest.yml/badge.svg?branch=master" alt='GitHub Actions'>
Expand Down
122 changes: 122 additions & 0 deletions finquant/asset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""
This module provides a public class ``Asset`` that represents a generic financial asset.
It serves as the parent class for specialized asset classes like ``Stock`` and ``Market``
in the finquant library.
An asset is characterized by its historical price data, from which various quantities
such as expected return, volatility, skewness, and kurtosis can be computed. The ``Asset``
class provides common functionality and attributes that are shared among different types
of assets.
The specialized asset classes, ``Stock`` and ``Market``, inherit from the ``Asset`` class
and add specific functionality tailored to their respective types.
"""


import numpy as np
import pandas as pd

from finquant.returns import daily_returns, historical_mean_return


class Asset:
"""
Parent class representing a generic financial asset.
:param ``data``: Historical price data of the asset as a ``pandas.Series``.
:param ``name``: Name of the asset.
:param ``asset_type``: Type of the asset (e.g., "Stock" or "Market index").
The ``Asset`` class provides common functionality and attributes for financial assets.
It represents a generic asset and serves as the parent class for specialized asset classes.
Attributes:
- ``data`` (``pandas.Series``): Historical price data of the asset.
- ``name`` (``str``): Name of the asset.
- ``asset_type`` (``str``): Type of the asset (e.g., "Stock" or "Market").
- ``expected_return`` (``float``): Expected return of the asset.
- ``volatility`` (``float``): Volatility of the asset.
- ``skew`` (``float``): Skewness of the asset.
- ``kurtosis`` (``float``): Kurtosis of the asset.
The ``Asset`` class provides methods to compute various quantities such as expected return,
volatility, skewness, and kurtosis based on the historical price data of the asset.
"""

def __init__(self, data: pd.Series, name: str, asset_type: str = 'Market index') -> None:
"""
:Input:
:data: ``pandas.Series``, of asset prices
:name: ``str``, Name of the asset
:asset_type: ``str`` (default: ``'Market index'``), Type of the asset (e.g., "Stock" or "Market index")
"""
self.data = data
self.name = name
# compute expected return and volatility of asset
self.expected_return = self.comp_expected_return()
self.volatility = self.comp_volatility()
self.skew = self._comp_skew()
self.kurtosis = self._comp_kurtosis()
# type of asset
self.asset_type = asset_type

# functions to compute quantities
def comp_daily_returns(self) -> pd.Series:
"""Computes the daily returns (percentage change) of the asset.
See ``finquant.returns.daily_returns``.
"""
return daily_returns(self.data)

def comp_expected_return(self, freq=252) -> float:
"""Computes the Expected Return of the asset.
See ``finquant.returns.historical_mean_return``.
:Input:
:freq: ``int`` (default: ``252``), number of trading days, default
value corresponds to trading days in a year
:Output:
:expected_return: ``float``, Expected Return of asset.
"""
return historical_mean_return(self.data, freq=freq)

def comp_volatility(self, freq=252) -> float:
"""Computes the Volatility of the asset.
:Input:
:freq: ``int`` (default: ``252``), number of trading days, default
value corresponds to trading days in a year
:Output:
:volatility: ``float``, Volatility of asset.
"""
return self.comp_daily_returns().std() * np.sqrt(freq)

def _comp_skew(self) -> float:
"""Computes and returns the skewness of the asset."""
return self.data.skew()

def _comp_kurtosis(self) -> float:
"""Computes and returns the kurtosis of the asset."""
return self.data.kurt()

def properties(self):
"""Nicely prints out the properties of the asset,
with customized messages based on the asset type.
"""
# nicely printing out information and quantities of the asset
string = "-" * 50
string += f"\n{self.asset_type}: {self.name}"
string += f"\nExpected Return: {self.expected_return:0.3f}"
string += f"\nVolatility: {self.volatility:0.3f}"
string += f"\nSkewness: {self.skew:0.5f}"
string += f"\nKurtosis: {self.kurtosis:0.5f}"
string += "\n" + "-" * 50
print(string)

def __str__(self):
# print short description
string = f"Contains information about {self.asset_type}: {self.name}."
return string
94 changes: 27 additions & 67 deletions finquant/market.py
Original file line number Diff line number Diff line change
@@ -1,86 +1,46 @@
"""This module provides a public class ``Market`` that holds and calculates quantities of a market index"""
"""
This module provides a public class ``Market`` that represents a market index.
It serves as a specialized asset class within the finquant library.
A market index represents the performance of a specific market or a segment of the market,
such as the S&P 500 or NASDAQ. The ``Market`` class is designed to hold and calculate quantities
related to a market index, such as expected return, volatility, skewness, and kurtosis.
The ``Market`` class extends the ``Asset`` class from ``finquant.asset`` and inherits its
common functionality and attributes for financial assets. It provides additional methods
and attributes specific to market indices.
"""

import numpy as np
import pandas as pd

from finquant.asset import Asset
from finquant.returns import daily_returns, historical_mean_return


class Market:
"""Object that contains information about a market index.
To initialise the object, it requires a name and information about
the index given as ``pandas.Series`` data structure.
class Market(Asset):
"""
Class representing a market index.
:param data: Historical price data of the market index as a ``pandas.Series``.
The ``Market`` class extends the ``Asset`` class and represents a specific type of asset,
specifically a market index.
It requires historical price data for the market index to initialize an instance.
"""

def __init__(self, data: pd.Series) -> None:
"""
:Input:
:data: ``pandas.Series`` of market index prices
"""
self.name = data.name
self.data = data
# compute expected return and volatility of market index
self.expected_return = self.comp_expected_return()
self.volatility = self.comp_volatility()
self.skew = self._comp_skew()
self.kurtosis = self._comp_kurtosis()
super().__init__(data, name=data.name, asset_type="Market index")
self.daily_returns = self.comp_daily_returns()

# functions to compute quantities
def comp_daily_returns(self) -> pd.Series:
"""Computes the daily returns (percentage change) of the market index.
See ``finance_portfolio.returns.daily_returns``.
See ``finquant.returns.daily_returns``.
"""
return daily_returns(self.data)

def comp_expected_return(self, freq=252) -> float:
"""Computes the Expected Return of the market index.
See ``finance_portfolio.returns.historical_mean_return``.
:Input:
:freq: ``int`` (default: ``252``), number of trading days, default
value corresponds to trading days in a year
:Output:
:expected_return: Expected Return of market index.
"""
return historical_mean_return(self.data, freq=freq)

def comp_volatility(self, freq=252) -> float:
"""Computes the Volatility of the market index.
:Input:
:freq: ``int`` (default: ``252``), number of trading days, default
value corresponds to trading days in a year
:Output:
:volatility: volatility of market index.
"""
return self.comp_daily_returns().std() * np.sqrt(freq)

def _comp_skew(self) -> float:
"""Computes and returns the skewness of the market index."""
return self.data.skew()

def _comp_kurtosis(self) -> float:
"""Computes and returns the Kurtosis of the market index."""
return self.data.kurt()

def properties(self):
"""Nicely prints out the properties of the market index:
Expected Return, Volatility, Skewness, and Kurtosis.
"""
# nicely printing out information and quantities of market index
string = "-" * 50
string += f"\nMarket index: {self.name}"
string += f"\nExpected Return:{self.expected_return:0.3f}"
string += f"\nVolatility: {self.volatility:0.3f}"
string += f"\nSkewness: {self.skew:0.5f}"
string += f"\nKurtosis: {self.kurtosis:0.5f}"
string += "-" * 50
print(string)

def __str__(self):
# print short description
string = "Contains information about market index " + str(self.name) + "."
return string
return daily_returns(self.data)

0 comments on commit 184c014

Please sign in to comment.