\[
% MathJax has no bm package; redefine \bm in terms of \boldsymbol, which it supports natively
\newcommand{\bm}[1]{\boldsymbol{#1}}
% --- Operators -----------------------------------------------------------
% Expectation operator
\DeclareMathOperator{\E}{E}
% Variance operator
\DeclareMathOperator{\Var}{Var}
% Covariance operator
\DeclareMathOperator{\Cov}{Cov}
% Correlation operator
\DeclareMathOperator{\Corr}{Corr}
% Rank operator (Spearman rank correlation)
\DeclareMathOperator{\Rank}{Rank}
% Skewness operator
\DeclareMathOperator{\Skewness}{Skewness}
% Kurtosis operator
\DeclareMathOperator{\Kurtosis}{Kurtosis}
% Difference/differential operator (upright d per ISO 80000-2)
\newcommand{\Diff}{\mathrm{d}}
% --- Risk Measures -------------------------------------------------------
% Value at Risk
\DeclareMathOperator{\VaR}{VaR}
% Expected Shortfall
\DeclareMathOperator{\ES}{ES}
% Marginal Value at Risk
\DeclareMathOperator{\MVaR}{MVaR}
% Component Value at Risk
\DeclareMathOperator{\CompVaR}{CVaR}
% Incremental Value at Risk
\DeclareMathOperator{\IVaR}{IVaR}
% Component Expected Shortfall
\DeclareMathOperator{\CompES}{CES}
% Weighted sensitivity for risk factor in FRTB SBM bucket
\DeclareMathOperator{\WS}{WS}
% Hedge-benefit ratio for FRTB DRC bucket
\DeclareMathOperator{\HBR}{HBR}
% Stress scenario risk measure for FRTB NMRF capital add-on
\DeclareMathOperator{\SES}{SES}
% Jump-to-default exposure for obligor (FRTB DRC)
\DeclareMathOperator{\JTD}{JTD}
% Loss given default for obligor (FRTB DRC)
\DeclareMathOperator{\LGD}{LGD}
% Default risk weight for obligor (FRTB DRC)
\DeclareMathOperator{\RW}{RW}
% ES ratio function
\newcommand{\ESratio}{\lambda}
% Arbitrary risk measure function (coherence axioms)
\newcommand{\RiskMeasure}{\varphi}
% Asset position (coherence axioms)
\newcommand{\Asset}{A}
% First named asset in examples
\newcommand{\AssetA}{A}
% Second named asset in examples
\newcommand{\AssetB}{B}
% Third named asset in examples
\newcommand{\AssetC}{C}
% Constant (risk measure axioms)
\newcommand{\Constant}{c}
% Bucket-level aggregate sensitivity in FRTB SBM
\newcommand{\BucketAgg}{S}
% Cross-bucket correlation in FRTB SBM
\newcommand{\CrossBucketCorr}{\gamma}
% Notional amount for an instrument (FRTB DRC and RRAO)
\newcommand{\Notional}{\text{Notional}}
% --- Distributions -------------------------------------------------------
% Binomial distribution
\DeclareMathOperator{\Binomial}{Binomial}
% Uniform distribution
\DeclareMathOperator{\Uniform}{Uniform}
% Normal distribution
\newcommand{\NormalDist}{\mathcal{N}}
% Student-t CDF
\newcommand{\StudentCDF}{t}
% Student-t PDF
\newcommand{\StudentPDF}{f}
% --- Returns -------------------------------------------------------------
% Price
\newcommand{\Price}{P}
% Simple (arithmetic) return
\newcommand{\SimpleReturns}{R}
% Log (compound) return
\newcommand{\CompoundReturns}{y}
% Matrix of compound returns
\newcommand{\ReturnMatrix}{\bm{y}}
% Dividend payment
\newcommand{\dividend}{d}
% --- Volatility ----------------------------------------------------------
% Realised variance
\DeclareMathOperator{\RealisedVar}{RV}
% Realised volatility (square root of realised variance)
\DeclareMathOperator{\RealisedVol}{RVol}
% Volatility
\newcommand{\Vol}{\sigma}
% GARCH intercept parameter
\newcommand{\GARCHconst}{\omega}
% ARCH coefficient (weight on past squared returns)
\newcommand{\ARCHcoeff}{\alpha}
% GARCH coefficient (weight on past variance)
\newcommand{\GARCHcoeff}{\beta}
% EWMA decay factor (typically 0.94)
\newcommand{\EWMAdecay}{\lambda}
% Standardized residual / error term
\newcommand{\StdNormal}{\epsilon}
% Leverage parameter in apARCH
\newcommand{\APARCHleverage}{\zeta}
% Power parameter in apARCH
\newcommand{\APARCHpower}{\delta}
% Degrees of freedom (Student-t)
\newcommand{\DOF}{\nu}
% GJR-GARCH leverage parameter
\newcommand{\GJRleverage}{\gamma}
% GARCH-X external regressor coefficient
\newcommand{\RegressorCoeff}{\xi}
% Mean (first moment)
\newcommand{\Mean}{\mu}
% Lag order in volatility models
\newcommand{\Lag}{L}
% Dummy variable (indicator in regressions)
\newcommand{\DummyVar}{D}
% --- Portfolio -----------------------------------------------------------
% Portfolio weight (scalar)
\newcommand{\weight}{w}
% Portfolio weight vector
\newcommand{\weights}{\bm{w}}
% Covariance matrix
\newcommand{\CovMatrix}{\bm{\Sigma}}
% Correlation matrix
\newcommand{\CorrMatrix}{\bm{C}}
% Correlation coefficient
\newcommand{\correlation}{\rho}
% Number of assets in portfolio
\newcommand{\NumberAssets}{K}
% Portfolio value
\newcommand{\PortfolioValue}{\vartheta}
% Asset beta (CAPM)
\newcommand{\AssetBeta}{\beta}
% Ledoit-Wolf shrinkage intensity
\newcommand{\ShrinkageIntensity}{\delta}
% Sample covariance matrix
\newcommand{\SampleCov}{\bm{S}}
% --- Time Series ---------------------------------------------------------
% Sample size
\newcommand{\SampleSize}{T}
% Generic count (number of lags, payments, etc.)
\newcommand{\Count}{N}
% Estimation window length
\newcommand{\EstWindow}{W_E}
% Testing window length
\newcommand{\TestWindow}{W_T}
% Stress window length
\newcommand{\StressWindow}{W_S}
% AR coefficient
\newcommand{\ARcoeff}{\phi}
% MA coefficient
\newcommand{\MAcoeff}{\psi}
% --- Probability ---------------------------------------------------------
% Probability level (e.g. 0.01 for 1% VaR)
\newcommand{\probability}{p}
% Cumulative sorted scenario weight
\newcommand{\CumScenarioWeight}{\Omega}
% p-quantile of the P and L distribution
\newcommand{\Quantile}{q}
% Quantile function
\newcommand{\QuantileFunction}{Q}
% Probability density function
\newcommand{\PDF}{f}
% Cumulative distribution function
\newcommand{\CDF}{F}
% Standard normal CDF
\newcommand{\NormalCDF}{\Phi}
% Inverse standard normal (quantile function)
\newcommand{\NormalQuantile}{\Phi^{-1}}
% Standard normal density function
\newcommand{\NormalPDF}{\phi}
% Likelihood function
\newcommand{\lik}{\mathcal{L}}
% Log-likelihood
\newcommand{\LogLikelihood}{\ell}
% Parameter vector (MLE estimation)
\newcommand{\ParamSet}{\theta}
% Parameter space
\newcommand{\ParamSpace}{\Theta}
% Fisher information matrix
\newcommand{\FisherInfo}{\mathcal{I}}
% Statistical power (Type II error rate)
\newcommand{\StatPower}{\beta}
% Significance level (CI coverage complement)
\newcommand{\SignifLevel}{\gamma}
% --- Options -------------------------------------------------------------
% Call option label
\newcommand{\CallOption}{\text{call}}
% Put option label
\newcommand{\PutOption}{\text{put}}
% Strike price
\newcommand{\Strike}{X}
% Risk-free interest rate
\newcommand{\RiskFree}{r_f}
% Option maturity (time to expiration)
\newcommand{\OptionMaturity}{\tau}
% Option delta
\newcommand{\OptionDelta}{\Delta}
% Option gamma
\newcommand{\OptionGamma}{\Gamma}
% Option vega
\newcommand{\Vega}{\mathcal{V}}
% Holding period
\newcommand{\HoldingPeriod}{H}
% Simulation profit/loss (signed; negative is a loss)
\newcommand{\ProfitLoss}{\Pi}
% Futures price
\newcommand{\Futures}{F}
% Hedge ratio
\newcommand{\HedgeRatio}{h}
% Units of basic asset held
\newcommand{\StockHolding}{x^b}
% Units of options held
\newcommand{\OptionHolding}{x^o}
% --- Interest Rates ------------------------------------------------------
% Bond convexity
\newcommand{\Convexity}{C}
% Interest rate / yield
\newcommand{\Yields}{r}
% Key rate change, basis points (scalar tenor component); used as \KeyRateChange_k or \KeyRateChange_{t,k}. EXCEPTION to the no-macro-to-macro-indirection rule, decided 2026-08-09: composed from \Yields on purpose, so a future change to the rate glyph propagates here without a follow-up edit. \Yields is defined earlier in generated output (same interest_rates category, TOML order), so expansion order is safe; verify this still holds if either entry is reordered.
\newcommand{\KeyRateChange}{\Delta \Yields^{\mathrm{bp}}}
% Key rate changes, basis points (vector); used bare or as \KeyRateChanges_t. EXCEPTION to the no-macro-to-macro-indirection rule, decided 2026-08-09: composed from \Yields on purpose, so a future change to the rate glyph propagates here without a follow-up edit. \bm{\Yields} depends on \bm/\boldsymbol correctly expanding a macro argument rather than a bare letter --- confirm this renders correctly the first time either consumer compiles it.
\newcommand{\KeyRateChanges}{\Delta \bm{\Yields}^{\mathrm{bp}}}
% Dollar value of a basis point
\newcommand{\DV}{\text{DV01}}
% Mean reversion speed (interest rate models)
\newcommand{\MeanReversion}{\varkappa}
% Modified duration
\newcommand{\ModDur}{D}
% Macaulay duration
\newcommand{\MacDur}{D_{\text{Mac}}}
% Effective duration
\newcommand{\EffDur}{D_{\text{eff}}}
% DV01 vector
\newcommand{\DVvec}{\bm{d}}
% Long-run mean rate (Vasicek/CIR/Hull-White)
\newcommand{\LongRunRate}{\theta}
% Hull-White time-varying drift
\newcommand{\HullWhiteDrift}{\varphi}
% Cash flow (coupon/principal payment)
\newcommand{\CashFlow}{c}
% --- Extreme Value -------------------------------------------------------
% Tail index (EVT, Pareto-type tails)
\newcommand{\TailIndex}{\iota}
% Shape parameter (xi = 1/iota)
\newcommand{\ShapeParam}{\varsigma}
% Threshold value (EVT)
\newcommand{\Threshold}{u}
% Extremal index (Leadbetter 1983)
\newcommand{\ExtremalIndex}{\theta}
% Multivariate extremal coefficient, theta in [1,d]. theta=1 complete tail dependence; theta=d asymptotic independence. Glyph collides with ExtremalIndex and ParamSet; disambiguated at source by macro name.
\newcommand{\ExtremalCoef}{\theta}
% GEV distribution function
\newcommand{\GEV}{\mathcal{H}}
% GPD distribution function
\newcommand{\GPD}{\mathcal{G}}
% GPD scale parameter
\newcommand{\GPDscale}{\beta}
% GPD scale parameter at a threshold u, distinct from the generic GPD scale
\newcommand{\GPDscaleAtThreshold}{\beta_u}
% Number of threshold exceedances (EVT)
\newcommand{\TailCount}{C}
% Sample maximum (block maxima, EVT)
\newcommand{\SampleMax}{M}
% Kurtosis value (realized, e.g. sample kurtosis)
\newcommand{\KurtosisVal}{\kappa}
% Pareto scaling constant (EVT)
\newcommand{\ParetoConst}{\mathcal{A}}
% Generic constant (EVT asymptotics)
\newcommand{\RemainderConst}{\mathcal{C}}
% Little-o asymptotic notation
\newcommand{\LittleO}{o}
% Moment order (EVT)
\newcommand{\MomentOrder}{\mathscr{m}}
% Doubled sample size (EVT block maxima)
\newcommand{\DoubleSample}{D}
% GEV normalizing location constant
\newcommand{\GEVloc}{a}
% GEV normalizing scale constant
\newcommand{\GEVscale}{b}
% Negative return (loss, EVT context)
\newcommand{\NegativeReturn}{L}
% --- Copulas -------------------------------------------------------------
% Copula function
\newcommand{\Copula}{\mathcal{C}}
% Copula density
\newcommand{\CopulaDensity}{c}
% Generator function (Archimedean copulas)
\newcommand{\generator}{\varphi}
% Copula dependence parameter
\newcommand{\CopulaParam}{\theta}
% Copula marginal parameter set
\newcommand{\MarginalParamSet}{\eta}
% Lower tail dependence coefficient
\newcommand{\LowerTailDep}{\lambda_L}
% Upper tail dependence coefficient
\newcommand{\UpperTailDep}{\lambda_U}
% Marginal CDF (second variable)
\newcommand{\MarginalCDF}{G}
% Joint density function
\newcommand{\JointDensity}{h}
% Marginal density function
\newcommand{\MarginalDensity}{g}
% Joint distribution function
\newcommand{\JointCDF}{H}
% Gaussian copula correlation parameter
\newcommand{\CopulaCorr}{\rho}
% --- Multivariate --------------------------------------------------------
% Diagonal matrix of conditional volatilities
\newcommand{\DiagVolD}{\bm{D}}
% Idiosyncratic variance matrix (diagonal, factor models)
\newcommand{\IdioVarMatrix}{\bm{\Psi}}
% Covariance matrix entry (two indices)
\newcommand{\CovElement}{\sigma}
% Auxiliary matrix in DCC dynamics
\newcommand{\DCCauxQ}{\bm{Q}}
% BEKK constant matrix
\newcommand{\BEKKconst}{\bm{\Omega}}
% BEKK ARCH parameter matrix
\newcommand{\BEKKarch}{\bm{A}}
% BEKK GARCH parameter matrix
\newcommand{\BEKKgarch}{\bm{B}}
% DCC rescaling diagonal matrix
\newcommand{\DCCrescaleZ}{\bm{Z}}
% DCC auxiliary matrix element
\newcommand{\DCCelement}{q}
% Factor loadings matrix (loadings/eigenvectors of the covariance matrix)
\newcommand{\FactorLoadings}{\bm{\Lambda}}
% Factor subscript label
\newcommand{\factor}{\text{factor}}
% PCA eigenvalue
\newcommand{\Eigenvalue}{\lambda}
% Number of factors in factor model
\newcommand{\NumberFactors}{m}
% Factor return vector
\newcommand{\FactorReturn}{\bm{g}}
% PCA factor score (scalar; not an eigenvector)
\newcommand{\PCAFactor}{F}
% BEKK cross-covariance coefficient
\newcommand{\BEKKcross}{\delta}
% Factor loading element
\newcommand{\FactorLoading}{\Lambda}
% DCC correlation persistence parameter
\newcommand{\DCCxi}{\xi}
% DCC news coefficient (weight on recent shocks)
\newcommand{\DCCzeta}{\zeta}
% --- Simulation ----------------------------------------------------------
% Number of simulation paths
\newcommand{\NumberSims}{B}
% Cholesky factor of covariance matrix
\newcommand{\Cholesky}{\bm{L}}
% Uniform random number
\newcommand{\UniformDraw}{\tilde{u}}
% --- Backtesting ---------------------------------------------------------
% Violation ratio (observed/expected violations)
\DeclareMathOperator{\ViolRatio}{VR}
% Stressed Value at Risk
\DeclareMathOperator{\StressedVaR}{SVaR}
% QLIKE loss function for variance forecasts
\DeclareMathOperator{\QLIKE}{QLIKE}
% Mean squared error (forecast loss function)
\DeclareMathOperator{\MSE}{MSE}
% Mean absolute error (forecast loss function)
\DeclareMathOperator{\MAE}{MAE}
% Markov transition probability
\newcommand{\TransProb}{\pi}
% Exception indicator: 1 if y_t < -VaR_t
\newcommand{\ExceptionInd}{\eta}
% Exception count
\newcommand{\ExceptionCount}{\upsilon}
% Probability Integral Transform
\newcommand{\ProbIntegralTransform}{\hat{u}}
% Quantile score (pinball loss function)
\newcommand{\QuantileScore}{\mathcal{S}}
% Kolmogorov-Smirnov test statistic
\newcommand{\KSstat}{D}
% Test statistic (generic base letter)
\newcommand{\TestStat}{J}
% --- General -------------------------------------------------------------
% Regression intercept
\newcommand{\RegressionIntercept}{a}
% Regression slope
\newcommand{\RegressionSlope}{\beta}
% Risk factor
\newcommand{\RiskFactor}{x}
% Forecast horizon
\newcommand{\ForecastHorizon}{h}
% Block length (bootstrap)
\newcommand{\BlockLength}{\ell}
% Capital tau variant
\newcommand{\DeliveryTime}{\Upsilon}
% Today's calendar time in years (option pricing input; distinct from trading-date index t)
\newcommand{\CalendarTime}{t^*}
% Probability measure
\newcommand{\ProbMeasure}{\mathbb{P}}
% Risk-neutral measure
\newcommand{\RiskNeutral}{\mathbb{Q}}
% Pricing function (Black-Scholes, bond pricing, etc.)
\newcommand{\PricingFn}{V}
% Indicator function
\newcommand{\Indicator}{\bm{1}}
% Vector of ones
\newcommand{\OnesVector}{\bm{1}}
% Risk factor sensitivity (first-order P&L)
\newcommand{\Sensitivity}{\delta}
% Second-order sensitivity (convexity/gamma)
\newcommand{\ConvexitySens}{\gamma}
% Output floor percentage (Basel)
\newcommand{\OutputFloor}{\alpha}
% --- Subscript Labels ----------------------------------------------------
% Subscript label: annualized
\newcommand{\Annual}{a}
% Subscript label: implied
\newcommand{\Implied}{I}
% Subscript label: portfolio
\newcommand{\Portfolio}{\pi}
% --- Text Abbreviations --------------------------------------------
% S&P 500 index
\newcommand{\SP}{\text{S\&P-500}}
% Student-t distribution (text)
\newcommand{\St}{\text{Student-t}}
% Geopolitical Risk index (Caldara and Iacoviello)
\newcommand{\GPR}{\text{GPR}}
\]
Risk models begin with assignment, arrays and tables. This chapter introduces the Python structures used throughout the book.
Assignment
In Python, we use the equal sign, =, to assign a value to a variable. The variable’s name is on the left, and the value to be stored is on the right.
x = 3
y = 4
x == y # Two equal signs test for equality
Two equal signs, ==, test equality. One equal sign assigns a value.
Python data structures
Python provides several built-in data structures for organising and manipulating data.
Lists
Python lists are ordered, mutable collections that can hold items of different types.
v = [1 , 2 , 3 , 4 , 5 ]
print (v)
v = list (range (1 , 6 ))
print (v)
v = [1 , 3 , 7 , 3 , 0.4 ]
v = [x * 3 for x in v]
print (v)
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[3, 9, 21, 9, 1.2000000000000002]
Lists can contain mixed types:
x = [1 , 4 , 0.9 , "ss" ]
print (x)
Here, we used both numbers and strings, and Python keeps them as their original types.
NumPy arrays
For numerical work, NumPy arrays are more efficient than Python lists. They let you apply the same calculation to an entire array at once.
import numpy as np
v = np.zeros(4 )
print (v)
v = np.array([1 , 2 , 3 , 4 , 5 ])
print (v)
v = np.arange(- 1 , 2.5 , 0.5 )
print (v)
v = np.array([1 , 3 , 7 , 3 , 0.4 ]) * 3
print (v)
[0. 0. 0. 0.]
[1 2 3 4 5]
[-1. -0.5 0. 0.5 1. 1.5 2. ]
[ 3. 9. 21. 9. 1.2]
Matrices (2D arrays)
NumPy can create two-dimensional arrays (matrices). We usually work with two-dimensional arrays, but we will encounter three-dimensional arrays in the multivariate volatility models.
m = np.zeros((3 , 1 ))
print (m)
m = np.zeros((3 , 2 ))
print (m)
m = np.full((3 , 2 ), 3 )
print (m)
[[0.]
[0.]
[0.]]
[[0. 0.]
[0. 0.]
[0. 0.]]
[[3 3]
[3 3]
[3 3]]
We can combine arrays with np.column_stack() and np.vstack() (similar to R’s cbind and rbind):
v = np.array([1 , 3 , 7 , 3 , 0.4 ]) * 3
m = np.column_stack((v, v))
print (m)
m = np.vstack((v, v))
print (m)
[[ 3. 3. ]
[ 9. 9. ]
[21. 21. ]
[ 9. 9. ]
[ 1.2 1.2]]
[[ 3. 9. 21. 9. 1.2]
[ 3. 9. 21. 9. 1.2]]
We can access individual elements of arrays:
print (m[0 , 1 ])
print (m[:, 1 ])
print (m[1 , :])
print (m[0 , 2 :5 ])
print (v[1 :3 ])
9.0
[9. 9.]
[ 3. 9. 21. 9. 1.2]
[21. 9. 1.2]
[ 9. 21.]
Note that Python uses zero-based indexing, unlike R, which uses one-based indexing.
Dictionaries
Python dictionaries are key-value pairs, similar to R lists. They allow us to group multiple variables together.
d = {}
d['a' ] = 2
d['b' ] = "Python is great."
print (d)
d = {'l' : [2 , 3 ], 'b' : "Risk" }
print (d)
w = {}
w['q' ] = "my dict"
w['d' ] = d
print (w)
{'a': 2, 'b': 'Python is great.'}
{'l': [2, 3], 'b': 'Risk'}
{'q': 'my dict', 'd': {'l': [2, 3], 'b': 'Risk'}}
We can find out what is in a dictionary:
Access individual elements:
{'l': [2, 3], 'b': 'Risk'}
We make extensive use of dictionaries in these notes.
DataFrames
For tabular data, pandas DataFrames are the standard in Python. They are similar to R data frames but add label-based indexing and built-in time-series handling.
import pandas as pd
df = pd.DataFrame({
'col1' : [1 , 2 , 3 ],
'col2' : ['A' , 'B' , 'C' ],
'col3' : [True , True , False ],
'col4' : [1.0 , 2.2 , 3.3 ]
})
print (df)
col1 col2 col3 col4
0 1 A True 1.0
1 2 B True 2.2
2 3 C False 3.3
You specify the name of each column and what goes inside it. We can check the structure:
print (df.dtypes)
print (df.shape)
print (df.columns.tolist())
col1 int64
col2 object
col3 bool
col4 float64
dtype: object
(3, 4)
['col1', 'col2', 'col3', 'col4']
Accessing data from columns
We can access data from columns by name using either bracket notation or dot notation:
print (df['col1' ])
print (df.col1)
0 1
1 2
2 3
Name: col1, dtype: int64
0 1
1 2
2 3
Name: col1, dtype: int64
Bracket notation, df['col1'], is the reliable form. Dot notation is a convenience that fails for column names that are not valid Python identifiers and for names that collide with a DataFrame attribute or method, such as count.
Python-specific concepts
Some Python features matter because they change how code behaves. Missing values, mutability and scope are the ones that cause trouble most often.
None and NaN
Python uses None to represent the absence of a value, and NumPy/pandas use np.nan (Not a Number) for missing numerical values:
a = None
print (a)
b = np.nan
print (b)
In pandas, missing values are typically represented as NaN:
df = pd.DataFrame({'a' : [1 , np.nan, 3 ]})
print (df)
print (df.isna())
a
0 1.0
1 NaN
2 3.0
a
0 False
1 True
2 False
Mutable vs immutable types
Python distinguishes between mutable (can be changed) and immutable (cannot be changed) types:
Immutable : integers, floats, strings, tuples
Mutable : lists, dictionaries, NumPy arrays, DataFrames
This affects how variables behave when passed to functions or assigned to new variables:
# Rebinding y does not affect x
x = 5
y = x
y = 10
print (f"x = { x} , y = { y} " )
# Both names refer to the same list
a = [1 , 2 , 3 ]
b = a
b[0 ] = 99
print (f"a = { a} , b = { b} " )
x = 5, y = 10
a = [99, 2, 3], b = [99, 2, 3]
To create an independent copy of a mutable object, use .copy(). For nested structures, use copy.deepcopy().
a = [1 , 2 , 3 ]
b = a.copy()
b[0 ] = 99
print (f"a = { a} , b = { b} " )
a = [1, 2, 3], b = [99, 2, 3]
Scope and global variables
Variables in Python have scope, meaning which part of the code can see them. Variables defined at the module level are global, while variables defined inside functions are local.
global_var = 100
def my_function():
local_var = 50
print (f"Inside function: global_var = { global_var} " )
print (f"Inside function: local_var = { local_var} " )
my_function()
Inside function: global_var = 100
Inside function: local_var = 50
To modify a global variable inside a function, use the global keyword:
counter = 0
def increment():
global counter
counter += 1
increment()
print (counter)
Python programming essentials
Printing
Python uses print() for output:
x = 10
y = 1.234
print (x)
print (f"This is the answer. x = { x} , and y = { y} ." )
10
This is the answer. x = 10, and y = 1.234.
Some useful functions
A few functions appear repeatedly in these notes:
len(): return the length of an object
range(): generate a sequence of numbers
print(): print values
type(): return the type of an object
list(), dict(), set(): create collections
NumPy: np.array(), np.zeros(), np.ones(), np.arange()
pandas: pd.DataFrame(), pd.read_csv(), pd.concat()
Packages/libraries
The main Python packages used in this book are numpy for numerical computing, pandas for data manipulation, plotnine for plotting, arch for GARCH models, scipy for scientific computing and statsmodels for statistical models. matplotlib and seaborn are general-purpose plotting alternatives not used here.
Install packages using pip or uv:
uv pip install numpy pandas plotnine arch scipy statsmodels
Import packages at the top of your code:
import numpy as np
import pandas as pd
Matrix algebra
NumPy supports matrix operations. Use * for element-by-element multiplication and @ or np.dot() for matrix multiplication:
weight = np.array([0.3 , 0.7 ])
prices = np.random.rand(5 , 2 ) * 100
print ("Weights:" )
print (weight)
print (" \n Prices:" )
print (prices)
Weights:
[0.3 0.7]
Prices:
[[87.79449977 83.37698779]
[92.15264547 62.64227629]
[84.50656971 12.76064219]
[52.21736541 40.81854528]
[12.84866796 56.65301195]]
# Element-by-element multiplication
print (weight * prices)
[[26.33834993 58.36389145]
[27.64579364 43.8495934 ]
[25.35197091 8.93244953]
[15.66520962 28.5729817 ]
[ 3.85460039 39.65710837]]
# Matrix multiplication
print (prices @ weight)
[84.70224139 71.49538705 34.28442044 44.23819132 43.51170875]
# Transpose and multiply
print (weight @ prices.T)
[84.70224139 71.49538705 34.28442044 44.23819132 43.51170875]
Source files — import and modules
Python code can be organised into modules (.py files) and imported:
# In my_helpers.py
def my_function():
return "Hello"
# In main script
from my_helpers import my_function
These notes keep common functions in common/functions.py, which you import when needed.
That is the Python material the rest of the book relies on. The Julia chapter that follows covers the same ground in Julia, so skip it unless you work in Julia. The book continues at Chapter 10 .