One of the projects I am working on is a fintech application–Céillí. One of the data points that are presented for the stock trading community is that of Earnings Per Share (EPS). It’s a key financial metric that represents the portion of a company’s profit allocated to each outstanding share of common stock. EPS is calculated by dividing the company’s net income (after preferred dividends, if any) by the average number of outstanding common shares during the period. It’s commonly used to gauge a company’s profitability and is a vital input for valuation metrics like the price-to-earnings (P/E) ratio.
Below is an example Python script that calculates the Earnings Per Share (EPS) for a commodity-producing company (or any company) and then uses that EPS value to compute the Price-to-Earnings (P/E) ratio.you should have the net income and outstanding shares data to calculate this:
def calculate_eps(net_income: float, num_shares: float) -> float:
"""
Calculate Earnings Per Share (EPS).
Args:
net_income (float): The company's net income.
num_shares (float): The average number of outstanding shares.
Returns:
float: EPS value.
"""
if num_shares == 0:
raise ValueError("Number of shares cannot be zero")
return net_income / num_shares
getting EPS is a cumbersome task as the data is not in a freely available API, and those that do have that data charge a hefty fee which can eat into your returns, this informatino is usually contained in transcripts of earnings reports and general market reports in the media.
For my acquisition of EPS data I rely on spidering news headlines which I also use for sentiment analysis purposes. I noticed that much of the information needed for fundamental analysis, rather then technical analysis, are contained in the news headlines as well as the transcripts of earnings calls where companies present their productive value at quarterly and annual conference calls. Usually, one would rely on REGEX to extract information from text. Now, with the advent of Large Language Models and Generative AI, this task can become alot less cumbersome and automated. One way to do this is to use python and a LLM that is hosted by Huggingface and developed by NuMind, https://huggingface.co/numind/NuExtract-1.5-tiny
At this link you can find more code samples using python. For my purposes, I used this code to extract EPS from the text. How this basically works is that you use a json model to structure the data and the LLM is able to use this to place key datapoints from the text into this model, which of course could easily be automatically pushed to a database for any UI needs you may have.
import json
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
device = torch.device("mps" if torch.backends.mps.is_available() else "cpu")
def predict_NuExtract(model, tokenizer, text, schema, examples=["", "", ""]):
# Parse and reformat the schema
schema = json.dumps(json.loads(schema), indent=4)
input_llm = "<|input|>\n" + schema + "\n"
# Only add examples if they are non-empty valid JSON strings
for ex in examples:
if ex.strip(): # only process if not empty
input_llm += json.dumps(json.loads(ex), indent=4) + "\n"
# Add the text to extract data from
input_llm += "### Text:\n" + text + "\n<|output|>\n"
# Tokenize and generate output
input_ids = tokenizer(input_llm, return_tensors="pt", truncation=True, max_length=4000).to(device)
#output = tokenizer.decode(model.generate(**input_ids)[0], skip_special_tokens=True)
output = tokenizer.decode(
model.generate(**input_ids, use_cache=False)[0], skip_special_tokens=True)
return output.split("<|output|>")[1].split("<|end-output|>")[0]
model = AutoModelForCausalLM.from_pretrained("numind/NuExtract-1.5-tiny", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("numind/NuExtract-1.5-tiny", trust_remote_code=True)
model.to(device)
#device = torch.device("mps" if torch.backends.mps.is_available() else "cpu")
model.eval()
text = ["Relmada Therapeutics Q4 2024 GAAP EPS $(0.62) Beats $(0.70) Estimate.",
"Clearside Biomedical Q4 2024 GAAP EPS $(0.10), Inline, Sales $306.00K Beat $176.67K Estimate.",
"Argan Q4 2024 GAAP EPS $2.22 Beats $1.15 Estimate, Sales $232.474M Beat $197.500M Estimate.",
"Plus Therapeutics FY24 EPS $(1.95) Vs. $(4.24) YoY, Grant Revenue $5.8M Up From $4.9M YoY",
"SeaStar Medical Holding Q4 EPS $(0.90) Misses $(0.89) Estimate, Sales $67.00K Miss $150.00K Estimate.",
"Pulse Biosciences Q4 EPS $(0.31) Down From $(0.21) YoY.",
"CalAmp FY 2024 GAAP EPS $(11.04), Inline.",
"VirTra Q4 2024 GAAP EPS $(0.08) Misses $0.04 Estimate, Sales $5.40M Miss $7.45M Estimate.",
"Better Choice Q4 EPS $(0.50), Sales $7.2M Up 26% From YoY."]
schema = """{
"company": "",
"period": "",
"eps_data": {
"eps_type": "",
"actual_eps": "",
"eps_estimate": "",
"eps_result": ""
},
"sales_data": {
"actual_sales": "",
"sales_estimate": "",
"sales_result": ""
}
}"""
for i in text:
prediction = predict_NuExtract(model, tokenizer, i, schema)
print(prediction)
'''
Output:
{
"company": "Relmada Therapeutics",
"period": "Q4 2024",
"eps_data": {
"eps_type": "GAAP",
"actual_eps": "0.62",
"eps_estimate": "0.70",
"eps_result": "$(0.62)"
},
"sales_data": {
"actual_sales": "",
"sales_estimate": "",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "Clearside Biomedical",
"period": "Q4 2024",
"eps_data": {
"eps_type": "GAAP",
"actual_eps": "0.10",
"eps_estimate": "176.67K",
"eps_result": ""
},
"sales_data": {
"actual_sales": "$306.00K",
"sales_estimate": "$176.67K",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "Argan",
"period": "Q4 2024",
"eps_data": {
"eps_type": "GAAP",
"actual_eps": "$2.22",
"eps_estimate": "$1.15",
"eps_result": "$232.474M"
},
"sales_data": {
"actual_sales": "$232.474M",
"sales_estimate": "$197.500M",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "Plus Therapeutics",
"period": "FY24",
"eps_data": {
"eps_type": "EPS",
"actual_eps": "1.95",
"eps_estimate": "4.24",
"eps_result": ""
},
"sales_data": {
"actual_sales": "5.8M",
"sales_estimate": "",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "SeaStar Medical Holding",
"period": "Q4",
"eps_data": {
"eps_type": "",
"actual_eps": "0.90",
"eps_estimate": "0.89",
"eps_result": "Misses"
},
"sales_data": {
"actual_sales": "$67.00K",
"sales_estimate": "$150.00K",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "Pulse Biosciences",
"period": "Q4",
"eps_data": {
"eps_type": "EPS",
"actual_eps": "0.31",
"eps_estimate": "0.21",
"eps_result": "Down From"
},
"sales_data": {
"actual_sales": "",
"sales_estimate": "",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "CalAmp",
"period": "FY 2024",
"eps_data": {
"eps_type": "GAAP",
"actual_eps": "11.04",
"eps_estimate": "",
"eps_result": ""
},
"sales_data": {
"actual_sales": "",
"sales_estimate": "",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "VirTra",
"period": "Q4 2024",
"eps_data": {
"eps_type": "GAAP",
"actual_eps": "0.08",
"eps_estimate": "0.04",
"eps_result": "Misses"
},
"sales_data": {
"actual_sales": "$5.40M",
"sales_estimate": "$7.45M",
"sales_result": ""
}
}
Setting `pad_token_id` to `eos_token_id`:151646 for open-end generation.
{
"company": "Better Choice",
"period": "Q4",
"eps_data": {
"eps_type": "EPS",
"actual_eps": "0.50",
"eps_estimate": "",
"eps_result": ""
},
"sales_data": {
"actual_sales": "$7.2M",
"sales_estimate": "",
"sales_result": "Up 26% From YoY"
}
}
'''
As one can see results can vary, although one could introduce steps into this basic process to further refine the models or even use case-based models that are specific to different patterns of headlines, as there are set ways that financial data is presented in the market news. Other financial ratios are also reported in the news, so having such an ability can help, such as collecting EBITDA, P/E, etc.
OpenAI’s chatGPT had this to add to EPS discussion that I found interesting:
me: is there an optimal eps value or is it relative to each stock? what constitutes a miss?
ChatGPT said:
Reasoned about optimal EPS and “Miss” for a couple of seconds
EPS (Earnings Per Share) isn’t a one-size-fits-all metric—it’s relative to the company, its industry, historical performance, and market expectations. There isn’t an “optimal” EPS value that applies across the board. Instead, investors look at trends, growth rates, and how the current EPS compares to analysts’ forecasts or the company’s own guidance.
What Constitutes a “Miss”
A “miss” typically occurs when a company’s reported EPS is below the consensus estimate or its internal guidance. Analysts and investors use these estimates as benchmarks, so if the actual EPS falls short, it’s seen as underperformance—even if the EPS might be strong in absolute terms. The severity of the miss can affect investor sentiment and, consequently, the stock’s price.
Key Considerations
- Relative Performance:
For one company, an EPS of, say, $2.00 might be excellent if the industry average is $1.00, while another company might be expected to have an EPS of $5.00 based on its size and market position. - Growth Trends:
Investors often consider not just the current EPS but also its trend over time. Consistent growth can be more important than a single high or low number. - Market Expectations:
EPS is closely watched around earnings announcements. A miss relative to consensus estimates can trigger a negative reaction, even if the company is profitable overall.
In summary, the “optimal” EPS is relative and context-dependent, and a miss is typically defined by falling short of pre-determined expectations rather than a fixed numeric benchmark.
me: if i have the eps for a company how do i get the P/E, what is the price i use?
ChatGPT said:
Reasoned for 10 seconds
The Price/Earnings (P/E) ratio is calculated by dividing the current market price of a company’s stock by its earnings per share (EPS). So if you have the EPS, the price you use is typically the current share price—often the last traded or closing price.
For example, if a company’s EPS is $2.00 and its current share price is $30.00, then the P/E ratio is calculated as:P/E=Current Share PriceEPS=30.002.00=15\text{P/E} = \frac{\text{Current Share Price}}{\text{EPS}} = \frac{30.00}{2.00} = 15P/E=EPSCurrent Share Price=2.0030.00=15

There are a couple of variations depending on your analysis:
- Trailing P/E: Uses the current share price and the EPS from the past 12 months.
- Forward P/E: Uses the current share price and forecasted EPS.
In most standard cases, you’d use the latest closing price from the market to compute the P/E ratio.
o3-mini-high
You said:
me: how do you get the trailing p/e, do you use daily bars? and how do you get the forecasted EPS?
ChatGPT said:
Reasoned for 12 seconds
Trailing P/E is calculated by dividing the current market price (usually the last closing price) by the earnings per share over the trailing twelve months (TTM EPS). Here’s how it typically works:
- Trailing P/E:
- Price: You take the most recent closing price of the stock. While daily bars provide the closing price, you don’t calculate the EPS from daily bars. Instead, you use the EPS figure from the company’s quarterly reports and annualize it (i.e., sum up the last four quarters of reported EPS).
- EPS: The earnings data comes from the company’s financial reports. For example, if you have EPS for Q1, Q2, Q3, and Q4, you add those together to get the TTM EPS.
- Calculation: Trailing P/E=Current Stock PriceTTM EPS\text{Trailing P/E} = \frac{\text{Current Stock Price}}{\text{TTM EPS}}Trailing P/E=TTM EPSCurrent Stock Price
- Forecasted (Forward) EPS:
- Source: Forecasted EPS isn’t derived directly from historical price data or daily bars. Instead, it’s typically provided by analysts’ consensus estimates or company guidance. Financial data providers (like Bloomberg, FactSet, or Reuters) compile these forecasts.
- Usage: You take the current stock price and divide it by the forecasted EPS (often for the next 12 months) to get the forward P/E ratio.
In summary, daily bars are mainly used to get the current price (closing price) for the calculation. The earnings figure for trailing P/E comes from reported quarterly earnings, and forecasted EPS comes from analysts’ estimates or management’s guidance.

Here is a development version, although rough in visual style as a prototype, gives you a picture of how you can put this altogether for algorithmic insights into the market.

Leave a Reply