Your First Day at Jolly Associates
Congratulations on joining Jolly Associates as an Article Assistant. The firm has just been appointed as statutory auditors of Infosys Limited for FY 2023-24. Your Audit Senior, Kritika, wastes no time β "Here's the annual report. I need the key ratios computed, materiality determined, and a preliminary analytical review by end of day. And yes, we're going to do all of this in Python. Welcome aboard."
5-Layer Fraud Detection in 1 Second
Run this script that analyses 500 journal entries using Benford's Law, TDS compliance checks, suspicious narration scanning, statistical outlier detection, and structural red flags. By Session 4, you will build this yourself.
The Engagement Begins
Kritika hands you the Infosys Annual Report for FY 2023-24 and says β "First things first. Let's get the key numbers from the financial statements into Python. Think of variables as labelled boxes where you store data β just like how we label working paper files."
π Core Concept: Variables & Data Types
In Python, a variable stores a value you can use later. Python automatically determines the data type:
intβ Whole numbers (e.g., Revenue:153670)floatβ Decimals (e.g., EPS:63.38)strβ Text in quotes (e.g.,"Infosys Limited")boolβ Logical values:TrueorFalse
Key syntax in the code below:
#β Comments (ignored by Python, notes for humans)print()β Display output to screentype()β Check a variable's data type:type(revenue)β<class 'int'>f"..."β f-strings embed variables inside text:f"Revenue: {revenue}"{revenue:,}β Format with commas:153,670"=" * 50β String repetition: prints=fifty times\nβ Newline character inside strings for line breaks
Every financial figure you'll encounter during articleship β revenue, assets, liabilities, ratios β is just a number that can be stored in a variable. Instead of scribbling on paper or manually entering into Excel, you define it once in Python and use it everywhere.
βοΈ Exercise β Extend the Engagement File
Add the following Balance Sheet figures to the code above and print them in the same formatted style:
total_assets = 117281(βΉ Crores)total_equity = 78847(βΉ Crores)current_assets = 53633(βΉ Crores)current_liabilities = 32585(βΉ Crores)total_debt = 3428(βΉ Crores)
Also print the data type of total_assets to confirm it's an int.
π Challenge
Can you also add a variable working_capital calculated as current_assets - current_liabilities and print it? What data type do you think the result will be?
The Senior Needs Ratios β Now
Kritika checks her watch β "Good, the data is in. Now I need you to compute these 8 key financial ratios. CA KS Jolly wants them in the review meeting at 4 PM. And format them properly β two decimal places, with percentage signs. He's particular about presentation."
π Core Concept: Arithmetic Operators & Formatted Output
Arithmetic operators work just like a calculator:
+-*β Addition, subtraction, multiplication/β Division (always returns float, even10/2β5.0)//β Floor division (rounds down)%β Modulus (remainder)**β Powerround(value, dp)β Round todpdecimal places
Key syntax in the code below:
- Chained arithmetic:
net_profit / revenue * 100β Python follows BODMAS/PEMDAS order - Derived variables:
capital_employed = total_assets - current_liabilitiesβ build new values from existing ones f"NPM: {npm:.2f}%"β:.2f= 2 decimal places;:.4f= 4 decimal places{value:,.0f}β Comma separator with 0 decimals:1,537- All ratios use
/β results are alwaysfloat, which is why:.2fformatting is needed
Ratio analysis is the backbone of SA 520 (Analytical Procedures). Every CA computes these ratios during audit. Doing it manually in a calculator is tedious and error-prone. In Python, you define the formula once and it computes instantly β even for 100 companies.
βοΈ Exercise β Add More Ratios
Extend the report above to include:
- Operating Profit Margin =
ebit / revenue * 100 - Working Capital =
current_assets - current_liabilities - Proprietary Ratio =
total_equity / total_assets(shows what proportion of assets are funded by equity)
Format each to 2 decimal places with appropriate labels.
π Challenge β DuPont Decomposition
Compute the DuPont 3-factor ROE: ROE = NPM Γ Asset Turnover Γ Equity Multiplier, where Equity Multiplier = total_assets / total_equity. Print all 3 components and verify that their product equals the ROE you calculated directly. Do they match?
Five Years of Infosys
Kritika pulls up a comparative statement β "Single-year ratios are a start, but for SA 520 analytical procedures we need trend data. Here are Infosys's last 5 years of key figures. Store them and let's analyse the trends."
π Core Concept: Lists
A list is an ordered collection of values in square brackets []:
- Indexing:
revenue[0]β first item,revenue[-1]β last item - Slicing:
revenue[2:4]β items at index 2 and 3 (end excluded);years[-3:]β last 3 items
Key syntax in the code below:
max(revenue)/min(revenue)β Largest / smallest value in a listsum(revenue)β Total of all values;len(revenue)β Count of itemsrevenue.index(max(revenue))β Find the position of a value (used to match with the year)sum(revenue) // len(revenue)β Floor division for integer averagerevenue.copy()β Create an independent copy of a list.append(170000)β Add a new item to the end of a list{revenue[0]:,}β Format a list element with commas:90,791
Trend analysis requires storing multiple years of data. Lists are the natural structure for time-series financial data β revenue over 5 years, quarterly profits, monthly cash flows. Once data is in a list, Python can instantly find the best year, worst year, averages, and more.
βοΈ Exercise β Profit Trend Analysis
- Using the
net_profitlist, find and print the year with the highest net profit - Calculate the 5-year average net profit using
sum()andlen() - Create a new list
total_assets = [75973, 84124, 95015, 110888, 117281]and print the most recent 3 years' values - Use
sorted()to print the revenue list in ascending order (without modifying the original)
π Challenge β Net Profit Margin List
Can you compute the Net Profit Margin for each year? You'll need to divide each item in net_profit by the corresponding item in revenue. Hint: you might need a loop (covered next topic), but see if you can do it for just 2-3 years using indexing: npm_fy24 = net_profit[4] / revenue[4] * 100
Materiality Assessment
Kritika opens SA 320 (Materiality in Planning and Performing an Audit) β "Before we test any account, we need to determine materiality. There are multiple benchmarks, and we need to pick the right one based on the entity's characteristics. This is a decision-making problem β perfect for conditionals."
π Core Concept: Conditionals (if / elif / else)
Conditionals let Python make decisions β run different code based on a condition:
if condition:β Runs the indented block if condition is Trueelif another:β Checked only if theifabove was Falseelse:β Runs if nothing above was True
Key syntax in the code below:
- Comparison:
><>=<===(equals)!=(not equals) - Logical:
and(both must be True),or(either can be True) - Colon
:β Required after everyif/elif/else - Indentation β The 4-space indent defines what belongs inside each branch
min(a, b, c)β Selects the smallest benchmark (SA 320: conservative approach)abs(pbt_change)β Absolute value: ignores sign (β12.5 β 12.5){value:,.0f}β Comma-separated format with zero decimals
SA 320 requires auditors to determine materiality using benchmarks like % of revenue, % of PBT, or % of total assets β and then apply professional judgment to select the most appropriate one. Conditional logic in Python mirrors this exact decision process. You can also use it for audit sampling thresholds, risk categorization, and CARO reporting triggers.
βοΈ Exercise β CARO Reporting Check
Under CARO 2020, certain conditions trigger specific reporting. Write conditional logic for:
- If
total_debt > 0andde_ratio > 1.0, print "CARO Flag: High leverage β report under Clause 3(ix)" - If
current_ratio < 1.0, print "Going concern risk β consider SA 570" - Otherwise, print "No CARO flags triggered"
Test with Infosys data (total_debt = 3428, total_equity = 78847, current_ratio = 1.65).
π Challenge β Multi-Level Materiality
Create a function (or just use nested if) that takes any account_balance and classifies it into 5 levels: "Highly Material" (>2Γ materiality), "Material", "Significant", "Insignificant" (>trivial but
Analytical Review Loop
Kritika looks at your ratio calculations β "Nice work for FY24. But SA 520 requires us to look at trends over multiple periods. Computing YoY growth for each year manually? That's what loops are for. Write it once, and Python processes every year automatically."
π Core Concept: For Loops
A for loop repeats code for each item in a sequence β no copy-paste needed:
for i in range(len(revenue)):β Loop by index (access[i]and[i-1])range(len(revenue))β Generates 0, 1, 2, 3, 4 for a 5-item list
Key syntax in the code below:
growth_rates = []then.append(growth)β Build a new list inside a loop (accumulator pattern)if i == 0:inside loop β Handle the base year differently (no prior year to compare)enumerate(years)β Gives both indexiand valueyearin one loopf"{years[i]:<14}"β Left-align text to 14 chars;{revenue[i]:>10,}β Right-align to 10 with commas{growth:>9.1f}%β Right-align, 1 decimal place"β" * int(npm)β Visual bar chart using string repetitionsum(growth_rates)/len(growth_rates)β Average of the accumulated list
Analytical procedures under SA 520 require comparing data across periods to identify unusual trends. A loop lets you compute YoY changes, growth rates, and variance flags for every account, every year β instantly. What takes 30 minutes of Excel formulas takes 5 lines of Python.
βοΈ Exercise β Total Assets Growth + Flags
Using the data total_assets = [75973, 84124, 95015, 110888, 117281]:
- Write a loop to compute and print YoY growth for total assets (same format as revenue above)
- Flag any year where asset growth exceeds 15% with "β οΈ Significant increase β investigate per SA 315"
- After the loop, print the average annual asset growth rate
π Challenge β Ratio Trend Table
Using both revenue and net_profit lists, compute and print a complete table showing NPM, and year-on-year change in NPM (in percentage points) for all 5 years. Flag any year where NPM dropped by more than 1 percentage point.
Analytical Memo Generator
Kritika looks at the clock β "CA KS Jolly's review meeting is in 30 minutes. I need a complete Preliminary Analytical Review Memo β 5-year trends, ratios, YoY changes, and anomaly flags. Let's combine everything we've learned into one deliverable. This is what goes into the audit file."
βοΈ Exercise β Enhance the Memo
Add a new section to the memo β "5. CURRENT RATIO TREND" β that loops through all 5 years, computes the Current Ratio for each year, and flags any year where it drops below 1.5. Also add a section showing the Working Capital trend (Current Assets - Current Liabilities) for all 5 years.
π Challenge β Complete Analytical Review
Add sections for: (a) Asset Turnover trend (Revenue / Total Assets for each year), (b) ROE trend for all 5 years, (c) A "Conclusion" section that counts total anomalies and prints a final risk assessment: "High Risk" if >3 anomalies, "Moderate Risk" if 1-3, "Low Risk" if 0. Make the memo partner-review ready!
π Test Your Knowledge
15 questions covering Python fundamentals applied to financial analysis. You need at least 60% (9/15) to pass. Take your time β check the code editors above if you need to.