Python Basics Sep 11 2025
Python Basics Sep 11 2025
by Dr. K. S. Parmar
Mea
ning
Na /
m Ty Exa
e pe mple Ordering Mutability
Int int -20, NA NA
eg 100,
ers 950
Fl flo - NA NA
oa at 20.0,
ts 100.
55,
950.
75
Bo bo Logic NA NA
ole ol al
an value
s indic
ating
True
or
False
Str str A Ordered Sequence Immutable
ing sequ
s ence
("Hel
lo",
"100
Mea
ning
Na /
m Ty Exa
e pe mple Ordering Mutability
0")
Lis list Sequ Ordered Sequence Mutable
ts ence
of
Obje
cts,
[10,
10.5,
"Hell
o",
10]
Di dic Unor Unordered Collection Mutable
cti t eder
on d
ari map
es ping
of
obje
cts,
{"Ke
y":
Valu
e}
Pairs
Tu tu Sequ Ordered Sequence Immutable
ple ple ence
s of
Obje
cts,
(20,
20.5
1,
"Hell
o")
Se set Colle Unordered Collection Mutable
ts ction
of
Uniq
ue
Obje
cts,
{"a",
Mea
ning
Na /
m Ty Exa
e pe mple Ordering Mutability
"b",
"10"}
_____________________________________________________________
3. Booleans: A boolean value is either True or False. Variables with boolean values are
often used to keep track of certain conditions within a program
5. Lists: A list stores a series of items in a particuar order. Index or loop can be used to
access them. Unlike strtings, mutation is possible through indexation
7. Tuples: Tuples are similar to lists, but the items in a tuple can't be modified, that is
like strings, they are immutable. These are in brackets
# this is a comm
print ('Hello World!')
Hello World!
"Hello"
pwd
'C:\\Users\\Kanaiyalal Parmar'
95*10
15/8
15 % 2
100 % 10
5**5
5+3 * 2 -1
(5+3) * 2 -1
0.1+0.2-0.3
Assignment Vs Equality
6 == 5
False
diksha_jogi[2]
'BMS'
type(diksha_jogi)
list
diksha_jogi.append(5)
diksha_jogi
diksha_jogi1
diksha_jogi2["Grad"]
'BMS'
diksha_jogi2.keys()
Variable Assignment
• Can not start with a number
• No spaces in the name, use _ instead
• No special characters
• PEP8 (Python Enhancement Proposal) suggests to use names in lower case
• Avoid using reserved words, highlighted in different color
type(sales)
sales
sales = 4
sales
sales + sales
Python also allows the reassignment with reference to the same object
sales
sales
Calculate Income tax, if tax rate is 30% and income is 5000000
Calculate FV if PV = 1000, IR = 9% and t = 5 years
Calculate PV if FV = 10000, IR = 8.5% and t = 10 years
my_income = 5000000
tax_rate = 0.3
my_tax = my_income * tax_rate
my_tax
pv = 1000
ir = 0.09
t = 5
fv = pv * (1+ir)**t
fv
fv1 = 10000
ir1 = 0.085
t1 = 10
pv1 = fv1 / (1+ir1)**t1
pv1
• .format method
• f method
"hello"
"hello 1"
"hello 2"
The above code returns only the second line, therefore print command is used which will not
show output but show the result
print("hello 1")
print ("hello 2")
Escape Sequence: backslash is an escape sequence, n stands for new line, t stands
for tab
print("hello world")
print("hello \nworld")
print("hello \nworld")
print("Hello World")
print("hello \tworld")
print("hello \tworld")
Length function
len("hello")
len("I am")
mystring
Indexing and Slicing
• White or blank space in a string is counted as a character
mystring[0]
mystring[5]
mystring[-1]
mystring[-2]
mystring = "abcdefghijklmn"
mystring
Slicing Syntax
[start:stop:step]
mystring[4:]
mystring[2:8]
mystring[4:5]
mystring[4:8]
mystring[:4]
mystring[:-5]
mystring[-5:]
mystring[-5:-1]
mystring[:]
mystring[::]
mystring[::3]
mystring[2::3]
mystring[2:9:2]
Reverse string
mystring[::-1]
mystring[::-2]
mystring[::-4]
mystring[-3::-1]
"Hello World" [-3]
Immutability
• Immutability of strings means that we can not change letters or individual elements from
string using indexing.
name
#To change name to TATAMOTORS, we can not use the following code
name[4:9] = "MOTORS"
name
# Instead we need to concatenate or merge
first_letters = name[:4]
first_letters
name
X = "Is TATAMOTRS"
Y = X + " undervalued?"
print(X)
print(Y)
X = "Is TATAMOTORS"
X = X + " undervalued?"
A = "No."
A
A
letter = "TATAMOTORS"
letter * 10
5 + 7
"5" + "7"
String Methods: Methods are functions that are inside the python objects
• .upper
• .lower
x = "Hello World"
x
Hit tab after x. to see a list of methods available on this string object
Hit shift tab in parenthesis to see docstring
x.upper()
x1 = x.upper()
x1
x.lower
x.lower()
x = x.lower()
x
x.split()
len(x)
x.split()
x.split('Y')
X = "This is a string"
Y = " INSERTED"
X+Y
print(X+Y)
result
f string method
name = "Spoorthi"
name
name = "Deepak"
age = 7
# Concatenating strings
stock_info = company_name + " (" + ticker_symbol + ") is trading at $"
+ str(price)
print(stock_info)
Practice Exercise:
Slice the first three letters of a company name.
Slice the last three characters of a stock ticker.
Extract the middle part of a string and print it.
# Convert to uppercase
ticker_upper = ticker.upper()
print(f"Uppercase ticker: {ticker_upper}")
ticker_upper
Practice Exercise:
Convert a stock ticker to uppercase.
Replace spaces in company names with underscores for a URL-friendly format.
Split the company name into individual words and print each.
# Company description
company_description = "Apple Inc. is a leading tech company. Inc.
represents incorporation."
Practice Exercise:
Search for a specific word (like "Corporation" or "Inc.") in a company description.
Count how many times a certain word appears in a text.
Practice Exercise:
Format stock prices to two decimal places and print them in a sentence.
Format large numbers (like trading volume) with commas and include them in a formatted
string.
Practice Exercise:
Split a string containing stock data into its components (ticker, price, volume).
Join the split components back into a single string.
stocks
len(stocks)
type(stocks)
list
Indexing, slicing and concatenating of lists works just like strings
stocks[1]
'REL'
stocks[1:]
['REL', 'TS']
stocks + anotherstocks
stocks
anotherstocks
newstocks
newstocks
newstocks.append(7)
newstocks
##### To remove an item, use pop, which pops out last item in parenthesis is empty
newstocks.pop()
7
newstocks
newstocks.count("TS")
newstocks.pop(2)
'TS'
newstocks
newstocks.sort()
newstocks
pwd
'C:\\Users\\Kanaiyalal Parmar'
newstocks.reverse()
newstocks
closing_prices[4]
Dictionaries
These are unordered mapping of objects allowing users to get the objects without
knowing index locations. These can not be sorted
Syntax: {"key1":value1,"key2":value2}
Dictionaries Vs Lists
my_dict = {'reliance': 2500,
'BPCL': 400,
'PFC': 200}
my_dict["BPCL"]
400
my_dict["BPCL"]
my_dict["BPCL"][2]
402
my_dict["MCX"]
my_dict["MCX"]["Gold"]
my_dict["MCX"]["Gold"] = 101500
my_dict
{'reliance': 2500,
'BPCL': [401, 'BSE', 402, 'NSE'],
'PFC': 200,
'MCX': {'Gold': 101500, 'Silver': 90000}}
Overwrite
my_dict["TM"]=650
my_dict
my_dict.values()
my_dict.items()
Practice Exercise:
Create a dictionary to store stock data like ticker, price, and volume.
Access and print individual dictionary values (e.g., the price).
Modify the stock price and print the updated value.
Tuples
t = (1,2,3)
t
(1, 2, 3)
type(t)
tuple
len(t)
#Overwrite
t = ("one", 2)
('one', 2)
t[0]
'one'
t[-1]
t.count("a")
t.index("a")
t.index("b")
Unlike Lists, Tuples are immutable in the sense that once an element is assigned to
an index position inside of a tuple, we can not grab that element and reassign it to
something else.
t
mylist
[1, 2, 3]
mylist[0] = "New"
mylist
['New', 2, 3]
t[0] = "New"
----------------------------------------------------------------------
-----
TypeError Traceback (most recent call
last)
Cell In[39], line 1
----> 1 t[0] = "New"
Practice:
Create tuples for three Indian stocks (ticker, price) and print the details.
myset
{2, '2', 9}
myset.add(10)
myset
{10, 2, '2', 9}
myset.add(2)
myset
{10, 2, '2', 9}
mylist = [7,7,7,1,1,1,1,2,2,2,2,5,5,5,5]
mylist
[7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5]
set = {7,7,7,7,1,1,1,1,10}
set
{1, 7, 10}
Practice Exercise:
Create two sets representing portfolios of different stocks.
Find and print the common stocks in both portfolios.
----------------------------------------------------------------------
-----
NameError Traceback (most recent call
last)
Cell In[215], line 1
----> 1 b
b = None
type(b)
NoneType
True
False
False
type(True)
bool
1>2
False
10 == 10
True
5 == 7
False
"Bye" == "bye"
False
"Bye" == "Bye"
True
2.0 == 2
Use != to represent inequality
7!=7
False
9!=10
True
2>1
True
1<0
False
2>=1
True
7>=8
False
7>=6
True
1 < 2 > 3
False
Logical Operators:
• and
• or
• not
1 < 2 and 2 > 3
False
1 < 2 or 2 > 3
True
True
To make the above code readable () can be used
("h" == "h") and (2 == 2)
True
1 == 1 and 2 != 22
10000 == 1 or 2 == 2
10000 == 1 or 2 == 2000
1 == 1
not (1==1)
not 1==10
True
Practice Exercise:
Create two variables representing today’s and yesterday’s stock prices.
Use a boolean expression to check if the price has increased and print the result.
Python Statements
if, else statements
• Keywords are if, elif, else
• Indentation is important
• Syntax:
if some_condition:
execute some code
else:
execute some another code
if True:
print("Its crect")
Its crect
if False:
print("Its crect")
if False:
print("Its true!")
else:
print ("Its wrong!")
Its wrong!
5>4
True
if 5>4:
print("BUY!")
BUY!
if 55<22:
print("its true!")
else:
print("pagal hai kya?")
x = 25
if 4<x:
print ("True")
True
x = 22
if 44<x:
print (True)
else:
print ("Fals")
Fals
x = 25
y = 25
if x>y:
print ("x is higher")
elif x < y:
print ("y is higher")
else:
print ("both are equal")
rm = 0.15
b = 1.5
rf = 0.07
er = 0.2
rrr = rf + b * (rm-rf)
rrr
0.19
er = 0.19
if er > rrr:
print("undervalued and BUY")
elif er < rrr:
print ("overvalued and SELL")
else :
print ("properly valued and NO TRADE")
pat = 4
equity = 100
if pat / equity <0:
print("Loss making firm")
elif pat / equity == 0:
print("BEP firm")
elif pat / equity > 0 and pat / equity < 0.08:
print("Low profit making firm")
elif pat / equity == 0.08 or pat / equity < 0.15:
print("Moderately profit making firm")
else:
print("High profit making firm")
if search_ticker in stock_tickers:
print(f"{search_ticker} is in the list of tickers.")
else:
print(f"{search_ticker} is not in the list of tickers.")
for loop
• Many objects in python are iterable
• As an example, we can iterate through lists, strings or dictionaries etc
Syntax
my_iterable = [1,2,3,4,5]
• item_name is a variable name you can choose which is a placeholder for each item in the
iterable object
• In this case, the item name represents the numbers of the list, 1,2,3,4 and 5
• for and in are keywords
for i in cashflow:
print(i)
100
10
20
50
30
25
for e in cashflow:
print(e)
for _ in cashflow:
print(_)
count = 0
for i in cashflow:
# count = count + 1
count +=1
print(count)
total = 0
for i in cashflow:
total +=i
print(total)
235
count = 0
for i in cashflow:
count +=1
print(count)
total = 0
for i in cashflow:
total += i
print(total)
total = 0
for i in cf:
total += i
print(total)
sum(cashflow)
mylist = [(1,2),(3,4),(5,6),(7,8)]
len(mylist)
mylist = [(1,2,3),(4,5,6),(7,8,9)]
for item in d:
print(item)
#### for loop mixed with a math operation and f string literals
while loop
• while loop will continue to execute a code while some condition is true
• for example, while my profit is less than Rs. 1lac, continue to trade
• or while the market is on, continue to trade
Syntax
while some_condition:
do something
else:
do something different
x = 0
while x<6: # while True, run it for eg. 5<6 for infinite loop
print (f"The current value of x is {x}")
x = x + 1
# instead of above, we can also write: x +=1
x = 0
while x<5:
print (f"The current value of x is {x}")
x = x + 1
# instead of above, we can also write: x +=1
x = 0
while x <5:
x +=1
print (f"The current value of x is {x}")
x = 0
while x<5:
print (f"The current value of x is {x}")
x +=1
else:
print ("X is not less than 5")
x = 50
while x<5:
print (f"The current value of x is {x}")
x +=1
else:
print ("X is not less than 5")
x = [1,2,3]
for item in x:
pass
#comment
x = [1,2,3]
for item in x:
# I will complete the code once I get the data
pass
print("Hello")
Hello
x = [1,2,3]
for item in x:
#comment
pass
print(nifty50)
print(stocks)
ADA
AD
AP
AS
BA
BAJF
# To stop printing from AXISBANK onwards, use break
for stocks in nifty50:
if stocks == "AXISBANK":
break
print(stocks)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(range(0,1000000,100000))
Enumerate Function:
To understand enumerate function, lets do the following excercise
index_count = 0
for letter in "abcde":
index_count +=1
print(index_count)
index_count = 0
a = "abcde"
for letter in a:
index_count +=1
print(index_count)
index_count = 0
for let in "abcde":
print("At index {} the letter is {}".format(index_count,let))
index_count +=1
(0, 'a')
(1, 'b')
(2, 'c')
(3, 'd')
(4, 'e')
Random library
from random import shuffle
mylist = [1,2,3,4,5,6,7,8,9]
See docstring
shuffle(mylist)
mylist
randint(600,700)
mynum = randint(0,100)
mynum
fa.
import random
ran_int = [random.randint(0,100)
for _ in range(20)]
ran_int
[68, 97, 71, 20, 72, 74, 3, 47, 99, 45, 11, 85, 40, 65, 20, 81, 40,
25, 24, 98]
# import random
ran_int
ran_fl = [round(random.uniform(4,8), 2)
for _ in range(10)]
ran_fl
The above help is also available by typing shifttab with a curser at the end of insert
For more documentation:
https://docs.python.org/3.11/
Importantly, explore librarary and tutorial references among other things in the
above link
Parameters:
rp : float - security / portfolio return
rm : float - market return
rf : float - risk-free rate
b : float - portfolio beta
Returns:
alpha : float
Jensen's Alpha
signal : str
Trading decision (BUY/SELL/HOLD)
"""
exp_ret = rf + b * (rm - rf) # CAPM expected return
alpha = rp - exp_ret # Jensen's alpha
# Trading decision
if alpha > 0:
signal = "BUY (Alpha > 0)"
elif alpha < 0:
signal = "SELL (Alpha < 0)"
else:
signal = "HOLD (Alpha = 0)"
# Print results
print("Jensen's Alpha:", round(alpha, 4))
print("Decision:", signal)
j_alpha()
rp = 0.12
rm = 0.12
rf = 0.07
b = 1.25
import finlatics as fa
144.35337051738043
fa.implied_volatility(S0 = 24530, X = 25500, T = 8/365, r = 0.12,
market_price = 155,
option_type='call',
tol=1e-05,
max_iterations=100,)
def say_hello():
"This is docstring which can be used to explain a function"
print("hello")
print("how are")
print("you?")
say_hello()
hello
how are
you?
say_hello ()
say_hello ("Arya")
Hello Arya
say_hello()
Hello Default
say_hello()
Hello Default
say_hello ("Kartik")
Hello Kartik
If we forget to passin the parameter (put a name), it will show an error, to avoid the
error,
def say_hello(name = "Default"):
print(f"Hi {name}")
say_hello ()
Hi Default
say_hello ("KP")
mult_num(5, 5,10)
250
add_num(234,345)
579
res = mult_num(100,2000,2)
res
type(res)
def print_result(a,b):
print(a+b)
def return_result(a,b):
return a+b
30
result
type(result)
NoneType
result1
type(result1)
def sum_numbers(num1,num2):
return num1+num2
sum_numbers(10,20)
sum_numbers("10","20")
sp = 100
cp = 100
if sp>cp:
print(f'Profit of ₹ {sp-cp}')
elif sp < cp:
print(f"Loss of ₹ {cp-sp}")
else:
print(f"No Profit, No Loss")
def porl(sp,cp):
"""
Calculate Profit or Loss using if statement
if SP > CP then it should print "Profit of ₹..."
if SP < CP then it should print "Loss of ₹..."
if SP = CP then it should print "No Profit, No Loss"
"""
if sp>cp:
print(f'Profit of ₹ {sp-cp}')
elif sp < cp:
print(f"Loss of ₹ {cp-sp}")
else:
print(f"No Profit, No Loss")
Profit of ₹ 60441996688
mylist = [1,2,3]
porl()
def porl(sp,cp):
"""if SP > CP then it should print "Profit of ₹..."
if SP < CP then it should print "Loss of ₹..."
if SP = CP then it should print "No Profit, No Loss"""
if sp>cp:
print(f"Profit of ₹ {sp-cp}")
elif sp<cp:
print(f"Loss of ₹ {cp-sp}")
else:
print("No Profit, No Loss")
porl(2376259086205,2309690257625)
sp = 100
cp = 100
if sp>cp:
print(f'Profit of ₹ {sp-cp}')
elif sp < cp:
print(f"Loss of ₹ {cp-sp}")
else:
print(f"No Profit, No Loss")
No Profit, No Loss
def porl(sp,cp):
"""Calculate Profit or Loss using if statement
if SP > CP then it should print "Profit of ₹..."
if SP < CP then it should print "Loss of ₹..."
if SP = CP then it should print "No Profit, No Loss"""
if sp>cp:
print(f'Profit of ₹ {sp-cp}')
elif sp < cp:
print(f"Loss of ₹ {cp-sp}")
else:
print(f"No Profit, No Loss")
porl(2314,1314)
porl
def porl(sp,cp):
porl(234572389467589, 923848123570349)
Loss of 689275734102760
selling_price = 25
cost_price = 25
if selling_price>cost_price:
print (f"Profit of ₹ {selling_price - cost_price}")
elif selling_price<cost_price:
print(f"Loss of ₹ {cost_price - selling_price}")
else:
print ("No Profit, No Loss")
# Example usage
print(calculate_profit_or_loss(100, 120)) # Profit
PorL
Returns:
float: The calculated NPV.
"""
pwd
# Example usage
cash_flows = [-100000, 200232, 3003, 400, 500, 700,
200,324,4135,324534,5234,5234,5234,534,534]
discount_rate = 0.18 # 10% discount rate
149776.63847691353
Parameters:
cash_flows (list): List of cash flows where the first element is
the initial investment.
discount_rate (float): The discount rate as a decimal (e.g., 0.10
for 10%).
Returns:
float: The calculated NPV.
"""
npv = sum(cf / (1 + discount_rate) ** t for t, cf in
enumerate(cash_flows))
return npv
# Calculate NPV
npv = calculate_npv(cash_flows, discount_rate)
#npv
# Print the NPV
print(f"The calculated NPV @ {discount_rate*100}% Discount Rate is ₹
{npv:.2f}")
Calculate Mean using a function
def mean(data):
"""
Calculate the arithmetic mean.
Formula: sum(x) / n
Data: List of floats or integers
"""
n = len(data)
return sum(data) / n
mean(data = [2134,12341,543,5])
3755.75
Project
import math
def std2(data):
"""Calculate the sample standard deviation.
Data: List of floats or integers"""
n = len(data)
if n < 2:
return None
# Step 1: compute mean
n = len(data)
m = sum(data) / n
# Step 2: compute squared deviations
sq_diff_sum = 0
for val in data:
sq_diff_sum += (val - m) ** 2
variance = sq_diff_sum / (n - 1)
return math.sqrt(variance)
std21
22767.424140644456
type(std21)
float
std21.
import math
def std(data):
"""
Calculate the sample standard deviation.
Formula: sqrt( Σ (x - mean)^2 / (n-1) )
Data: List of floats or integers
"""
n = len(data)
if n < 2:
return None
std([234,345,345, 0.001,625,625])
239.30872365489176
import math
def std1(data):
"""
Calculate the sample standard deviation.
Formula: sqrt( Σ (x - mean)^2 / (n-1) )
data: List of floats or integers
"""
n = len(data)
if n < 2:
return None
m = sum(data) / n
variance = sum((x - m) ** 2 for x in data) / (n - 1)
return math.sqrt(variance)
std1([234,345,345, 0.00001,625,625])
239.30872365489174
3
8
11
def total_dividends(dividends):
"""
Calculate the total sum of dividends received.
"""
total = 0
for div in dividends:
total += div
return total
total_dividends([3245,456,5367,567,458,5678,67,456,356,35636356,356,36
7])
35653729
# Example usage
divids = [2.5, 3.0, 2.8, 3.5, 50.5, 100, 150]
div = total_dividends(divids)
#div
print(f"Total Dividend = {div}")
DDM
def three_stage_ddm(d0, g1, n1, g2, n2, g3, r1, r2, r3):
"""
Three-stage Dividend Discount Model (concise).
Stages:
- Stage 1: dividend grows at g1 for n1 years
- Stage 2: dividend grows at g2 for n2 years
- Stage 3: perpetual growth at g3 thereafter (Gordon growth)
Inputs (decimals):
d0 : last dividend just paid (D0)
g1 : growth in stage 1, years 1..n1
n1 : years in stage 1 (int >= 0)
g2 : growth in stage 2, years n1+1..n1+n2
n2 : years in stage 2 (int >= 0)
g3 : perpetual growth in stage 3 (must be < r)
r : required return (cost of equity)
Returns:
Intrinsic value (float): PV of all explicit dividends + PV of
terminal value
Notes:
- Requires r > g3 and (n1 + n2) >= 1
"""
if r1 <= g1:
raise ValueError("r1 must be greater than g2 for the terminal
leg.")
if r2 <= g2:
raise ValueError("r2 must be greater than g2 for the terminal
leg.")
if r3 <= g3:
raise ValueError("r3 must be greater than g3 for the terminal
leg.")
N = n1 + n2
if N < 1:
raise ValueError("Total forecast years (n1 + n2) must be at
least 1.")
div = d0
pv = 0.0
# Inputs:
# D0 = 5.00
# Stage 1: g1=12% for n1=3 years
# Stage 2: g2=7% for n2=2 years
# Stage 3: g3=4% perpetual
# r = 10%
110.13
# Example usage
calculate_emi(10000000, 10, 25) # Output: EMI for the given
parameters
'EMI: ₹90870.07'
# Example usage
print(classify_investment(18)) # High Growth Investment
print(classify_investment(12)) # Moderate Growth Investment
print(classify_investment(8)) # Low Growth Investment
print(classify_investment(3)) # Unprofitable Investment
# Example usage
print(years_to_double_investment(10000, 9))
myfunc(900,100,500)
150.0
myfunc(400,200,400)
*args
which is an arbitrary word, which creates a tuple of values
def myfunc(*args):
print(args)
return sum(args)* 0.1
myfunc(55,550,200,100,150,25,35,500)
161.5
1300
def stock_info(**kwargs):
#print(kwargs)
if "stock_name" in kwargs:
print (f"Stock: {kwargs["stock_name"]}")
if "sector" in kwargs:
print(f"Sector: {kwargs['sector']}")
if 'market_cap' in kwargs:
print(f"Market Cap: {kwargs['market_cap']}")
if 'pe_ratio' in kwargs:
print(f"P/E Ratio: {kwargs['pe_ratio']}")
if "ps_ratio" in kwargs:
print(f"P/S Ratio: {kwargs['ps_ratio']}")
# Example Usage
stock_info(stock_name = "Reliance Industries", sector="Energy",
market_cap="₹16.2 Trillion",
pe_ratio=30.5, ps_ratio = 14.5)
stu_present
type(stu_present)
list
type(list)
type
#.tab
stu_present.
• Functions are not enough for automation when you scale-up the Python sripts and do
more meaningful work
• Commonly repeated tasks and objects can be defined with OOP to create code that is
more usable
• OOP allows you to create your own objects that have methods and attributes
• Recall that after defining a variable or datatype; or after creating instance of the objects,
like; list, string, dictionary etc. you were able to call methods with the .method_name()
or .function_name syntax
• These methods act as functions which use information about the object you create to
return results, or edit the object, for example, .sort, .upper methods
Syntax
class NameOfClass():
def _init_(self,param1,param2):
self.param1 = param1
self.param2 = param2
my_sample = Smpl()
type(my_sample)
If you ask for type of a class called Smpl, it just returns type (datatype) as no instance is created
yet
type(Smpl)
my_sample.
# Creating class with attributes
# ind as a parameter
class Company():
def __init__(self,ind):
self.industry = ind
mycompany.industry
type(Company)
type(mycompany)
mycom.industry
# mycom.attribute
class Company():
def __init__(self, industry, name, profit):
#init is construction for
self.industry = industry
self.name = name
class Company():
def __init__(self, industry, name, profit):
self.industry = industry
self.name = name
self.profit = profit
mycomp.name
mycomp.profit
class Company():
def __init__(self, industry, name, profit):
#init is construction for
self.industry = industry
self.name = name
# Expect boolean True / False
self.profit = profit
def porl(self,rev,cost):
print(f"Profit = {rev-cost}")
myco.porl(832454,693234)
class Company():
""" This class / object is created for company analysis"""
def __init__(self, industry, name, profit):
""" This is dunder init method to add attributes"""
#init is construction for
self.industry = industry
self.name = name
# Expect boolean True / False
self.profit = profit
def porl(self,sp,cp):
mycomp.porl(10,10)
Prompt Engineering
class Company():
""" This class / object is created for company analysis"""
def __init__(self, industry, name, profit):
""" This is dunder init method"""
self.industry = industry
self.name = name
# Expect boolean True / False
self.profit = profit
def porl(self,sp,cp):
# Trading decision
if alpha > 0:
signal = "BUY (Alpha > 0)"
elif alpha < 0:
signal = "SELL (Alpha < 0)"
else:
signal = "HOLD (Alpha = 0)"
# Print results
print("Jensen's Alpha:", round(alpha, 4))
print("Decision:", signal)
class Company():
""" This class / object is created for company analysis"""
def __init__(self, industry, name, profit):
""" This is dunder init method"""
self.industry = industry
self.name = name
# Expect boolean True / False
self.profit = profit
def porl(self,sp,cp):
Parameters:
rp : float - security / portfolio return
rm : float - market return
rf : float - risk-free rate
b : float - portfolio beta
Returns:
alpha : float
Jensen's Alpha
signal : str
Trading decision (BUY/SELL/HOLD)
"""
exp_ret = rf + b * (rm - rf) # CAPM expected return
alpha = rp - exp_ret # Jensen's alpha
# Trading decision
if alpha > 0:
signal = "BUY (Alpha > 0)"
elif alpha < 0:
signal = "SELL (Alpha < 0)"
else:
signal = "HOLD (Alpha = 0)"
# Print results
print("Jensen's Alpha:", round(alpha, 4))
print("Decision:", signal)
Parameters:
cash_flows (list): List of cash flows where the first element
is the initial investment.
discount_rate (float): The discount rate as a decimal (e.g.,
0.10 for 10%).
Returns:
float: The calculated NPV.
"""
npv = sum(cf / (1 + discount_rate) ** t for t, cf in
enumerate(cash_flows))
return round(npv,2)
myco1.calculate_npv([-100,25,40,60,100,10], 0.20)
class Company():
def __init__(self, industry, name, profit):
#init is construction for
self.industry = industry
self.name = name
# Expect boolean True / False
self.profit = profit
def porl(self,sp,cp):
Parameters:
rp : float - security / portfolio return
rm : float - market return
rf : float - risk-free rate
b : float - portfolio beta
Returns:
alpha : float
Jensen's Alpha
signal : str
Trading decision (BUY/SELL/HOLD)
"""
exp_ret = rf + b * (rm - rf) # CAPM expected return
alpha = rp - exp_ret # Jensen's alpha
# Trading decision
if alpha > 0:
signal = "BUY (Alpha > 0)"
elif alpha < 0:
signal = "SELL (Alpha < 0)"
else:
signal = "HOLD (Alpha = 0)"
# Print results
print("Jensen's Alpha:", round(alpha, 4))
print("Decision:", signal)
Parameters:
cash_flows (list): List of cash flows where the first element
is the initial investment.
discount_rate (float): The discount rate as a decimal (e.g.,
0.10 for 10%).
Returns:
float: The calculated NPV.
"""
npv = sum(cf / (1 + discount_rate) ** t for t, cf in
enumerate(cash_flows))
return round(npv,2)
def three_stage_ddm(self, d0, g1, n1, g2, n2, g3, r1, r2, r3):
"""
Three-stage Dividend Discount Model (concise).
Stages:
- Stage 1: dividend grows at g1 for n1 years
- Stage 2: dividend grows at g2 for n2 years
- Stage 3: perpetual growth at g3 thereafter (Gordon growth)
Inputs (decimals):
d0 : last dividend just paid (D0)
g1 : growth in stage 1, years 1..n1
n1 : years in stage 1 (int >= 0)
g2 : growth in stage 2, years n1+1..n1+n2
n2 : years in stage 2 (int >= 0)
g3 : perpetual growth in stage 3 (must be < r)
r : required return (cost of equity)
Returns:
Intrinsic value (float): PV of all explicit dividends + PV
of terminal value
Notes:
- Requires r > g3 and (n1 + n2) >= 1
"""
if r1 <= g1:
raise ValueError("r1 must be greater than g2 for the
terminal leg.")
if r2 <= g2:
raise ValueError("r2 must be greater than g2 for the
terminal leg.")
if r3 <= g3:
raise ValueError("r3 must be greater than g3 for the
terminal leg.")
N = n1 + n2
if N < 1:
raise ValueError("Total forecast years (n1 + n2) must be
at least 1.")
div = d0
pv = 0.0
mycom1.calculate_npv([-10000,3000,5000,7000], 0.16)
mycom1.calculate_npv([-1000,300,400,800],0.1)
class Company():
def __init__(self, industry, name, profit):
#init is construction for
self.industry = industry
self.name = name
# Expect boolean True / False
self.profit = profit
def porl(self,sales,cost):
print(f"Profit = {sales-cost}")
Parameters:
cash_flows (list): List of cash flows where the first element
is the initial investment.
discount_rate (float): The discount rate as a decimal (e.g.,
0.10 for 10%).
Returns:
float: The calculated NPV.
"""
npv = sum(cf / (1 + discount_rate) ** t for t, cf in
enumerate(cash_flows))
return npv
def three_stage_ddm(self, d0, g1, n1, g2, n2, g3, r1, r2, r3):
"""
Three-stage Dividend Discount Model (concise).
Stages:
- Stage 1: dividend grows at g1 for n1 years
- Stage 2: dividend grows at g2 for n2 years
- Stage 3: perpetual growth at g3 thereafter (Gordon growth)
Inputs (decimals):
d0 : last dividend just paid (D0)
g1 : growth in stage 1, years 1..n1
n1 : years in stage 1 (int >= 0)
g2 : growth in stage 2, years n1+1..n1+n2
n2 : years in stage 2 (int >= 0)
g3 : perpetual growth in stage 3 (must be < r)
r1 : required return (cost of equity) during stage 1
r2 : required return (cost of equity) during stage 2
r3 : required return (cost of equity) during stage 3
Returns:
Intrinsic value (float): PV of all explicit dividends + PV
of terminal value
Notes:
- Requires r > g3 and (n1 + n2) >= 1
"""
if r1 <= g1:
raise ValueError("r1 must be greater than g2 for the
terminal leg.")
if r2 <= g2:
raise ValueError("r2 must be greater than g2 for the
terminal leg.")
if r3 <= g3:
raise ValueError("r3 must be greater than g3 for the
terminal leg.")
N = n1 + n2
if N < 1:
raise ValueError("Total forecast years (n1 + n2) must be
at least 1.")
div = d0
pv = 0.0
def ddm_three_stage_taper(d0, g1, n1, g2_start, g2_end, n2, g3, r1, r2, r3): """ Three-stage DDM
with linear taper in Stage-2 and different discount rates per stage.
Constraints:
- n1 + n2 >= 1
- r3 > g3 (only perpetual leg needs this)
- r1, r2, r3 > -1 and g1, g2_start, g2_end, g3 > -1 (to keep 1+r
and 1+g positive)
"""
N = n1 + n2
if N < 1: raise ValueError("n1 + n2 must be >= 1.")
if r3 <= g3: raise ValueError("Require r3 > g3 for the terminal leg.")
if min(r1, r2, r3) <= -1: raise ValueError("All discount rates must be
> -1.")
if min(g1, g2_start, g2_end, g3) <= -1: raise ValueError("All growth
rates must be > -1.")
if d0 < 0: raise ValueError("d0 must be non-negative.")
class BasicStats:
"""
Minimal class for basic statistics and z-based inference (intro
MBA analytics).
Only __init__ is used as a dunder; all other capabilities are
plain methods.
What it provides
----------------
Descriptives:
mean(xs), sample_variance(xs), sample_sd(xs)
Distribution helpers:
phi(z) : standard normal CDF via math.erf
z_crit(conf) : two-sided critical values for {0.90, 0.95,
0.99}
Hypothesis tests:
one_sample_mean_ztest(data, mu0, alternative)
two_sample_mean_ztest(a, b, alternative) # Welch-style SE
one_sample_prop_ztest(successes, n, p0, alternative)
two_sample_prop_ztest(s1, n1, s2, n2, alternative)
Confidence intervals:
ci_mean(data, confidence) # z-based
ci_proportion(successes, n, confidence,
method='wilson'|'wald')
Notes
-----
- z-based methods are exact if population sigma is known;
otherwise good for large n.
- For small samples with unknown sigma, use t criticals from a
table (same formulas with t*).
"""
def __init__(self):
# store constants, lookups, and small helpers as attributes
(added only via __init__)
self.Z_TWO_SIDED = {0.90: 1.6448536269514722, 0.95:
1.959963984540054, 0.99: 2.5758293035489004}
if alternative == "two-sided":
p = 2.0 * (1.0 - self.phi(abs(z)))
elif alternative == "larger":
p = 1.0 - self.phi(z)
elif alternative == "smaller":
p = self.phi(z)
else:
raise ValueError("alternative ∈ {'two-
sided','larger','smaller'}")
Returns dict:
{'z','p','mean_a','mean_b','sd_a','sd_b','n_a','n_b'}
"""
a, b = list(a), list(b)
n_a, n_b = len(a), len(b)
m_a, m_b = self.mean(a), self.mean(b)
s_a, s_b = self.sample_sd(a), self.sample_sd(b)
se = math.sqrt((s_a**2)/n_a + (s_b**2)/n_b)
z = (m_a - m_b) / se
if alternative == "two-sided":
p = 2.0 * (1.0 - self.phi(abs(z)))
elif alternative == "larger":
p = 1.0 - self.phi(z)
elif alternative == "smaller":
p = self.phi(z)
else:
raise ValueError("alternative ∈ {'two-
sided','larger','smaller'}")
if alternative == "two-sided":
p = 2.0 * (1.0 - self.phi(abs(z)))
elif alternative == "larger":
p = 1.0 - self.phi(z)
elif alternative == "smaller":
p = self.phi(z)
else:
raise ValueError("alternative ∈ {'two-
sided','larger','smaller'}")
if alternative == "two-sided":
p = 2.0 * (1.0 - self.phi(abs(z)))
elif alternative == "larger":
p = 1.0 - self.phi(z)
elif alternative == "smaller":
p = self.phi(z)
else:
raise ValueError("alternative ∈ {'two-
sided','larger','smaller'}")
if method == "wald":
se = math.sqrt(phat * (1 - phat) / n)
lower, upper = phat - z * se, phat + z * se
elif method == "wilson":
denom = 1 + (z*z)/n
center = (phat + (z*z)/(2*n)) / denom
adj = z * math.sqrt((phat*(1 - phat)/n) + (z*z)/(4*n*n)) /
denom
lower, upper = center - adj, center + adj
else:
raise ValueError("method ∈ {'wilson','wald'}")
# truncate to [0,1]
lower = max(0.0, lower)
upper = min(1.0, upper)
return {"lower": lower, "upper": upper, "phat": phat, "n": n,
"method": method, "zcrit": z}
class FinancialBasics():
"""
Finance toolkit covering:
- Liquidity Ratios
- Efficiency / Activity Ratios
- Leverage / Solvency Ratios
- Profitability Ratios
- Market Ratios
- DuPont Analysis
- Break-even & Leverage
- WACC
- Time Value of Money (PV, FV, NPV, IRR)
"""
def __init__(self):
# For IRR calculations
self.eps = 1e-9
self.max_iter = 10000
self.irr_low = -0.999
self.irr_high = 10.0
f = FinancialBasics()
f.epss(150, 100)
1.5
f.dps(1000, 100)
10.0