Skip to content

Commit

Permalink
Add 10Cap valuation (closes #88).
Browse files Browse the repository at this point in the history
  • Loading branch information
kocielnik committed Dec 6, 2024
1 parent 090c982 commit aac02de
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 8 deletions.
6 changes: 5 additions & 1 deletion isthisstockgood/DataFetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def fetchDataForTickerSymbol(ticker):
'debt_equity_ratio',
'margin_of_safety_price',
'current_price'
'ten_cap_price'
"""
if not ticker:
return None
Expand All @@ -56,7 +57,9 @@ def fetchDataForTickerSymbol(ticker):
margin_of_safety_price, sticker_price = \
_calculateMarginOfSafetyPrice(msn_money.equity_growth_rates[-1], msn_money.pe_low, msn_money.pe_high, msn_money.eps[-1], five_year_growth_rate)
payback_time = _calculatePaybackTime(msn_money.equity_growth_rates[-1], msn_money.last_year_net_income, msn_money.market_cap, five_year_growth_rate)
computed_free_cash_flow = round(float(msn_money.free_cash_flow[-1]) * msn_money.shares_outstanding)
free_cash_flow_per_share = float(msn_money.free_cash_flow[-1])
computed_free_cash_flow = round(free_cash_flow_per_share * msn_money.shares_outstanding)
ten_cap_price = 10 * free_cash_flow_per_share
template_values = {
'ticker' : ticker,
'name' : msn_money.name if msn_money and msn_money.name else 'null',
Expand All @@ -68,6 +71,7 @@ def fetchDataForTickerSymbol(ticker):
'cash': msn_money.free_cash_flow_growth_rates if msn_money and msn_money.free_cash_flow_growth_rates else [],
'total_debt' : msn_money.total_debt,
'free_cash_flow' : computed_free_cash_flow,
'ten_cap_price' : ten_cap_price,
'debt_payoff_time' : round(float(msn_money.total_debt) / computed_free_cash_flow),
'debt_equity_ratio' : msn_money.debt_equity_ratio if msn_money and msn_money.debt_equity_ratio >= 0 else -1,
'margin_of_safety_price' : margin_of_safety_price if margin_of_safety_price else 'null',
Expand Down
3 changes: 2 additions & 1 deletion isthisstockgood/templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
{% include "management.html" %}
{% include "margin_of_safety.html" %}
{% include "payback_time.html" %}
{% include "ten_cap.html" %}
{% include "market_cap.html" %}
<script>
// Initialize all popover elements for the Bootstrap plugin.
$(document).ready(function(){
$('[data-toggle="popover"]').popover({ trigger: "hover" });
});
</script>
{% endblock %}
{% endblock %}
18 changes: 17 additions & 1 deletion isthisstockgood/templates/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,22 @@ $(document).ready(function() {
colorCellWithBackgroundColor('#' + key, Color.red());
}

// Update 10 Cap section
let ten_cap_key = 'ten_cap_price';
let ten_cap_field_id = '#' + ten_cap_key;
let current_price = data['current_price'];
updateHtmlWithValueForKey(data, ten_cap_key, /*commas=*/true);
if (!data[ten_cap_key]) {
colorCellWithBackgroundColor(ten_cap_field_id, Color.red());
}
if (current_price > data[ten_cap_key]) {
colorCellWithBackgroundColor(ten_cap_field_id, Color.red());
}
else {
colorCellWithBackgroundColor(ten_cap_field_id, Color.green());
}


// Update Market Cap numbers
updateHtmlWithValueForKey(data, 'average_volume', /*commas=*/true);
let averageVolume = data['average_volume'];
Expand Down Expand Up @@ -212,4 +228,4 @@ function colorCellWithIDForZeroBasedRange(id, range) {
}

colorCellWithBackgroundColor(id, backgroundColor);
}
}
3 changes: 2 additions & 1 deletion isthisstockgood/templates/json/stock_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
"current_price" : {{ current_price }},
"sticker_price" : {{ sticker_price }},
"payback_time" : {{ payback_time }},
"ten_cap_price" : {{ ten_cap_price }},
"average_volume" : {{ average_volume }}
}
}
2 changes: 1 addition & 1 deletion isthisstockgood/templates/loading.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@

this.shadowRoot.append(style, wrapper);

this.animationTimeout = None;
this.animationTimeout = null;
}

static get observedAttributes() { return ['data-message']; }
Expand Down
6 changes: 3 additions & 3 deletions isthisstockgood/templates/searchbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<div class="col-md-3 nopadding">
<input
type="text"
autofocus
class="form-control"
id="ticker"
placeholder="Ticker Symbol"
maxlength=8
onkeydown="return validateInput(event)"/>
maxlength=8/>
</div>
<div class="col-md-1 nopadding">
<input
Expand All @@ -32,4 +32,4 @@

<script>
{% include "js/search.js" %}
</script>
</script>
25 changes: 25 additions & 0 deletions isthisstockgood/templates/ten_cap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div class="container pb-2 pt-2" id="Market Cap">
<div class="row justify-content-center">
<button
type="button"
class="btn btn-raised btn-lg btn-primary"
data-toggle="popover"
title="10 Cap"
data-content="{% include 'txt/ten_cap_tooltip.txt' %}"
>10 Cap</button>
</div>

<div class="row pt-3 justify-content-center">
<div class="col-sm-5">
<table class="table table-bordered text-center">
<tr id="debt_equity_title_label">
<thead class="thead-light">
<th>10 Cap Price</th>
</thead>
<td id="ten_cap_price">
-
</td>
</tr>
</table>
</div>
</div>
2 changes: 2 additions & 0 deletions isthisstockgood/templates/txt/ten_cap_tooltip.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Price at which the company is expected to return to you about 10% of your invested amount via Free Cash Flow (Owner's Earnings).
Discussed in the book 'Invested' by Danielle Town.
8 changes: 8 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ def test_get_data():
data = res.text
assert json.loads(data)['debt_payoff_time'] == 0
assert res.status_code == 200

def test_get_ten_cap_price():
app = create_app(fetchDataForTickerSymbol)

with app.test_client() as test_client:
test_client = app.test_client()
res = test_client.get('/api/ticker/nvda')
assert res.json['ten_cap_price'] > 0

0 comments on commit aac02de

Please sign in to comment.