Code#
Our convention is to follow PEP8 unless there is a good reason to do otherwise.
One good reason is to get closer to mathematical notation in a given lecture.
Hence it’s fine to use capitals for matrices, etc.
Operators are typically surrounded by spaces, as in a * b
and a +
b, but we write a**b
for \(a^b\).
Variable Naming Conventions#
Unicode Variable Names#
Prefer Unicode symbols for Greek letters commonly used in economics:
Use
α
instead ofalpha
Use
β
instead ofbeta
Use
γ
instead ofgamma
Use
δ
instead ofdelta
Use
ε
instead ofepsilon
Use
σ
instead ofsigma
Use
θ
instead oftheta
Use
ρ
instead ofrho
This makes the code more readable and closer to mathematical notation used in economic literature.
Example:
# ✅ Preferred: Unicode variables
def utility_function(c, α=0.5, β=0.95):
"""CRRA utility function with discount factor."""
return (c**(1-α) - 1) / (1-α) * β
# ❌ Avoid: Spelled-out Greek letters
def utility_function(c, alpha=0.5, beta=0.95):
"""CRRA utility function with discount factor."""
return (c**(1-alpha) - 1) / (1-alpha) * beta
Guiding principle
QuantEcon lecture’s should run in a base installation of Anaconda python.
Any packages (that are not included in anaconda) need to be installed at the top of the lecture.
An example:
In addition to what’s in Anaconda, this lecture will need the following libraries:
In the example above we install the quantecon
and yfinance
packages.
We use tags: [hide-output]
as the output is not central to the lecture.
There are a couple of exceptions to this guideline.
when the software involves specific configuration for the hardware (i.e.
gpu
computing), orif additional software needs to be installed on your system via
apt
or some other binary source.
JAX#
When using jax
you should not install jax
at the top of your lecture.
This may install jax[cpu]
which will run but is not the optimal configuration for executing the lecture.
The following admonition can be used.
```{admonition} GPU
:class: warning
This lecture is accelerated via [hardware](status:machine-details) that has access to a GPU and JAX for GPU programming.
Free GPUs are available on Google Colab. To use this option, please click on the play icon top right, select Colab, and set the runtime environment to include a GPU.
Alternatively, if you have your own GPU, you can follow the [instructions](https://github.com/google/jax) for installing JAX with GPU support. If you would like to install JAX running on the `cpu` only you can use `pip install jax[cpu]`
```
which will render as
GPU
This lecture is accelerated via hardware that has access to a GPU and JAX for GPU programming.
Free GPUs are available on Google Colab. To use this option, please click on the play icon top right, select Colab, and set the runtime environment to include a GPU.
Alternatively, if you have your own GPU, you can follow the instructions for installing JAX with GPU support. If you would like to install jax running on the cpu
only you can use pip install jax[cpu]
The jax[gpu]
package needs to be properly installed via Docker
or GitHub Actions
.
See also
Make sure the repo is compliant with the following configuration requirements such as Support files
Please consult with Matt McKay should you need to update these settings.
Binary packages with Python frontends#
The graphviz package is a python interface
to a local installation of graphviz and is useful
for rendering DOT
source code.
If you need to use graphviz
you should:
Install
pip install graphviz
at the top of your lectureCheck if
graphviz
is getting installed in.github/workflows/ci.yml
for preview buildsAdd the below
note
admonition to your lecture.
which will render as
Performance Timing Patterns#
Timer Context Manager#
Use the modern qe.Timer()
context manager instead of manual timing patterns.
The QuantEcon library provides a Timer
context manager that replaces older timing approaches like tic
/tac
/toc
functions with cleaner, more reliable syntax.
❌ Avoid: Manual timing patterns
import time
# Old pattern - verbose and error-prone
start_time = time.time()
result = expensive_computation()
end_time = time.time()
print(f"Elapsed time: {(end_time - start_time) * 1000:.6f} ms")
✅ Preferred: Timer context manager
import quantecon as qe
# Modern pattern - clean and reliable
with qe.Timer():
result = expensive_computation()
# Output: 0.05 seconds elapsed
Timer Features and Usage Patterns#
The Timer
context manager supports various usage patterns:
Basic Timing#
import quantecon as qe
with qe.Timer():
result = expensive_computation()
# Output: 0.05 seconds elapsed
Custom Messages and Units#
# Custom message with milliseconds
with qe.Timer("Computing eigenvalues", unit="milliseconds"):
eigenvals = compute_eigenvalues(matrix)
# Output: Computing eigenvalues: 50.25 ms elapsed
# Microseconds for very fast operations
with qe.Timer("Quick calculation", unit="microseconds"):
result = simple_operation()
# Output: Quick calculation: 125.4 μs elapsed
Silent Mode for Method Comparison#
# Store timing without printing for performance comparisons
timer = qe.Timer(silent=True)
with timer:
result = expensive_computation()
elapsed_time = timer.elapsed # Access stored time
# Compare multiple methods
methods = [method_a, method_b, method_c]
timers = []
for method in methods:
timer = qe.Timer(f"{method.__name__}", silent=True)
with timer:
method(data)
timers.append((method.__name__, timer.elapsed))
# Find fastest method
fastest = min(timers, key=lambda x: x[1])
print(f"Fastest method: {fastest[0]} ({fastest[1]:.6f}s)")
Precision Control#
# Control decimal places in output
with qe.Timer("High precision timing", precision=8):
result = computation()
# Output: High precision timing: 0.12345678 seconds elapsed
Exception Safety#
The Timer
context manager works correctly even when exceptions occur:
timer = qe.Timer("Error-prone operation", silent=True)
try:
with timer:
risky_computation()
except Exception as e:
print(f"Operation failed after {timer.elapsed:.4f} seconds")
raise
Migration from Legacy Patterns#
Replace tic
/tac
/toc
patterns:
# Old approach
from quantecon.util.timing import tic, tac, toc
tic()
result = computation()
toc()
# New approach
with qe.Timer():
result = computation()
Note
The tic
/tac
/toc
functions remain available for backward compatibility, but new code should use the Timer
context manager for better readability and reliability.