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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 301e35254de56b06adcdbb3e168c70998e63ef0b22141c016e03206744929101
4
- data.tar.gz: 715976e46da9f92cf579a9d546d91262c9712a157e23ff1ff9e96388dbd44445
3
+ metadata.gz: acb408b2adaf80663d870ba7ff7e58881cfbff271757b486ad43b72ce45d480d
4
+ data.tar.gz: c7db5e55d712622e51bc4c1730cc222df1369cb8d0db867b45129f4170b4049c
5
5
  SHA512:
6
- metadata.gz: f35926ae82acf6835a76aa04672e668228874d6a925d9484c0d170a07fdea270507a3c54e248563ba3d6c5ebb0a1bd7c3f9543e42055ccf761df9731eacabeab
7
- data.tar.gz: b47411050fea5cdb894eae1ef9920aebccce3078fc1b3a3eb92089bbc2a8a9b6cb6c5f0cb38f9e396a3960203e64e79c894474883c5c3d295d1cb5281b7ab82d
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module FundamentalistaRails
4
4
  # The version of the fundamentalista-rails gem, as a string.
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  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.1.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.1'
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.1'
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