Skip to content

Commit

Permalink
formatting with black
Browse files Browse the repository at this point in the history
  • Loading branch information
fmilthaler committed Jul 26, 2023
1 parent b71933a commit 2090462
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 17 deletions.
16 changes: 13 additions & 3 deletions finquant/portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@
from finquant.monte_carlo import MonteCarloOpt
from finquant.quants import sharpe_ratio, value_at_risk, weighted_mean, weighted_std
from finquant.quants import sharpe_ratio, weighted_mean, weighted_std, sortino_ratio, downside_risk
from finquant.quants import (
sharpe_ratio,
weighted_mean,
weighted_std,
sortino_ratio,
downside_risk,
)
from finquant.returns import (
cumulative_returns,
daily_log_returns,
Expand Down Expand Up @@ -363,8 +370,9 @@ def comp_downside_risk(self, freq=252):
:Output:
:volatility: Downside risk of stock.
"""
return downside_risk(self.data, self.comp_weights(), self.risk_free_rate) * np.sqrt(freq)

return downside_risk(
self.data, self.comp_weights(), self.risk_free_rate
) * np.sqrt(freq)

def comp_cov(self):
"""Compute and return a ``pandas.DataFrame`` of the covariance matrix
Expand Down Expand Up @@ -427,7 +435,9 @@ def comp_sortino(self, freq=252):
:sortino: ``float``, the Sortino Ratio of the portfolio
May be NaN if the portoflio outperformed the risk free rate at every point
"""
return sortino_ratio(self.expected_return, self.downside_risk, self.risk_free_rate)
return sortino_ratio(
self.expected_return, self.downside_risk, self.risk_free_rate
)

def _comp_skew(self):
"""Computes and returns the skewness of the stocks in the portfolio."""
Expand Down
5 changes: 3 additions & 2 deletions finquant/quants.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def sharpe_ratio(exp_return, volatility, risk_free_rate=0.005):
raise ValueError("risk_free_rate is expected to be an integer or float.")
return (exp_return - risk_free_rate) / float(volatility)


def sortino_ratio(exp_return, downside_risk, risk_free_rate=0.005):
"""Computes the Sharpe Ratio
Expand All @@ -101,13 +102,14 @@ def sortino_ratio(exp_return, downside_risk, risk_free_rate=0.005):
raise ValueError("risk_free_rate is expected to be an integer or float.")
return (exp_return - risk_free_rate) / float(downside_risk)


def downside_risk(data, weights, risk_free_rate=0.005):
"""Computes the downside risk (target semideviation of returns, given a risk free rate)
:Input:
:data: ``pandas.DataFrame`` with daily stock prices
:weights: ``numpy.ndarray``/``pd.Series`` of weights
:risk_free_rate: ``int``/``float`` (default=``0.005``), risk free rate
:Output:
:downside_risk: ``float`` (can be NaN if all returns outperform the risk free rate)
"""
Expand All @@ -120,7 +122,6 @@ def downside_risk(data, weights, risk_free_rate=0.005):
return np.sqrt((downside * downside).mean())



def value_at_risk(investment, mu, sigma, conf_level=0.95) -> float:
"""Computes and returns the expected value at risk of an investment/assets.
Expand Down
2 changes: 2 additions & 0 deletions finquant/returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def daily_returns(data):
"""
return data.pct_change().dropna(how="all").replace([np.inf, -np.inf], np.nan)


def weighted_mean_daily_returns(data, weights):
"""Returns DataFrame with the daily weighted mean returns
Expand All @@ -47,6 +48,7 @@ def weighted_mean_daily_returns(data, weights):
"""
return np.dot(daily_returns(data), weights)


def daily_log_returns(data):
"""
Returns DataFrame with daily log returns
Expand Down
9 changes: 5 additions & 4 deletions tests/test_quants.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from finquant.quants import sharpe_ratio, annualised_portfolio_quantities
import pdb


def test_weighted_mean():
means = np.array([1])
weights = np.array([1])
Expand Down Expand Up @@ -82,17 +83,17 @@ def test_annualised_portfolio_quantities():
for i in range(len(res)):
assert abs(res[i] - orig[i]) <= 1e-15


def test_downside_risk():
data1 = pd.DataFrame({ "1": [1, 2, 4, 8], "2" : [1, 2, 3, 4] })
data1 = pd.DataFrame({"1": [1, 2, 4, 8], "2": [1, 2, 3, 4]})
weights = np.array([0.25, 0.75])
rf_rate = 0.005
dr1 = downside_risk(data1, weights, rf_rate)
assert np.isnan(dr1)

data2 = pd.DataFrame({"1": [10, 7, 10, 6, 11]})
weights = np.array([1])
rf_rate = 0.
rf_rate = 0.0
dr2 = downside_risk(data2, weights, rf_rate)
print(dr2)
assert abs(dr2 - .35355339059327376220) <= 1e-15

assert abs(dr2 - 0.35355339059327376220) <= 1e-15
23 changes: 15 additions & 8 deletions tests/test_returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@
)

import numpy as np
from finquant.returns import cumulative_returns, daily_returns, weighted_mean_daily_returns
from finquant.returns import (
cumulative_returns,
daily_returns,
weighted_mean_daily_returns,
)
from finquant.returns import daily_log_returns, historical_mean_return


def test_cumulative_returns():
orig = [
list(range(10)),
Expand Down Expand Up @@ -43,22 +48,24 @@ def test_daily_returns():
assert all(abs(ret["1"].values - orig[0]) <= 1e-15)
assert all(abs(ret["2"].values - orig[1]) <= 1e-15)


def test_weighted_daily_mean_returns():
l1 = [ 1., 1.5, 2.25, 3.375 ]
l2 = [ 1., 2., 4., 8. ]
expected = [ 0.5 * 0.25 + 1 * 0.75 for i in range(len(l1)-1) ]
weights = np.array([ 0.25, 0.75 ])
d = { "1": l1, "2": l2 }
l1 = [1.0, 1.5, 2.25, 3.375]
l2 = [1.0, 2.0, 4.0, 8.0]
expected = [0.5 * 0.25 + 1 * 0.75 for i in range(len(l1) - 1)]
weights = np.array([0.25, 0.75])
d = {"1": l1, "2": l2}
df = pd.DataFrame(d)
ret = weighted_mean_daily_returns(df, weights)
assert all(abs(ret - expected) <= 1e-15)

d = { "1": l1 }
expected = [ 0.5 for i in range(len(l1)-1) ]
d = {"1": l1}
expected = [0.5 for i in range(len(l1) - 1)]
df = pd.DataFrame(d)
ret = weighted_mean_daily_returns(df, np.array([1]))
assert all(abs(ret - expected) <= 1e-15)


def test_daily_log_returns():
orig = [
[
Expand Down

0 comments on commit 2090462

Please sign in to comment.