From 262f1803ac3871cd57a6ffafd973ff02192e18d9 Mon Sep 17 00:00:00 2001 From: kp992 Date: Mon, 4 Mar 2024 11:49:44 +0530 Subject: [PATCH 1/5] Use np.interp instead of interpolation.interp --- lectures/BCG_complete_mkts.md | 1 - lectures/BCG_incomplete_mkts.md | 53 +++++++++++++++++---------------- lectures/coase.md | 42 +++++++++++--------------- lectures/lucas_model.md | 33 +++++++++----------- lectures/opt_tax_recur.md | 2 -- 5 files changed, 60 insertions(+), 71 deletions(-) diff --git a/lectures/BCG_complete_mkts.md b/lectures/BCG_complete_mkts.md index 0e77e277..dac8dea0 100644 --- a/lectures/BCG_complete_mkts.md +++ b/lectures/BCG_complete_mkts.md @@ -31,7 +31,6 @@ In addition to what's in Anaconda, this lecture will need the following librarie tags: [hide-output] --- !pip install --upgrade quantecon -!pip install interpolation !conda install -y -c plotly plotly plotly-orca ``` diff --git a/lectures/BCG_incomplete_mkts.md b/lectures/BCG_incomplete_mkts.md index 78cb5578..90d3a53e 100644 --- a/lectures/BCG_incomplete_mkts.md +++ b/lectures/BCG_incomplete_mkts.md @@ -3,8 +3,10 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- @@ -26,12 +28,10 @@ kernelspec: In addition to what's in Anaconda, this lecture will need the following libraries: -```{code-cell} ipython ---- -tags: [hide-output] ---- +```{code-cell} ipython3 +:tags: [hide-output] + !pip install --upgrade quantecon -!pip install interpolation !conda install -y -c plotly plotly plotly-orca ``` @@ -703,15 +703,14 @@ Parameters include: - $\beta$: Discount factor. Default value is 0.96. - bound: Bound for truncated normal distribution. Default value is 3. -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np from scipy.stats import truncnorm from scipy.integrate import quad from numba import njit -from interpolation import interp ``` -```{code-cell} python3 +```{code-cell} ipython3 class BCG_incomplete_markets: # init method or constructor @@ -784,7 +783,7 @@ class BCG_incomplete_markets: rv = truncnorm(ta, tb, loc=πœ‡, scale=𝜎) πœ–_range = np.linspace(ta, tb, 1000000) pdf_range = rv.pdf(πœ–_range) - self.g = njit(lambda πœ–: interp(πœ–_range, pdf_range, πœ–)) + self.g = njit(lambda πœ–: np.interp(πœ–, πœ–_range, pdf_range)) #************************************************************* @@ -1206,14 +1205,14 @@ Below we show some examples computed with the class `BCG_incomplete markets`. In the first example, we set up an instance of the BCG incomplete markets model with default parameter values. -```{code-cell} python3 -:tags: ["hide-output"] +```{code-cell} ipython3 +:tags: [hide-output] mdl = BCG_incomplete_markets() kss,bss,Vss,qss,pss,c10ss,c11ss,c20ss,c21ss,πœƒ1ss = mdl.solve_eq(print_crit=False) ``` -```{code-cell} python3 +```{code-cell} ipython3 print(-kss+qss+pss*bss) print(Vss) print(πœƒ1ss) @@ -1229,7 +1228,7 @@ Thus, let’s see if the firm is actually maximizing its firm value given the equilibrium pricing function $q(k,b)$ for equity and $p(k,b)$ for bonds. -```{code-cell} python3 +```{code-cell} ipython3 kgrid, bgrid, Vgrid, Qgrid, Pgrid = mdl.eq_valuation(c10ss, c11ss, c20ss, c21ss,N=30) print('Maximum valuation of the firm value in the (k,B) grid: {:.5f}'.format(Vgrid.max())) @@ -1246,7 +1245,7 @@ Below we will plot the firm’s value as a function of $k,b$. We’ll also plot the equilibrium price functions $q(k,b)$ and $p(k,b)$. -```{code-cell} python3 +```{code-cell} ipython3 from IPython.display import Image import matplotlib.pyplot as plt from mpl_toolkits import mplot3d @@ -1367,7 +1366,7 @@ $$ The function also outputs agent 1’s bond holdings $\xi_1$. -```{code-cell} python3 +```{code-cell} ipython3 def off_eq_check(mdl,kss,bss,e=0.1): # Big K and big B k = kss @@ -1603,7 +1602,7 @@ structure for the firm. We first check the case in which $b^{**} = b^* - e$ where $e = 0.1$: -```{code-cell} python3 +```{code-cell} ipython3 #====================== Experiment 1 ======================# Ve1,ke1,be1,pe1,qe1,c10e1,c11e1,c20e1,c21e1,πœ‰1e1 = off_eq_check(mdl, kss, @@ -1655,7 +1654,7 @@ Therefore, $(k^*,b^{*}-e)$ would not be an equilibrium. Next, we check for $b^{**} = b^* + e$. -```{code-cell} python3 +```{code-cell} ipython3 #====================== Experiment 2 ======================# Ve2,ke2,be2,pe2,qe2,c10e2,c11e2,c20e2,c21e2,πœ‰1e2 = off_eq_check(mdl, kss, @@ -1708,7 +1707,7 @@ want to hold corporate debt. For example, $\xi^1 > 0$: -```{code-cell} python3 +```{code-cell} ipython3 print('Bond holdings of agent 1: {:.3f}'.format(πœ‰1e2)) ``` @@ -1726,7 +1725,7 @@ It is also interesting to look at the equilibrium price functions $q(k,b)$ and $p(k,b)$ faced by firms in our rational expectations equilibrium. -```{code-cell} python3 +```{code-cell} ipython3 # Equity Valuation fig = go.Figure(data=[go.Scatter3d(x=[kss], y=[bss], @@ -1756,7 +1755,7 @@ Image(fig.to_image(format="png")) # code locally ``` -```{code-cell} python3 +```{code-cell} ipython3 # Bond Valuation fig = go.Figure(data=[go.Scatter3d(x=[kss], y=[bss], @@ -1815,8 +1814,8 @@ $$ The function `valuations_by_agent` is used in calculating these valuations. -```{code-cell} python3 -:tags: ["hide-output"] +```{code-cell} ipython3 +:tags: [hide-output] # Lists for storage wlist = [] @@ -1864,7 +1863,7 @@ for i in range(10): p2list.append(P2) ``` -```{code-cell} python3 +```{code-cell} ipython3 # Plot fig, ax = plt.subplots(3,2,figsize=(12,12)) ax[0,0].plot(wlist,klist) @@ -1909,7 +1908,7 @@ Now let’s see how the two types of agents value bonds and equities, keeping in mind that the type that values the asset highest determines the equilibrium price (and thus the pertinent set of Big $C$’s). -```{code-cell} python3 +```{code-cell} ipython3 # Comparing the prices fig, ax = plt.subplots(1,3,figsize=(16,6)) @@ -1943,3 +1942,7 @@ Agents of type 2 value bonds more highly (they want more hedging). Taken together with our earlier plot of equity holdings, these graphs confirm our earlier conjecture that while both type of agents hold equities, only agents of type 2 holds bonds. + +```{code-cell} ipython3 + +``` diff --git a/lectures/coase.md b/lectures/coase.md index 41fe1c99..6bd33285 100644 --- a/lectures/coase.md +++ b/lectures/coase.md @@ -3,8 +3,10 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- @@ -24,14 +26,7 @@ kernelspec: :depth: 2 ``` -In addition to what's in Anaconda, this lecture will need the following libraries: - -```{code-cell} ipython ---- -tags: [hide-output] ---- -!pip install interpolation -``` ++++ ## Overview @@ -57,12 +52,10 @@ Couldn't the associated within-firm planning be done more efficiently by the mar We'll use the following imports: -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np import matplotlib.pyplot as plt -%matplotlib inline from scipy.optimize import fminbound -from interpolation import interp ``` ### Why Firms Exist @@ -447,7 +440,7 @@ At each iterate, we will use continuous piecewise linear interpolation of functi To begin, here's a class to store primitives and a grid: -```{code-cell} python3 +```{code-cell} ipython3 class ProductionChain: def __init__(self, @@ -464,7 +457,7 @@ Now let's implement and iterate with $T$ until convergence. Recalling that our initial condition must lie in $\mathcal P$, we set $p_0 = c$ -```{code-cell} python3 +```{code-cell} ipython3 def compute_prices(pc, tol=1e-5, max_iter=5000): """ Compute prices by iterating with T @@ -481,7 +474,7 @@ def compute_prices(pc, tol=1e-5, max_iter=5000): while error > tol and i < max_iter: for j, s in enumerate(grid): - Tp = lambda t: delta * interp(grid, p, t) + c(s - t) + Tp = lambda t: delta * np.interp(t, grid, p) + c(s - t) new_p[j] = Tp(fminbound(Tp, 0, s)) error = np.max(np.abs(p - new_p)) p = new_p @@ -492,14 +485,14 @@ def compute_prices(pc, tol=1e-5, max_iter=5000): else: print(f"Warning: iteration hit upper bound {max_iter}") - p_func = lambda x: interp(grid, p, x) + p_func = lambda x: np.interp(x, grid, p) return p_func ``` The next function computes optimal choice of upstream boundary and range of task implemented for a firm face price function p_function and with downstream boundary $s$. -```{code-cell} python3 +```{code-cell} ipython3 def optimal_choices(pc, p_function, s): """ Takes p_func as the true function, minimizes on [0,s] @@ -524,7 +517,7 @@ their respective upstream boundary, treating the previous firm's upstream bounda In doing so, we start with firm 1, who has downstream boundary $s=1$. -```{code-cell} python3 +```{code-cell} ipython3 def compute_stages(pc, p_function): s = 1.0 transaction_stages = [s] @@ -539,7 +532,7 @@ Let's try this at the default parameters. The next figure shows the equilibrium price function, as well as the boundaries of firms as vertical lines -```{code-cell} python3 +```{code-cell} ipython3 pc = ProductionChain() p_star = compute_prices(pc) @@ -558,7 +551,7 @@ plt.show() Here's the function $\ell^*$, which shows how large a firm with downstream boundary $s$ chooses to be -```{code-cell} python3 +```{code-cell} ipython3 ell_star = np.empty(pc.n) for i, s in enumerate(pc.grid): t, e = optimal_choices(pc, p_star, s) @@ -590,9 +583,9 @@ Check your intuition by computing the number of firms at delta in (1.01, 1.05, 1 ```{solution-start} coa_ex1 :class: dropdown ``` -Here is one solution +Here is one solution -```{code-cell} python3 +```{code-cell} ipython3 for delta in (1.01, 1.05, 1.1): pc = ProductionChain(delta=delta) @@ -601,6 +594,7 @@ for delta in (1.01, 1.05, 1.1): num_firms = len(transaction_stages) print(f"When delta={delta} there are {num_firms} firms") ``` + ```{solution-end} ``` @@ -636,7 +630,7 @@ associated with diminishing returns to management --- which induce convexity --- Here's one way to compute and graph value added across firms -```{code-cell} python3 +```{code-cell} ipython3 pc = ProductionChain() p_star = compute_prices(pc) stages = compute_stages(pc, p_star) @@ -654,4 +648,4 @@ plt.show() ``` ```{solution-end} -``` \ No newline at end of file +``` diff --git a/lectures/lucas_model.md b/lectures/lucas_model.md index cc931e81..5d9f8496 100644 --- a/lectures/lucas_model.md +++ b/lectures/lucas_model.md @@ -3,8 +3,10 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- @@ -27,14 +29,7 @@ kernelspec: :depth: 2 ``` -In addition to what's in Anaconda, this lecture will need the following libraries: - -```{code-cell} ipython ---- -tags: [hide-output] ---- -!pip install interpolation -``` ++++ ## Overview @@ -52,13 +47,11 @@ Another difference to our [first asset pricing lecture](https://python-intro.qua Let's start with some imports: -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np -from interpolation import interp from numba import njit, prange from scipy.stats import lognorm import matplotlib.pyplot as plt -%matplotlib inline ``` ## The Lucas Model @@ -401,7 +394,7 @@ Utility will take the isoelastic form $u(c) = c^{1-\gamma}/(1-\gamma)$, where $\ We will set up a `LucasTree` class to hold parameters of the model -```{code-cell} python3 +```{code-cell} ipython3 class LucasTree: """ Class to store parameters of the Lucas tree model. @@ -436,7 +429,7 @@ class LucasTree: The following function takes an instance of the `LucasTree` and generates a jitted version of the Lucas operator -```{code-cell} python3 +```{code-cell} ipython3 def operator_factory(tree, parallel_flag=True): """ @@ -458,7 +451,7 @@ def operator_factory(tree, parallel_flag=True): """ # Turn f into a function - Af = lambda x: interp(grid, f, x) + Af = lambda x: np.interp(x, grid, f) Tf = np.empty_like(f) # Apply the T operator to f using Monte Carlo integration @@ -474,7 +467,7 @@ def operator_factory(tree, parallel_flag=True): To solve the model, we write a function that iterates using the Lucas operator to find the fixed point. -```{code-cell} python3 +```{code-cell} ipython3 def solve_model(tree, tol=1e-6, max_iter=500): """ Compute the equilibrium price function associated with Lucas @@ -505,7 +498,7 @@ def solve_model(tree, tol=1e-6, max_iter=500): Solving the model and plotting the resulting price function -```{code-cell} python3 +```{code-cell} ipython3 tree = LucasTree() price_vals = solve_model(tree) @@ -552,7 +545,8 @@ Replicate {ref}`the figure ` to show how discount factors affect pri ```{solution-start} lucas_ex1 :class: dropdown ``` -```{code-cell} python3 + +```{code-cell} ipython3 fig, ax = plt.subplots(figsize=(10, 6)) for Ξ² in (.95, 0.98): @@ -566,5 +560,6 @@ ax.legend(loc='upper left') ax.set(xlabel='$y$', ylabel='price', xlim=(min(grid), max(grid))) plt.show() ``` + ```{solution-end} -``` \ No newline at end of file +``` diff --git a/lectures/opt_tax_recur.md b/lectures/opt_tax_recur.md index 8c8815ec..929f48fc 100644 --- a/lectures/opt_tax_recur.md +++ b/lectures/opt_tax_recur.md @@ -31,7 +31,6 @@ In addition to what's in Anaconda, this lecture will need the following librarie tags: [hide-output] --- !pip install --upgrade quantecon -!pip install interpolation ``` ## Overview @@ -73,7 +72,6 @@ import matplotlib.pyplot as plt from scipy.optimize import root from quantecon import MarkovChain from quantecon.optimize.nelder_mead import nelder_mead -from interpolation import interp from numba import njit, prange, float64 from numba.experimental import jitclass ``` From 5faa7b081a613272f9a6c642e2a5ba740376261e Mon Sep 17 00:00:00 2001 From: kp992 Date: Sat, 9 Mar 2024 10:23:55 +0530 Subject: [PATCH 2/5] apply suggestions --- lectures/BCG_incomplete_mkts.md | 4 ---- lectures/coase.md | 2 -- lectures/lucas_model.md | 2 -- 3 files changed, 8 deletions(-) diff --git a/lectures/BCG_incomplete_mkts.md b/lectures/BCG_incomplete_mkts.md index 90d3a53e..91df9591 100644 --- a/lectures/BCG_incomplete_mkts.md +++ b/lectures/BCG_incomplete_mkts.md @@ -1942,7 +1942,3 @@ Agents of type 2 value bonds more highly (they want more hedging). Taken together with our earlier plot of equity holdings, these graphs confirm our earlier conjecture that while both type of agents hold equities, only agents of type 2 holds bonds. - -```{code-cell} ipython3 - -``` diff --git a/lectures/coase.md b/lectures/coase.md index 6bd33285..b34cec1a 100644 --- a/lectures/coase.md +++ b/lectures/coase.md @@ -26,8 +26,6 @@ kernelspec: :depth: 2 ``` -+++ - ## Overview In 1937, Ronald Coase wrote a brilliant essay on the nature of the firm {cite}`coase1937nature`. diff --git a/lectures/lucas_model.md b/lectures/lucas_model.md index 5d9f8496..69900538 100644 --- a/lectures/lucas_model.md +++ b/lectures/lucas_model.md @@ -29,8 +29,6 @@ kernelspec: :depth: 2 ``` -+++ - ## Overview As stated in an [earlier lecture](https://python-intro.quantecon.org/markov_asset.html), an asset is a claim on a stream of prospective payments. From fb38c5562d7827ca8c69133c0f371445080b43c6 Mon Sep 17 00:00:00 2001 From: mmcky Date: Tue, 12 Mar 2024 10:06:08 +1100 Subject: [PATCH 3/5] re-enable build failures on warnings --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7934f3a5..787ab802 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: shell: bash -l {0} run: | rm -r _build/.doctrees - jb build lectures --path-output ./ + jb build lectures --path-output ./ -nW --keep-going - name: Save Build as Artifact uses: actions/upload-artifact@v1 with: From cbd987617ec0742c7add7635eee713add851b157 Mon Sep 17 00:00:00 2001 From: mmcky Date: Tue, 12 Mar 2024 10:30:14 +1100 Subject: [PATCH 4/5] MAINT: update ci.yml workflow versions and report upload --- .github/workflows/ci.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 787ab802..f072929a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,9 +5,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup Anaconda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true auto-activate-base: true @@ -35,7 +35,7 @@ jobs: shell: bash -l {0} run: pip list - name: Download "build" folder (cache) - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3 with: workflow: cache.yml branch: main @@ -62,13 +62,19 @@ jobs: run: | rm -r _build/.doctrees jb build lectures --path-output ./ -nW --keep-going + - name: Upload Execution Reports (Download Notebooks) + uses: actions/upload-artifact@v4 + if: failure() + with: + name: execution-reports + path: _build/jupyter/reports - name: Save Build as Artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: _build path: _build - name: Preview Deploy to Netlify - uses: nwtgck/actions-netlify@v1.1 + uses: nwtgck/actions-netlify@v2 with: publish-dir: '_build/html/' production-branch: master From 794a3763f09544baf088003d27a58240379095a6 Mon Sep 17 00:00:00 2001 From: kp992 Date: Tue, 12 Mar 2024 07:29:36 +0530 Subject: [PATCH 5/5] Fix interp issues --- .../opt_tax_recur/recursive_allocation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py b/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py index 2ce9387e..c197f11c 100644 --- a/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py +++ b/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py @@ -131,8 +131,8 @@ def simulate(self, b0, s0, T, sHist=None): # Time 1 onward for t in range(1, T): s, x = sHist[t], xHist[t-1] - cHist[t] = interp(self.x_grid, self.c1[:, s], x) - nHist[t] = interp(self.x_grid, self.n1[:, s], x) + cHist[t] = np.interp(x, self.x_grid, self.c1[:, s]) + nHist[t] = np.interp(x, self.x_grid, self.n1[:, s]) Ο„Hist[t] = self.Ο„(cHist[t], nHist[t]) @@ -140,8 +140,8 @@ def simulate(self, b0, s0, T, sHist=None): c, n = np.empty((2, self.S)) for sprime in range(self.S): - c[sprime] = interp(x_grid, self.c1[:, sprime], x) - n[sprime] = interp(x_grid, self.n1[:, sprime], x) + c[sprime] = np.interp(x, x_grid, self.c1[:, sprime]) + n[sprime] = np.interp(x, x_grid, self.n1[:, sprime]) Euc = Ο€[sHist[t-1]] @ Uc(c, 1-n) RHist[t-1] = Uc(cHist[t-1], 1-nHist[t-1]) / (self.pref.Ξ² * Euc) @@ -150,7 +150,7 @@ def simulate(self, b0, s0, T, sHist=None): if t < T-1: sprime = sHist[t+1] - xHist[t] = interp(self.x_grid, self.xprime1[:, s, sprime], x) + xHist[t] = np.interp(x, self.x_grid, self.xprime1[:, s, sprime]) return [cHist, nHist, Bhist, Ο„Hist, gHist, yHist, xHist, RHist] @@ -209,7 +209,7 @@ def obj_V(z_sub, x, s, V, pref, Ο€, g, x_grid, b0=None): # prepare Vprime vector Vprime = np.empty(S) for sprime in range(S): - Vprime[sprime] = interp(x_grid, V[:, sprime], xprime[sprime]) + Vprime[sprime] = np.interp(xprime[sprime], x_grid, V[:, sprime]) # compute the objective value obj = U(c, l) + Ξ² * Ο€[s] @ Vprime