options-lib 0.9.2 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +56 -1
- data/Rakefile +56 -0
- data/bin/show_quotes +1 -1
- data/lib/options-lib/option_quote.rb +3 -6
- data/lib/options-lib/yahoo_crawler.rb +26 -10
- data/options-lib.gemspec +1 -1
- data/spec/option_quote_spec.rb +11 -4
- data/spec/yahoo_crawler_spec.rb +11 -2
- metadata +2 -1
data/README.markdown
CHANGED
@@ -3,7 +3,62 @@
|
|
3
3
|
A set of classes for dealing with options. It includes a crawler for Yahoo!Finance. The crawler has an internal
|
4
4
|
thread that can be started to periodically update the option quotes.
|
5
5
|
|
6
|
+
## Install
|
7
|
+
|
8
|
+
gem install options-lib
|
9
|
+
|
6
10
|
## Usage
|
7
11
|
|
8
|
-
|
12
|
+
require 'options-lib'
|
13
|
+
|
14
|
+
# Create a crawler for all the options for ('AAPL') expiring on '2013-01-18'
|
15
|
+
y = YahooCrawler.new('AAPL', '2013-01-18')
|
16
|
+
|
17
|
+
# Fetch the entire options chain for this stock and expiration
|
18
|
+
y.fetch
|
19
|
+
|
20
|
+
# Show an option quote for a given strike price
|
21
|
+
y.call_options[300] # => AAPL_C300_18JAN2013: bid => 88.5, ask => 90.5
|
22
|
+
y.put_options[300] # => AAPL_P300_18JAN2013: bid => 40.7, ask => 41.95
|
23
|
+
|
24
|
+
# Options quote has stock price, bid and ask for option
|
25
|
+
q = y.call_options[300]
|
26
|
+
q.stock_price # => 342.88
|
27
|
+
q.bid # => 88.5
|
28
|
+
q.ask # => 90.5
|
29
|
+
|
30
|
+
# Crawler also has current stock price, as each option quote
|
31
|
+
y.stock_price # => 342.88
|
32
|
+
|
33
|
+
# You can get a list of all stock prices from the crawler
|
34
|
+
y.call_strikes # => [135.0, 140.0, ..., 530.0, 540.0]
|
35
|
+
y.put_strikes # => [135.0, 140.0, ..., 530.0, 540.0]
|
36
|
+
|
37
|
+
# So to print the entire options chain, you can do something like that
|
38
|
+
y.call_strikes.each { |strike| puts y.call_options[strike] }
|
39
|
+
y.put_strikes.each { |strike| puts y.put_options[strike] }
|
40
|
+
|
41
|
+
# you can place the crawler in auto_reload mode, passing a period to refresh itself
|
42
|
+
y.auto_reload 5
|
43
|
+
y.call_options[300].bid # => 88.5
|
44
|
+
sleep 6
|
45
|
+
y.call_options[300].bid # => 90.3
|
46
|
+
|
47
|
+
# you can also receive callbacks from the internal thread when the crawler gets updated
|
48
|
+
y.auto_reload(5) do
|
49
|
+
puts "Current bid: #{y.call_options[300].bid}"
|
50
|
+
end
|
51
|
+
|
52
|
+
# if you need to block ruby from exiting while your thread is executing in the background
|
53
|
+
# you can use the method below
|
54
|
+
y.join_reload_thread
|
55
|
+
|
56
|
+
# internal symbol versus real symbol
|
57
|
+
y.internal_symbol # => AAPL_C300_18JAN2013
|
58
|
+
y.symbol # => AAPL130119C00300000
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
|
9
64
|
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
def gemspec
|
4
|
+
@gemspec ||= begin
|
5
|
+
file = File.expand_path("../options-lib.gemspec", __FILE__)
|
6
|
+
eval(File.read(file), binding, file)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def alias_task(old_task, new_task)
|
11
|
+
task new_task do
|
12
|
+
Rake::Task[old_task].invoke
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
desc "Validate the gemspec"
|
18
|
+
task :gemspec do
|
19
|
+
gemspec.validate
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Build gem locally"
|
23
|
+
task :build => :gemspec do
|
24
|
+
system "gem build #{gemspec.name}.gemspec"
|
25
|
+
FileUtils.mkdir_p "pkg"
|
26
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Install gem locally"
|
30
|
+
task :install => :build do
|
31
|
+
system "gem install pkg/#{gemspec.name}-#{gemspec.version}"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Uninstall gem locally"
|
35
|
+
task :uninstall => :gemspec do
|
36
|
+
system "gem uninstall -x #{gemspec.name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Reinstall gem locally"
|
40
|
+
task :reinstall do
|
41
|
+
Rake::Task[:uninstall].invoke
|
42
|
+
Rake::Task[:install].invoke
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Push gem to RubyGems.org"
|
46
|
+
task :push do
|
47
|
+
system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_task(:reinstall, :r)
|
51
|
+
alias_task(:uninstall, :u)
|
52
|
+
alias_task(:install, :i)
|
53
|
+
alias_task(:build, :b)
|
54
|
+
alias_task(:push, :p)
|
55
|
+
|
56
|
+
|
data/bin/show_quotes
CHANGED
@@ -25,7 +25,7 @@ y.auto_reload(reload_period) do
|
|
25
25
|
|
26
26
|
options = is_call ? y.call_options : y.put_options
|
27
27
|
quote = options[strike]
|
28
|
-
stock_price = y.
|
28
|
+
stock_price = y.stock_price
|
29
29
|
|
30
30
|
puts "Stock @ #{stock_price} Options: #{quote.bid} | #{quote.ask} Spread: #{quote.spread}"
|
31
31
|
|
@@ -2,12 +2,13 @@ require_relative 'option'
|
|
2
2
|
|
3
3
|
class OptionQuote
|
4
4
|
|
5
|
-
attr_reader :option, :bid, :ask
|
5
|
+
attr_reader :option, :bid, :ask, :stock_price
|
6
6
|
|
7
7
|
def initialize(option, args)
|
8
8
|
@option = option
|
9
9
|
@bid = args[:bid] || nil
|
10
10
|
@ask = args[:ask] || nil
|
11
|
+
@stock_price = args[:stock_price] || nil
|
11
12
|
end
|
12
13
|
|
13
14
|
def spread
|
@@ -19,11 +20,7 @@ class OptionQuote
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def to_s
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def inspect
|
26
|
-
"#{option.inspect}: bid => #{bid.inspect}, ask => #{ask.inspect}"
|
23
|
+
"#{option}: bid => #{bid}, ask => #{ask}"
|
27
24
|
end
|
28
25
|
|
29
26
|
end
|
@@ -11,9 +11,9 @@ class YahooCrawler
|
|
11
11
|
|
12
12
|
def initialize(stock, exp)
|
13
13
|
@mech = Mechanize.new
|
14
|
-
@stock, @exp = stock, exp
|
14
|
+
@stock, @exp = stock.upcase, exp
|
15
15
|
@url = "http://finance.yahoo.com/q/op?s=#{stock}&m=#{exp[0,7]}"
|
16
|
-
@
|
16
|
+
@stock_price = nil
|
17
17
|
@call_options = Hash.new
|
18
18
|
@put_options = Hash.new
|
19
19
|
@call_strikes = Array.new
|
@@ -23,6 +23,10 @@ class YahooCrawler
|
|
23
23
|
@thread = nil
|
24
24
|
end
|
25
25
|
|
26
|
+
def to_s
|
27
|
+
"YahooCrawler('#{@stock}','#{@exp})"
|
28
|
+
end
|
29
|
+
|
26
30
|
def auto_reload(period = 60)
|
27
31
|
if not @thread.nil?
|
28
32
|
stop
|
@@ -58,6 +62,9 @@ class YahooCrawler
|
|
58
62
|
c_options, p_options = Hash.new, Hash.new
|
59
63
|
c_strikes, p_strikes = Array.new, Array.new
|
60
64
|
stock_price = nil
|
65
|
+
|
66
|
+
# A small hack to make my hashes accept integers instead of floats for the strike prices
|
67
|
+
add_convert_method_for_keys(c_options, p_options)
|
61
68
|
|
62
69
|
@t_lock.synchronize { # don't step into each other in case someone calls fetch
|
63
70
|
|
@@ -74,7 +81,7 @@ class YahooCrawler
|
|
74
81
|
lines = lines.chunk(lines.length / 8)
|
75
82
|
|
76
83
|
lines.each do |array|
|
77
|
-
quote = parse_quote(array, Option::CALL)
|
84
|
+
quote = parse_quote(array, Option::CALL, stock_price)
|
78
85
|
c_options[quote.option.strike] = quote
|
79
86
|
end
|
80
87
|
|
@@ -82,7 +89,7 @@ class YahooCrawler
|
|
82
89
|
lines = lines.chunk(lines.length / 8)
|
83
90
|
|
84
91
|
lines.each do |array|
|
85
|
-
quote = parse_quote(array, Option::PUT)
|
92
|
+
quote = parse_quote(array, Option::PUT, stock_price)
|
86
93
|
p_options[quote.option.strike] = quote
|
87
94
|
end
|
88
95
|
|
@@ -95,9 +102,9 @@ class YahooCrawler
|
|
95
102
|
@lock.synchronize {
|
96
103
|
@call_options, @put_options = c_options, p_options
|
97
104
|
@call_strikes, @put_strikes = c_strikes, p_strikes
|
98
|
-
@
|
105
|
+
@stock_price = stock_price
|
99
106
|
}
|
100
|
-
|
107
|
+
nil
|
101
108
|
end
|
102
109
|
|
103
110
|
def get_option_quote(type, strike)
|
@@ -132,8 +139,8 @@ class YahooCrawler
|
|
132
139
|
@lock.synchronize { @put_options }
|
133
140
|
end
|
134
141
|
|
135
|
-
def
|
136
|
-
@lock.synchronize { @
|
142
|
+
def stock_price
|
143
|
+
@lock.synchronize { @stock_price }
|
137
144
|
end
|
138
145
|
|
139
146
|
def show_calls
|
@@ -146,14 +153,14 @@ class YahooCrawler
|
|
146
153
|
|
147
154
|
private
|
148
155
|
|
149
|
-
def parse_quote(line, type)
|
156
|
+
def parse_quote(line, type, stock_price)
|
150
157
|
strike = line[0].to_f
|
151
158
|
symbol = line[1]
|
152
159
|
bid = f line[4]
|
153
160
|
ask = f line[5]
|
154
161
|
|
155
162
|
o = Option.new(type, @stock, strike, @exp, symbol)
|
156
|
-
OptionQuote.new(o, :bid => bid, :ask => ask)
|
163
|
+
OptionQuote.new(o, :bid => bid, :ask => ask, :stock_price => stock_price)
|
157
164
|
end
|
158
165
|
|
159
166
|
# Get all values inside tags
|
@@ -165,5 +172,14 @@ class YahooCrawler
|
|
165
172
|
def f(data)
|
166
173
|
data == 'N/A' ? nil : data.to_f
|
167
174
|
end
|
175
|
+
|
176
|
+
def add_convert_method_for_keys(*args)
|
177
|
+
args.each do |obj|
|
178
|
+
def obj.[](key)
|
179
|
+
super key.to_f
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
168
184
|
|
169
185
|
end
|
data/options-lib.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'options-lib'
|
3
|
-
s.version = '0.9.
|
3
|
+
s.version = '0.9.4'
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.summary = 'Options Library'
|
6
6
|
s.description = 'A set of classes for dealing with options. It includes a crawler for Yahoo!Finance.'
|
data/spec/option_quote_spec.rb
CHANGED
@@ -3,10 +3,15 @@ Dir["./lib/*.rb"].each {|file| require file }
|
|
3
3
|
|
4
4
|
describe OptionQuote do
|
5
5
|
|
6
|
+
o,q = nil,nil
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
o = Option.new(Option::CALL, 'AAPL', 250, '2010-02-14')
|
10
|
+
q = OptionQuote.new(o, :bid => 1.2, :ask => 1.4, :stock_price => 10)
|
11
|
+
end
|
12
|
+
|
6
13
|
it 'has option, bid and ask prices' do
|
7
14
|
|
8
|
-
o = Option.new(Option::CALL, 'AAPL', 250, '2010-02-14')
|
9
|
-
q = OptionQuote.new(o, :bid => 1.2, :ask => 1.4)
|
10
15
|
q.option.should == o
|
11
16
|
q.bid.should == 1.2
|
12
17
|
q.ask.should == 1.4
|
@@ -14,10 +19,12 @@ describe OptionQuote do
|
|
14
19
|
end
|
15
20
|
|
16
21
|
it 'should have an spread' do
|
17
|
-
o = Option.new(Option::CALL, 'AAPL', 250, '2010-02-14')
|
18
|
-
q = OptionQuote.new(o, :bid => 1.2, :ask => 1.4)
|
19
22
|
q.spread.prettify.should == "0.2"
|
20
23
|
|
21
24
|
end
|
22
25
|
|
26
|
+
it 'should have the current stock price' do
|
27
|
+
q.stock_price.should == 10
|
28
|
+
end
|
29
|
+
|
23
30
|
end
|
data/spec/yahoo_crawler_spec.rb
CHANGED
@@ -19,7 +19,7 @@ describe YahooCrawler do
|
|
19
19
|
|
20
20
|
it 'should be able to get current price of stock' do
|
21
21
|
|
22
|
-
y.
|
22
|
+
y.stock_price.should > 0
|
23
23
|
|
24
24
|
end
|
25
25
|
|
@@ -33,17 +33,19 @@ describe YahooCrawler do
|
|
33
33
|
it 'should be able to give an option quote by strike price' do
|
34
34
|
|
35
35
|
# get a good strike price by rounding the current stock price
|
36
|
-
good_price = ((y.
|
36
|
+
good_price = ((y.stock_price / 100).to_i * 100).to_f
|
37
37
|
|
38
38
|
call_quote = y.call_options[good_price]
|
39
39
|
call_quote.option.internal_symbol.should == "AAPL_C#{good_price.to_i}_18JAN2013"
|
40
40
|
call_quote.bid.should > 0 if not call_quote.bid.nil?
|
41
41
|
call_quote.ask.should > 0 if not call_quote.ask.nil?
|
42
|
+
call_quote.stock_price.should > 0 if not call_quote.stock_price.nil?
|
42
43
|
|
43
44
|
put_quote = y.put_options[good_price]
|
44
45
|
put_quote.option.internal_symbol.should == "AAPL_P#{good_price.to_i}_18JAN2013"
|
45
46
|
put_quote.bid.should > 0 if not put_quote.bid.nil?
|
46
47
|
put_quote.ask.should > 0 if not put_quote.ask.nil?
|
48
|
+
put_quote.stock_price.should > 0 if not put_quote.stock_price.nil?
|
47
49
|
|
48
50
|
end
|
49
51
|
|
@@ -54,6 +56,13 @@ describe YahooCrawler do
|
|
54
56
|
y.put_options.length.should > 0
|
55
57
|
|
56
58
|
end
|
59
|
+
|
60
|
+
it 'should accept integers as well as floats for strike prices when accessing the options hash' do
|
61
|
+
|
62
|
+
y.call_options[300].should == y.call_options[300.0]
|
63
|
+
|
64
|
+
end
|
65
|
+
|
57
66
|
|
58
67
|
|
59
68
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: options-lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.9.
|
5
|
+
version: 0.9.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Sergio Oliveira Jr.
|
@@ -45,6 +45,7 @@ extra_rdoc_files: []
|
|
45
45
|
|
46
46
|
files:
|
47
47
|
- README.markdown
|
48
|
+
- Rakefile
|
48
49
|
- bin/show_quotes
|
49
50
|
- lib/options-lib.rb
|
50
51
|
- lib/options-lib/helpers.rb
|