portfolio_stocks 1.0.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 +7 -0
- data/.gitignore +25 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +39 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +2 -0
- data/bin/portfolio +24 -0
- data/lib/portfolio.rb +10 -0
- data/lib/portfolio/commands.rb +113 -0
- data/lib/portfolio/formatter.rb +63 -0
- data/lib/portfolio/stockprices.rb +36 -0
- data/lib/portfolio/store.rb +72 -0
- data/lib/portfolio/version.rb +3 -0
- data/portfolio.gemspec +31 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 80710f31ff25a31a585ce43341f8c465a763db14
|
4
|
+
data.tar.gz: 8d5fd582950fa0c00ae284c55d1f68d4ca4c861a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3193ff31d2a3d18af814e536e3dc91d5006eb72510ca1e10a0d19d691575944d7699cb9a02890a76d421126cb406270eed45e96cf3f98c296cfef8e09f4d33f9
|
7
|
+
data.tar.gz: 37e6e2e4af8fc6b087c84c955f964f6cfe0829ceb37296d2ffac48dd55ab5b535b0ad34c1062b5ac2f499d4af98f984deb46eaf94572ec41da1a84fe845e44c9
|
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
portfolio_stocks (1.0.0)
|
5
|
+
colored (~> 1.2)
|
6
|
+
stock_quote
|
7
|
+
terminal-table
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
colored (1.2)
|
13
|
+
diff-lcs (1.2.5)
|
14
|
+
json (1.8.1)
|
15
|
+
mime-types (2.3)
|
16
|
+
rake (10.3.2)
|
17
|
+
rest-client (1.6.7)
|
18
|
+
mime-types (>= 1.16)
|
19
|
+
rspec (2.99.0)
|
20
|
+
rspec-core (~> 2.99.0)
|
21
|
+
rspec-expectations (~> 2.99.0)
|
22
|
+
rspec-mocks (~> 2.99.0)
|
23
|
+
rspec-core (2.99.0)
|
24
|
+
rspec-expectations (2.99.0)
|
25
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
26
|
+
rspec-mocks (2.99.0)
|
27
|
+
stock_quote (1.1.8)
|
28
|
+
json
|
29
|
+
rest-client (~> 1.6)
|
30
|
+
terminal-table (1.4.5)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
bundler
|
37
|
+
portfolio_stocks!
|
38
|
+
rake (~> 10.3)
|
39
|
+
rspec (~> 2.14)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Tim Davies
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
## Portfolio 💰
|
2
|
+
|
3
|
+
A command-line tool for managing your stocks.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
|
7
|
+
gem install portfolio_stocks
|
8
|
+
|
9
|
+
### Usage
|
10
|
+
|
11
|
+
Start watching a stock:
|
12
|
+
|
13
|
+
--watch <stock>
|
14
|
+
|
15
|
+
Stop watching a stock:
|
16
|
+
|
17
|
+
--ignore <stock>
|
18
|
+
|
19
|
+
Add investment to portfolio:
|
20
|
+
|
21
|
+
--invest <stock> <amount bought> <price paid per stock> <total commission paid>
|
22
|
+
|
23
|
+
Remove investment from portfolio:
|
24
|
+
|
25
|
+
--sell <stock>
|
26
|
+
|
27
|
+
### Small disclaimer
|
28
|
+
|
29
|
+
I'm using this to monitor a few stocks and keep track of a few investments -
|
30
|
+
nothing heavy by any means. It has none of the features that a more seasoned
|
31
|
+
investor would require but if you just want to keep track of a bit of money,
|
32
|
+
hopefully you'll find it useful.
|
data/Rakefile
ADDED
data/bin/portfolio
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'portfolio')
|
4
|
+
|
5
|
+
# Get the subcommand (and if there isn't one, default to 'show', which displays
|
6
|
+
# the portfolio):
|
7
|
+
if ARGV.length != 0
|
8
|
+
command = ARGV[0].gsub('--', '')
|
9
|
+
else
|
10
|
+
command = "show"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Initialise commands object which stores the methods for each of the
|
14
|
+
# subcommands:
|
15
|
+
commands = Portfolio::Commands.new
|
16
|
+
|
17
|
+
# Check to see if the subcommand is defined:
|
18
|
+
if commands.methods.include? command.to_sym
|
19
|
+
# Execute command:
|
20
|
+
commands.send command
|
21
|
+
else
|
22
|
+
# Display usage information:
|
23
|
+
commands.help
|
24
|
+
end
|
data/lib/portfolio.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
module Portfolio
|
2
|
+
class Commands
|
3
|
+
# Show watched stocks and user portfolio
|
4
|
+
def show
|
5
|
+
# Get list of watched stocks:
|
6
|
+
watched_stocks = Store.instance.watched_stocks
|
7
|
+
|
8
|
+
# Get stock prices:
|
9
|
+
watched_stocks.map! do |stock|
|
10
|
+
{
|
11
|
+
symbol: stock,
|
12
|
+
price: StockPrices.instance.get_price_formatted(stock),
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get portfolio:
|
17
|
+
portfolio = Formatter.instance.format_portfolio(Store.instance.portfolio)
|
18
|
+
|
19
|
+
# Output watched stock table:
|
20
|
+
Formatter.instance.output_table("Watched Stocks", [:symbol, :price], watched_stocks)
|
21
|
+
|
22
|
+
# Output portfolio:
|
23
|
+
Formatter.instance.output_table("Portfolio",
|
24
|
+
[:symbol, :current_price, :number_owned, :price_paid, :commission, :profit],
|
25
|
+
portfolio,
|
26
|
+
['Symbol', 'Current Price', 'Number Owned', 'Price Paid', 'Commission', 'Profit'],
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Start watching a stock
|
31
|
+
def watch
|
32
|
+
if ARGV.length != 2
|
33
|
+
return help()
|
34
|
+
end
|
35
|
+
|
36
|
+
watched_stocks = Store.instance.watched_stocks
|
37
|
+
watched_stocks << ARGV[1].upcase
|
38
|
+
|
39
|
+
Store.instance.watched_stocks = watched_stocks
|
40
|
+
end
|
41
|
+
|
42
|
+
# Stop watching a stock
|
43
|
+
def ignore
|
44
|
+
if ARGV.length != 2
|
45
|
+
return help()
|
46
|
+
end
|
47
|
+
|
48
|
+
stock_to_remove = ARGV[1].upcase
|
49
|
+
watched_stocks = Store.instance.watched_stocks
|
50
|
+
watched_stocks.delete stock_to_remove
|
51
|
+
|
52
|
+
Store.instance.watched_stocks = watched_stocks
|
53
|
+
end
|
54
|
+
|
55
|
+
def invest
|
56
|
+
if ARGV.length != 5
|
57
|
+
return help()
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get parameters:
|
61
|
+
stock = ARGV[1]
|
62
|
+
amount_bought = ARGV[2]
|
63
|
+
price_paid = ARGV[3]
|
64
|
+
commission_paid = ARGV[4]
|
65
|
+
|
66
|
+
# Store new investment:
|
67
|
+
portfolio = Store.instance.portfolio
|
68
|
+
portfolio << {
|
69
|
+
stock: stock,
|
70
|
+
amount_bought: amount_bought,
|
71
|
+
price_paid: price_paid,
|
72
|
+
commission_paid: commission_paid,
|
73
|
+
}
|
74
|
+
Store.instance.portfolio = portfolio
|
75
|
+
|
76
|
+
# Tell the user that the investment has been logged and wish the user
|
77
|
+
# good luck.
|
78
|
+
puts "Investment in #{stock} logged - good luck!"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Remove stocks from portfolio
|
82
|
+
#
|
83
|
+
# FEATURE: Would be nice to be able to have multiple stocks from the same
|
84
|
+
# company, bought at different times, and be able to pick which one
|
85
|
+
# you're selling - rather than just automatically selling them all.
|
86
|
+
def sell
|
87
|
+
if ARGV.length != 2
|
88
|
+
return help()
|
89
|
+
end
|
90
|
+
|
91
|
+
stock_to_remove = ARGV[1].upcase
|
92
|
+
portfolio = Store.instance.portfolio
|
93
|
+
portfolio.reject! do |investment|
|
94
|
+
investment['stock'].upcase == stock_to_remove
|
95
|
+
end
|
96
|
+
|
97
|
+
Store.instance.portfolio = portfolio
|
98
|
+
end
|
99
|
+
|
100
|
+
# Show usage information
|
101
|
+
def help
|
102
|
+
puts "Portfolio, v#{Portfolio::VERSION}. Commands:\n".bold.underline
|
103
|
+
puts "Start watching a stock:".blue
|
104
|
+
puts " " + "--watch <stock>\n".underline
|
105
|
+
puts "Stop watching a stock:".blue
|
106
|
+
puts " " + "--ignore <stock>\n".underline
|
107
|
+
puts "Add investment to portfolio:".blue
|
108
|
+
puts " " + "--invest <stock> <amount bought> <price paid per stock> <total commission paid>\n".underline
|
109
|
+
puts "Remove investment from portfolio:".blue
|
110
|
+
puts " " + "--sell <stock>\n".underline
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'terminal-table'
|
3
|
+
|
4
|
+
module Portfolio
|
5
|
+
class Formatter
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def output_table(title, columns, data, headings = nil)
|
9
|
+
# Format data correctly for table:
|
10
|
+
data.map! do |row|
|
11
|
+
new_row = []
|
12
|
+
|
13
|
+
columns.each do |col|
|
14
|
+
new_row << row[col]
|
15
|
+
end
|
16
|
+
|
17
|
+
new_row
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create table with headings if some are passed in (or without if nil):
|
21
|
+
if headings.nil?
|
22
|
+
table = Terminal::Table.new(rows: data, title: title)
|
23
|
+
else
|
24
|
+
table = Terminal::Table.new(rows: data, title: title, headings: headings)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Output table:
|
28
|
+
puts table
|
29
|
+
end
|
30
|
+
|
31
|
+
def format_portfolio(portfolio)
|
32
|
+
portfolio.map! do |investment|
|
33
|
+
# Work out price paid, value, current stock price and profit for
|
34
|
+
# this investment:
|
35
|
+
symbol = investment['stock']
|
36
|
+
current_price = StockPrices.instance.get_stock(symbol).ask
|
37
|
+
total_paid = (investment['amount_bought'].to_f * investment['price_paid'].to_f) + investment['commission_paid'].to_f
|
38
|
+
total_value = investment['amount_bought'].to_f * current_price
|
39
|
+
profit = (total_value - total_paid).round(2)
|
40
|
+
|
41
|
+
# If profit is negative, highlight as red:
|
42
|
+
if profit < 0.00
|
43
|
+
profit = profit.to_s.red
|
44
|
+
# If profit is positive, highlight as green:
|
45
|
+
elsif profit > 0.00
|
46
|
+
profit = profit.to_s.green
|
47
|
+
# Otherwise, don't highlight it - no profit or loss:
|
48
|
+
else
|
49
|
+
profit = profit.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
{
|
53
|
+
symbol: symbol,
|
54
|
+
current_price: current_price,
|
55
|
+
number_owned: investment['amount_bought'],
|
56
|
+
price_paid: investment['price_paid'],
|
57
|
+
commission: investment['commission_paid'],
|
58
|
+
profit: profit,
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'stock_quote'
|
3
|
+
|
4
|
+
module Portfolio
|
5
|
+
class StockPrices
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def get_stock(symbol)
|
9
|
+
StockQuote::Stock.quote(symbol)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_price_formatted(symbol)
|
13
|
+
# Lookup stock price:
|
14
|
+
stock = get_stock(symbol)
|
15
|
+
|
16
|
+
# If the response code isn't 200, something went wrong:
|
17
|
+
if stock.response_code != 200
|
18
|
+
"ERROR".red
|
19
|
+
else
|
20
|
+
# Get the current stock price:
|
21
|
+
price = stock.ask.to_s
|
22
|
+
|
23
|
+
# If it's up, show it in green:
|
24
|
+
if stock.change > 0.0
|
25
|
+
price.green
|
26
|
+
# If it's down, show it in red:
|
27
|
+
elsif stock.change < 0.0
|
28
|
+
return price.red
|
29
|
+
# Otherwise, show it normally:
|
30
|
+
else
|
31
|
+
price
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Portfolio
|
5
|
+
class Store
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def watched_stocks
|
9
|
+
datastore = get_datastore
|
10
|
+
datastore['watched_stocks']
|
11
|
+
end
|
12
|
+
|
13
|
+
def watched_stocks=(watched_stocks)
|
14
|
+
data = get_datastore()
|
15
|
+
data['watched_stocks'] = watched_stocks
|
16
|
+
save_datastore(data)
|
17
|
+
end
|
18
|
+
|
19
|
+
def portfolio
|
20
|
+
datastore = get_datastore
|
21
|
+
datastore['portfolio']
|
22
|
+
end
|
23
|
+
|
24
|
+
def portfolio=(portfolio)
|
25
|
+
data = get_datastore()
|
26
|
+
data['portfolio'] = portfolio
|
27
|
+
save_datastore(data)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def get_datastore
|
33
|
+
if @datastore
|
34
|
+
@datastore
|
35
|
+
else
|
36
|
+
begin
|
37
|
+
datastore_file_str = File.read(datastore_location)
|
38
|
+
@datastore = JSON.parse(datastore_file_str)
|
39
|
+
rescue
|
40
|
+
create_datastore
|
41
|
+
get_datastore
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def save_datastore(data)
|
47
|
+
File.open(datastore_location, 'w') do |f|
|
48
|
+
f.write(data.to_json)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def datastore_location
|
53
|
+
File.expand_path('~/.portfolio/datastore.json')
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_datastore
|
57
|
+
begin
|
58
|
+
Dir.mkdir File.expand_path('~/.portfolio')
|
59
|
+
rescue
|
60
|
+
end
|
61
|
+
|
62
|
+
File.open(datastore_location, 'w') do |f|
|
63
|
+
datastore_hash = {
|
64
|
+
watched_stocks: [],
|
65
|
+
portfolio: [],
|
66
|
+
}
|
67
|
+
|
68
|
+
f.write(datastore_hash.to_json)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/portfolio.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'portfolio/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "portfolio_stocks"
|
8
|
+
spec.version = Portfolio::VERSION
|
9
|
+
spec.authors = ["Tim Davies"]
|
10
|
+
spec.email = ["mail@timdavi.es"]
|
11
|
+
spec.summary = %q{A simple command-line tool for managing your stock portfolio}
|
12
|
+
spec.description = <<-DESC
|
13
|
+
A simple command-line tool for managing your stock portfolio,
|
14
|
+
tracking your investments and watching stock prices.
|
15
|
+
DESC
|
16
|
+
spec.homepage = "https://github.com/timdavies/Portfolio"
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f =~ /docs\// }
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.3"
|
26
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
27
|
+
|
28
|
+
spec.add_dependency "colored", "~> 1.2"
|
29
|
+
spec.add_dependency "terminal-table"
|
30
|
+
spec.add_dependency "stock_quote"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: portfolio_stocks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Davies
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: colored
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: terminal-table
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: stock_quote
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: |2
|
98
|
+
A simple command-line tool for managing your stock portfolio,
|
99
|
+
tracking your investments and watching stock prices.
|
100
|
+
email:
|
101
|
+
- mail@timdavi.es
|
102
|
+
executables:
|
103
|
+
- portfolio
|
104
|
+
extensions: []
|
105
|
+
extra_rdoc_files: []
|
106
|
+
files:
|
107
|
+
- .gitignore
|
108
|
+
- Gemfile
|
109
|
+
- Gemfile.lock
|
110
|
+
- LICENSE.txt
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/portfolio
|
114
|
+
- lib/portfolio.rb
|
115
|
+
- lib/portfolio/commands.rb
|
116
|
+
- lib/portfolio/formatter.rb
|
117
|
+
- lib/portfolio/stockprices.rb
|
118
|
+
- lib/portfolio/store.rb
|
119
|
+
- lib/portfolio/version.rb
|
120
|
+
- portfolio.gemspec
|
121
|
+
homepage: https://github.com/timdavies/Portfolio
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.1.10
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: A simple command-line tool for managing your stock portfolio
|
145
|
+
test_files: []
|