Compare commits
	
		
			2 Commits
		
	
	
		
			38fb9ca7d0
			...
			177e3bc4c8
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 177e3bc4c8 | |||
| 922fe0f027 | 
@ -7,7 +7,6 @@ from collections import UserList
 | 
				
			|||||||
from dataclasses import dataclass
 | 
					from dataclasses import dataclass
 | 
				
			||||||
from numbers import Number
 | 
					from numbers import Number
 | 
				
			||||||
from typing import Any, Callable, Iterable, List, Literal, Mapping, Sequence, Type
 | 
					from typing import Any, Callable, Iterable, List, Literal, Mapping, Sequence, Type
 | 
				
			||||||
from unittest import skip
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from dateutil.relativedelta import relativedelta
 | 
					from dateutil.relativedelta import relativedelta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,11 @@
 | 
				
			|||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
 | 
					import statistics
 | 
				
			||||||
from typing import Literal
 | 
					from typing import Literal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from fincal.core import date_parser
 | 
					from fincal.core import date_parser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .fincal import TimeSeries
 | 
					from .fincal import TimeSeries
 | 
				
			||||||
 | 
					from .utils import _interval_to_years
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@date_parser(3, 4)
 | 
					@date_parser(3, 4)
 | 
				
			||||||
@ -21,6 +23,13 @@ def sharpe_ratio(
 | 
				
			|||||||
    closest: Literal["previous", "next"] = "previous",
 | 
					    closest: Literal["previous", "next"] = "previous",
 | 
				
			||||||
    date_format: str = None,
 | 
					    date_format: str = None,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
 | 
					    interval_days = int(_interval_to_years(return_period_unit, return_period_value) * 365 + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if from_date is None:
 | 
				
			||||||
 | 
					        from_date = time_series_data.start_date + datetime.timedelta(days=interval_days)
 | 
				
			||||||
 | 
					    if to_date is None:
 | 
				
			||||||
 | 
					        to_date = time_series_data.end_date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if risk_free_data is None and risk_free_rate is None:
 | 
					    if risk_free_data is None and risk_free_rate is None:
 | 
				
			||||||
        raise ValueError("At least one of risk_free_data or risk_free rate is required")
 | 
					        raise ValueError("At least one of risk_free_data or risk_free rate is required")
 | 
				
			||||||
    elif risk_free_data is not None:
 | 
					    elif risk_free_data is not None:
 | 
				
			||||||
@ -47,3 +56,47 @@ def sharpe_ratio(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    sharpe_ratio_value = excess_returns / sd
 | 
					    sharpe_ratio_value = excess_returns / sd
 | 
				
			||||||
    return sharpe_ratio_value
 | 
					    return sharpe_ratio_value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@date_parser(2, 3)
 | 
				
			||||||
 | 
					def beta(
 | 
				
			||||||
 | 
					    asset_data: TimeSeries,
 | 
				
			||||||
 | 
					    market_data: TimeSeries,
 | 
				
			||||||
 | 
					    from_date: str | datetime.datetime = None,
 | 
				
			||||||
 | 
					    to_date: str | datetime.datetime = None,
 | 
				
			||||||
 | 
					    frequency: Literal["D", "W", "M", "Q", "H", "Y"] = None,
 | 
				
			||||||
 | 
					    return_period_unit: Literal["years", "months", "days"] = "years",
 | 
				
			||||||
 | 
					    return_period_value: int = 1,
 | 
				
			||||||
 | 
					    as_on_match: str = "closest",
 | 
				
			||||||
 | 
					    prior_match: str = "closest",
 | 
				
			||||||
 | 
					    closest: Literal["previous", "next"] = "previous",
 | 
				
			||||||
 | 
					    date_format: str = None,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interval_days = int(_interval_to_years(return_period_unit, return_period_value) * 365 + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if from_date is None:
 | 
				
			||||||
 | 
					        from_date = asset_data.start_date + datetime.timedelta(days=interval_days)
 | 
				
			||||||
 | 
					    if to_date is None:
 | 
				
			||||||
 | 
					        to_date = asset_data.end_date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    common_params = {
 | 
				
			||||||
 | 
					        "from_date": from_date,
 | 
				
			||||||
 | 
					        "to_date": to_date,
 | 
				
			||||||
 | 
					        "frequency": frequency,
 | 
				
			||||||
 | 
					        "return_period_unit": return_period_unit,
 | 
				
			||||||
 | 
					        "return_period_value": return_period_value,
 | 
				
			||||||
 | 
					        "as_on_match": as_on_match,
 | 
				
			||||||
 | 
					        "prior_match": prior_match,
 | 
				
			||||||
 | 
					        "closest": closest,
 | 
				
			||||||
 | 
					        "date_format": date_format,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    asset_rr = asset_data.calculate_rolling_returns(**common_params)
 | 
				
			||||||
 | 
					    market_rr = market_data.calculate_rolling_returns(**common_params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cov = statistics.covariance(asset_rr.values, market_rr.values)
 | 
				
			||||||
 | 
					    market_var = statistics.variance(market_rr.values)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    beta = cov / market_var
 | 
				
			||||||
 | 
					    return beta
 | 
				
			||||||
 | 
				
			|||||||
@ -355,6 +355,24 @@ class TestReadCsv:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestTransform:
 | 
					class TestTransform:
 | 
				
			||||||
 | 
					    def test_daily_to_weekly(self, create_test_data):
 | 
				
			||||||
 | 
					        ts_data = create_test_data(AllFrequencies.D, num=782, skip_weekends=True)
 | 
				
			||||||
 | 
					        ts = TimeSeries(ts_data, "D")
 | 
				
			||||||
 | 
					        tst = ts.transform("W", "mean")
 | 
				
			||||||
 | 
					        assert isinstance(tst, TimeSeries)
 | 
				
			||||||
 | 
					        assert len(tst) == 157
 | 
				
			||||||
 | 
					        assert "2017-01-30" in tst
 | 
				
			||||||
 | 
					        assert tst.iloc[4] == (datetime.datetime(2017, 1, 30), 1021.19)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_daily_to_monthly(self, create_test_data):
 | 
				
			||||||
 | 
					        ts_data = create_test_data(AllFrequencies.D, num=782, skip_weekends=False)
 | 
				
			||||||
 | 
					        ts = TimeSeries(ts_data, "D")
 | 
				
			||||||
 | 
					        tst = ts.transform("M", "mean")
 | 
				
			||||||
 | 
					        assert isinstance(tst, TimeSeries)
 | 
				
			||||||
 | 
					        assert len(tst) == 26
 | 
				
			||||||
 | 
					        assert "2018-01-01" in tst
 | 
				
			||||||
 | 
					        assert round(tst.iloc[12][1], 2) == 1146.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_daily_to_yearly(self, create_test_data):
 | 
					    def test_daily_to_yearly(self, create_test_data):
 | 
				
			||||||
        ts_data = create_test_data(AllFrequencies.D, num=782, skip_weekends=True)
 | 
					        ts_data = create_test_data(AllFrequencies.D, num=782, skip_weekends=True)
 | 
				
			||||||
        ts = TimeSeries(ts_data, "D")
 | 
					        ts = TimeSeries(ts_data, "D")
 | 
				
			||||||
@ -386,6 +404,18 @@ class TestTransform:
 | 
				
			|||||||
        tst = ts.transform("Y", "mean")
 | 
					        tst = ts.transform("Y", "mean")
 | 
				
			||||||
        assert "2019-01-01" in tst
 | 
					        assert "2019-01-01" in tst
 | 
				
			||||||
        assert round(tst.iloc[2][1], 2) == 1054.50
 | 
					        assert round(tst.iloc[2][1], 2) == 1054.50
 | 
				
			||||||
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
 | 
					            ts.transform("D", "mean")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_monthly_to_qty(self, create_test_data):
 | 
				
			||||||
 | 
					        ts_data = create_test_data(AllFrequencies.M, num=36)
 | 
				
			||||||
 | 
					        ts = TimeSeries(ts_data, "M")
 | 
				
			||||||
 | 
					        tst = ts.transform("Q", "mean")
 | 
				
			||||||
 | 
					        assert len(tst) == 12
 | 
				
			||||||
 | 
					        assert "2018-10-01" in tst
 | 
				
			||||||
 | 
					        assert tst.iloc[7] == (datetime.datetime(2018, 10, 1), 1021.19)
 | 
				
			||||||
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
 | 
					            ts.transform("M", "sum")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestReturnsAgain:
 | 
					class TestReturnsAgain:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user