class MyCoins
Attributes
ccf[R]
mycurrency[RW]
Public Class Methods
new(source, date: nil, debug: false, mycurrency: 'USD', filepath: 'mycoins', colored: true, exchangerate_key: nil)
click to toggle source
# File lib/mycoins.rb, line 15 def initialize(source, date: nil, debug: false, mycurrency: 'USD', filepath: 'mycoins', colored: true, exchangerate_key: nil) @debug, @filepath, @colored = debug, filepath, colored @exchangerate_key = exchangerate_key @jer = JustExchangeRates.new(base: 'USD', debug: @debug, app_id: exchangerate_key) s = RXFHelper.read(source).first if s =~ /<\?dynarex / then @dx = Dynarex.new @dx.import s end puts '@dx.to_xml: ' + @dx.to_xml if @debug @mycurrency = (@dx.currency || mycurrency).upcase puts '@mycurrency: ' + @mycurrency.inspect if @debug coin_names = @dx.all.map{ |x| x.title.gsub(/\s+\[[^\]]+\]/,'')}.uniq @cache_file = File.join(filepath, 'mycoins_lookup.yaml') h = if File.exist? @cache_file then puts 'reading coins symbols frome the cache' if @debug h2 = Psych.load(File.read(@cache_file)) puts 'h2: ' + h2.inspect if @debug if (coin_names - h2.keys).empty? then h2 else fetch_symbols coin_names end else fetch_symbols coin_names end puts 'h: ' + h.inspect if @debug mycoins = h.values puts 'mycoins: ' + mycoins.inspect if @debug @ccf = CryptocoinFanboi.new(watch: mycoins, debug: debug, exchangerate_key: exchangerate_key) end
Public Instance Methods
archive()
click to toggle source
# File lib/mycoins.rb, line 68 def archive() filepath = File.join(@filepath, Time.now.year.to_s, Time.now.strftime("c%d%m%Y.xml")) FileUtils.mkdir_p File.dirname(filepath) File.write filepath, to_xml end
portfolio(order_by: :rank)
click to toggle source
# File lib/mycoins.rb, line 135 def portfolio(order_by: :rank) puts 'inside portfolio' if @debug r = build_portfolio(@dx.title) format_portfolio(r, order_by: order_by) end
price(coin_name, qty, btc: nil, date: nil)
click to toggle source
return the value of a coin given either the qty or purchase amount in BTC
# File lib/mycoins.rb, line 122 def price(coin_name, qty, btc: nil, date: nil) price_usd = if date then @ccf.price coin_name, date else coin = @ccf.find(coin_name) coin.price_usd.to_f end "%.2f %s" % [(price_usd * qty.to_f) * @jer.rate(@mycurrency), @mycurrency] end
to_dx()
click to toggle source
# File lib/mycoins.rb, line 77 def to_dx() r = build_portfolio(@dx.title) dx = Dynarex.new dx.import r.records h = r.to_h h.delete :records dx.summary.merge!(h) dx end
to_openstruct()
click to toggle source
# File lib/mycoins.rb, line 91 def to_openstruct() build_portfolio(@dx.title) end
to_percentages()
click to toggle source
# File lib/mycoins.rb, line 95 def to_percentages() all = self.to_dx.to_a val = ('value_' + @mycurrency.downcase).to_sym a = all.map {|x| x[val].to_f } sum = a.inject(&:+) a2 = all.map do |x| [x[:title].sub(/\s+\[[^\]]\]+/,''), (x[val].to_f).round(2)] end.group_by(&:first).to_a a3 = a2.map do |x| [x.first, ((x[1].inject(0) {|r,y| r + y[1].to_f} / sum.to_f) * 100)\ .round(2)] end a3.sort_by(&:last).reverse.to_h end
to_s()
click to toggle source
# File lib/mycoins.rb, line 116 def to_s() @ccf.to_s end
to_values()
click to toggle source
returns a Hash object containing the value as well as the percentage relative to the total value of the portfolio for each cryptocurrency
# File lib/mycoins.rb, line 146 def to_values() portfolio = build_portfolio() self.to_percentages.inject({}) do |r, x| currency, pct = x r.merge!(currency => [pct, ((portfolio.value * pct) / 100).round(2)]) end end
to_xml()
click to toggle source
# File lib/mycoins.rb, line 157 def to_xml() self.to_dx().to_xml pretty: true end
Private Instance Methods
build_portfolio(title='CryptoCurrency Portfolio ' + Time.now.year.to_s)
click to toggle source
# File lib/mycoins.rb, line 165 def build_portfolio(title='CryptoCurrency Portfolio ' + Time.now.year.to_s) if @portfolio and \ DateTime.parse(@portfolio.datetime) + 60 > DateTime.now then return @portfolio end a = build_records() invested = sum(a, :paid) gross_profit_list, losses_list = a.partition {|x| x[:roi].to_f > 0} gross_profit, losses = [gross_profit_list, losses_list]\ .map{|x| sum(x, :roi)} pct_gross_profit = (100 / (invested / gross_profit)).round(2) pct_losses = (100 / (invested / losses)).round(2) total_value = sum(a, ('value_' + @mycurrency.downcase).to_sym) rate = JustExchangeRates.new(base: 'GBP', app_id: @exchangerate_key).rate('USD') btc = @ccf.price('bitcoin') if @debug then puts 'rate: ' + rate.inspect puts 'bicoin price: ' + btc.inspect puts 'total value: ' + total_value.inspect end btc_val = ((total_value * rate) / btc).round(4) h = { title: title, mycurrency: @mycurrency, records: a, datetime: Time.now.strftime("%d/%m/%Y at %H:%M%p"), btc_price: btc, invested: invested, value: total_value, btc_value: btc_val, gross_profit: gross_profit.round(2), losses: losses.round(2), pct_gross_profit: pct_gross_profit, pct_losses: pct_losses, net_profit: sum(a, :roi).round(2), pct_net_profit: (pct_gross_profit + pct_losses).round(2) } @portfolio = OpenStruct.new(h) end
build_records()
click to toggle source
# File lib/mycoins.rb, line 213 def build_records() # print out the coin name, qty,value in USD,value in Sterling, and BTC @dx.all.inject([]) do |r, x| puts 'x: ' + x.inspect if @debug title = x.title.gsub(/\s+\[[^\]]+\]/,'') if @debug then puts 'title: ' + title.inspect puts '@ccf: ' + @ccf.class.inspect end coin = @ccf.find(title) if coin.nil? then puts 'warning: build_records error: coin nil for title ' \ + title.inspect return r end puts 'coin: ' + coin.inspect if @debug usd_rate = coin.price_usd.to_f paid = ((x.qty.to_f * x.btc_price.to_f) * \ @ccf.price('bitcoin', x.date_purchased) * \ @jer.rate(@mycurrency)).round(2) value_usd = (usd_rate * x.qty.to_f).round(2) h = { title: x.title, rank: coin.rank.to_i, qty: "%.2f" % x.qty, btc_price: "%.5f" % x.btc_price, paid: "%.0f" % paid } mycurrency = if @mycurrency and @mycurrency != 'USD' then local_value = ((usd_rate * x.qty.to_f) \ * @jer.rate(@mycurrency)).round(2) h.merge!(('value_' \ + @mycurrency.downcase).to_sym => "%.2f" % local_value) @mycurrency else 'USD' end puts 'local_value: ' + local_value.inspect if @debug value = (local_value || value_usd) h2 = { roi: "%s" % (value - paid).round(2), pct_roi: "%s" % (100 / (paid / (value - paid))).round(2) } r << h.merge!(h2) end end
fetch_symbols(coin_names)
click to toggle source
# File lib/mycoins.rb, line 280 def fetch_symbols(coin_names) c = CryptocoinFanboi.new debug: @debug h = coin_names.inject({}) do |r, name| puts 'name: ' + name.inspect if @debug found = c.find name r.merge(name => found.symbol) end FileUtils.mkdir_p File.dirname(@cache_file) File.write @cache_file, h.to_yaml return h end
format_portfolio(r, order_by: :rank)
click to toggle source
# File lib/mycoins.rb, line 319 def format_portfolio(r, order_by: :rank) coins = r.records.sort_by {|x| -x[order_by].to_f}.map {|x| x.values} coins.reverse! if order_by == :rank labels = %w(Name Rank Qty btc_price) \ + ["paid:"] labels << "value:" if @mycurrency labels += ['ROI:', 'ROI (%):'] puts 'labels: ' + labels.inspect if @debug out = "# " + @dx.title + "\n\n" out << "last_updated: %s\n\n" % r.datetime out << format_table(coins, labels: labels) out << "\nNote: paid and value columns displayed in " + @mycurrency out << "\n\nBTC price: %.2f USD" % [r.btc_price] out << "\nInvested: %.2f %s" % [r.invested, @mycurrency] out << "\n\nGross profit: %s %s (%s)" % \ [c(r.gross_profit), @mycurrency, c(r.pct_gross_profit.to_s + "%")] out << "\nLosses: %.2f %s (%.2f%%)" % [r.losses, @mycurrency, r.pct_losses] out << "\n\nNet profit: %s %s (%s)" % [c(r.net_profit), @mycurrency, c(r.pct_net_profit.to_s + "%")] out << "\nCurrent value: %.2f %s (%s BTC)" % [r.value, @mycurrency, r.btc_value] out end
format_table(source, markdown: markdown, labels: [])
click to toggle source
# File lib/mycoins.rb, line 299 def format_table(source, markdown: markdown, labels: []) s = TableFormatter.new(source: source, labels: labels).display return s if @colored == false a = s.lines body = a[3..-2].map do |line| fields = line.split('|') a2 = fields[-3..-1].map {|x| c(x) } (fields[0..-4] + a2 ).join('|') end (a[0..2] + body + [a[-1]]).join end
sum(a, field)
click to toggle source
# File lib/mycoins.rb, line 351 def sum(a, field) a.inject(0) {|r, x| r + x[field].to_f } end