The video above shows how to use constants in Python to keep your code reliable and maintainable. Read on for the practitioner depth and worked examples.
What Is a Constant?
A constant is a value that must never change during program execution. Once you set it, it stays set. Python does not enforce this at the language level (you can overwrite anything), but the convention is clear: if you name something in UPPER_CASE, you and everyone else reading your code is promising not to change it.
Think of it like this. A variable is a box you put a value in, and you might change what is inside. A constant is a sealed box. You label it clearly so no one accidentally opens it and changes the contents.
In finance code, this matters deeply. When you define an LCR threshold, a funding transfer pricing (FTP) rate, or a haircut on a collateral asset, you do not want that value drifting mid calculation. A constant makes your intention explicit: this value is fixed. If someone (including you, three months from now) tries to change it, the UPPER_CASE naming screams "wait, why are you modifying this?"
Why Constants Matter in Finance Code
Finance practitioners live in a world of rules and thresholds. Your liquidity coverage ratio must stay above 100%. Haircuts on AAA rated securities are fixed by your risk framework. Regulatory cutoff dates do not move. Magic numbers hiding in your code break all of this.
Consider a real scenario. You are building a daily LCR calculation in a notebook. You hardcode 0.75 as the weighting for a certain liability class. Weeks later, risk changes the weighting to 0.80. Your calculation still uses 0.75. If the value is not flagged as a constant, the change gets lost in a sea of similar numbers. If it is a constant, and someone reads the code, they immediately ask: "where is the constant definition? Should I update it?" The naming convention does the work.
Constants also prevent a silent class of errors: the typo that becomes a bug. If you type a number inline every time you need it, sooner or later you will type it wrong. A constant, defined once and used everywhere, removes that risk.
Beyond safety, constants make code readable. Compare these two:
# Without constants
lcr_calculation = (hqla_stock * 1.0) / (cash_outflows * 1.25)
# With constants
HQLA_HAIRCUT = 1.0
OUTFLOW_STRESS_MULTIPLIER = 1.25
lcr_calculation = (hqla_stock * HQLA_HAIRCUT) / (cash_outflows * OUTFLOW_STRESS_MULTIPLIER)
The second version tells you what each number represents. A colleague (or your future self) reads it and understands the logic at a glance. You know where to go if the haircut changes.
In regulatory reporting, a constant is often your first documentation of where a threshold or rate came from. The UPPER_CASE name signals to an auditor or a reviewer: "this value is fixed and intentional".
How to Define a Constant in Python
Defining a constant in Python is simple. You assign a value to a name in UPPER_CASE, usually at the top of your script or notebook.
# Define constants at the top of your module or notebook
REGULATORY_CUTOFF_DATE = "2024-03-31"
MIN_LCR_THRESHOLD = 1.0
FTP_RATE_OPERATIONAL = 0.045
HAIRCUT_AAA_RATED = 0.99
MAX_COUNTERPARTY_EXPOSURE = 500_000_000 # £500m
That is it. You use them like any variable:
current_lcr = hqla / outflows
is_compliant = current_lcr >= MIN_LCR_THRESHOLD
adjusted_cost = loan_amount * (1 + FTP_RATE_OPERATIONAL)
haircut_value = security_value * (1 - HAIRCUT_AAA_RATED)
exposure_remaining = MAX_COUNTERPARTY_EXPOSURE - exposure_used
Python does not stop you from reassigning a constant. You can write MIN_LCR_THRESHOLD = 0.95 and Python will let you. What the convention does is make you think before you do it. The all caps naming is a visual and semantic signal: "this should not change". Your linter will warn you (and your IDE will flag it). Your code reviewers will ask why.
When you need a value in multiple places, or a value that represents a business rule or regulatory threshold, make it a constant. If it is a simple loop counter or a temporary working value, leave it lowercase.
# Constant: regulatory threshold, used in multiple places
MIN_NSFR = 1.0
# Variable: temporary working values
for i in range(10):
interim_calculation = data[i] * MIN_NSFR
print(interim_calculation)
Notice that MIN_NSFR is uppercase (it must not change), while i and interim_calculation are lowercase (they are temporary).
Constants in Real Treasury and Regulatory Work
Let us walk through a practical example: a daily FTP charge allocation.
Your risk framework defines FTP rates by term bucket. These rates are set by the ALM committee and only change monthly. You need to build a script that pulls positions and applies the correct rate to each. Without constants, you might write this:
A weekly note on treasury, liquidity and practical Python. No spam, unsubscribe any time.
# Bad: magic numbers scattered in the code
def calculate_ftp_charge(position_amount, term_months):
if term_months <= 3:
return position_amount * 0.035
elif term_months <= 12:
return position_amount * 0.045
else:
return position_amount * 0.055
The rates are locked inside the logic. If the ALM committee changes a rate, you have to hunt through the code. Worse, someone might use a similar function elsewhere and hardcode different rates, creating inconsistency.
Now with constants:
# Good: rates defined once, clearly, at the top
FTP_RATE_UP_TO_3M = 0.035
FTP_RATE_3M_TO_12M = 0.045
FTP_RATE_OVER_12M = 0.055
def calculate_ftp_charge(position_amount, term_months):
# term_months: loan or deposit maturity in months
if term_months <= 3:
return position_amount * FTP_RATE_UP_TO_3M
elif term_months <= 12:
return position_amount * FTP_RATE_3M_TO_12M
else:
return position_amount * FTP_RATE_OVER_12M
Now the rates are transparent. You see them at the top of the file. If rates change, you update them once, and the whole program reflects the change. You can even document when they were last updated:
# FTP rates effective 2024-04-01, set by ALM committee
FTP_RATE_UP_TO_3M = 0.035
FTP_RATE_3M_TO_12M = 0.045
FTP_RATE_OVER_12M = 0.055
Here is another example: regulatory cutoff dates. Many reporting rules care about whether a transaction occurred before or after a specific date. Rather than scattering dates in conditionals, define them once:
# Regulatory cutoff dates
ICAAP_REPORTING_DATE = "2024-12-31"
LCR_OBSERVATION_PERIOD_END = "2024-12-31"
STRESS_TEST_HORIZON_DAYS = 30
NSFR_OBSERVATION_PERIOD_MONTHS = 12
# Then use them consistently
if transaction_date <= ICAAP_REPORTING_DATE:
include_in_stress_test = True
If your compliance officer says the cutoff moves to the 31st of March, you change one line and you are done.
Common Mistakes and How to Avoid Them
Mistake 1: Confusing constants with variables.
# Wrong: looks like a constant but it changes
DAILY_LIMIT = 100_000
# Later...
DAILY_LIMIT = 150_000 # Oops, you just broke the contract
If you find yourself reassigning something, it is not a constant; call it a variable and use lowercase. Constants should be set once and left alone.
Mistake 2: Using magic numbers and never explaining them.
# Wrong: what is 1.3?
stress_scenario_outflow = daily_outflow * 1.3
Define the number with a clear name:
# Right: now it is obvious
STRESS_OUTFLOW_MULTIPLIER = 1.3
stress_scenario_outflow = daily_outflow * STRESS_OUTFLOW_MULTIPLIER
Mistake 3: Putting constants in the wrong place.
In a notebook, define all constants in a cell near the top, before any calculations. In a module, define them at the module level, before function definitions. This makes them easy to find and update.
# Good structure
import pandas as pd
from datetime import date
# Constants first
MIN_LCR = 1.0
REPORTING_DATE = date(2024, 12, 31)
HAIRCUT_LEVEL_1 = 0.99
# Then functions and logic
def check_lcr_compliance(lcr_value):
return lcr_value >= MIN_LCR
Mistake 4: Not using constants when you should.
If you are tempted to add a comment explaining what a number is, that is a sign it should be a constant:
# Before: comment does the explaining
threshold = 0.75 # FTP margin haircut
# After: constant name does the explaining
FTP_MARGIN_HAIRCUT = 0.75
threshold = FTP_MARGIN_HAIRCUT
Optional: Enforcing Constants in Large Codebases
For larger projects, Python 3.8 and later offer typing.Final as an optional enforcement layer. This signals intent to type checkers and makes violation more visible in code review, though Python still permits reassignment at runtime.
from typing import Final
MIN_LCR_THRESHOLD: Final = 1.0
This is useful if your team runs a static type checker like mypy. For most treasury notebooks and single scripts, the UPPER_CASE convention alone is sufficient.
The Practical Takeaway
Constants are not a syntax ornament. They are a tool for writing code that other people can trust and maintain. In finance, where a single wrong number can cascade into a missed regulatory ratio or a broken risk model, they earn their place in every serious piece of code you write.
Start now. The next time you write a calculation that depends on a threshold, a rate, or a date, define it as a constant at the top. Use UPPER_CASE. Add a comment if the value came from a policy or a regulatory source. When you refactor old code, look for hardcoded numbers and promote them to constants. You will be surprised how much clearer your logic becomes.
If you are building in a Jupyter notebook, read the post on getting started with Jupyter to understand the best structure for constants in notebooks. And if you want to see how constants fit into the broader structure of readable code, check out the post on reading code like you read English.
Your future self, and your code reviewers, will thank you.
Get the next one in your inbox
A weekly note across Finance & Treasury, Innovation & Automation and Career Development. No spam, unsubscribe any time.
Notes across finance and treasury, innovation and automation, and career development, written by practitioners who do the work.
