σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademySkills
Ctrl K
AO
+1.2k Learners
LoginJoin ↗
Skills
AO
+1.2k Learners
Login
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python skill›Module 1 · Python foundations for quants›Topic 1.21·~40 minBeginner

Packages and project layout

Skill positionModule 1 of 11 · Topic 21 of 33
1.21 Packages and project layout
—Lab score— / 100Total XP—Streak—

From a file to a folder of modules

A single file stops being enough once a project grows. A package is a folder of modules that Python can import as one unit. Mark the folder with a file named __init__.py (it can be empty) and every .py file inside becomes a module of the package, addressed with dots: quant/pricing.py is quant.pricing, and quant/data/loaders.py is quant.data.loaders. Folders inside a package are subpackages and need their own __init__.py.

# A small project on disk
#
# quant-tools/
#   pyproject.toml
#   README.md
#   quant/
#     __init__.py
#     pricing.py
#     data/
#       __init__.py
#       loaders.py
#   tests/
#     test_pricing.py

# quant/pricing.py
def mid(bid, ask):
    return (bid + ask) / 2

# anywhere else in the project
from quant.pricing import mid
import quant.data.loaders

print(mid(184.0, 185.0))  # 184.5

A layout that scales

Keep the importable code in one package folder named after the project, and keep everything else beside it, not inside: tests in tests/, a README.md that explains the project, a pyproject.toml that names it and lists its dependencies, and data or notebooks in their own folders. Test files are named test_*.py so tools like pytest find them. Small, focused modules with clear names (pricing.py, loaders.py) are easier to test and reuse than one long utils.py.

# pyproject.toml (names the project and its dependencies)
#
# [project]
# name = "quant-tools"
# version = "0.1.0"
# requires-python = ">=3.11"
# dependencies = ["numpy"]

# tests/test_pricing.py: found automatically because of the name
from quant.pricing import mid

def test_mid():
    assert mid(184.0, 185.0) == 184.5

Importing inside a package

Inside the package you can import by full path from the top (from quant.pricing import mid, an absolute import) or relative to the current module (from .pricing import mid, one dot for the same package, two for its parent, a relative import). Absolute imports are usually clearer. __init__.py runs when the package is first imported, so it can re-export the names users need (from .pricing import mid) and then import quant; quant.mid(...) works. Run package code with python -m quant.data.loaders, not python quant/data/loaders.py, so the dotted names resolve.

# quant/__init__.py: runs on the first "import quant"
from .pricing import mid          # relative: same package

__all__ = ["mid"]                 # what "from quant import *" would give

# quant/data/loaders.py
from quant.pricing import mid     # absolute: always starts at the top
from .. import pricing            # relative: two dots = the parent package

# In a terminal, from the project folder:
#   python -m quant.data.loaders   (runs the module as part of the package)
#   pytest -q                      (finds tests/test_*.py)
# A file path and its module name are two spellings of one thing
path = "quant/data/loaders.py"
name = path[:-3].replace("/", ".")
print(name)                          # quant.data.loaders
print(name.split(".")[0])            # quant  (the top-level package)

# __init__.py stands for its folder
print("quant/__init__.py"[:-3].replace("/", "."))  # quant.__init__ -> the package is "quant"
A missing __init__.py is a silent trapPython can sometimes import a folder without __init__.py (a "namespace package"), but tools, test runners and installers behave inconsistently with it, and imports that worked on your computer fail elsewhere. Give every package folder an __init__.py. The lab asks you to find folders that hold code but lack one.
  • A package is a folder with __init__.py; quant/data/loaders.py is the module quant.data.loaders.
  • Keep code in the package; tests, README, pyproject.toml and data beside it.
  • Prefer absolute imports; run package code with python -m package.module.

Next up: virtual environments and pip, so each project gets exactly the libraries it needs.

Lab · what's graded

  • Turn a file path into a module name with module_name25 pts
  • List a project's importable modules with find_modules25 pts
  • Spot folders that lack an __init__.py with missing_init25 pts
  • Write the import statement for a module with import_line25 pts
Explorer · lab-21-1
▾ lab-21-1
…
bash · in-browser
learner@quantcraft:~/lab-21-1$
Python not loaded yetPythonLn 1, Col 1Spaces: 4UTF-8

Reset this topic?

Everything in lab-21-1 goes back to the starter files and the terminal is cleared. Your current solution will be lost — this can't be undone.

Will be reset
  • main.py → starter code
  • Terminal history and test output
  • Unsubmitted changes
Will be kept
  • Best lab score
  • Your XP and streak
  • Lecture progress and notes

Log in to run your code.

Every lecture is free to read. Create an account or log in to run code, run tests and submit this lab.

  • In-browser IDE with a bash terminal — nothing to install
  • Instant grading, XP and your place on the skill
Create an accountLog in
OR
Continue with GitHub