stockfolio 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,4 +3,9 @@
3
3
  $LOAD_PATH << './lib'
4
4
 
5
5
  require 'stockfolio'
6
- StockFolio::Runner.start
6
+ begin
7
+ StockFolio::Runner.start
8
+ rescue Boson::OptionParser::Error => e
9
+ puts e.message
10
+ exit 1
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'stockfolio/version'
2
+ require 'gems'
3
+
4
+ class StockFolio::Check
5
+
6
+ def self.has_newer
7
+ @info = Gems.info 'stockfolio'
8
+ Gem::Version.new(@info["version"]) > Gem::Version.new(StockFolio::VERSION)
9
+ end
10
+
11
+ def self.version_available
12
+ return @info["version"]
13
+ end
14
+
15
+ end
@@ -12,11 +12,46 @@ class StockFolio::Runner < Boson::Runner
12
12
  option :date, :type => :string, :desc => 'Transaction date'
13
13
  end
14
14
 
15
+ def version
16
+ require 'stockfolio/version'
17
+ require 'stockfolio/check'
18
+ puts StockFolio::VERSION
19
+ if StockFolio::Check.has_newer
20
+ puts "There is a more recent version #{StockFolio::Check.version_available}"
21
+ end
22
+ end
23
+
24
+ desc "Current quote for a stock"
15
25
  def quote(symbol)
16
26
  quote = StockFolio::Web.quote(symbol)
17
27
  print_quotes(quote)
18
28
  end
19
29
 
30
+ desc "Historical prices for a stock"
31
+ def historical(symbol,start_date,end_date)
32
+ history = StockFolio::Web.historical(symbol, DateTime.parse(start_date), DateTime.parse(end_date))
33
+ puts Hirb::Helpers::Table.render(history, :fields => [:date, :open, :close, :low, :high, :volume])
34
+ end
35
+
36
+ desc "Search symbol"
37
+ def search(term)
38
+ matches = StockFolio::Web.search(term)
39
+
40
+ lines = []
41
+ matches.each do |match|
42
+ if match['e'].length > 0 && match['t'].length > 0
43
+ line = {
44
+ :Symbol => "#{match['e']}:#{match['t']}",
45
+ :Name => match['n']
46
+ }
47
+ lines << line
48
+ end
49
+ end
50
+
51
+ puts Hirb::Helpers::Table.render(lines, :fields => [:Symbol, :Name])
52
+
53
+ end
54
+
20
55
  desc 'List porfolios'
21
56
  def portfolios
22
57
  q = Portfolio.all
@@ -122,6 +157,72 @@ class StockFolio::Runner < Boson::Runner
122
157
  puts "Created portfolio \"#{name}\""
123
158
  end
124
159
 
160
+ desc 'List transactions for a portfolio'
161
+ def transactions(name)
162
+ p = Portfolio.first(:name => name)
163
+ if p == nil
164
+ puts "Portfolio #{name} not found"
165
+ exit
166
+ end
167
+
168
+ transactions = []
169
+ p.transactions.each do |transaction|
170
+ transactions << {
171
+ :id => transaction.id,
172
+ :symbol => transaction.symbol,
173
+ :quantity => transaction.quantity,
174
+ :price => transaction.price,
175
+ :executed_at => transaction.executed_at,
176
+ :fee => transaction.fee,
177
+ :created_at => transaction.created_at
178
+ }
179
+ end
180
+ puts Hirb::Helpers::Table.render(transactions, fields: [:id, :symbol, :quantity, :price, :fee, :executed_at, :created_at])
181
+
182
+ end
183
+
184
+ def delete(type,alpha,beta = nil)
185
+ if type == "transaction"
186
+ name = alpha
187
+ id = beta
188
+ puts "Deleting transaction #{id} from #{name}"
189
+
190
+ portfolio = Portfolio.first(:name => name)
191
+ if portfolio == nil
192
+ puts "Portfolio #{name} not found"
193
+ exit
194
+ end
195
+
196
+ transaction = Transaction.get(id)
197
+
198
+ if transaction != nil && transaction.portfolio == portfolio
199
+ transaction.destroy!
200
+ else
201
+ puts "Could not find transaction #{id} in portfolio #{name}"
202
+ end
203
+
204
+ elsif type == "portfolio"
205
+ name = alpha
206
+ puts "Deleting portfolio #{name}"
207
+
208
+ portfolio = Portfolio.first(:name => name)
209
+ if portfolio == nil
210
+ puts "Portfolio #{name} not found"
211
+ exit
212
+ end
213
+
214
+ portfolio.transactions.each do |transaction|
215
+ transaction.destroy!
216
+ end
217
+ portfolio.destroy!
218
+
219
+ end
220
+ end
221
+
222
+ #
223
+ # WATCHLIST
224
+ #
225
+
125
226
  desc 'Add to watchlist'
126
227
  def watch(symbol)
127
228
  # Validate symbol
@@ -137,6 +238,15 @@ class StockFolio::Runner < Boson::Runner
137
238
  end
138
239
  end
139
240
 
241
+ desc 'Remove from watchlist'
242
+ def unwatch(symbol)
243
+ item = WatchList.first(:symbol => symbol)
244
+ if item != nil
245
+ item.destroy
246
+ puts "Removed #{symbol} from watchlist"
247
+ end
248
+ end
249
+
140
250
  desc 'Show Watchlist'
141
251
  def watchlist
142
252
  items = WatchList.all(:order => [:symbol.asc])
@@ -1,3 +1,3 @@
1
1
  module StockFolio
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
@@ -1,3 +1,4 @@
1
+ require 'uri'
1
2
  require 'json'
2
3
  require 'net/http'
3
4
 
@@ -13,4 +14,49 @@ class StockFolio::Web
13
14
  end
14
15
  JSON.parse(data.slice(3, data.length).strip)
15
16
  end
17
+
18
+ def self.historical(symbol, startDate, endDate)
19
+ s = startDate.strftime("%b+%d,+%Y")
20
+ e = endDate.strftime("%b+%d,+%Y")
21
+ url = "http://finance.google.com/finance/historical?q=#{symbol}&startdate=#{s}&enddate=#{e}&output=csv"
22
+
23
+ resp = Net::HTTP.get_response(URI.parse(url))
24
+ data = resp.body
25
+
26
+ if data.empty?
27
+ return nil
28
+ end
29
+
30
+ lines = data.split("\n")
31
+ lines.shift
32
+ items = []
33
+ lines.each do |line|
34
+ parts = line.split(",")
35
+ i = 0
36
+ item = {}
37
+ item[:date] = Date.parse(parts[0])
38
+ item[:open] = parts[1]
39
+ item[:high] = parts[2]
40
+ item[:low] = parts[3]
41
+ item[:close] = parts[4]
42
+ item[:volume] = parts[5]
43
+ items << item
44
+ end
45
+
46
+ items
47
+ end
48
+
49
+ def self.search(term)
50
+ q = URI.escape(term, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
51
+ url = "http://www.google.com/finance/match?matchtype=matchall&q=#{q}"
52
+ resp = Net::HTTP.get_response(URI.parse(url))
53
+ data = resp.body
54
+
55
+ if data.empty?
56
+ return nil
57
+ end
58
+ result = JSON.parse(data)
59
+ result["matches"]
60
+ end
61
+
16
62
  end
metadata CHANGED
@@ -1,89 +1,136 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: stockfolio
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.4
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 5
9
+ version: 0.1.5
6
10
  platform: ruby
7
- authors:
11
+ authors:
8
12
  - Jerome Poichet
9
13
  autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
- date: 2012-03-22 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
16
+
17
+ date: 2012-03-22 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: boson
16
- requirement: &2169047320 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
22
31
  type: :runtime
23
- prerelease: false
24
- version_requirements: *2169047320
25
- - !ruby/object:Gem::Dependency
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
26
34
  name: hirb
27
- requirement: &2169046660 !ruby/object:Gem::Requirement
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
28
37
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
33
44
  type: :runtime
34
- prerelease: false
35
- version_requirements: *2169046660
36
- - !ruby/object:Gem::Dependency
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
37
47
  name: data_mapper
38
- requirement: &2169045840 !ruby/object:Gem::Requirement
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
39
50
  none: false
40
- requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
43
- version: '0'
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
44
57
  type: :runtime
45
- prerelease: false
46
- version_requirements: *2169045840
47
- - !ruby/object:Gem::Dependency
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
48
60
  name: dm-migrations
49
- requirement: &2169045220 !ruby/object:Gem::Requirement
61
+ prerelease: false
62
+ requirement: &id004 !ruby/object:Gem::Requirement
50
63
  none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
55
70
  type: :runtime
56
- prerelease: false
57
- version_requirements: *2169045220
58
- - !ruby/object:Gem::Dependency
71
+ version_requirements: *id004
72
+ - !ruby/object:Gem::Dependency
59
73
  name: dm-sqlite-adapter
60
- requirement: &2169044620 !ruby/object:Gem::Requirement
74
+ prerelease: false
75
+ requirement: &id005 !ruby/object:Gem::Requirement
61
76
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
66
83
  type: :runtime
67
- prerelease: false
68
- version_requirements: *2169044620
69
- - !ruby/object:Gem::Dependency
84
+ version_requirements: *id005
85
+ - !ruby/object:Gem::Dependency
70
86
  name: json
71
- requirement: &2169043820 !ruby/object:Gem::Requirement
87
+ prerelease: false
88
+ requirement: &id006 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ type: :runtime
97
+ version_requirements: *id006
98
+ - !ruby/object:Gem::Dependency
99
+ name: uri
100
+ prerelease: false
101
+ requirement: &id007 !ruby/object:Gem::Requirement
72
102
  none: false
73
- requirements:
74
- - - ! '>='
75
- - !ruby/object:Gem::Version
76
- version: '0'
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ segments:
107
+ - 0
108
+ version: "0"
77
109
  type: :runtime
110
+ version_requirements: *id007
111
+ - !ruby/object:Gem::Dependency
112
+ name: gems
78
113
  prerelease: false
79
- version_requirements: *2169043820
114
+ requirement: &id008 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ type: :runtime
123
+ version_requirements: *id008
80
124
  description:
81
125
  email: poitch@gmail.com
82
- executables:
126
+ executables:
83
127
  - stockfolio
84
128
  extensions: []
129
+
85
130
  extra_rdoc_files: []
86
- files:
131
+
132
+ files:
133
+ - lib/stockfolio/check.rb
87
134
  - lib/stockfolio/portfolio.rb
88
135
  - lib/stockfolio/runner.rb
89
136
  - lib/stockfolio/transaction.rb
@@ -92,29 +139,38 @@ files:
92
139
  - lib/stockfolio/web.rb
93
140
  - lib/stockfolio.rb
94
141
  - bin/stockfolio
142
+ has_rdoc: true
95
143
  homepage: http://github.com/poitch/stockfolio
96
144
  licenses: []
145
+
97
146
  post_install_message:
98
147
  rdoc_options: []
99
- require_paths:
148
+
149
+ require_paths:
100
150
  - lib
101
151
  - lib
102
- required_ruby_version: !ruby/object:Gem::Requirement
152
+ required_ruby_version: !ruby/object:Gem::Requirement
103
153
  none: false
104
- requirements:
105
- - - ! '>='
106
- - !ruby/object:Gem::Version
107
- version: '0'
108
- required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ segments:
158
+ - 0
159
+ version: "0"
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
161
  none: false
110
- requirements:
111
- - - ! '>='
112
- - !ruby/object:Gem::Version
113
- version: '0'
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ segments:
166
+ - 0
167
+ version: "0"
114
168
  requirements: []
169
+
115
170
  rubyforge_project:
116
- rubygems_version: 1.8.10
171
+ rubygems_version: 1.3.7
117
172
  signing_key:
118
173
  specification_version: 3
119
174
  summary: Track stock portfolio from the command line
120
175
  test_files: []
176
+