2 # This file is part of SMR.
4 # SMR is free software: you can redistribute it and/or modify it under the
5 # terms of the GNU General Public License as published by the Free Software
6 # Foundation, either version 3 of the License, or (at your option) any later
9 # SMR is distributed in the hope that it will be useful, but WITHOUT ANY
10 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License along with
14 # SMR. If not, see <http://www.gnu.org/licenses/>.
16 require 'asset_position'
20 # Total assets of current user at some point in time.
22 # Use #open_positions to access Smr::AssetPosition objects of all positions
23 # held. Then each knows more details about itself.
25 # collection of Smr::AssetPosition objects of currently open positions
26 attr_reader :open_positions
28 # currently invested amount of money
31 # current market value of all assets
32 attr_reader :market_value
34 # current profit/loss on all assets
35 attr_reader :profit_loss
38 # age of +Quote+ data before its considered old
39 QUOTE_OUTDATED_DAYS = 4
42 # date defines the point of Time this object sits at
43 def initialize(id_user, date, id_portfolio=false)
44 raise 'date must be of Time' unless date.is_a?(Time)
50 limit_portfolio = if id_portfolio then 'AND po.id=%i' % id_portfolio else '' end
56 @_have_old_quotes = false
57 @_have_missing_quotes = false
59 @open_positions = Array.new
61 # ATTENTION: not portable!
62 # - thats not the preferred way to do a query.
63 # - this one is just too complex for ActiveRecord at the moment
64 open_positions = Smr::AssetPositions.new(@date, '
68 p.id_portfolio, # if those values could be used
69 pr.id_order, # things would be much faster since
70 pr.id_position, # subsequent SmrPosition objects query
71 pr.date, # these again... too many queries...
80 MAX(pr1.date) AS LASTDATE,
81 pr1.id_position AS LASTPOSITION
86 GROUP BY pr1.id_position
91 AND p.id_portfolio=po.id
94 AND (p.closed=0 OR p.closed>%i)
96 AND pr.id_position=LASTPOSITION
97 AND po.name NOT LIKE "watchlist:%%" /* HACK for speed on old DBs */
99 ORDER BY s.name, pr.date' % [@date, limit_portfolio, @id_user, @date]).get_all
101 # turn Position objects into SmrPosition
102 # - for the sake of performance we calculate totals right here
103 open_positions.each do |p|
104 sp = Smr::AssetPosition.new(p.id, id_user, @date)
105 @open_positions << sp
107 @invested += sp.invested
108 @market_value += sp.market_value if sp.market_value
109 @profit_loss += sp.profit_loss if sp.profit_loss
111 if not sp.market_value then @_have_missing_quotes = true end
112 if sp.quote_time and sp.quote_time < QUOTE_OUTDATED_DAYS.days.ago then
113 @_have_old_quotes = true
120 # tell whether this Asset report includes outdated quotes
125 # tell whether this Asset report is lacking quote data
126 def have_missing_quotes?
127 @_have_missing_quotes