fundamentalista-rails 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/app/controllers/fundamentalista_rails/companies_controller.rb +9 -0
- data/app/controllers/fundamentalista_rails/holdings_controller.rb +5 -0
- data/app/views/fundamentalista_rails/companies/show.html.erb +19 -1
- data/app/views/fundamentalista_rails/holdings/show.html.erb +25 -0
- data/app/views/fundamentalista_rails/shared/_valuation.html.erb +5 -0
- data/app/views/fundamentalista_rails/watchlists/show.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/lib/fundamentalista-rails.rb +5 -0
- data/lib/fundamentalista_rails/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: acb408b2adaf80663d870ba7ff7e58881cfbff271757b486ad43b72ce45d480d
|
|
4
|
+
data.tar.gz: c7db5e55d712622e51bc4c1730cc222df1369cb8d0db867b45129f4170b4049c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5390738f4c6696c501f8bbbbc7b83f36a2e9f2770215aea142b56e0580d11e5e559cdbd3fce67d64f368ab6dffbf1a237be528f19364dc8817368e67c8d7e59
|
|
7
|
+
data.tar.gz: 799f2c7e898ed8af174d06450a77ef1bbcba41956d33f2074bcffa646c4d5b8c2c03651446b14c25fefee181a0616e0d7d273006cb32a6936ed229ac1a003eb0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
- Valuation history on the company page when the provider serves prices, one row per fiscal year at its closing price.
|
|
6
|
+
- A snapshot history page per holding.
|
|
7
|
+
- WACC and the intrinsic value at it on the valuation, when the provider reports a beta; `FundamentalistaRails.risk_free_rate` and `equity_premium` set the inputs.
|
|
8
|
+
|
|
3
9
|
## 0.1.0
|
|
4
10
|
|
|
5
11
|
- Mountable engine with company pages, peer comparison with the magic formula, and watchlists.
|
|
@@ -13,6 +13,15 @@ module FundamentalistaRails
|
|
|
13
13
|
@year = @company.latest_period
|
|
14
14
|
@price = price_param
|
|
15
15
|
@valuation = @company.valuation(price: @price) if @price
|
|
16
|
+
@history = history_of(@company)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def history_of(company)
|
|
22
|
+
company.valuation_history(:pe, :pb, :fcf_yield, :ev_to_ebitda)
|
|
23
|
+
rescue Fundamentalista::QuoteUnavailableError
|
|
24
|
+
nil
|
|
16
25
|
end
|
|
17
26
|
end
|
|
18
27
|
end
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
module FundamentalistaRails
|
|
4
4
|
# Adds companies to a watchlist and removes them.
|
|
5
5
|
class HoldingsController < ApplicationController
|
|
6
|
+
def show
|
|
7
|
+
@holding = Holding.find(params[:id])
|
|
8
|
+
@snapshots = @holding.snapshots
|
|
9
|
+
end
|
|
10
|
+
|
|
6
11
|
def create
|
|
7
12
|
watchlist = Watchlist.find(params[:watchlist_id])
|
|
8
13
|
holding = watchlist.holdings.create!(params.require(:holding).permit(:ticker, :price))
|
|
@@ -30,7 +30,25 @@
|
|
|
30
30
|
<% if @valuation %>
|
|
31
31
|
<section>
|
|
32
32
|
<h2>Valuation at <%= number(@price) %></h2>
|
|
33
|
-
<%= render "fundamentalista_rails/shared/valuation", valuation: @valuation %>
|
|
33
|
+
<%= render "fundamentalista_rails/shared/valuation", valuation: @valuation, beta: @company.beta %>
|
|
34
|
+
</section>
|
|
35
|
+
<% end %>
|
|
36
|
+
|
|
37
|
+
<% if @history.present? %>
|
|
38
|
+
<section>
|
|
39
|
+
<h2>Valuation history</h2>
|
|
40
|
+
<p class="muted">Each fiscal year at the close of its last day.</p>
|
|
41
|
+
<table>
|
|
42
|
+
<thead><tr><th>Year</th><th>Price</th><th>P/E</th><th>P/B</th><th>FCF yield</th><th>EV/EBITDA</th></tr></thead>
|
|
43
|
+
<tbody>
|
|
44
|
+
<% @history.each do |year, row| %>
|
|
45
|
+
<tr>
|
|
46
|
+
<td><%= year %></td><td><%= number(row[:price]) %></td><td><%= multiple(row[:pe]) %></td>
|
|
47
|
+
<td><%= multiple(row[:pb]) %></td><td><%= percent(row[:fcf_yield]) %></td><td><%= multiple(row[:ev_to_ebitda]) %></td>
|
|
48
|
+
</tr>
|
|
49
|
+
<% end %>
|
|
50
|
+
</tbody>
|
|
51
|
+
</table>
|
|
34
52
|
</section>
|
|
35
53
|
<% end %>
|
|
36
54
|
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<% content_for :title, "#{@holding.ticker} snapshots" %>
|
|
2
|
+
<h1><%= link_to @holding.ticker, company_path(@holding.ticker, price: @holding.price) %> <span class="muted">in <%= link_to @holding.watchlist.name, @holding.watchlist %></span></h1>
|
|
3
|
+
<%= button_to "Take a snapshot", watchlist_holding_snapshots_path(@holding.watchlist, @holding) %>
|
|
4
|
+
<% if @snapshots.any? %>
|
|
5
|
+
<table>
|
|
6
|
+
<thead><tr><th>Date</th><th>Price</th><th>P/E</th><th>P/B</th><th>FCF yield</th><th>EV/EBITDA</th><th>ROE</th><th>Piotroski</th><th>Altman</th></tr></thead>
|
|
7
|
+
<tbody>
|
|
8
|
+
<% @snapshots.each do |snapshot| %>
|
|
9
|
+
<tr>
|
|
10
|
+
<td><%= snapshot.taken_on %></td>
|
|
11
|
+
<td><%= number(snapshot.price) %></td>
|
|
12
|
+
<td><%= multiple(snapshot.dig(:valuation, :pe)) %></td>
|
|
13
|
+
<td><%= multiple(snapshot.dig(:valuation, :pb)) %></td>
|
|
14
|
+
<td><%= percent(snapshot.dig(:valuation, :fcf_yield)) %></td>
|
|
15
|
+
<td><%= multiple(snapshot.dig(:valuation, :ev_to_ebitda)) %></td>
|
|
16
|
+
<td><%= percent(snapshot.dig(:ratios, :roe)) %></td>
|
|
17
|
+
<td><%= snapshot.dig(:scores, :piotroski) || "–" %></td>
|
|
18
|
+
<td><%= number(snapshot.dig(:scores, :altman_z, :score)) %></td>
|
|
19
|
+
</tr>
|
|
20
|
+
<% end %>
|
|
21
|
+
</tbody>
|
|
22
|
+
</table>
|
|
23
|
+
<% else %>
|
|
24
|
+
<p class="muted">No snapshots yet.</p>
|
|
25
|
+
<% end %>
|
|
@@ -12,5 +12,10 @@
|
|
|
12
12
|
<tr><td>Graham number</td><td><%= number(valuation.graham_number) %></td></tr>
|
|
13
13
|
<tr><td>Intrinsic value (6% growth, 9% discount)</td><td><%= number(valuation.intrinsic_value(growth: 0.06, discount_rate: 0.09)) %></td></tr>
|
|
14
14
|
<tr><td>Implied growth at 9% discount</td><td><%= percent(valuation.implied_growth(discount_rate: 0.09)) %></td></tr>
|
|
15
|
+
<% if local_assigns[:beta] %>
|
|
16
|
+
<% rate = valuation.wacc(beta: beta, risk_free: FundamentalistaRails.risk_free_rate, equity_premium: FundamentalistaRails.equity_premium) %>
|
|
17
|
+
<tr><td>WACC (beta <%= number(beta) %>)</td><td><%= percent(rate) %></td></tr>
|
|
18
|
+
<tr><td>Intrinsic value at WACC, 6% growth</td><td><%= number(rate && valuation.intrinsic_value(growth: 0.06, discount_rate: rate)) %></td></tr>
|
|
19
|
+
<% end %>
|
|
15
20
|
</tbody>
|
|
16
21
|
</table>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<tr>
|
|
15
15
|
<td><%= link_to holding.ticker, company_path(holding.ticker, price: holding.price) %></td>
|
|
16
16
|
<td><%= number(holding.price) %></td>
|
|
17
|
-
<td><%= holding.snapshots.size %><% if latest %> <span class="muted">last <%= latest.taken_on %></span><% end %></td>
|
|
17
|
+
<td><%= link_to holding.snapshots.size, watchlist_holding_path(@watchlist, holding) %><% if latest %> <span class="muted">last <%= latest.taken_on %></span><% end %></td>
|
|
18
18
|
<td><%= multiple(latest&.dig(:valuation, :pe)) %></td>
|
|
19
19
|
<td><%= percent(latest&.dig(:valuation, :fcf_yield)) %></td>
|
|
20
20
|
<td><%= latest&.dig(:scores, :piotroski) || "–" %></td>
|
data/config/routes.rb
CHANGED
|
@@ -5,7 +5,7 @@ FundamentalistaRails::Engine.routes.draw do
|
|
|
5
5
|
resources :companies, only: :show, param: :ticker
|
|
6
6
|
resource :comparison, only: :show
|
|
7
7
|
resources :watchlists, only: %i[index create show destroy] do
|
|
8
|
-
resources :holdings, only: %i[create destroy] do
|
|
8
|
+
resources :holdings, only: %i[show create destroy] do
|
|
9
9
|
resources :snapshots, only: :create
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'fundamentalista'
|
|
4
4
|
require 'rails/engine'
|
|
5
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
|
5
6
|
require 'fundamentalista_rails/version'
|
|
6
7
|
require 'fundamentalista_rails/cache'
|
|
7
8
|
require 'fundamentalista_rails/engine'
|
|
@@ -14,4 +15,8 @@ require 'fundamentalista_rails/engine'
|
|
|
14
15
|
# mount FundamentalistaRails::Engine, at: "/fundamentals"
|
|
15
16
|
#
|
|
16
17
|
module FundamentalistaRails
|
|
18
|
+
# The risk free rate and equity premium the pages use for the WACC,
|
|
19
|
+
# as decimals. Set them in an initializer.
|
|
20
|
+
mattr_accessor :risk_free_rate, default: BigDecimal('0.04')
|
|
21
|
+
mattr_accessor :equity_premium, default: BigDecimal('0.05')
|
|
17
22
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fundamentalista-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bruno Costanzo
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.
|
|
18
|
+
version: '0.2'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0.
|
|
25
|
+
version: '0.2'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: rails
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -64,6 +64,7 @@ files:
|
|
|
64
64
|
- app/views/fundamentalista_rails/companies/index.html.erb
|
|
65
65
|
- app/views/fundamentalista_rails/companies/show.html.erb
|
|
66
66
|
- app/views/fundamentalista_rails/comparisons/show.html.erb
|
|
67
|
+
- app/views/fundamentalista_rails/holdings/show.html.erb
|
|
67
68
|
- app/views/fundamentalista_rails/shared/_ratios.html.erb
|
|
68
69
|
- app/views/fundamentalista_rails/shared/_scores.html.erb
|
|
69
70
|
- app/views/fundamentalista_rails/shared/_series.html.erb
|