pyeconomics 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyeconomics-0.1.0/LICENSE +21 -0
- pyeconomics-0.1.0/PKG-INFO +13 -0
- pyeconomics-0.1.0/README.md +0 -0
- pyeconomics-0.1.0/pyeconomics/__init__.py +0 -0
- pyeconomics-0.1.0/pyeconomics/api.py +136 -0
- pyeconomics-0.1.0/pyeconomics/balanced_approach_rule.py +0 -0
- pyeconomics-0.1.0/pyeconomics/balanced_approach_shortfalls_rule.py +0 -0
- pyeconomics-0.1.0/pyeconomics/first_difference_rule.py +0 -0
- pyeconomics-0.1.0/pyeconomics/fred_data.py +28 -0
- pyeconomics-0.1.0/pyeconomics/quantity_of_money.py +0 -0
- pyeconomics-0.1.0/pyeconomics/stock_to_flow.py +0 -0
- pyeconomics-0.1.0/pyeconomics/taylor_rule.py +228 -0
- pyeconomics-0.1.0/pyeconomics.egg-info/PKG-INFO +13 -0
- pyeconomics-0.1.0/pyeconomics.egg-info/SOURCES.txt +17 -0
- pyeconomics-0.1.0/pyeconomics.egg-info/dependency_links.txt +1 -0
- pyeconomics-0.1.0/pyeconomics.egg-info/top_level.txt +2 -0
- pyeconomics-0.1.0/setup.cfg +4 -0
- pyeconomics-0.1.0/setup.py +22 -0
- pyeconomics-0.1.0/tests/__init__.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Nathan Ramos, CFA®
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyeconomics
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A library for economic and financial analysis
|
|
5
|
+
Home-page: https://github.com/nathanramoscfa/pyeconomics
|
|
6
|
+
Author: Nathan Ramos, CFA
|
|
7
|
+
Author-email: nathan.ramos.github@gmail.com
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import keyring
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from fredapi import Fred
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DataSource:
|
|
11
|
+
"""
|
|
12
|
+
Abstract base class for all data source clients.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
api_key (Optional[str]): API key for accessing the data source.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, api_key: Optional[str] = None):
|
|
19
|
+
self.api_key = api_key
|
|
20
|
+
|
|
21
|
+
def fetch_data(self, series_id: str) -> pd.Series:
|
|
22
|
+
"""
|
|
23
|
+
Abstract method to fetch data from a data source given a series ID.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
series_id (str): The identifier for the data series.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
pandas.Series: Series containing the requested data.
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
NotImplementedError: If method is not implemented.
|
|
33
|
+
"""
|
|
34
|
+
raise NotImplementedError(
|
|
35
|
+
"This method should be overridden by subclasses."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class FredClient(DataSource):
|
|
40
|
+
"""
|
|
41
|
+
A client for fetching data from the FRED API.
|
|
42
|
+
|
|
43
|
+
Inherits from DataSource and implements methods to fetch data from FRED.
|
|
44
|
+
"""
|
|
45
|
+
_instance = None
|
|
46
|
+
|
|
47
|
+
def __new__(cls, api_key: Optional[str] = None):
|
|
48
|
+
"""
|
|
49
|
+
Ensures a single instance of FredClient.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
api_key (Optional[str]): The FRED API key, retrieved from
|
|
53
|
+
keyring if None.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
FredClient: Singleton instance.
|
|
57
|
+
"""
|
|
58
|
+
if not isinstance(cls._instance, cls):
|
|
59
|
+
cls._instance = super(FredClient, cls).__new__(cls)
|
|
60
|
+
api_key = api_key or keyring.get_password(
|
|
61
|
+
"fred", "api_key")
|
|
62
|
+
cls._instance.client = Fred(api_key=api_key)
|
|
63
|
+
return cls._instance
|
|
64
|
+
|
|
65
|
+
def fetch_data(self, series_id: str) -> pd.Series:
|
|
66
|
+
"""
|
|
67
|
+
Fetches data for a given series ID from FRED.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
series_id (str): FRED series ID to fetch data for.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
pandas.Series: Series containing the requested data.
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
ValueError: If no data is found for series ID.
|
|
77
|
+
Exception: For fetch operation errors.
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
data = self.client.get_series(series_id)
|
|
81
|
+
if data.empty:
|
|
82
|
+
raise ValueError(f"No data found for series ID {series_id}")
|
|
83
|
+
return data
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logging.error(f"Fetching error for {series_id}: {e}")
|
|
86
|
+
raise
|
|
87
|
+
|
|
88
|
+
def get_latest_value(self, series_id: str) -> Optional[float]:
|
|
89
|
+
"""
|
|
90
|
+
Fetches the latest value for a FRED series ID, considering only dates
|
|
91
|
+
up to today.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
series_id (str): Identifier for the FRED data series.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
float: Most recent data point up to today, or None if no data.
|
|
98
|
+
"""
|
|
99
|
+
try:
|
|
100
|
+
data = self.fetch_data(series_id)
|
|
101
|
+
today = datetime.date.today()
|
|
102
|
+
filtered_data = data[:str(today)]
|
|
103
|
+
return filtered_data.iloc[-1] if not filtered_data.empty else None
|
|
104
|
+
except Exception as e:
|
|
105
|
+
logging.error(f"Error in getting latest value for {series_id}: {e}")
|
|
106
|
+
raise
|
|
107
|
+
|
|
108
|
+
def get_historical_value(
|
|
109
|
+
self,
|
|
110
|
+
series_id: str,
|
|
111
|
+
periods: int = -1
|
|
112
|
+
) -> Optional[float]:
|
|
113
|
+
"""
|
|
114
|
+
Fetches a historical value for a FRED series ID.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
series_id (str): Identifier for the FRED data series.
|
|
118
|
+
periods (int): Index of period to retrieve (negative for
|
|
119
|
+
historical).
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
float: Historical data point value, or None if unavailable.
|
|
123
|
+
"""
|
|
124
|
+
series = self.fetch_data(series_id)
|
|
125
|
+
return series.iloc[periods] \
|
|
126
|
+
if not series.empty and len(series) > -periods else None
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def get_data_or_fetch(default, series_id):
|
|
130
|
+
"""Fetches data if default is None using the given FRED series ID."""
|
|
131
|
+
return fred_client.get_latest_value(
|
|
132
|
+
series_id) if default is None else default
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# Global instance of the FredClient
|
|
136
|
+
fred_client = FredClient()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
from .api import fred_client
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def fetch_historical_fed_funds_rate() -> pd.DataFrame:
|
|
7
|
+
"""
|
|
8
|
+
Fetches and combines Federal Funds Target Rate historical data.
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
pandas.DataFrame: DataFrame containing the Federal Funds Target Rate
|
|
12
|
+
historical data.
|
|
13
|
+
|
|
14
|
+
Notes:
|
|
15
|
+
- Prior to 2008-12-15, the Federal Funds Target Rate was a single value.
|
|
16
|
+
- Post 2008-12-15, the Federal Funds Target Rate is a range.
|
|
17
|
+
- This function uses the single value up to 2008-12-15, and the upper
|
|
18
|
+
limit of the range post 2008-12-15.
|
|
19
|
+
"""
|
|
20
|
+
dfedtar = fred_client.fetch_data('DFEDTAR')
|
|
21
|
+
dfedtaru = fred_client.fetch_data('DFEDTARU')
|
|
22
|
+
|
|
23
|
+
# Use only the upper limit post 2008-12-15
|
|
24
|
+
df = pd.concat([
|
|
25
|
+
dfedtar[dfedtar.index <= '2008-12-15'],
|
|
26
|
+
dfedtaru[dfedtaru.index > '2008-12-15']
|
|
27
|
+
])
|
|
28
|
+
return df
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
from .api import fred_client
|
|
4
|
+
from .fred_data import fetch_historical_fed_funds_rate
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def taylor_rule(
|
|
8
|
+
inflation_series_id: str = 'PCETRIM12M159SFRBDAL',
|
|
9
|
+
unemployment_rate_series_id: str = 'UNRATE',
|
|
10
|
+
natural_unemployment_series_id: str = 'NROU',
|
|
11
|
+
real_interest_rate_series_id: str = 'DFII10',
|
|
12
|
+
fed_rate_series: pd.Series = None,
|
|
13
|
+
current_inflation: float = None,
|
|
14
|
+
current_unemployment_rate: float = None,
|
|
15
|
+
natural_unemployment_rate: float = None,
|
|
16
|
+
long_term_real_interest_rate: float = None,
|
|
17
|
+
fed_rate: float = None,
|
|
18
|
+
inflation_target: float = 2.0,
|
|
19
|
+
alpha: float = 0.5,
|
|
20
|
+
beta: float = 0.5,
|
|
21
|
+
okun_factor: float = 2.0,
|
|
22
|
+
rho: float = 0.0,
|
|
23
|
+
elb: float = 0.125,
|
|
24
|
+
apply_elb: bool = False,
|
|
25
|
+
verbose: bool = False
|
|
26
|
+
) -> float:
|
|
27
|
+
"""
|
|
28
|
+
Computes the Taylor Rule interest rate based on economic indicators.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
inflation_series_id (str): Series ID for inflation data.
|
|
32
|
+
unemployment_rate_series_id (str): Series ID for unemployment rate.
|
|
33
|
+
natural_unemployment_series_id (str): Series ID for natural
|
|
34
|
+
unemployment rate.
|
|
35
|
+
real_interest_rate_series_id (str): Series ID for long-term real
|
|
36
|
+
interest rate.
|
|
37
|
+
fed_rate_series (pd.Series): Series of Federal Funds Target Rate.
|
|
38
|
+
current_inflation (float): Current inflation rate.
|
|
39
|
+
current_unemployment_rate (float): Current unemployment rate.
|
|
40
|
+
natural_unemployment_rate (float): Natural unemployment rate.
|
|
41
|
+
long_term_real_interest_rate (float): Long-term real interest rate.
|
|
42
|
+
fed_rate (float): Current Federal Funds Target Rate.
|
|
43
|
+
inflation_target (float): Target inflation rate.
|
|
44
|
+
alpha (float): Weight for inflation gap.
|
|
45
|
+
beta (float): Weight for unemployment gap.
|
|
46
|
+
okun_factor (float): Multiplier for the unemployment gap.
|
|
47
|
+
rho (float): Policy inertia coefficient. Defaults to 0.0 which means
|
|
48
|
+
no inertia and no adjustment is made to Taylor Rule estimate. A
|
|
49
|
+
value of 1.0 would mean full inertia and immediate central bank
|
|
50
|
+
adjustment to the Taylor Rule estimate.
|
|
51
|
+
elb (float): Effective lower bound for interest rates.
|
|
52
|
+
apply_elb (bool): Whether to apply the effective lower bound
|
|
53
|
+
constraint to the Taylor Rule estimate.
|
|
54
|
+
verbose (bool): Whether to print verbose output.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
float: Taylor Rule interest rate estimate.
|
|
58
|
+
"""
|
|
59
|
+
# Fetch data if not provided
|
|
60
|
+
current_inflation = fred_client.get_data_or_fetch(
|
|
61
|
+
current_inflation, inflation_series_id)
|
|
62
|
+
current_unemployment_rate = fred_client.get_data_or_fetch(
|
|
63
|
+
current_unemployment_rate, unemployment_rate_series_id)
|
|
64
|
+
natural_unemployment_rate = fred_client.get_data_or_fetch(
|
|
65
|
+
natural_unemployment_rate, natural_unemployment_series_id)
|
|
66
|
+
long_term_real_interest_rate = fred_client.get_data_or_fetch(
|
|
67
|
+
long_term_real_interest_rate, real_interest_rate_series_id)
|
|
68
|
+
|
|
69
|
+
if fed_rate is None:
|
|
70
|
+
fed_rate = (fed_rate_series.iloc[-1] if fed_rate_series is not None
|
|
71
|
+
else fred_client.get_latest_value('DFEDTARU'))
|
|
72
|
+
|
|
73
|
+
if None in (current_inflation, current_unemployment_rate,
|
|
74
|
+
natural_unemployment_rate, long_term_real_interest_rate,
|
|
75
|
+
fed_rate):
|
|
76
|
+
raise ValueError("Required economic data is missing.")
|
|
77
|
+
|
|
78
|
+
# Calculate gaps and Taylor Rule estimate
|
|
79
|
+
inflation_gap = current_inflation - inflation_target
|
|
80
|
+
unemployment_gap = natural_unemployment_rate - current_unemployment_rate
|
|
81
|
+
|
|
82
|
+
taylor_est = (long_term_real_interest_rate +
|
|
83
|
+
current_inflation +
|
|
84
|
+
alpha * inflation_gap +
|
|
85
|
+
beta * okun_factor * unemployment_gap)
|
|
86
|
+
|
|
87
|
+
if apply_elb:
|
|
88
|
+
taylor_est = max(taylor_est, elb)
|
|
89
|
+
|
|
90
|
+
adjusted_taylor_rule_interest_rate = (
|
|
91
|
+
rho * fed_rate + (1 - rho) * taylor_est
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Verbose output
|
|
95
|
+
if verbose:
|
|
96
|
+
print(f"\n==== Economic Indicators ===================================="
|
|
97
|
+
f"==")
|
|
98
|
+
print(f"Current Inflation: "
|
|
99
|
+
f" {current_inflation:.2f}%")
|
|
100
|
+
print(f"Current Unemployment Rate: "
|
|
101
|
+
f" {current_unemployment_rate:.2f}%")
|
|
102
|
+
print(f"Natural Unemployment Rate: "
|
|
103
|
+
f" {natural_unemployment_rate:.2f}%")
|
|
104
|
+
print(f"Long-Term Real Interest Rate: "
|
|
105
|
+
f" {long_term_real_interest_rate:.2f}%")
|
|
106
|
+
print(f"Current Fed Rate: "
|
|
107
|
+
f" {fed_rate:.2f}%")
|
|
108
|
+
print(f"\n==== Gaps ==================================================="
|
|
109
|
+
f"==")
|
|
110
|
+
print(f"Inflation Gap: "
|
|
111
|
+
f" {inflation_gap:.2f}%")
|
|
112
|
+
print(f"Unemployment Gap: "
|
|
113
|
+
f" {unemployment_gap:.2f}%")
|
|
114
|
+
print(f"\n==== Taylor Rule ============================================"
|
|
115
|
+
f"==")
|
|
116
|
+
print(f" Long-Term Real Interest Rate: "
|
|
117
|
+
f" {long_term_real_interest_rate:.2f}%")
|
|
118
|
+
print(f" Current Inflation: "
|
|
119
|
+
f"+ {current_inflation:.2f}%")
|
|
120
|
+
print(f" Alpha * Inflation Gap: "
|
|
121
|
+
f"+ {alpha:.2f} * {inflation_gap:.2f}%")
|
|
122
|
+
print(f" Beta * Okun Factor * Unemployment Gap: "
|
|
123
|
+
f"+ {beta:.2f} * {okun_factor:.2f} * {unemployment_gap:.2f}%")
|
|
124
|
+
print("---------------------------------------------------------------")
|
|
125
|
+
print(f" Taylor Rule: "
|
|
126
|
+
f" {taylor_est:.2f}%")
|
|
127
|
+
print(f"\n==== Adjusted Taylor Rule ==================================="
|
|
128
|
+
f"==")
|
|
129
|
+
print(" Adjustment Computation:")
|
|
130
|
+
print(f" Policy Inertia Coefficient (rho): "
|
|
131
|
+
f" {rho:.2f}")
|
|
132
|
+
print(f" Current Fed Rate: "
|
|
133
|
+
f"* {fed_rate:.2f}%")
|
|
134
|
+
print(f" Adjustment Coefficient (1 - rho): "
|
|
135
|
+
f"+ (1 - {rho:.2f})")
|
|
136
|
+
print(f" Taylor Rule Estimate: "
|
|
137
|
+
f"* {taylor_est:.2f}%")
|
|
138
|
+
print("---------------------------------------------------------------")
|
|
139
|
+
print(f" Adjusted Taylor Rule Estimate: "
|
|
140
|
+
f" {adjusted_taylor_rule_interest_rate:.2f}%")
|
|
141
|
+
|
|
142
|
+
return round(adjusted_taylor_rule_interest_rate, 2)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def historical_taylor_rule(
|
|
146
|
+
inflation_series_id: str = 'PCETRIM12M159SFRBDAL',
|
|
147
|
+
unemployment_rate_series_id: str = 'UNRATE',
|
|
148
|
+
natural_unemployment_series_id: str = 'NROU',
|
|
149
|
+
real_interest_rate_series_id: str = 'DFII10',
|
|
150
|
+
inflation_target: float = 2.0,
|
|
151
|
+
alpha: float = 0.5,
|
|
152
|
+
beta: float = 0.5,
|
|
153
|
+
okun_factor: float = 2.0,
|
|
154
|
+
rho: float = 0.0,
|
|
155
|
+
elb: float = 0.125,
|
|
156
|
+
apply_elb: bool = False
|
|
157
|
+
) -> pd.DataFrame:
|
|
158
|
+
"""
|
|
159
|
+
Computes historical Taylor Rule interest rates using
|
|
160
|
+
economic indicators up to the last date with available
|
|
161
|
+
real interest rate data.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
inflation_series_id (str): Series ID for inflation data.
|
|
165
|
+
unemployment_rate_series_id (str): Series ID for unemployment rate.
|
|
166
|
+
natural_unemployment_series_id (str): Series ID for natural
|
|
167
|
+
unemployment rate.
|
|
168
|
+
real_interest_rate_series_id (str): Series ID for long-term real
|
|
169
|
+
interest rate.
|
|
170
|
+
inflation_target (float): Target inflation rate.
|
|
171
|
+
alpha (float): Weight for inflation gap.
|
|
172
|
+
beta (float): Weight for unemployment gap.
|
|
173
|
+
okun_factor (float): Multiplier for the unemployment gap.
|
|
174
|
+
rho (float): Policy inertia coefficient. Defaults to 0.0 which means
|
|
175
|
+
no inertia and no adjustment is made to Taylor Rule estimate. A
|
|
176
|
+
value of 1.0 would mean full inertia and immediate central bank
|
|
177
|
+
adjustment to the Taylor Rule estimate.
|
|
178
|
+
elb (float): Effective lower bound for interest rates.
|
|
179
|
+
apply_elb (bool): Whether to apply the effective lower bound
|
|
180
|
+
constraint to the Taylor Rule estimate.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
pd.DataFrame: DataFrame with computed Taylor Rule rates.
|
|
184
|
+
"""
|
|
185
|
+
# Fetch historical data for all series
|
|
186
|
+
inflation = fred_client.fetch_data(inflation_series_id)
|
|
187
|
+
unemployment_rate = fred_client.fetch_data(unemployment_rate_series_id)
|
|
188
|
+
natural_unemployment = fred_client.fetch_data(
|
|
189
|
+
natural_unemployment_series_id)
|
|
190
|
+
real_interest_rate = fred_client.fetch_data(real_interest_rate_series_id)
|
|
191
|
+
fed_rate = fetch_historical_fed_funds_rate()
|
|
192
|
+
|
|
193
|
+
# Combine into a DataFrame and ensure data alignment
|
|
194
|
+
data = pd.DataFrame({
|
|
195
|
+
'Inflation': inflation,
|
|
196
|
+
'UnemploymentRate': unemployment_rate,
|
|
197
|
+
'NaturalUnemploymentRate': natural_unemployment,
|
|
198
|
+
'RealInterestRate': real_interest_rate,
|
|
199
|
+
'FedRate': fed_rate
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
# Determine the cutoff date based on RealInterestRate data
|
|
203
|
+
last_real_interest_date = data['RealInterestRate'].last_valid_index()
|
|
204
|
+
data = data.loc[:last_real_interest_date]
|
|
205
|
+
|
|
206
|
+
# Handle missing data
|
|
207
|
+
data.ffill(inplace=True)
|
|
208
|
+
data.dropna(inplace=True)
|
|
209
|
+
|
|
210
|
+
# Calculate gaps and Taylor Rule estimation
|
|
211
|
+
data['InflationGap'] = data['Inflation'] - inflation_target
|
|
212
|
+
data['UnemploymentGap'] = (data['NaturalUnemploymentRate'] -
|
|
213
|
+
data['UnemploymentRate'])
|
|
214
|
+
data['TaylorEst'] = (data['RealInterestRate'] +
|
|
215
|
+
data['Inflation'] +
|
|
216
|
+
alpha * data['InflationGap'] +
|
|
217
|
+
beta * okun_factor * data['UnemploymentGap'])
|
|
218
|
+
|
|
219
|
+
# Apply effective lower bound constraint
|
|
220
|
+
if apply_elb:
|
|
221
|
+
data['AdjustedTaylorRule'] = data['TaylorEst'].apply(
|
|
222
|
+
lambda x: max(x, elb))
|
|
223
|
+
|
|
224
|
+
# Apply policy inertia
|
|
225
|
+
data['AdjustedTaylorRule'] = (rho * data['FedRate'] +
|
|
226
|
+
(1 - rho) * data['AdjustedTaylorRule'])
|
|
227
|
+
|
|
228
|
+
return round(data, 2)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyeconomics
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A library for economic and financial analysis
|
|
5
|
+
Home-page: https://github.com/nathanramoscfa/pyeconomics
|
|
6
|
+
Author: Nathan Ramos, CFA
|
|
7
|
+
Author-email: nathan.ramos.github@gmail.com
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
pyeconomics/__init__.py
|
|
5
|
+
pyeconomics/api.py
|
|
6
|
+
pyeconomics/balanced_approach_rule.py
|
|
7
|
+
pyeconomics/balanced_approach_shortfalls_rule.py
|
|
8
|
+
pyeconomics/first_difference_rule.py
|
|
9
|
+
pyeconomics/fred_data.py
|
|
10
|
+
pyeconomics/quantity_of_money.py
|
|
11
|
+
pyeconomics/stock_to_flow.py
|
|
12
|
+
pyeconomics/taylor_rule.py
|
|
13
|
+
pyeconomics.egg-info/PKG-INFO
|
|
14
|
+
pyeconomics.egg-info/SOURCES.txt
|
|
15
|
+
pyeconomics.egg-info/dependency_links.txt
|
|
16
|
+
pyeconomics.egg-info/top_level.txt
|
|
17
|
+
tests/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='pyeconomics',
|
|
5
|
+
version='0.1.0',
|
|
6
|
+
author='Nathan Ramos, CFA',
|
|
7
|
+
author_email='nathan.ramos.github@gmail.com',
|
|
8
|
+
packages=find_packages(),
|
|
9
|
+
description='A library for economic and financial analysis',
|
|
10
|
+
long_description=open('README.md').read(),
|
|
11
|
+
long_description_content_type='text/markdown',
|
|
12
|
+
url='https://github.com/nathanramoscfa/pyeconomics',
|
|
13
|
+
install_requires=[
|
|
14
|
+
# Dependencies, e.g., 'numpy', 'pandas'
|
|
15
|
+
],
|
|
16
|
+
classifiers=[
|
|
17
|
+
'Development Status :: 3 - Alpha',
|
|
18
|
+
'Intended Audience :: Developers',
|
|
19
|
+
'Programming Language :: Python :: 3',
|
|
20
|
+
'License :: OSI Approved :: MIT License'
|
|
21
|
+
]
|
|
22
|
+
)
|
|
File without changes
|