σμ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.18·~35 minBeginner

JSON data

Skill positionModule 1 of 11 · Topic 18 of 33
1.18 JSON data
—Lab score— / 100Total XP—Streak—

Nested data as text

JSON is the everyday format for configuration files and for data sent between programs and web APIs. It is built from objects {"key": value}, arrays [1, 2], strings, numbers, true/false and null. These map directly onto Python: objects become dictionaries, arrays become lists, true/false become True/False and null becomes None. Unlike a CSV table, JSON can nest: an order can hold a list of fills, each with its own fields.

import json

# Text to Python: loads() ("load string")
text = '{"symbol": "AAPL", "fills": [{"price": 184.25, "qty": 100}], "open": true, "note": null}'
order = json.loads(text)
print(order["fills"][0]["price"])   # 184.25
print(order["open"], order["note"]) # True None

# Python to text: dumps() ("dump string")
print(json.dumps({"symbol": "AAPL", "qty": 200}))  # {"symbol": "AAPL", "qty": 200}

Files: load and dump

The versions without the s work on files: json.load(file) reads and parses an open file, and json.dump(data, file) writes it. Pass indent=2 to make the file readable by humans and sort_keys=True for a stable key order, which keeps diffs in version control small. Always open with with and encoding="utf-8".

import json

# Save a config, then load it back
config = {"fee": 0.001, "symbols": ["MSFT", "AAPL"], "limits": {"max_qty": 500}}
with open("config.json", "w", encoding="utf-8") as file:
    json.dump(config, file, indent=2, sort_keys=True)

with open("config.json", encoding="utf-8") as file:
    print(file.read())
    # {
    #   "fee": 0.001,
    #   "limits": {
    #     "max_qty": 500
    #   },
    #   "symbols": [
    #     "MSFT",
    #     "AAPL"
    #   ]
    # }

with open("config.json", encoding="utf-8") as file:
    print(json.load(file) == config)  # True

What does not survive the trip

JSON only has a few types, so some Python values change on the way. Tuples come back as lists, dictionary keys always come back as strings ({1: "a"} returns {"1": "a"}), and sets, dates and custom objects cannot be dumped at all (TypeError) until you convert them, for example a date with .isoformat() or a set with sorted(...). Also remember NaN and infinity are not valid JSON.

import json
from datetime import date

# Tuples become lists, int keys become strings
data = {"pair": (1, 2), 7: "seven"}
print(json.loads(json.dumps(data)))  # {'pair': [1, 2], '7': 'seven'}

# A date has to be converted by hand
today = date(2025, 1, 2)
print(json.dumps({"day": today.isoformat()}))  # {"day": "2025-01-02"}

Bad input

Text that arrives from outside, such as a message from an exchange, may not be valid JSON at all. json.loads then raises json.JSONDecodeError, a kind of ValueError, and valid JSON may still lack the key you want (KeyError) or have another shape (TypeError). Wrap the parsing in try/except and decide what a bad message means for your program. The next topic covers exceptions in full.

import json

# Bad input raises, so catch it where you parse
def get_price(text):
    try:
        return json.loads(text)["price"]
    except (ValueError, KeyError, TypeError):
        return None

print(get_price('{"price": 184.25}'))  # 184.25
print(get_price("not json"))           # None
print(get_price('{"symbol": "AAPL"}')) # None
Never build JSON by gluing strings togetherA quote, a backslash or a non-ASCII letter inside a value breaks hand-built JSON. Build a Python dictionary and let json.dumps or json.dump produce the text, and let json.loads or json.load read it. The same goes for merging settings: copy before you change, so one configuration does not leak into another.
  • json.loads(text) / json.dumps(data) work on strings; json.load(file) / json.dump(data, file) on files.
  • indent=2 and sort_keys=True make files readable and stable.
  • Bad input raises ValueError, KeyError or TypeError: catch what you expect.

Next up: exceptions and error handling, so your programs fail clearly and recover when they should.

Lab · what's graded

  • Total the orders in a JSON file with order_total25 pts
  • Save settings as readable JSON with save_config25 pts
  • Read a quote message safely with parse_quote25 pts
  • Layer settings over defaults with merge_configs25 pts
Explorer · lab-18-1
▾ lab-18-1
…
bash · in-browser
learner@quantcraft:~/lab-18-1$
Python not loaded yetPythonLn 1, Col 1Spaces: 4UTF-8

Reset this topic?

Everything in lab-18-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